00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "OVR_String.h"
00018
00019 #include <stdlib.h>
00020 #include <ctype.h>
00021
00022 #ifdef OVR_OS_QNX
00023 # include <strings.h>
00024 #endif
00025
00026 namespace OVR {
00027
00028 #define String_LengthIsSize (UPInt(1) << String::Flag_LengthIsSizeShift)
00029
00030 String::DataDesc String::NullData = {String_LengthIsSize, 1, {0} };
00031
00032
00033 String::String()
00034 {
00035 pData = &NullData;
00036 pData->AddRef();
00037 };
00038
00039 String::String(const char* pdata)
00040 {
00041
00042 UPInt size = pdata ? OVR_strlen(pdata) : 0;
00043 pData = AllocDataCopy1(size, 0, pdata, size);
00044 };
00045
00046 String::String(const char* pdata1, const char* pdata2, const char* pdata3)
00047 {
00048
00049 UPInt size1 = pdata1 ? OVR_strlen(pdata1) : 0;
00050 UPInt size2 = pdata2 ? OVR_strlen(pdata2) : 0;
00051 UPInt size3 = pdata3 ? OVR_strlen(pdata3) : 0;
00052
00053 DataDesc *pdataDesc = AllocDataCopy2(size1 + size2 + size3, 0,
00054 pdata1, size1, pdata2, size2);
00055 memcpy(pdataDesc->Data + size1 + size2, pdata3, size3);
00056 pData = pdataDesc;
00057 }
00058
00059 String::String(const char* pdata, UPInt size)
00060 {
00061 OVR_ASSERT((size == 0) || (pdata != 0));
00062 pData = AllocDataCopy1(size, 0, pdata, size);
00063 };
00064
00065
00066 String::String(const InitStruct& src, UPInt size)
00067 {
00068 pData = AllocData(size, 0);
00069 src.InitString(GetData()->Data, size);
00070 }
00071
00072 String::String(const String& src)
00073 {
00074 pData = src.GetData();
00075 pData->AddRef();
00076 }
00077
00078 String::String(const StringBuffer& src)
00079 {
00080 pData = AllocDataCopy1(src.GetSize(), 0, src.ToCStr(), src.GetSize());
00081 }
00082
00083 String::String(const wchar_t* data)
00084 {
00085 pData = &NullData;
00086 pData->AddRef();
00087
00088 if (data)
00089 *this = data;
00090 }
00091
00092
00093 String::DataDesc* String::AllocData(UPInt size, UPInt lengthIsSize)
00094 {
00095 String::DataDesc* pdesc;
00096
00097 if (size == 0)
00098 {
00099 pdesc = &NullData;
00100 pdesc->AddRef();
00101 return pdesc;
00102 }
00103
00104 pdesc = (DataDesc*)OVR_ALLOC(sizeof(DataDesc)+ size);
00105 pdesc->Data[size] = 0;
00106 pdesc->RefCount = 1;
00107 pdesc->Size = size | lengthIsSize;
00108 return pdesc;
00109 }
00110
00111
00112 String::DataDesc* String::AllocDataCopy1(UPInt size, UPInt lengthIsSize,
00113 const char* pdata, UPInt copySize)
00114 {
00115 String::DataDesc* pdesc = AllocData(size, lengthIsSize);
00116 memcpy(pdesc->Data, pdata, copySize);
00117 return pdesc;
00118 }
00119
00120 String::DataDesc* String::AllocDataCopy2(UPInt size, UPInt lengthIsSize,
00121 const char* pdata1, UPInt copySize1,
00122 const char* pdata2, UPInt copySize2)
00123 {
00124 String::DataDesc* pdesc = AllocData(size, lengthIsSize);
00125 memcpy(pdesc->Data, pdata1, copySize1);
00126 memcpy(pdesc->Data + copySize1, pdata2, copySize2);
00127 return pdesc;
00128 }
00129
00130
00131 UPInt String::GetLength() const
00132 {
00133
00134 DataDesc* pdata = GetData();
00135 UPInt length, size = pdata->GetSize();
00136
00137 if (pdata->LengthIsSize())
00138 return size;
00139
00140 length = (UPInt)UTF8Util::GetLength(pdata->Data, (UPInt)size);
00141
00142 if (length == size)
00143 pdata->Size |= String_LengthIsSize;
00144
00145 return length;
00146 }
00147
00148
00149
00150
00151
00152 UInt32 String::GetCharAt(UPInt index) const
00153 {
00154 SPInt i = (SPInt) index;
00155 DataDesc* pdata = GetData();
00156 const char* buf = pdata->Data;
00157 UInt32 c;
00158
00159 if (pdata->LengthIsSize())
00160 {
00161 OVR_ASSERT(index < pdata->GetSize());
00162 buf += i;
00163 return UTF8Util::DecodeNextChar_Advance0(&buf);
00164 }
00165
00166 c = UTF8Util::GetCharAt(index, buf, pdata->GetSize());
00167 return c;
00168 }
00169
00170 UInt32 String::GetFirstCharAt(UPInt index, const char** offset) const
00171 {
00172 DataDesc* pdata = GetData();
00173 SPInt i = (SPInt) index;
00174 const char* buf = pdata->Data;
00175 const char* end = buf + pdata->GetSize();
00176 UInt32 c;
00177
00178 do
00179 {
00180 c = UTF8Util::DecodeNextChar_Advance0(&buf);
00181 i--;
00182
00183 if (buf >= end)
00184 {
00185
00186 OVR_ASSERT(i == 0);
00187 return c;
00188 }
00189 } while (i >= 0);
00190
00191 *offset = buf;
00192
00193 return c;
00194 }
00195
00196 UInt32 String::GetNextChar(const char** offset) const
00197 {
00198 return UTF8Util::DecodeNextChar(offset);
00199 }
00200
00201
00202
00203 void String::AppendChar(UInt32 ch)
00204 {
00205 DataDesc* pdata = GetData();
00206 UPInt size = pdata->GetSize();
00207 char buff[8];
00208 SPInt encodeSize = 0;
00209
00210
00211 UTF8Util::EncodeChar(buff, &encodeSize, ch);
00212 OVR_ASSERT(encodeSize >= 0);
00213
00214 SetData(AllocDataCopy2(size + (UPInt)encodeSize, 0,
00215 pdata->Data, size, buff, (UPInt)encodeSize));
00216 pdata->Release();
00217 }
00218
00219
00220 void String::AppendString(const wchar_t* pstr, SPInt len)
00221 {
00222 if (!pstr)
00223 return;
00224
00225 DataDesc* pdata = GetData();
00226 UPInt oldSize = pdata->GetSize();
00227 UPInt encodeSize = (UPInt)UTF8Util::GetEncodeStringSize(pstr, len);
00228
00229 DataDesc* pnewData = AllocDataCopy1(oldSize + (UPInt)encodeSize, 0,
00230 pdata->Data, oldSize);
00231 UTF8Util::EncodeString(pnewData->Data + oldSize, pstr, len);
00232
00233 SetData(pnewData);
00234 pdata->Release();
00235 }
00236
00237
00238 void String::AppendString(const char* putf8str, SPInt utf8StrSz)
00239 {
00240 if (!putf8str || !utf8StrSz)
00241 return;
00242 if (utf8StrSz == -1)
00243 utf8StrSz = (SPInt)OVR_strlen(putf8str);
00244
00245 DataDesc* pdata = GetData();
00246 UPInt oldSize = pdata->GetSize();
00247
00248 SetData(AllocDataCopy2(oldSize + (UPInt)utf8StrSz, 0,
00249 pdata->Data, oldSize, putf8str, (UPInt)utf8StrSz));
00250 pdata->Release();
00251 }
00252
00253 void String::AssignString(const InitStruct& src, UPInt size)
00254 {
00255 DataDesc* poldData = GetData();
00256 DataDesc* pnewData = AllocData(size, 0);
00257 src.InitString(pnewData->Data, size);
00258 SetData(pnewData);
00259 poldData->Release();
00260 }
00261
00262 void String::AssignString(const char* putf8str, UPInt size)
00263 {
00264 DataDesc* poldData = GetData();
00265 SetData(AllocDataCopy1(size, 0, putf8str, size));
00266 poldData->Release();
00267 }
00268
00269 void String::operator = (const char* pstr)
00270 {
00271 AssignString(pstr, pstr ? OVR_strlen(pstr) : 0);
00272 }
00273
00274 void String::operator = (const wchar_t* pwstr)
00275 {
00276 DataDesc* poldData = GetData();
00277 UPInt size = pwstr ? (UPInt)UTF8Util::GetEncodeStringSize(pwstr) : 0;
00278
00279 DataDesc* pnewData = AllocData(size, 0);
00280 UTF8Util::EncodeString(pnewData->Data, pwstr);
00281 SetData(pnewData);
00282 poldData->Release();
00283 }
00284
00285
00286 void String::operator = (const String& src)
00287 {
00288 DataDesc* psdata = src.GetData();
00289 DataDesc* pdata = GetData();
00290
00291 SetData(psdata);
00292 psdata->AddRef();
00293 pdata->Release();
00294 }
00295
00296
00297 void String::operator = (const StringBuffer& src)
00298 {
00299 DataDesc* polddata = GetData();
00300 SetData(AllocDataCopy1(src.GetSize(), 0, src.ToCStr(), src.GetSize()));
00301 polddata->Release();
00302 }
00303
00304 void String::operator += (const String& src)
00305 {
00306 DataDesc *pourData = GetData(),
00307 *psrcData = src.GetData();
00308 UPInt ourSize = pourData->GetSize(),
00309 srcSize = psrcData->GetSize();
00310 UPInt lflag = pourData->GetLengthFlag() & psrcData->GetLengthFlag();
00311
00312 SetData(AllocDataCopy2(ourSize + srcSize, lflag,
00313 pourData->Data, ourSize, psrcData->Data, srcSize));
00314 pourData->Release();
00315 }
00316
00317
00318 String String::operator + (const char* str) const
00319 {
00320 String tmp1(*this);
00321 tmp1 += (str ? str : "");
00322 return tmp1;
00323 }
00324
00325 String String::operator + (const String& src) const
00326 {
00327 String tmp1(*this);
00328 tmp1 += src;
00329 return tmp1;
00330 }
00331
00332 void String::Remove(UPInt posAt, SPInt removeLength)
00333 {
00334 DataDesc* pdata = GetData();
00335 UPInt oldSize = pdata->GetSize();
00336
00337 UPInt length = GetLength();
00338
00339
00340 if (posAt >= length)
00341 return;
00342
00343 if ((posAt + removeLength) > length)
00344 removeLength = length - posAt;
00345
00346
00347 SPInt bytePos = UTF8Util::GetByteIndex(posAt, pdata->Data, oldSize);
00348 SPInt removeSize = UTF8Util::GetByteIndex(removeLength, pdata->Data + bytePos, oldSize-bytePos);
00349
00350 SetData(AllocDataCopy2(oldSize - removeSize, pdata->GetLengthFlag(),
00351 pdata->Data, bytePos,
00352 pData->Data + bytePos + removeSize, (oldSize - bytePos - removeSize)));
00353 pdata->Release();
00354 }
00355
00356
00357 String String::Substring(UPInt start, UPInt end) const
00358 {
00359 UPInt length = GetLength();
00360 if ((start >= length) || (start >= end))
00361 return String();
00362
00363 DataDesc* pdata = GetData();
00364
00365
00366 if (pdata->LengthIsSize())
00367 return String(pdata->Data + start, end - start);
00368
00369
00370 SPInt byteStart = UTF8Util::GetByteIndex(start, pdata->Data, pdata->GetSize());
00371 SPInt byteSize = UTF8Util::GetByteIndex(end - start, pdata->Data + byteStart, pdata->GetSize()-byteStart);
00372 return String(pdata->Data + byteStart, (UPInt)byteSize);
00373 }
00374
00375 void String::Clear()
00376 {
00377 NullData.AddRef();
00378 GetData()->Release();
00379 SetData(&NullData);
00380 }
00381
00382
00383 String String::ToUpper() const
00384 {
00385 UInt32 c;
00386 const char* psource = GetData()->Data;
00387 const char* pend = psource + GetData()->GetSize();
00388 String str;
00389 SPInt bufferOffset = 0;
00390 char buffer[512];
00391
00392 while(psource < pend)
00393 {
00394 do {
00395 c = UTF8Util::DecodeNextChar_Advance0(&psource);
00396 UTF8Util::EncodeChar(buffer, &bufferOffset, OVR_towupper(wchar_t(c)));
00397 } while ((psource < pend) && (bufferOffset < SPInt(sizeof(buffer)-8)));
00398
00399
00400 str.AppendString(buffer, bufferOffset);
00401 bufferOffset = 0;
00402 }
00403
00404 return str;
00405 }
00406
00407 String String::ToLower() const
00408 {
00409 UInt32 c;
00410 const char* psource = GetData()->Data;
00411 const char* pend = psource + GetData()->GetSize();
00412 String str;
00413 SPInt bufferOffset = 0;
00414 char buffer[512];
00415
00416 while(psource < pend)
00417 {
00418 do {
00419 c = UTF8Util::DecodeNextChar_Advance0(&psource);
00420 UTF8Util::EncodeChar(buffer, &bufferOffset, OVR_towlower(wchar_t(c)));
00421 } while ((psource < pend) && (bufferOffset < SPInt(sizeof(buffer)-8)));
00422
00423
00424 str.AppendString(buffer, bufferOffset);
00425 bufferOffset = 0;
00426 }
00427
00428 return str;
00429 }
00430
00431
00432
00433 String& String::Insert(const char* substr, UPInt posAt, SPInt strSize)
00434 {
00435 DataDesc* poldData = GetData();
00436 UPInt oldSize = poldData->GetSize();
00437 UPInt insertSize = (strSize < 0) ? OVR_strlen(substr) : (UPInt)strSize;
00438 UPInt byteIndex = (poldData->LengthIsSize()) ?
00439 posAt : (UPInt)UTF8Util::GetByteIndex(posAt, poldData->Data, oldSize);
00440
00441 OVR_ASSERT(byteIndex <= oldSize);
00442
00443 DataDesc* pnewData = AllocDataCopy2(oldSize + insertSize, 0,
00444 poldData->Data, byteIndex, substr, insertSize);
00445 memcpy(pnewData->Data + byteIndex + insertSize,
00446 poldData->Data + byteIndex, oldSize - byteIndex);
00447 SetData(pnewData);
00448 poldData->Release();
00449 return *this;
00450 }
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464 UPInt String::InsertCharAt(UInt32 c, UPInt posAt)
00465 {
00466 char buf[8];
00467 SPInt index = 0;
00468 UTF8Util::EncodeChar(buf, &index, c);
00469 OVR_ASSERT(index >= 0);
00470 buf[(UPInt)index] = 0;
00471
00472 Insert(buf, posAt, index);
00473 return (UPInt)index;
00474 }
00475
00476
00477 int String::CompareNoCase(const char* a, const char* b)
00478 {
00479 return OVR_stricmp(a, b);
00480 }
00481
00482 int String::CompareNoCase(const char* a, const char* b, SPInt len)
00483 {
00484 if (len)
00485 {
00486 SPInt f,l;
00487 SPInt slen = len;
00488 const char *s = b;
00489 do {
00490 f = (SPInt)OVR_tolower((int)(*(a++)));
00491 l = (SPInt)OVR_tolower((int)(*(b++)));
00492 } while (--len && f && (f == l) && *b != 0);
00493
00494 if (f == l && (len != 0 || *b != 0))
00495 {
00496 f = (SPInt)slen;
00497 l = (SPInt)OVR_strlen(s);
00498 return int(f - l);
00499 }
00500
00501 return int(f - l);
00502 }
00503 else
00504 return (0-(int)OVR_strlen(b));
00505 }
00506
00507
00508
00509
00510 UPInt String::BernsteinHashFunction(const void* pdataIn, UPInt size, UPInt seed)
00511 {
00512 const UByte* pdata = (const UByte*) pdataIn;
00513 UPInt h = seed;
00514 while (size > 0)
00515 {
00516 size--;
00517 h = ((h << 5) + h) ^ (unsigned) pdata[size];
00518 }
00519
00520 return h;
00521 }
00522
00523
00524 UPInt String::BernsteinHashFunctionCIS(const void* pdataIn, UPInt size, UPInt seed)
00525 {
00526 const UByte* pdata = (const UByte*) pdataIn;
00527 UPInt h = seed;
00528 while (size > 0)
00529 {
00530 size--;
00531 h = ((h << 5) + h) ^ OVR_tolower(pdata[size]);
00532 }
00533
00534
00535
00536
00537 return h;
00538 }
00539
00540
00541
00542
00543
00544
00545 #define OVR_SBUFF_DEFAULT_GROW_SIZE 512
00546
00547 StringBuffer::StringBuffer()
00548 : pData(NULL), Size(0), BufferSize(0), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false)
00549 {
00550 }
00551
00552 StringBuffer::StringBuffer(UPInt growSize)
00553 : pData(NULL), Size(0), BufferSize(0), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false)
00554 {
00555 SetGrowSize(growSize);
00556 }
00557
00558 StringBuffer::StringBuffer(const char* data)
00559 : pData(NULL), Size(0), BufferSize(0), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false)
00560 {
00561 *this = data;
00562 }
00563
00564 StringBuffer::StringBuffer(const char* data, UPInt dataSize)
00565 : pData(NULL), Size(0), BufferSize(0), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false)
00566 {
00567 AppendString(data, dataSize);
00568 }
00569
00570 StringBuffer::StringBuffer(const String& src)
00571 : pData(NULL), Size(0), BufferSize(0), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false)
00572 {
00573 AppendString(src.ToCStr(), src.GetSize());
00574 }
00575
00576 StringBuffer::StringBuffer(const StringBuffer& src)
00577 : pData(NULL), Size(0), BufferSize(src.GetGrowSize()), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false)
00578 {
00579 AppendString(src.ToCStr(), src.GetSize());
00580 LengthIsSize = src.LengthIsSize;
00581 }
00582
00583 StringBuffer::StringBuffer(const wchar_t* data)
00584 : pData(NULL), Size(0), BufferSize(0), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false)
00585 {
00586 *this = data;
00587 }
00588
00589 StringBuffer::~StringBuffer()
00590 {
00591 if (pData)
00592 OVR_FREE(pData);
00593 }
00594 void StringBuffer::SetGrowSize(UPInt growSize)
00595 {
00596 if (growSize <= 16)
00597 GrowSize = 16;
00598 else
00599 {
00600 UByte bits = Alg::UpperBit(UInt32(growSize-1));
00601 UPInt size = 1<<bits;
00602 GrowSize = size == growSize ? growSize : size;
00603 }
00604 }
00605
00606 UPInt StringBuffer::GetLength() const
00607 {
00608 UPInt length, size = GetSize();
00609 if (LengthIsSize)
00610 return size;
00611
00612 length = (UPInt)UTF8Util::GetLength(pData, (UPInt)GetSize());
00613
00614 if (length == GetSize())
00615 LengthIsSize = true;
00616 return length;
00617 }
00618
00619 void StringBuffer::Reserve(UPInt _size)
00620 {
00621 if (_size >= BufferSize)
00622 {
00623 BufferSize = (_size + 1 + GrowSize - 1)& ~(GrowSize-1);
00624 if (!pData)
00625 pData = (char*)OVR_ALLOC(BufferSize);
00626 else
00627 pData = (char*)OVR_REALLOC(pData, BufferSize);
00628 }
00629 }
00630 void StringBuffer::Resize(UPInt _size)
00631 {
00632 Reserve(_size);
00633 LengthIsSize = false;
00634 Size = _size;
00635 if (pData)
00636 pData[Size] = 0;
00637 }
00638
00639 void StringBuffer::Clear()
00640 {
00641 Resize(0);
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651 }
00652
00653 void StringBuffer::AppendChar(UInt32 ch)
00654 {
00655 char buff[8];
00656 UPInt origSize = GetSize();
00657
00658
00659
00660 SPInt srcSize = 0;
00661 UTF8Util::EncodeChar(buff, &srcSize, ch);
00662 OVR_ASSERT(srcSize >= 0);
00663
00664 UPInt size = origSize + srcSize;
00665 Resize(size);
00666 memcpy(pData + origSize, buff, srcSize);
00667 }
00668
00669
00670 void StringBuffer::AppendString(const wchar_t* pstr, SPInt len)
00671 {
00672 if (!pstr)
00673 return;
00674
00675 SPInt srcSize = UTF8Util::GetEncodeStringSize(pstr, len);
00676 UPInt origSize = GetSize();
00677 UPInt size = srcSize + origSize;
00678
00679 Resize(size);
00680 UTF8Util::EncodeString(pData + origSize, pstr, len);
00681 }
00682
00683 void StringBuffer::AppendString(const char* putf8str, SPInt utf8StrSz)
00684 {
00685 if (!putf8str || !utf8StrSz)
00686 return;
00687 if (utf8StrSz == -1)
00688 utf8StrSz = (SPInt)OVR_strlen(putf8str);
00689
00690 UPInt origSize = GetSize();
00691 UPInt size = utf8StrSz + origSize;
00692
00693 Resize(size);
00694 memcpy(pData + origSize, putf8str, utf8StrSz);
00695 }
00696
00697
00698 void StringBuffer::operator = (const char* pstr)
00699 {
00700 pstr = pstr ? pstr : "";
00701 UPInt size = OVR_strlen(pstr);
00702 Resize(size);
00703 memcpy(pData, pstr, size);
00704 }
00705
00706 void StringBuffer::operator = (const wchar_t* pstr)
00707 {
00708 pstr = pstr ? pstr : L"";
00709 UPInt size = (UPInt)UTF8Util::GetEncodeStringSize(pstr);
00710 Resize(size);
00711 UTF8Util::EncodeString(pData, pstr);
00712 }
00713
00714 void StringBuffer::operator = (const String& src)
00715 {
00716 Resize(src.GetSize());
00717 memcpy(pData, src.ToCStr(), src.GetSize());
00718 }
00719
00720
00721
00722 void StringBuffer::Insert(const char* substr, UPInt posAt, SPInt len)
00723 {
00724 UPInt oldSize = Size;
00725 UPInt insertSize = (len < 0) ? OVR_strlen(substr) : (UPInt)len;
00726 UPInt byteIndex = LengthIsSize ? posAt :
00727 (UPInt)UTF8Util::GetByteIndex(posAt, pData, (SPInt)Size);
00728
00729 OVR_ASSERT(byteIndex <= oldSize);
00730 Reserve(oldSize + insertSize);
00731
00732 memmove(pData + byteIndex + insertSize, pData + byteIndex, oldSize - byteIndex + 1);
00733 memcpy (pData + byteIndex, substr, insertSize);
00734 LengthIsSize = false;
00735 Size = oldSize + insertSize;
00736 pData[Size] = 0;
00737 }
00738
00739
00740 UPInt StringBuffer::InsertCharAt(UInt32 c, UPInt posAt)
00741 {
00742 char buf[8];
00743 SPInt len = 0;
00744 UTF8Util::EncodeChar(buf, &len, c);
00745 OVR_ASSERT(len >= 0);
00746 buf[(UPInt)len] = 0;
00747
00748 Insert(buf, posAt, len);
00749 return (UPInt)len;
00750 }
00751
00752 }