rev |
line source |
nuclear@3
|
1 /************************************************************************************
|
nuclear@3
|
2
|
nuclear@3
|
3 Filename : OVR_String.cpp
|
nuclear@3
|
4 Content : String UTF8 string implementation with copy-on-write semantics
|
nuclear@3
|
5 (thread-safe for assignment but not modification).
|
nuclear@3
|
6 Created : September 19, 2012
|
nuclear@3
|
7 Notes :
|
nuclear@3
|
8
|
nuclear@3
|
9 Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved.
|
nuclear@3
|
10
|
nuclear@3
|
11 Use of this software is subject to the terms of the Oculus license
|
nuclear@3
|
12 agreement provided at the time of installation or download, or which
|
nuclear@3
|
13 otherwise accompanies this software in either electronic or hard copy form.
|
nuclear@3
|
14
|
nuclear@3
|
15 ************************************************************************************/
|
nuclear@3
|
16
|
nuclear@3
|
17 #include "OVR_String.h"
|
nuclear@3
|
18
|
nuclear@3
|
19 #include <stdlib.h>
|
nuclear@3
|
20 #include <ctype.h>
|
nuclear@3
|
21
|
nuclear@3
|
22 #ifdef OVR_OS_QNX
|
nuclear@3
|
23 # include <strings.h>
|
nuclear@3
|
24 #endif
|
nuclear@3
|
25
|
nuclear@3
|
26 namespace OVR {
|
nuclear@3
|
27
|
nuclear@3
|
28 #define String_LengthIsSize (UPInt(1) << String::Flag_LengthIsSizeShift)
|
nuclear@3
|
29
|
nuclear@3
|
30 String::DataDesc String::NullData = {String_LengthIsSize, 1, {0} };
|
nuclear@3
|
31
|
nuclear@3
|
32
|
nuclear@3
|
33 String::String()
|
nuclear@3
|
34 {
|
nuclear@3
|
35 pData = &NullData;
|
nuclear@3
|
36 pData->AddRef();
|
nuclear@3
|
37 };
|
nuclear@3
|
38
|
nuclear@3
|
39 String::String(const char* pdata)
|
nuclear@3
|
40 {
|
nuclear@3
|
41 // Obtain length in bytes; it doesn't matter if _data is UTF8.
|
nuclear@3
|
42 UPInt size = pdata ? OVR_strlen(pdata) : 0;
|
nuclear@3
|
43 pData = AllocDataCopy1(size, 0, pdata, size);
|
nuclear@3
|
44 };
|
nuclear@3
|
45
|
nuclear@3
|
46 String::String(const char* pdata1, const char* pdata2, const char* pdata3)
|
nuclear@3
|
47 {
|
nuclear@3
|
48 // Obtain length in bytes; it doesn't matter if _data is UTF8.
|
nuclear@3
|
49 UPInt size1 = pdata1 ? OVR_strlen(pdata1) : 0;
|
nuclear@3
|
50 UPInt size2 = pdata2 ? OVR_strlen(pdata2) : 0;
|
nuclear@3
|
51 UPInt size3 = pdata3 ? OVR_strlen(pdata3) : 0;
|
nuclear@3
|
52
|
nuclear@3
|
53 DataDesc *pdataDesc = AllocDataCopy2(size1 + size2 + size3, 0,
|
nuclear@3
|
54 pdata1, size1, pdata2, size2);
|
nuclear@3
|
55 memcpy(pdataDesc->Data + size1 + size2, pdata3, size3);
|
nuclear@3
|
56 pData = pdataDesc;
|
nuclear@3
|
57 }
|
nuclear@3
|
58
|
nuclear@3
|
59 String::String(const char* pdata, UPInt size)
|
nuclear@3
|
60 {
|
nuclear@3
|
61 OVR_ASSERT((size == 0) || (pdata != 0));
|
nuclear@3
|
62 pData = AllocDataCopy1(size, 0, pdata, size);
|
nuclear@3
|
63 };
|
nuclear@3
|
64
|
nuclear@3
|
65
|
nuclear@3
|
66 String::String(const InitStruct& src, UPInt size)
|
nuclear@3
|
67 {
|
nuclear@3
|
68 pData = AllocData(size, 0);
|
nuclear@3
|
69 src.InitString(GetData()->Data, size);
|
nuclear@3
|
70 }
|
nuclear@3
|
71
|
nuclear@3
|
72 String::String(const String& src)
|
nuclear@3
|
73 {
|
nuclear@3
|
74 pData = src.GetData();
|
nuclear@3
|
75 pData->AddRef();
|
nuclear@3
|
76 }
|
nuclear@3
|
77
|
nuclear@3
|
78 String::String(const StringBuffer& src)
|
nuclear@3
|
79 {
|
nuclear@3
|
80 pData = AllocDataCopy1(src.GetSize(), 0, src.ToCStr(), src.GetSize());
|
nuclear@3
|
81 }
|
nuclear@3
|
82
|
nuclear@3
|
83 String::String(const wchar_t* data)
|
nuclear@3
|
84 {
|
nuclear@3
|
85 pData = &NullData;
|
nuclear@3
|
86 pData->AddRef();
|
nuclear@3
|
87 // Simplified logic for wchar_t constructor.
|
nuclear@3
|
88 if (data)
|
nuclear@3
|
89 *this = data;
|
nuclear@3
|
90 }
|
nuclear@3
|
91
|
nuclear@3
|
92
|
nuclear@3
|
93 String::DataDesc* String::AllocData(UPInt size, UPInt lengthIsSize)
|
nuclear@3
|
94 {
|
nuclear@3
|
95 String::DataDesc* pdesc;
|
nuclear@3
|
96
|
nuclear@3
|
97 if (size == 0)
|
nuclear@3
|
98 {
|
nuclear@3
|
99 pdesc = &NullData;
|
nuclear@3
|
100 pdesc->AddRef();
|
nuclear@3
|
101 return pdesc;
|
nuclear@3
|
102 }
|
nuclear@3
|
103
|
nuclear@3
|
104 pdesc = (DataDesc*)OVR_ALLOC(sizeof(DataDesc)+ size);
|
nuclear@3
|
105 pdesc->Data[size] = 0;
|
nuclear@3
|
106 pdesc->RefCount = 1;
|
nuclear@3
|
107 pdesc->Size = size | lengthIsSize;
|
nuclear@3
|
108 return pdesc;
|
nuclear@3
|
109 }
|
nuclear@3
|
110
|
nuclear@3
|
111
|
nuclear@3
|
112 String::DataDesc* String::AllocDataCopy1(UPInt size, UPInt lengthIsSize,
|
nuclear@3
|
113 const char* pdata, UPInt copySize)
|
nuclear@3
|
114 {
|
nuclear@3
|
115 String::DataDesc* pdesc = AllocData(size, lengthIsSize);
|
nuclear@3
|
116 memcpy(pdesc->Data, pdata, copySize);
|
nuclear@3
|
117 return pdesc;
|
nuclear@3
|
118 }
|
nuclear@3
|
119
|
nuclear@3
|
120 String::DataDesc* String::AllocDataCopy2(UPInt size, UPInt lengthIsSize,
|
nuclear@3
|
121 const char* pdata1, UPInt copySize1,
|
nuclear@3
|
122 const char* pdata2, UPInt copySize2)
|
nuclear@3
|
123 {
|
nuclear@3
|
124 String::DataDesc* pdesc = AllocData(size, lengthIsSize);
|
nuclear@3
|
125 memcpy(pdesc->Data, pdata1, copySize1);
|
nuclear@3
|
126 memcpy(pdesc->Data + copySize1, pdata2, copySize2);
|
nuclear@3
|
127 return pdesc;
|
nuclear@3
|
128 }
|
nuclear@3
|
129
|
nuclear@3
|
130
|
nuclear@3
|
131 UPInt String::GetLength() const
|
nuclear@3
|
132 {
|
nuclear@3
|
133 // Optimize length accesses for non-UTF8 character strings.
|
nuclear@3
|
134 DataDesc* pdata = GetData();
|
nuclear@3
|
135 UPInt length, size = pdata->GetSize();
|
nuclear@3
|
136
|
nuclear@3
|
137 if (pdata->LengthIsSize())
|
nuclear@3
|
138 return size;
|
nuclear@3
|
139
|
nuclear@3
|
140 length = (UPInt)UTF8Util::GetLength(pdata->Data, (UPInt)size);
|
nuclear@3
|
141
|
nuclear@3
|
142 if (length == size)
|
nuclear@3
|
143 pdata->Size |= String_LengthIsSize;
|
nuclear@3
|
144
|
nuclear@3
|
145 return length;
|
nuclear@3
|
146 }
|
nuclear@3
|
147
|
nuclear@3
|
148
|
nuclear@3
|
149 //static UInt32 String_CharSearch(const char* buf, )
|
nuclear@3
|
150
|
nuclear@3
|
151
|
nuclear@3
|
152 UInt32 String::GetCharAt(UPInt index) const
|
nuclear@3
|
153 {
|
nuclear@3
|
154 SPInt i = (SPInt) index;
|
nuclear@3
|
155 DataDesc* pdata = GetData();
|
nuclear@3
|
156 const char* buf = pdata->Data;
|
nuclear@3
|
157 UInt32 c;
|
nuclear@3
|
158
|
nuclear@3
|
159 if (pdata->LengthIsSize())
|
nuclear@3
|
160 {
|
nuclear@3
|
161 OVR_ASSERT(index < pdata->GetSize());
|
nuclear@3
|
162 buf += i;
|
nuclear@3
|
163 return UTF8Util::DecodeNextChar_Advance0(&buf);
|
nuclear@3
|
164 }
|
nuclear@3
|
165
|
nuclear@3
|
166 c = UTF8Util::GetCharAt(index, buf, pdata->GetSize());
|
nuclear@3
|
167 return c;
|
nuclear@3
|
168 }
|
nuclear@3
|
169
|
nuclear@3
|
170 UInt32 String::GetFirstCharAt(UPInt index, const char** offset) const
|
nuclear@3
|
171 {
|
nuclear@3
|
172 DataDesc* pdata = GetData();
|
nuclear@3
|
173 SPInt i = (SPInt) index;
|
nuclear@3
|
174 const char* buf = pdata->Data;
|
nuclear@3
|
175 const char* end = buf + pdata->GetSize();
|
nuclear@3
|
176 UInt32 c;
|
nuclear@3
|
177
|
nuclear@3
|
178 do
|
nuclear@3
|
179 {
|
nuclear@3
|
180 c = UTF8Util::DecodeNextChar_Advance0(&buf);
|
nuclear@3
|
181 i--;
|
nuclear@3
|
182
|
nuclear@3
|
183 if (buf >= end)
|
nuclear@3
|
184 {
|
nuclear@3
|
185 // We've hit the end of the string; don't go further.
|
nuclear@3
|
186 OVR_ASSERT(i == 0);
|
nuclear@3
|
187 return c;
|
nuclear@3
|
188 }
|
nuclear@3
|
189 } while (i >= 0);
|
nuclear@3
|
190
|
nuclear@3
|
191 *offset = buf;
|
nuclear@3
|
192
|
nuclear@3
|
193 return c;
|
nuclear@3
|
194 }
|
nuclear@3
|
195
|
nuclear@3
|
196 UInt32 String::GetNextChar(const char** offset) const
|
nuclear@3
|
197 {
|
nuclear@3
|
198 return UTF8Util::DecodeNextChar(offset);
|
nuclear@3
|
199 }
|
nuclear@3
|
200
|
nuclear@3
|
201
|
nuclear@3
|
202
|
nuclear@3
|
203 void String::AppendChar(UInt32 ch)
|
nuclear@3
|
204 {
|
nuclear@3
|
205 DataDesc* pdata = GetData();
|
nuclear@3
|
206 UPInt size = pdata->GetSize();
|
nuclear@3
|
207 char buff[8];
|
nuclear@3
|
208 SPInt encodeSize = 0;
|
nuclear@3
|
209
|
nuclear@3
|
210 // Converts ch into UTF8 string and fills it into buff.
|
nuclear@3
|
211 UTF8Util::EncodeChar(buff, &encodeSize, ch);
|
nuclear@3
|
212 OVR_ASSERT(encodeSize >= 0);
|
nuclear@3
|
213
|
nuclear@3
|
214 SetData(AllocDataCopy2(size + (UPInt)encodeSize, 0,
|
nuclear@3
|
215 pdata->Data, size, buff, (UPInt)encodeSize));
|
nuclear@3
|
216 pdata->Release();
|
nuclear@3
|
217 }
|
nuclear@3
|
218
|
nuclear@3
|
219
|
nuclear@3
|
220 void String::AppendString(const wchar_t* pstr, SPInt len)
|
nuclear@3
|
221 {
|
nuclear@3
|
222 if (!pstr)
|
nuclear@3
|
223 return;
|
nuclear@3
|
224
|
nuclear@3
|
225 DataDesc* pdata = GetData();
|
nuclear@3
|
226 UPInt oldSize = pdata->GetSize();
|
nuclear@3
|
227 UPInt encodeSize = (UPInt)UTF8Util::GetEncodeStringSize(pstr, len);
|
nuclear@3
|
228
|
nuclear@3
|
229 DataDesc* pnewData = AllocDataCopy1(oldSize + (UPInt)encodeSize, 0,
|
nuclear@3
|
230 pdata->Data, oldSize);
|
nuclear@3
|
231 UTF8Util::EncodeString(pnewData->Data + oldSize, pstr, len);
|
nuclear@3
|
232
|
nuclear@3
|
233 SetData(pnewData);
|
nuclear@3
|
234 pdata->Release();
|
nuclear@3
|
235 }
|
nuclear@3
|
236
|
nuclear@3
|
237
|
nuclear@3
|
238 void String::AppendString(const char* putf8str, SPInt utf8StrSz)
|
nuclear@3
|
239 {
|
nuclear@3
|
240 if (!putf8str || !utf8StrSz)
|
nuclear@3
|
241 return;
|
nuclear@3
|
242 if (utf8StrSz == -1)
|
nuclear@3
|
243 utf8StrSz = (SPInt)OVR_strlen(putf8str);
|
nuclear@3
|
244
|
nuclear@3
|
245 DataDesc* pdata = GetData();
|
nuclear@3
|
246 UPInt oldSize = pdata->GetSize();
|
nuclear@3
|
247
|
nuclear@3
|
248 SetData(AllocDataCopy2(oldSize + (UPInt)utf8StrSz, 0,
|
nuclear@3
|
249 pdata->Data, oldSize, putf8str, (UPInt)utf8StrSz));
|
nuclear@3
|
250 pdata->Release();
|
nuclear@3
|
251 }
|
nuclear@3
|
252
|
nuclear@3
|
253 void String::AssignString(const InitStruct& src, UPInt size)
|
nuclear@3
|
254 {
|
nuclear@3
|
255 DataDesc* poldData = GetData();
|
nuclear@3
|
256 DataDesc* pnewData = AllocData(size, 0);
|
nuclear@3
|
257 src.InitString(pnewData->Data, size);
|
nuclear@3
|
258 SetData(pnewData);
|
nuclear@3
|
259 poldData->Release();
|
nuclear@3
|
260 }
|
nuclear@3
|
261
|
nuclear@3
|
262 void String::AssignString(const char* putf8str, UPInt size)
|
nuclear@3
|
263 {
|
nuclear@3
|
264 DataDesc* poldData = GetData();
|
nuclear@3
|
265 SetData(AllocDataCopy1(size, 0, putf8str, size));
|
nuclear@3
|
266 poldData->Release();
|
nuclear@3
|
267 }
|
nuclear@3
|
268
|
nuclear@3
|
269 void String::operator = (const char* pstr)
|
nuclear@3
|
270 {
|
nuclear@3
|
271 AssignString(pstr, pstr ? OVR_strlen(pstr) : 0);
|
nuclear@3
|
272 }
|
nuclear@3
|
273
|
nuclear@3
|
274 void String::operator = (const wchar_t* pwstr)
|
nuclear@3
|
275 {
|
nuclear@3
|
276 DataDesc* poldData = GetData();
|
nuclear@3
|
277 UPInt size = pwstr ? (UPInt)UTF8Util::GetEncodeStringSize(pwstr) : 0;
|
nuclear@3
|
278
|
nuclear@3
|
279 DataDesc* pnewData = AllocData(size, 0);
|
nuclear@3
|
280 UTF8Util::EncodeString(pnewData->Data, pwstr);
|
nuclear@3
|
281 SetData(pnewData);
|
nuclear@3
|
282 poldData->Release();
|
nuclear@3
|
283 }
|
nuclear@3
|
284
|
nuclear@3
|
285
|
nuclear@3
|
286 void String::operator = (const String& src)
|
nuclear@3
|
287 {
|
nuclear@3
|
288 DataDesc* psdata = src.GetData();
|
nuclear@3
|
289 DataDesc* pdata = GetData();
|
nuclear@3
|
290
|
nuclear@3
|
291 SetData(psdata);
|
nuclear@3
|
292 psdata->AddRef();
|
nuclear@3
|
293 pdata->Release();
|
nuclear@3
|
294 }
|
nuclear@3
|
295
|
nuclear@3
|
296
|
nuclear@3
|
297 void String::operator = (const StringBuffer& src)
|
nuclear@3
|
298 {
|
nuclear@3
|
299 DataDesc* polddata = GetData();
|
nuclear@3
|
300 SetData(AllocDataCopy1(src.GetSize(), 0, src.ToCStr(), src.GetSize()));
|
nuclear@3
|
301 polddata->Release();
|
nuclear@3
|
302 }
|
nuclear@3
|
303
|
nuclear@3
|
304 void String::operator += (const String& src)
|
nuclear@3
|
305 {
|
nuclear@3
|
306 DataDesc *pourData = GetData(),
|
nuclear@3
|
307 *psrcData = src.GetData();
|
nuclear@3
|
308 UPInt ourSize = pourData->GetSize(),
|
nuclear@3
|
309 srcSize = psrcData->GetSize();
|
nuclear@3
|
310 UPInt lflag = pourData->GetLengthFlag() & psrcData->GetLengthFlag();
|
nuclear@3
|
311
|
nuclear@3
|
312 SetData(AllocDataCopy2(ourSize + srcSize, lflag,
|
nuclear@3
|
313 pourData->Data, ourSize, psrcData->Data, srcSize));
|
nuclear@3
|
314 pourData->Release();
|
nuclear@3
|
315 }
|
nuclear@3
|
316
|
nuclear@3
|
317
|
nuclear@3
|
318 String String::operator + (const char* str) const
|
nuclear@3
|
319 {
|
nuclear@3
|
320 String tmp1(*this);
|
nuclear@3
|
321 tmp1 += (str ? str : "");
|
nuclear@3
|
322 return tmp1;
|
nuclear@3
|
323 }
|
nuclear@3
|
324
|
nuclear@3
|
325 String String::operator + (const String& src) const
|
nuclear@3
|
326 {
|
nuclear@3
|
327 String tmp1(*this);
|
nuclear@3
|
328 tmp1 += src;
|
nuclear@3
|
329 return tmp1;
|
nuclear@3
|
330 }
|
nuclear@3
|
331
|
nuclear@3
|
332 void String::Remove(UPInt posAt, SPInt removeLength)
|
nuclear@3
|
333 {
|
nuclear@3
|
334 DataDesc* pdata = GetData();
|
nuclear@3
|
335 UPInt oldSize = pdata->GetSize();
|
nuclear@3
|
336 // Length indicates the number of characters to remove.
|
nuclear@3
|
337 UPInt length = GetLength();
|
nuclear@3
|
338
|
nuclear@3
|
339 // If index is past the string, nothing to remove.
|
nuclear@3
|
340 if (posAt >= length)
|
nuclear@3
|
341 return;
|
nuclear@3
|
342 // Otherwise, cap removeLength to the length of the string.
|
nuclear@3
|
343 if ((posAt + removeLength) > length)
|
nuclear@3
|
344 removeLength = length - posAt;
|
nuclear@3
|
345
|
nuclear@3
|
346 // Get the byte position of the UTF8 char at position posAt.
|
nuclear@3
|
347 SPInt bytePos = UTF8Util::GetByteIndex(posAt, pdata->Data, oldSize);
|
nuclear@3
|
348 SPInt removeSize = UTF8Util::GetByteIndex(removeLength, pdata->Data + bytePos, oldSize-bytePos);
|
nuclear@3
|
349
|
nuclear@3
|
350 SetData(AllocDataCopy2(oldSize - removeSize, pdata->GetLengthFlag(),
|
nuclear@3
|
351 pdata->Data, bytePos,
|
nuclear@3
|
352 pData->Data + bytePos + removeSize, (oldSize - bytePos - removeSize)));
|
nuclear@3
|
353 pdata->Release();
|
nuclear@3
|
354 }
|
nuclear@3
|
355
|
nuclear@3
|
356
|
nuclear@3
|
357 String String::Substring(UPInt start, UPInt end) const
|
nuclear@3
|
358 {
|
nuclear@3
|
359 UPInt length = GetLength();
|
nuclear@3
|
360 if ((start >= length) || (start >= end))
|
nuclear@3
|
361 return String();
|
nuclear@3
|
362
|
nuclear@3
|
363 DataDesc* pdata = GetData();
|
nuclear@3
|
364
|
nuclear@3
|
365 // If size matches, we know the exact index range.
|
nuclear@3
|
366 if (pdata->LengthIsSize())
|
nuclear@3
|
367 return String(pdata->Data + start, end - start);
|
nuclear@3
|
368
|
nuclear@3
|
369 // Get position of starting character.
|
nuclear@3
|
370 SPInt byteStart = UTF8Util::GetByteIndex(start, pdata->Data, pdata->GetSize());
|
nuclear@3
|
371 SPInt byteSize = UTF8Util::GetByteIndex(end - start, pdata->Data + byteStart, pdata->GetSize()-byteStart);
|
nuclear@3
|
372 return String(pdata->Data + byteStart, (UPInt)byteSize);
|
nuclear@3
|
373 }
|
nuclear@3
|
374
|
nuclear@3
|
375 void String::Clear()
|
nuclear@3
|
376 {
|
nuclear@3
|
377 NullData.AddRef();
|
nuclear@3
|
378 GetData()->Release();
|
nuclear@3
|
379 SetData(&NullData);
|
nuclear@3
|
380 }
|
nuclear@3
|
381
|
nuclear@3
|
382
|
nuclear@3
|
383 String String::ToUpper() const
|
nuclear@3
|
384 {
|
nuclear@3
|
385 UInt32 c;
|
nuclear@3
|
386 const char* psource = GetData()->Data;
|
nuclear@3
|
387 const char* pend = psource + GetData()->GetSize();
|
nuclear@3
|
388 String str;
|
nuclear@3
|
389 SPInt bufferOffset = 0;
|
nuclear@3
|
390 char buffer[512];
|
nuclear@3
|
391
|
nuclear@3
|
392 while(psource < pend)
|
nuclear@3
|
393 {
|
nuclear@3
|
394 do {
|
nuclear@3
|
395 c = UTF8Util::DecodeNextChar_Advance0(&psource);
|
nuclear@3
|
396 UTF8Util::EncodeChar(buffer, &bufferOffset, OVR_towupper(wchar_t(c)));
|
nuclear@3
|
397 } while ((psource < pend) && (bufferOffset < SPInt(sizeof(buffer)-8)));
|
nuclear@3
|
398
|
nuclear@3
|
399 // Append string a piece at a time.
|
nuclear@3
|
400 str.AppendString(buffer, bufferOffset);
|
nuclear@3
|
401 bufferOffset = 0;
|
nuclear@3
|
402 }
|
nuclear@3
|
403
|
nuclear@3
|
404 return str;
|
nuclear@3
|
405 }
|
nuclear@3
|
406
|
nuclear@3
|
407 String String::ToLower() const
|
nuclear@3
|
408 {
|
nuclear@3
|
409 UInt32 c;
|
nuclear@3
|
410 const char* psource = GetData()->Data;
|
nuclear@3
|
411 const char* pend = psource + GetData()->GetSize();
|
nuclear@3
|
412 String str;
|
nuclear@3
|
413 SPInt bufferOffset = 0;
|
nuclear@3
|
414 char buffer[512];
|
nuclear@3
|
415
|
nuclear@3
|
416 while(psource < pend)
|
nuclear@3
|
417 {
|
nuclear@3
|
418 do {
|
nuclear@3
|
419 c = UTF8Util::DecodeNextChar_Advance0(&psource);
|
nuclear@3
|
420 UTF8Util::EncodeChar(buffer, &bufferOffset, OVR_towlower(wchar_t(c)));
|
nuclear@3
|
421 } while ((psource < pend) && (bufferOffset < SPInt(sizeof(buffer)-8)));
|
nuclear@3
|
422
|
nuclear@3
|
423 // Append string a piece at a time.
|
nuclear@3
|
424 str.AppendString(buffer, bufferOffset);
|
nuclear@3
|
425 bufferOffset = 0;
|
nuclear@3
|
426 }
|
nuclear@3
|
427
|
nuclear@3
|
428 return str;
|
nuclear@3
|
429 }
|
nuclear@3
|
430
|
nuclear@3
|
431
|
nuclear@3
|
432
|
nuclear@3
|
433 String& String::Insert(const char* substr, UPInt posAt, SPInt strSize)
|
nuclear@3
|
434 {
|
nuclear@3
|
435 DataDesc* poldData = GetData();
|
nuclear@3
|
436 UPInt oldSize = poldData->GetSize();
|
nuclear@3
|
437 UPInt insertSize = (strSize < 0) ? OVR_strlen(substr) : (UPInt)strSize;
|
nuclear@3
|
438 UPInt byteIndex = (poldData->LengthIsSize()) ?
|
nuclear@3
|
439 posAt : (UPInt)UTF8Util::GetByteIndex(posAt, poldData->Data, oldSize);
|
nuclear@3
|
440
|
nuclear@3
|
441 OVR_ASSERT(byteIndex <= oldSize);
|
nuclear@3
|
442
|
nuclear@3
|
443 DataDesc* pnewData = AllocDataCopy2(oldSize + insertSize, 0,
|
nuclear@3
|
444 poldData->Data, byteIndex, substr, insertSize);
|
nuclear@3
|
445 memcpy(pnewData->Data + byteIndex + insertSize,
|
nuclear@3
|
446 poldData->Data + byteIndex, oldSize - byteIndex);
|
nuclear@3
|
447 SetData(pnewData);
|
nuclear@3
|
448 poldData->Release();
|
nuclear@3
|
449 return *this;
|
nuclear@3
|
450 }
|
nuclear@3
|
451
|
nuclear@3
|
452 /*
|
nuclear@3
|
453 String& String::Insert(const UInt32* substr, UPInt posAt, SPInt len)
|
nuclear@3
|
454 {
|
nuclear@3
|
455 for (SPInt i = 0; i < len; ++i)
|
nuclear@3
|
456 {
|
nuclear@3
|
457 UPInt charw = InsertCharAt(substr[i], posAt);
|
nuclear@3
|
458 posAt += charw;
|
nuclear@3
|
459 }
|
nuclear@3
|
460 return *this;
|
nuclear@3
|
461 }
|
nuclear@3
|
462 */
|
nuclear@3
|
463
|
nuclear@3
|
464 UPInt String::InsertCharAt(UInt32 c, UPInt posAt)
|
nuclear@3
|
465 {
|
nuclear@3
|
466 char buf[8];
|
nuclear@3
|
467 SPInt index = 0;
|
nuclear@3
|
468 UTF8Util::EncodeChar(buf, &index, c);
|
nuclear@3
|
469 OVR_ASSERT(index >= 0);
|
nuclear@3
|
470 buf[(UPInt)index] = 0;
|
nuclear@3
|
471
|
nuclear@3
|
472 Insert(buf, posAt, index);
|
nuclear@3
|
473 return (UPInt)index;
|
nuclear@3
|
474 }
|
nuclear@3
|
475
|
nuclear@3
|
476
|
nuclear@3
|
477 int String::CompareNoCase(const char* a, const char* b)
|
nuclear@3
|
478 {
|
nuclear@3
|
479 return OVR_stricmp(a, b);
|
nuclear@3
|
480 }
|
nuclear@3
|
481
|
nuclear@3
|
482 int String::CompareNoCase(const char* a, const char* b, SPInt len)
|
nuclear@3
|
483 {
|
nuclear@3
|
484 if (len)
|
nuclear@3
|
485 {
|
nuclear@3
|
486 SPInt f,l;
|
nuclear@3
|
487 SPInt slen = len;
|
nuclear@3
|
488 const char *s = b;
|
nuclear@3
|
489 do {
|
nuclear@3
|
490 f = (SPInt)OVR_tolower((int)(*(a++)));
|
nuclear@3
|
491 l = (SPInt)OVR_tolower((int)(*(b++)));
|
nuclear@3
|
492 } while (--len && f && (f == l) && *b != 0);
|
nuclear@3
|
493
|
nuclear@3
|
494 if (f == l && (len != 0 || *b != 0))
|
nuclear@3
|
495 {
|
nuclear@3
|
496 f = (SPInt)slen;
|
nuclear@3
|
497 l = (SPInt)OVR_strlen(s);
|
nuclear@3
|
498 return int(f - l);
|
nuclear@3
|
499 }
|
nuclear@3
|
500
|
nuclear@3
|
501 return int(f - l);
|
nuclear@3
|
502 }
|
nuclear@3
|
503 else
|
nuclear@3
|
504 return (0-(int)OVR_strlen(b));
|
nuclear@3
|
505 }
|
nuclear@3
|
506
|
nuclear@3
|
507 // ***** Implement hash static functions
|
nuclear@3
|
508
|
nuclear@3
|
509 // Hash function
|
nuclear@3
|
510 UPInt String::BernsteinHashFunction(const void* pdataIn, UPInt size, UPInt seed)
|
nuclear@3
|
511 {
|
nuclear@3
|
512 const UByte* pdata = (const UByte*) pdataIn;
|
nuclear@3
|
513 UPInt h = seed;
|
nuclear@3
|
514 while (size > 0)
|
nuclear@3
|
515 {
|
nuclear@3
|
516 size--;
|
nuclear@3
|
517 h = ((h << 5) + h) ^ (unsigned) pdata[size];
|
nuclear@3
|
518 }
|
nuclear@3
|
519
|
nuclear@3
|
520 return h;
|
nuclear@3
|
521 }
|
nuclear@3
|
522
|
nuclear@3
|
523 // Hash function, case-insensitive
|
nuclear@3
|
524 UPInt String::BernsteinHashFunctionCIS(const void* pdataIn, UPInt size, UPInt seed)
|
nuclear@3
|
525 {
|
nuclear@3
|
526 const UByte* pdata = (const UByte*) pdataIn;
|
nuclear@3
|
527 UPInt h = seed;
|
nuclear@3
|
528 while (size > 0)
|
nuclear@3
|
529 {
|
nuclear@3
|
530 size--;
|
nuclear@3
|
531 h = ((h << 5) + h) ^ OVR_tolower(pdata[size]);
|
nuclear@3
|
532 }
|
nuclear@3
|
533
|
nuclear@3
|
534 // Alternative: "sdbm" hash function, suggested at same web page above.
|
nuclear@3
|
535 // h = 0;
|
nuclear@3
|
536 // for bytes { h = (h << 16) + (h << 6) - hash + *p; }
|
nuclear@3
|
537 return h;
|
nuclear@3
|
538 }
|
nuclear@3
|
539
|
nuclear@3
|
540
|
nuclear@3
|
541
|
nuclear@3
|
542 // ***** String Buffer used for Building Strings
|
nuclear@3
|
543
|
nuclear@3
|
544
|
nuclear@3
|
545 #define OVR_SBUFF_DEFAULT_GROW_SIZE 512
|
nuclear@3
|
546 // Constructors / Destructor.
|
nuclear@3
|
547 StringBuffer::StringBuffer()
|
nuclear@3
|
548 : pData(NULL), Size(0), BufferSize(0), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false)
|
nuclear@3
|
549 {
|
nuclear@3
|
550 }
|
nuclear@3
|
551
|
nuclear@3
|
552 StringBuffer::StringBuffer(UPInt growSize)
|
nuclear@3
|
553 : pData(NULL), Size(0), BufferSize(0), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false)
|
nuclear@3
|
554 {
|
nuclear@3
|
555 SetGrowSize(growSize);
|
nuclear@3
|
556 }
|
nuclear@3
|
557
|
nuclear@3
|
558 StringBuffer::StringBuffer(const char* data)
|
nuclear@3
|
559 : pData(NULL), Size(0), BufferSize(0), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false)
|
nuclear@3
|
560 {
|
nuclear@3
|
561 *this = data;
|
nuclear@3
|
562 }
|
nuclear@3
|
563
|
nuclear@3
|
564 StringBuffer::StringBuffer(const char* data, UPInt dataSize)
|
nuclear@3
|
565 : pData(NULL), Size(0), BufferSize(0), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false)
|
nuclear@3
|
566 {
|
nuclear@3
|
567 AppendString(data, dataSize);
|
nuclear@3
|
568 }
|
nuclear@3
|
569
|
nuclear@3
|
570 StringBuffer::StringBuffer(const String& src)
|
nuclear@3
|
571 : pData(NULL), Size(0), BufferSize(0), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false)
|
nuclear@3
|
572 {
|
nuclear@3
|
573 AppendString(src.ToCStr(), src.GetSize());
|
nuclear@3
|
574 }
|
nuclear@3
|
575
|
nuclear@3
|
576 StringBuffer::StringBuffer(const StringBuffer& src)
|
nuclear@3
|
577 : pData(NULL), Size(0), BufferSize(src.GetGrowSize()), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false)
|
nuclear@3
|
578 {
|
nuclear@3
|
579 AppendString(src.ToCStr(), src.GetSize());
|
nuclear@3
|
580 LengthIsSize = src.LengthIsSize;
|
nuclear@3
|
581 }
|
nuclear@3
|
582
|
nuclear@3
|
583 StringBuffer::StringBuffer(const wchar_t* data)
|
nuclear@3
|
584 : pData(NULL), Size(0), BufferSize(0), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false)
|
nuclear@3
|
585 {
|
nuclear@3
|
586 *this = data;
|
nuclear@3
|
587 }
|
nuclear@3
|
588
|
nuclear@3
|
589 StringBuffer::~StringBuffer()
|
nuclear@3
|
590 {
|
nuclear@3
|
591 if (pData)
|
nuclear@3
|
592 OVR_FREE(pData);
|
nuclear@3
|
593 }
|
nuclear@3
|
594 void StringBuffer::SetGrowSize(UPInt growSize)
|
nuclear@3
|
595 {
|
nuclear@3
|
596 if (growSize <= 16)
|
nuclear@3
|
597 GrowSize = 16;
|
nuclear@3
|
598 else
|
nuclear@3
|
599 {
|
nuclear@3
|
600 UByte bits = Alg::UpperBit(UInt32(growSize-1));
|
nuclear@3
|
601 UPInt size = 1<<bits;
|
nuclear@3
|
602 GrowSize = size == growSize ? growSize : size;
|
nuclear@3
|
603 }
|
nuclear@3
|
604 }
|
nuclear@3
|
605
|
nuclear@3
|
606 UPInt StringBuffer::GetLength() const
|
nuclear@3
|
607 {
|
nuclear@3
|
608 UPInt length, size = GetSize();
|
nuclear@3
|
609 if (LengthIsSize)
|
nuclear@3
|
610 return size;
|
nuclear@3
|
611
|
nuclear@3
|
612 length = (UPInt)UTF8Util::GetLength(pData, (UPInt)GetSize());
|
nuclear@3
|
613
|
nuclear@3
|
614 if (length == GetSize())
|
nuclear@3
|
615 LengthIsSize = true;
|
nuclear@3
|
616 return length;
|
nuclear@3
|
617 }
|
nuclear@3
|
618
|
nuclear@3
|
619 void StringBuffer::Reserve(UPInt _size)
|
nuclear@3
|
620 {
|
nuclear@3
|
621 if (_size >= BufferSize) // >= because of trailing zero! (!AB)
|
nuclear@3
|
622 {
|
nuclear@3
|
623 BufferSize = (_size + 1 + GrowSize - 1)& ~(GrowSize-1);
|
nuclear@3
|
624 if (!pData)
|
nuclear@3
|
625 pData = (char*)OVR_ALLOC(BufferSize);
|
nuclear@3
|
626 else
|
nuclear@3
|
627 pData = (char*)OVR_REALLOC(pData, BufferSize);
|
nuclear@3
|
628 }
|
nuclear@3
|
629 }
|
nuclear@3
|
630 void StringBuffer::Resize(UPInt _size)
|
nuclear@3
|
631 {
|
nuclear@3
|
632 Reserve(_size);
|
nuclear@3
|
633 LengthIsSize = false;
|
nuclear@3
|
634 Size = _size;
|
nuclear@3
|
635 if (pData)
|
nuclear@3
|
636 pData[Size] = 0;
|
nuclear@3
|
637 }
|
nuclear@3
|
638
|
nuclear@3
|
639 void StringBuffer::Clear()
|
nuclear@3
|
640 {
|
nuclear@3
|
641 Resize(0);
|
nuclear@3
|
642 /*
|
nuclear@3
|
643 if (pData != pEmptyNullData)
|
nuclear@3
|
644 {
|
nuclear@3
|
645 OVR_FREE(pHeap, pData);
|
nuclear@3
|
646 pData = pEmptyNullData;
|
nuclear@3
|
647 Size = BufferSize = 0;
|
nuclear@3
|
648 LengthIsSize = false;
|
nuclear@3
|
649 }
|
nuclear@3
|
650 */
|
nuclear@3
|
651 }
|
nuclear@3
|
652 // Appends a character
|
nuclear@3
|
653 void StringBuffer::AppendChar(UInt32 ch)
|
nuclear@3
|
654 {
|
nuclear@3
|
655 char buff[8];
|
nuclear@3
|
656 UPInt origSize = GetSize();
|
nuclear@3
|
657
|
nuclear@3
|
658 // Converts ch into UTF8 string and fills it into buff. Also increments index according to the number of bytes
|
nuclear@3
|
659 // in the UTF8 string.
|
nuclear@3
|
660 SPInt srcSize = 0;
|
nuclear@3
|
661 UTF8Util::EncodeChar(buff, &srcSize, ch);
|
nuclear@3
|
662 OVR_ASSERT(srcSize >= 0);
|
nuclear@3
|
663
|
nuclear@3
|
664 UPInt size = origSize + srcSize;
|
nuclear@3
|
665 Resize(size);
|
nuclear@3
|
666 memcpy(pData + origSize, buff, srcSize);
|
nuclear@3
|
667 }
|
nuclear@3
|
668
|
nuclear@3
|
669 // Append a string
|
nuclear@3
|
670 void StringBuffer::AppendString(const wchar_t* pstr, SPInt len)
|
nuclear@3
|
671 {
|
nuclear@3
|
672 if (!pstr)
|
nuclear@3
|
673 return;
|
nuclear@3
|
674
|
nuclear@3
|
675 SPInt srcSize = UTF8Util::GetEncodeStringSize(pstr, len);
|
nuclear@3
|
676 UPInt origSize = GetSize();
|
nuclear@3
|
677 UPInt size = srcSize + origSize;
|
nuclear@3
|
678
|
nuclear@3
|
679 Resize(size);
|
nuclear@3
|
680 UTF8Util::EncodeString(pData + origSize, pstr, len);
|
nuclear@3
|
681 }
|
nuclear@3
|
682
|
nuclear@3
|
683 void StringBuffer::AppendString(const char* putf8str, SPInt utf8StrSz)
|
nuclear@3
|
684 {
|
nuclear@3
|
685 if (!putf8str || !utf8StrSz)
|
nuclear@3
|
686 return;
|
nuclear@3
|
687 if (utf8StrSz == -1)
|
nuclear@3
|
688 utf8StrSz = (SPInt)OVR_strlen(putf8str);
|
nuclear@3
|
689
|
nuclear@3
|
690 UPInt origSize = GetSize();
|
nuclear@3
|
691 UPInt size = utf8StrSz + origSize;
|
nuclear@3
|
692
|
nuclear@3
|
693 Resize(size);
|
nuclear@3
|
694 memcpy(pData + origSize, putf8str, utf8StrSz);
|
nuclear@3
|
695 }
|
nuclear@3
|
696
|
nuclear@3
|
697
|
nuclear@3
|
698 void StringBuffer::operator = (const char* pstr)
|
nuclear@3
|
699 {
|
nuclear@3
|
700 pstr = pstr ? pstr : "";
|
nuclear@3
|
701 UPInt size = OVR_strlen(pstr);
|
nuclear@3
|
702 Resize(size);
|
nuclear@3
|
703 memcpy(pData, pstr, size);
|
nuclear@3
|
704 }
|
nuclear@3
|
705
|
nuclear@3
|
706 void StringBuffer::operator = (const wchar_t* pstr)
|
nuclear@3
|
707 {
|
nuclear@3
|
708 pstr = pstr ? pstr : L"";
|
nuclear@3
|
709 UPInt size = (UPInt)UTF8Util::GetEncodeStringSize(pstr);
|
nuclear@3
|
710 Resize(size);
|
nuclear@3
|
711 UTF8Util::EncodeString(pData, pstr);
|
nuclear@3
|
712 }
|
nuclear@3
|
713
|
nuclear@3
|
714 void StringBuffer::operator = (const String& src)
|
nuclear@3
|
715 {
|
nuclear@3
|
716 Resize(src.GetSize());
|
nuclear@3
|
717 memcpy(pData, src.ToCStr(), src.GetSize());
|
nuclear@3
|
718 }
|
nuclear@3
|
719
|
nuclear@3
|
720
|
nuclear@3
|
721 // Inserts substr at posAt
|
nuclear@3
|
722 void StringBuffer::Insert(const char* substr, UPInt posAt, SPInt len)
|
nuclear@3
|
723 {
|
nuclear@3
|
724 UPInt oldSize = Size;
|
nuclear@3
|
725 UPInt insertSize = (len < 0) ? OVR_strlen(substr) : (UPInt)len;
|
nuclear@3
|
726 UPInt byteIndex = LengthIsSize ? posAt :
|
nuclear@3
|
727 (UPInt)UTF8Util::GetByteIndex(posAt, pData, (SPInt)Size);
|
nuclear@3
|
728
|
nuclear@3
|
729 OVR_ASSERT(byteIndex <= oldSize);
|
nuclear@3
|
730 Reserve(oldSize + insertSize);
|
nuclear@3
|
731
|
nuclear@3
|
732 memmove(pData + byteIndex + insertSize, pData + byteIndex, oldSize - byteIndex + 1);
|
nuclear@3
|
733 memcpy (pData + byteIndex, substr, insertSize);
|
nuclear@3
|
734 LengthIsSize = false;
|
nuclear@3
|
735 Size = oldSize + insertSize;
|
nuclear@3
|
736 pData[Size] = 0;
|
nuclear@3
|
737 }
|
nuclear@3
|
738
|
nuclear@3
|
739 // Inserts character at posAt
|
nuclear@3
|
740 UPInt StringBuffer::InsertCharAt(UInt32 c, UPInt posAt)
|
nuclear@3
|
741 {
|
nuclear@3
|
742 char buf[8];
|
nuclear@3
|
743 SPInt len = 0;
|
nuclear@3
|
744 UTF8Util::EncodeChar(buf, &len, c);
|
nuclear@3
|
745 OVR_ASSERT(len >= 0);
|
nuclear@3
|
746 buf[(UPInt)len] = 0;
|
nuclear@3
|
747
|
nuclear@3
|
748 Insert(buf, posAt, len);
|
nuclear@3
|
749 return (UPInt)len;
|
nuclear@3
|
750 }
|
nuclear@3
|
751
|
nuclear@3
|
752 } // OVR
|