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