oculus1

annotate libovr/Src/Kernel/OVR_String.cpp @ 1:e2f9e4603129

added LibOVR and started a simple vr wrapper.
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 14 Sep 2013 16:14:59 +0300
parents
children b069a5c27388
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