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