ovr_sdk

annotate LibOVR/Src/Kernel/OVR_String.cpp @ 0:1b39a1b46319

initial 0.4.4
author John Tsiombikas <nuclear@member.fsf.org>
date Wed, 14 Jan 2015 06:51:16 +0200
parents
children
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