oculus1

diff libovr/Src/Kernel/OVR_String.cpp @ 3:b069a5c27388

added a couple more stuff, fixed all the LibOVR line endings
author John Tsiombikas <nuclear@member.fsf.org>
date Sun, 15 Sep 2013 04:10:05 +0300
parents e2f9e4603129
children
line diff
     1.1 --- a/libovr/Src/Kernel/OVR_String.cpp	Sat Sep 14 17:51:03 2013 +0300
     1.2 +++ b/libovr/Src/Kernel/OVR_String.cpp	Sun Sep 15 04:10:05 2013 +0300
     1.3 @@ -1,1 +1,752 @@
     1.4 -/************************************************************************************
     1.5 
     1.6 Filename    :   OVR_String.cpp
     1.7 Content     :   String UTF8 string implementation with copy-on-write semantics
     1.8                 (thread-safe for assignment but not modification).
     1.9 Created     :   September 19, 2012
    1.10 Notes       : 
    1.11 
    1.12 Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
    1.13 
    1.14 Use of this software is subject to the terms of the Oculus license
    1.15 agreement provided at the time of installation or download, or which
    1.16 otherwise accompanies this software in either electronic or hard copy form.
    1.17 
    1.18 ************************************************************************************/
    1.19 
    1.20 #include "OVR_String.h"
    1.21 
    1.22 #include <stdlib.h>
    1.23 #include <ctype.h>
    1.24 
    1.25 #ifdef OVR_OS_QNX
    1.26 # include <strings.h>
    1.27 #endif
    1.28 
    1.29 namespace OVR {
    1.30 
    1.31 #define String_LengthIsSize (UPInt(1) << String::Flag_LengthIsSizeShift)
    1.32 
    1.33 String::DataDesc String::NullData = {String_LengthIsSize, 1, {0} };
    1.34 
    1.35 
    1.36 String::String()
    1.37 {
    1.38     pData = &NullData;
    1.39     pData->AddRef();
    1.40 };
    1.41 
    1.42 String::String(const char* pdata)
    1.43 {
    1.44     // Obtain length in bytes; it doesn't matter if _data is UTF8.
    1.45     UPInt size = pdata ? OVR_strlen(pdata) : 0; 
    1.46     pData = AllocDataCopy1(size, 0, pdata, size);
    1.47 };
    1.48 
    1.49 String::String(const char* pdata1, const char* pdata2, const char* pdata3)
    1.50 {
    1.51     // Obtain length in bytes; it doesn't matter if _data is UTF8.
    1.52     UPInt size1 = pdata1 ? OVR_strlen(pdata1) : 0; 
    1.53     UPInt size2 = pdata2 ? OVR_strlen(pdata2) : 0; 
    1.54     UPInt size3 = pdata3 ? OVR_strlen(pdata3) : 0; 
    1.55 
    1.56     DataDesc *pdataDesc = AllocDataCopy2(size1 + size2 + size3, 0,
    1.57                                          pdata1, size1, pdata2, size2);
    1.58     memcpy(pdataDesc->Data + size1 + size2, pdata3, size3);   
    1.59     pData = pdataDesc;    
    1.60 }
    1.61 
    1.62 String::String(const char* pdata, UPInt size)
    1.63 {
    1.64     OVR_ASSERT((size == 0) || (pdata != 0));
    1.65     pData = AllocDataCopy1(size, 0, pdata, size);
    1.66 };
    1.67 
    1.68 
    1.69 String::String(const InitStruct& src, UPInt size)
    1.70 {
    1.71     pData = AllocData(size, 0);
    1.72     src.InitString(GetData()->Data, size);
    1.73 }
    1.74 
    1.75 String::String(const String& src)
    1.76 {    
    1.77     pData = src.GetData();
    1.78     pData->AddRef();
    1.79 }
    1.80 
    1.81 String::String(const StringBuffer& src)
    1.82 {
    1.83     pData = AllocDataCopy1(src.GetSize(), 0, src.ToCStr(), src.GetSize());
    1.84 }
    1.85 
    1.86 String::String(const wchar_t* data)
    1.87 {
    1.88     pData = &NullData;
    1.89     pData->AddRef();
    1.90     // Simplified logic for wchar_t constructor.
    1.91     if (data)    
    1.92         *this = data;    
    1.93 }
    1.94 
    1.95 
    1.96 String::DataDesc* String::AllocData(UPInt size, UPInt lengthIsSize)
    1.97 {
    1.98     String::DataDesc* pdesc;
    1.99 
   1.100     if (size == 0)
   1.101     {
   1.102         pdesc = &NullData;
   1.103         pdesc->AddRef();
   1.104         return pdesc;
   1.105     }
   1.106 
   1.107     pdesc = (DataDesc*)OVR_ALLOC(sizeof(DataDesc)+ size);
   1.108     pdesc->Data[size] = 0;
   1.109     pdesc->RefCount = 1;
   1.110     pdesc->Size     = size | lengthIsSize;  
   1.111     return pdesc;
   1.112 }
   1.113 
   1.114 
   1.115 String::DataDesc* String::AllocDataCopy1(UPInt size, UPInt lengthIsSize,
   1.116                                          const char* pdata, UPInt copySize)
   1.117 {
   1.118     String::DataDesc* pdesc = AllocData(size, lengthIsSize);
   1.119     memcpy(pdesc->Data, pdata, copySize);
   1.120     return pdesc;
   1.121 }
   1.122 
   1.123 String::DataDesc* String::AllocDataCopy2(UPInt size, UPInt lengthIsSize,
   1.124                                          const char* pdata1, UPInt copySize1,
   1.125                                          const char* pdata2, UPInt copySize2)
   1.126 {
   1.127     String::DataDesc* pdesc = AllocData(size, lengthIsSize);
   1.128     memcpy(pdesc->Data, pdata1, copySize1);
   1.129     memcpy(pdesc->Data + copySize1, pdata2, copySize2);
   1.130     return pdesc;
   1.131 }
   1.132 
   1.133 
   1.134 UPInt String::GetLength() const 
   1.135 {
   1.136     // Optimize length accesses for non-UTF8 character strings. 
   1.137     DataDesc* pdata = GetData();
   1.138     UPInt     length, size = pdata->GetSize();
   1.139     
   1.140     if (pdata->LengthIsSize())
   1.141         return size;    
   1.142     
   1.143     length = (UPInt)UTF8Util::GetLength(pdata->Data, (UPInt)size);
   1.144     
   1.145     if (length == size)
   1.146         pdata->Size |= String_LengthIsSize;
   1.147     
   1.148     return length;
   1.149 }
   1.150 
   1.151 
   1.152 //static UInt32 String_CharSearch(const char* buf, )
   1.153 
   1.154 
   1.155 UInt32 String::GetCharAt(UPInt index) const 
   1.156 {  
   1.157     SPInt       i = (SPInt) index;
   1.158     DataDesc*   pdata = GetData();
   1.159     const char* buf = pdata->Data;
   1.160     UInt32      c;
   1.161     
   1.162     if (pdata->LengthIsSize())
   1.163     {
   1.164         OVR_ASSERT(index < pdata->GetSize());
   1.165         buf += i;
   1.166         return UTF8Util::DecodeNextChar_Advance0(&buf);
   1.167     }
   1.168 
   1.169     c = UTF8Util::GetCharAt(index, buf, pdata->GetSize());
   1.170     return c;
   1.171 }
   1.172 
   1.173 UInt32 String::GetFirstCharAt(UPInt index, const char** offset) const
   1.174 {
   1.175     DataDesc*   pdata = GetData();
   1.176     SPInt       i = (SPInt) index;
   1.177     const char* buf = pdata->Data;
   1.178     const char* end = buf + pdata->GetSize();
   1.179     UInt32      c;
   1.180 
   1.181     do 
   1.182     {
   1.183         c = UTF8Util::DecodeNextChar_Advance0(&buf);
   1.184         i--;
   1.185 
   1.186         if (buf >= end)
   1.187         {
   1.188             // We've hit the end of the string; don't go further.
   1.189             OVR_ASSERT(i == 0);
   1.190             return c;
   1.191         }
   1.192     } while (i >= 0);
   1.193 
   1.194     *offset = buf;
   1.195 
   1.196     return c;
   1.197 }
   1.198 
   1.199 UInt32 String::GetNextChar(const char** offset) const
   1.200 {
   1.201     return UTF8Util::DecodeNextChar(offset);
   1.202 }
   1.203 
   1.204 
   1.205 
   1.206 void String::AppendChar(UInt32 ch)
   1.207 {
   1.208     DataDesc*   pdata = GetData();
   1.209     UPInt       size = pdata->GetSize();
   1.210     char        buff[8];
   1.211     SPInt       encodeSize = 0;
   1.212 
   1.213     // Converts ch into UTF8 string and fills it into buff.   
   1.214     UTF8Util::EncodeChar(buff, &encodeSize, ch);
   1.215     OVR_ASSERT(encodeSize >= 0);
   1.216 
   1.217     SetData(AllocDataCopy2(size + (UPInt)encodeSize, 0,
   1.218                            pdata->Data, size, buff, (UPInt)encodeSize));
   1.219     pdata->Release();
   1.220 }
   1.221 
   1.222 
   1.223 void String::AppendString(const wchar_t* pstr, SPInt len)
   1.224 {
   1.225     if (!pstr)
   1.226         return;
   1.227 
   1.228     DataDesc*   pdata = GetData();
   1.229     UPInt       oldSize = pdata->GetSize();    
   1.230     UPInt       encodeSize = (UPInt)UTF8Util::GetEncodeStringSize(pstr, len);
   1.231 
   1.232     DataDesc*   pnewData = AllocDataCopy1(oldSize + (UPInt)encodeSize, 0,
   1.233                                           pdata->Data, oldSize);
   1.234     UTF8Util::EncodeString(pnewData->Data + oldSize,  pstr, len);
   1.235 
   1.236     SetData(pnewData);
   1.237     pdata->Release();
   1.238 }
   1.239 
   1.240 
   1.241 void String::AppendString(const char* putf8str, SPInt utf8StrSz)
   1.242 {
   1.243     if (!putf8str || !utf8StrSz)
   1.244         return;
   1.245     if (utf8StrSz == -1)
   1.246         utf8StrSz = (SPInt)OVR_strlen(putf8str);
   1.247 
   1.248     DataDesc*   pdata = GetData();
   1.249     UPInt       oldSize = pdata->GetSize();
   1.250 
   1.251     SetData(AllocDataCopy2(oldSize + (UPInt)utf8StrSz, 0,
   1.252                            pdata->Data, oldSize, putf8str, (UPInt)utf8StrSz));
   1.253     pdata->Release();
   1.254 }
   1.255 
   1.256 void    String::AssignString(const InitStruct& src, UPInt size)
   1.257 {
   1.258     DataDesc*   poldData = GetData();
   1.259     DataDesc*   pnewData = AllocData(size, 0);
   1.260     src.InitString(pnewData->Data, size);
   1.261     SetData(pnewData);
   1.262     poldData->Release();
   1.263 }
   1.264 
   1.265 void    String::AssignString(const char* putf8str, UPInt size)
   1.266 {
   1.267     DataDesc* poldData = GetData();
   1.268     SetData(AllocDataCopy1(size, 0, putf8str, size));
   1.269     poldData->Release();
   1.270 }
   1.271 
   1.272 void    String::operator = (const char* pstr)
   1.273 {
   1.274     AssignString(pstr, pstr ? OVR_strlen(pstr) : 0);
   1.275 }
   1.276 
   1.277 void    String::operator = (const wchar_t* pwstr)
   1.278 {
   1.279     DataDesc*   poldData = GetData();
   1.280     UPInt       size = pwstr ? (UPInt)UTF8Util::GetEncodeStringSize(pwstr) : 0;
   1.281 
   1.282     DataDesc*   pnewData = AllocData(size, 0);
   1.283     UTF8Util::EncodeString(pnewData->Data, pwstr);
   1.284     SetData(pnewData);
   1.285     poldData->Release();
   1.286 }
   1.287 
   1.288 
   1.289 void    String::operator = (const String& src)
   1.290 {     
   1.291     DataDesc*    psdata = src.GetData();
   1.292     DataDesc*    pdata = GetData();    
   1.293 
   1.294     SetData(psdata);
   1.295     psdata->AddRef();
   1.296     pdata->Release();
   1.297 }
   1.298 
   1.299 
   1.300 void    String::operator = (const StringBuffer& src)
   1.301 { 
   1.302     DataDesc* polddata = GetData();    
   1.303     SetData(AllocDataCopy1(src.GetSize(), 0, src.ToCStr(), src.GetSize()));
   1.304     polddata->Release();
   1.305 }
   1.306 
   1.307 void    String::operator += (const String& src)
   1.308 {
   1.309     DataDesc   *pourData = GetData(),
   1.310                *psrcData = src.GetData();
   1.311     UPInt       ourSize  = pourData->GetSize(),
   1.312                 srcSize  = psrcData->GetSize();
   1.313     UPInt       lflag    = pourData->GetLengthFlag() & psrcData->GetLengthFlag();
   1.314 
   1.315     SetData(AllocDataCopy2(ourSize + srcSize, lflag,
   1.316                            pourData->Data, ourSize, psrcData->Data, srcSize));
   1.317     pourData->Release();
   1.318 }
   1.319 
   1.320 
   1.321 String   String::operator + (const char* str) const
   1.322 {   
   1.323     String tmp1(*this);
   1.324     tmp1 += (str ? str : "");
   1.325     return tmp1;
   1.326 }
   1.327 
   1.328 String   String::operator + (const String& src) const
   1.329 { 
   1.330     String tmp1(*this);
   1.331     tmp1 += src;
   1.332     return tmp1;
   1.333 }
   1.334 
   1.335 void    String::Remove(UPInt posAt, SPInt removeLength)
   1.336 {
   1.337     DataDesc*   pdata = GetData();
   1.338     UPInt       oldSize = pdata->GetSize();    
   1.339     // Length indicates the number of characters to remove. 
   1.340     UPInt       length = GetLength();
   1.341 
   1.342     // If index is past the string, nothing to remove.
   1.343     if (posAt >= length)
   1.344         return;
   1.345     // Otherwise, cap removeLength to the length of the string.
   1.346     if ((posAt + removeLength) > length)
   1.347         removeLength = length - posAt;
   1.348 
   1.349     // Get the byte position of the UTF8 char at position posAt.
   1.350     SPInt bytePos    = UTF8Util::GetByteIndex(posAt, pdata->Data, oldSize);
   1.351     SPInt removeSize = UTF8Util::GetByteIndex(removeLength, pdata->Data + bytePos, oldSize-bytePos);
   1.352 
   1.353     SetData(AllocDataCopy2(oldSize - removeSize, pdata->GetLengthFlag(),
   1.354                            pdata->Data, bytePos,
   1.355                            pData->Data + bytePos + removeSize, (oldSize - bytePos - removeSize)));
   1.356     pdata->Release();
   1.357 }
   1.358 
   1.359 
   1.360 String   String::Substring(UPInt start, UPInt end) const
   1.361 {
   1.362     UPInt length = GetLength();
   1.363     if ((start >= length) || (start >= end))
   1.364         return String();   
   1.365 
   1.366     DataDesc* pdata = GetData();
   1.367     
   1.368     // If size matches, we know the exact index range.
   1.369     if (pdata->LengthIsSize())
   1.370         return String(pdata->Data + start, end - start);
   1.371     
   1.372     // Get position of starting character.
   1.373     SPInt byteStart = UTF8Util::GetByteIndex(start, pdata->Data, pdata->GetSize());
   1.374     SPInt byteSize  = UTF8Util::GetByteIndex(end - start, pdata->Data + byteStart, pdata->GetSize()-byteStart);
   1.375     return String(pdata->Data + byteStart, (UPInt)byteSize);
   1.376 }
   1.377 
   1.378 void String::Clear()
   1.379 {   
   1.380     NullData.AddRef();
   1.381     GetData()->Release();
   1.382     SetData(&NullData);
   1.383 }
   1.384 
   1.385 
   1.386 String   String::ToUpper() const 
   1.387 {       
   1.388     UInt32      c;
   1.389     const char* psource = GetData()->Data;
   1.390     const char* pend = psource + GetData()->GetSize();
   1.391     String      str;
   1.392     SPInt       bufferOffset = 0;
   1.393     char        buffer[512];
   1.394     
   1.395     while(psource < pend)
   1.396     {
   1.397         do {            
   1.398             c = UTF8Util::DecodeNextChar_Advance0(&psource);
   1.399             UTF8Util::EncodeChar(buffer, &bufferOffset, OVR_towupper(wchar_t(c)));
   1.400         } while ((psource < pend) && (bufferOffset < SPInt(sizeof(buffer)-8)));
   1.401 
   1.402         // Append string a piece at a time.
   1.403         str.AppendString(buffer, bufferOffset);
   1.404         bufferOffset = 0;
   1.405     }
   1.406 
   1.407     return str;
   1.408 }
   1.409 
   1.410 String   String::ToLower() const 
   1.411 {
   1.412     UInt32      c;
   1.413     const char* psource = GetData()->Data;
   1.414     const char* pend = psource + GetData()->GetSize();
   1.415     String      str;
   1.416     SPInt       bufferOffset = 0;
   1.417     char        buffer[512];
   1.418 
   1.419     while(psource < pend)
   1.420     {
   1.421         do {
   1.422             c = UTF8Util::DecodeNextChar_Advance0(&psource);
   1.423             UTF8Util::EncodeChar(buffer, &bufferOffset, OVR_towlower(wchar_t(c)));
   1.424         } while ((psource < pend) && (bufferOffset < SPInt(sizeof(buffer)-8)));
   1.425 
   1.426         // Append string a piece at a time.
   1.427         str.AppendString(buffer, bufferOffset);
   1.428         bufferOffset = 0;
   1.429     }
   1.430 
   1.431     return str;
   1.432 }
   1.433 
   1.434 
   1.435 
   1.436 String& String::Insert(const char* substr, UPInt posAt, SPInt strSize)
   1.437 {
   1.438     DataDesc* poldData   = GetData();
   1.439     UPInt     oldSize    = poldData->GetSize();
   1.440     UPInt     insertSize = (strSize < 0) ? OVR_strlen(substr) : (UPInt)strSize;    
   1.441     UPInt     byteIndex  =  (poldData->LengthIsSize()) ?
   1.442                             posAt : (UPInt)UTF8Util::GetByteIndex(posAt, poldData->Data, oldSize);
   1.443 
   1.444     OVR_ASSERT(byteIndex <= oldSize);
   1.445     
   1.446     DataDesc* pnewData = AllocDataCopy2(oldSize + insertSize, 0,
   1.447                                         poldData->Data, byteIndex, substr, insertSize);
   1.448     memcpy(pnewData->Data + byteIndex + insertSize,
   1.449            poldData->Data + byteIndex, oldSize - byteIndex);
   1.450     SetData(pnewData);
   1.451     poldData->Release();
   1.452     return *this;
   1.453 }
   1.454 
   1.455 /*
   1.456 String& String::Insert(const UInt32* substr, UPInt posAt, SPInt len)
   1.457 {
   1.458     for (SPInt i = 0; i < len; ++i)
   1.459     {
   1.460         UPInt charw = InsertCharAt(substr[i], posAt);
   1.461         posAt += charw;
   1.462     }
   1.463     return *this;
   1.464 }
   1.465 */
   1.466 
   1.467 UPInt String::InsertCharAt(UInt32 c, UPInt posAt)
   1.468 {
   1.469     char    buf[8];
   1.470     SPInt   index = 0;
   1.471     UTF8Util::EncodeChar(buf, &index, c);
   1.472     OVR_ASSERT(index >= 0);
   1.473     buf[(UPInt)index] = 0;
   1.474 
   1.475     Insert(buf, posAt, index);
   1.476     return (UPInt)index;
   1.477 }
   1.478 
   1.479 
   1.480 int String::CompareNoCase(const char* a, const char* b)
   1.481 {
   1.482     return OVR_stricmp(a, b);
   1.483 }
   1.484 
   1.485 int String::CompareNoCase(const char* a, const char* b, SPInt len)
   1.486 {
   1.487     if (len)
   1.488     {
   1.489         SPInt f,l;
   1.490         SPInt slen = len;
   1.491         const char *s = b;
   1.492         do {
   1.493             f = (SPInt)OVR_tolower((int)(*(a++)));
   1.494             l = (SPInt)OVR_tolower((int)(*(b++)));
   1.495         } while (--len && f && (f == l) && *b != 0);
   1.496 
   1.497         if (f == l && (len != 0 || *b != 0))
   1.498         {
   1.499             f = (SPInt)slen;
   1.500             l = (SPInt)OVR_strlen(s);
   1.501             return int(f - l);
   1.502         }
   1.503 
   1.504         return int(f - l);
   1.505     }
   1.506     else
   1.507         return (0-(int)OVR_strlen(b));
   1.508 }
   1.509 
   1.510 // ***** Implement hash static functions
   1.511 
   1.512 // Hash function
   1.513 UPInt String::BernsteinHashFunction(const void* pdataIn, UPInt size, UPInt seed)
   1.514 {
   1.515     const UByte*    pdata   = (const UByte*) pdataIn;
   1.516     UPInt           h       = seed;
   1.517     while (size > 0)
   1.518     {
   1.519         size--;
   1.520         h = ((h << 5) + h) ^ (unsigned) pdata[size];
   1.521     }
   1.522 
   1.523     return h;
   1.524 }
   1.525 
   1.526 // Hash function, case-insensitive
   1.527 UPInt String::BernsteinHashFunctionCIS(const void* pdataIn, UPInt size, UPInt seed)
   1.528 {
   1.529     const UByte*    pdata = (const UByte*) pdataIn;
   1.530     UPInt           h = seed;
   1.531     while (size > 0)
   1.532     {
   1.533         size--;
   1.534         h = ((h << 5) + h) ^ OVR_tolower(pdata[size]);
   1.535     }
   1.536 
   1.537     // Alternative: "sdbm" hash function, suggested at same web page above.
   1.538     // h = 0;
   1.539     // for bytes { h = (h << 16) + (h << 6) - hash + *p; }
   1.540     return h;
   1.541 }
   1.542 
   1.543 
   1.544 
   1.545 // ***** String Buffer used for Building Strings
   1.546 
   1.547 
   1.548 #define OVR_SBUFF_DEFAULT_GROW_SIZE 512
   1.549 // Constructors / Destructor.
   1.550 StringBuffer::StringBuffer()
   1.551     : pData(NULL), Size(0), BufferSize(0), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false)
   1.552 {
   1.553 }
   1.554 
   1.555 StringBuffer::StringBuffer(UPInt growSize)
   1.556     : pData(NULL), Size(0), BufferSize(0), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false)
   1.557 {
   1.558     SetGrowSize(growSize);
   1.559 }
   1.560 
   1.561 StringBuffer::StringBuffer(const char* data)
   1.562     : pData(NULL), Size(0), BufferSize(0), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false)
   1.563 {
   1.564     *this = data;
   1.565 }
   1.566 
   1.567 StringBuffer::StringBuffer(const char* data, UPInt dataSize)
   1.568     : pData(NULL), Size(0), BufferSize(0), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false)
   1.569 {
   1.570     AppendString(data, dataSize);
   1.571 }
   1.572 
   1.573 StringBuffer::StringBuffer(const String& src)
   1.574     : pData(NULL), Size(0), BufferSize(0), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false)
   1.575 {
   1.576     AppendString(src.ToCStr(), src.GetSize());
   1.577 }
   1.578 
   1.579 StringBuffer::StringBuffer(const StringBuffer& src)
   1.580     : pData(NULL), Size(0), BufferSize(src.GetGrowSize()), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false)
   1.581 {
   1.582     AppendString(src.ToCStr(), src.GetSize());
   1.583     LengthIsSize = src.LengthIsSize;
   1.584 }
   1.585 
   1.586 StringBuffer::StringBuffer(const wchar_t* data)
   1.587     : pData(NULL), Size(0), BufferSize(0), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false)
   1.588 {
   1.589     *this = data;
   1.590 }
   1.591 
   1.592 StringBuffer::~StringBuffer()
   1.593 {
   1.594     if (pData)
   1.595         OVR_FREE(pData);
   1.596 }
   1.597 void StringBuffer::SetGrowSize(UPInt growSize) 
   1.598 { 
   1.599     if (growSize <= 16)
   1.600         GrowSize = 16;
   1.601     else
   1.602     {
   1.603         UByte bits = Alg::UpperBit(UInt32(growSize-1));
   1.604         UPInt size = 1<<bits;
   1.605         GrowSize = size == growSize ? growSize : size;
   1.606     }
   1.607 }
   1.608 
   1.609 UPInt StringBuffer::GetLength() const
   1.610 {
   1.611     UPInt length, size = GetSize();
   1.612     if (LengthIsSize)
   1.613         return size;
   1.614 
   1.615     length = (UPInt)UTF8Util::GetLength(pData, (UPInt)GetSize());
   1.616 
   1.617     if (length == GetSize())
   1.618         LengthIsSize = true;
   1.619     return length;
   1.620 }
   1.621 
   1.622 void    StringBuffer::Reserve(UPInt _size)
   1.623 {
   1.624     if (_size >= BufferSize) // >= because of trailing zero! (!AB)
   1.625     {
   1.626         BufferSize = (_size + 1 + GrowSize - 1)& ~(GrowSize-1);
   1.627         if (!pData)
   1.628             pData = (char*)OVR_ALLOC(BufferSize);
   1.629         else 
   1.630             pData = (char*)OVR_REALLOC(pData, BufferSize);
   1.631     }
   1.632 }
   1.633 void    StringBuffer::Resize(UPInt _size)
   1.634 {
   1.635     Reserve(_size);
   1.636     LengthIsSize = false;
   1.637     Size = _size;
   1.638     if (pData)
   1.639         pData[Size] = 0;
   1.640 }
   1.641 
   1.642 void StringBuffer::Clear()
   1.643 {
   1.644     Resize(0);
   1.645     /*
   1.646     if (pData != pEmptyNullData)
   1.647     {
   1.648         OVR_FREE(pHeap, pData);
   1.649         pData = pEmptyNullData;
   1.650         Size = BufferSize = 0;
   1.651         LengthIsSize = false;
   1.652     }
   1.653     */
   1.654 }
   1.655 // Appends a character
   1.656 void     StringBuffer::AppendChar(UInt32 ch)
   1.657 {
   1.658     char    buff[8];
   1.659     UPInt   origSize = GetSize();
   1.660 
   1.661     // Converts ch into UTF8 string and fills it into buff. Also increments index according to the number of bytes
   1.662     // in the UTF8 string.
   1.663     SPInt   srcSize = 0;
   1.664     UTF8Util::EncodeChar(buff, &srcSize, ch);
   1.665     OVR_ASSERT(srcSize >= 0);
   1.666     
   1.667     UPInt size = origSize + srcSize;
   1.668     Resize(size);
   1.669     memcpy(pData + origSize, buff, srcSize);
   1.670 }
   1.671 
   1.672 // Append a string
   1.673 void     StringBuffer::AppendString(const wchar_t* pstr, SPInt len)
   1.674 {
   1.675     if (!pstr)
   1.676         return;
   1.677 
   1.678     SPInt   srcSize     = UTF8Util::GetEncodeStringSize(pstr, len);
   1.679     UPInt   origSize    = GetSize();
   1.680     UPInt   size        = srcSize + origSize;
   1.681 
   1.682     Resize(size);
   1.683     UTF8Util::EncodeString(pData + origSize,  pstr, len);
   1.684 }
   1.685 
   1.686 void      StringBuffer::AppendString(const char* putf8str, SPInt utf8StrSz)
   1.687 {
   1.688     if (!putf8str || !utf8StrSz)
   1.689         return;
   1.690     if (utf8StrSz == -1)
   1.691         utf8StrSz = (SPInt)OVR_strlen(putf8str);
   1.692 
   1.693     UPInt   origSize    = GetSize();
   1.694     UPInt   size        = utf8StrSz + origSize;
   1.695 
   1.696     Resize(size);
   1.697     memcpy(pData + origSize, putf8str, utf8StrSz);
   1.698 }
   1.699 
   1.700 
   1.701 void      StringBuffer::operator = (const char* pstr)
   1.702 {
   1.703     pstr = pstr ? pstr : "";
   1.704     UPInt size = OVR_strlen(pstr);
   1.705     Resize(size);
   1.706     memcpy(pData, pstr, size);
   1.707 }
   1.708 
   1.709 void      StringBuffer::operator = (const wchar_t* pstr)
   1.710 {
   1.711     pstr = pstr ? pstr : L"";
   1.712     UPInt size = (UPInt)UTF8Util::GetEncodeStringSize(pstr);
   1.713     Resize(size);
   1.714     UTF8Util::EncodeString(pData, pstr);
   1.715 }
   1.716 
   1.717 void      StringBuffer::operator = (const String& src)
   1.718 {
   1.719     Resize(src.GetSize());
   1.720     memcpy(pData, src.ToCStr(), src.GetSize());
   1.721 }
   1.722 
   1.723 
   1.724 // Inserts substr at posAt
   1.725 void      StringBuffer::Insert(const char* substr, UPInt posAt, SPInt len)
   1.726 {
   1.727     UPInt     oldSize    = Size;
   1.728     UPInt     insertSize = (len < 0) ? OVR_strlen(substr) : (UPInt)len;    
   1.729     UPInt     byteIndex  = LengthIsSize ? posAt : 
   1.730                            (UPInt)UTF8Util::GetByteIndex(posAt, pData, (SPInt)Size);
   1.731 
   1.732     OVR_ASSERT(byteIndex <= oldSize);
   1.733     Reserve(oldSize + insertSize);
   1.734 
   1.735     memmove(pData + byteIndex + insertSize, pData + byteIndex, oldSize - byteIndex + 1);
   1.736     memcpy (pData + byteIndex, substr, insertSize);
   1.737     LengthIsSize = false;
   1.738     Size = oldSize + insertSize;
   1.739     pData[Size] = 0;
   1.740 }
   1.741 
   1.742 // Inserts character at posAt
   1.743 UPInt     StringBuffer::InsertCharAt(UInt32 c, UPInt posAt)
   1.744 {
   1.745     char    buf[8];
   1.746     SPInt   len = 0;
   1.747     UTF8Util::EncodeChar(buf, &len, c);
   1.748     OVR_ASSERT(len >= 0);
   1.749     buf[(UPInt)len] = 0;
   1.750 
   1.751     Insert(buf, posAt, len);
   1.752     return (UPInt)len;
   1.753 }
   1.754 
   1.755 } // OVR
   1.756 \ No newline at end of file
   1.757 +/************************************************************************************
   1.758 +
   1.759 +Filename    :   OVR_String.cpp
   1.760 +Content     :   String UTF8 string implementation with copy-on-write semantics
   1.761 +                (thread-safe for assignment but not modification).
   1.762 +Created     :   September 19, 2012
   1.763 +Notes       : 
   1.764 +
   1.765 +Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
   1.766 +
   1.767 +Use of this software is subject to the terms of the Oculus license
   1.768 +agreement provided at the time of installation or download, or which
   1.769 +otherwise accompanies this software in either electronic or hard copy form.
   1.770 +
   1.771 +************************************************************************************/
   1.772 +
   1.773 +#include "OVR_String.h"
   1.774 +
   1.775 +#include <stdlib.h>
   1.776 +#include <ctype.h>
   1.777 +
   1.778 +#ifdef OVR_OS_QNX
   1.779 +# include <strings.h>
   1.780 +#endif
   1.781 +
   1.782 +namespace OVR {
   1.783 +
   1.784 +#define String_LengthIsSize (UPInt(1) << String::Flag_LengthIsSizeShift)
   1.785 +
   1.786 +String::DataDesc String::NullData = {String_LengthIsSize, 1, {0} };
   1.787 +
   1.788 +
   1.789 +String::String()
   1.790 +{
   1.791 +    pData = &NullData;
   1.792 +    pData->AddRef();
   1.793 +};
   1.794 +
   1.795 +String::String(const char* pdata)
   1.796 +{
   1.797 +    // Obtain length in bytes; it doesn't matter if _data is UTF8.
   1.798 +    UPInt size = pdata ? OVR_strlen(pdata) : 0; 
   1.799 +    pData = AllocDataCopy1(size, 0, pdata, size);
   1.800 +};
   1.801 +
   1.802 +String::String(const char* pdata1, const char* pdata2, const char* pdata3)
   1.803 +{
   1.804 +    // Obtain length in bytes; it doesn't matter if _data is UTF8.
   1.805 +    UPInt size1 = pdata1 ? OVR_strlen(pdata1) : 0; 
   1.806 +    UPInt size2 = pdata2 ? OVR_strlen(pdata2) : 0; 
   1.807 +    UPInt size3 = pdata3 ? OVR_strlen(pdata3) : 0; 
   1.808 +
   1.809 +    DataDesc *pdataDesc = AllocDataCopy2(size1 + size2 + size3, 0,
   1.810 +                                         pdata1, size1, pdata2, size2);
   1.811 +    memcpy(pdataDesc->Data + size1 + size2, pdata3, size3);   
   1.812 +    pData = pdataDesc;    
   1.813 +}
   1.814 +
   1.815 +String::String(const char* pdata, UPInt size)
   1.816 +{
   1.817 +    OVR_ASSERT((size == 0) || (pdata != 0));
   1.818 +    pData = AllocDataCopy1(size, 0, pdata, size);
   1.819 +};
   1.820 +
   1.821 +
   1.822 +String::String(const InitStruct& src, UPInt size)
   1.823 +{
   1.824 +    pData = AllocData(size, 0);
   1.825 +    src.InitString(GetData()->Data, size);
   1.826 +}
   1.827 +
   1.828 +String::String(const String& src)
   1.829 +{    
   1.830 +    pData = src.GetData();
   1.831 +    pData->AddRef();
   1.832 +}
   1.833 +
   1.834 +String::String(const StringBuffer& src)
   1.835 +{
   1.836 +    pData = AllocDataCopy1(src.GetSize(), 0, src.ToCStr(), src.GetSize());
   1.837 +}
   1.838 +
   1.839 +String::String(const wchar_t* data)
   1.840 +{
   1.841 +    pData = &NullData;
   1.842 +    pData->AddRef();
   1.843 +    // Simplified logic for wchar_t constructor.
   1.844 +    if (data)    
   1.845 +        *this = data;    
   1.846 +}
   1.847 +
   1.848 +
   1.849 +String::DataDesc* String::AllocData(UPInt size, UPInt lengthIsSize)
   1.850 +{
   1.851 +    String::DataDesc* pdesc;
   1.852 +
   1.853 +    if (size == 0)
   1.854 +    {
   1.855 +        pdesc = &NullData;
   1.856 +        pdesc->AddRef();
   1.857 +        return pdesc;
   1.858 +    }
   1.859 +
   1.860 +    pdesc = (DataDesc*)OVR_ALLOC(sizeof(DataDesc)+ size);
   1.861 +    pdesc->Data[size] = 0;
   1.862 +    pdesc->RefCount = 1;
   1.863 +    pdesc->Size     = size | lengthIsSize;  
   1.864 +    return pdesc;
   1.865 +}
   1.866 +
   1.867 +
   1.868 +String::DataDesc* String::AllocDataCopy1(UPInt size, UPInt lengthIsSize,
   1.869 +                                         const char* pdata, UPInt copySize)
   1.870 +{
   1.871 +    String::DataDesc* pdesc = AllocData(size, lengthIsSize);
   1.872 +    memcpy(pdesc->Data, pdata, copySize);
   1.873 +    return pdesc;
   1.874 +}
   1.875 +
   1.876 +String::DataDesc* String::AllocDataCopy2(UPInt size, UPInt lengthIsSize,
   1.877 +                                         const char* pdata1, UPInt copySize1,
   1.878 +                                         const char* pdata2, UPInt copySize2)
   1.879 +{
   1.880 +    String::DataDesc* pdesc = AllocData(size, lengthIsSize);
   1.881 +    memcpy(pdesc->Data, pdata1, copySize1);
   1.882 +    memcpy(pdesc->Data + copySize1, pdata2, copySize2);
   1.883 +    return pdesc;
   1.884 +}
   1.885 +
   1.886 +
   1.887 +UPInt String::GetLength() const 
   1.888 +{
   1.889 +    // Optimize length accesses for non-UTF8 character strings. 
   1.890 +    DataDesc* pdata = GetData();
   1.891 +    UPInt     length, size = pdata->GetSize();
   1.892 +    
   1.893 +    if (pdata->LengthIsSize())
   1.894 +        return size;    
   1.895 +    
   1.896 +    length = (UPInt)UTF8Util::GetLength(pdata->Data, (UPInt)size);
   1.897 +    
   1.898 +    if (length == size)
   1.899 +        pdata->Size |= String_LengthIsSize;
   1.900 +    
   1.901 +    return length;
   1.902 +}
   1.903 +
   1.904 +
   1.905 +//static UInt32 String_CharSearch(const char* buf, )
   1.906 +
   1.907 +
   1.908 +UInt32 String::GetCharAt(UPInt index) const 
   1.909 +{  
   1.910 +    SPInt       i = (SPInt) index;
   1.911 +    DataDesc*   pdata = GetData();
   1.912 +    const char* buf = pdata->Data;
   1.913 +    UInt32      c;
   1.914 +    
   1.915 +    if (pdata->LengthIsSize())
   1.916 +    {
   1.917 +        OVR_ASSERT(index < pdata->GetSize());
   1.918 +        buf += i;
   1.919 +        return UTF8Util::DecodeNextChar_Advance0(&buf);
   1.920 +    }
   1.921 +
   1.922 +    c = UTF8Util::GetCharAt(index, buf, pdata->GetSize());
   1.923 +    return c;
   1.924 +}
   1.925 +
   1.926 +UInt32 String::GetFirstCharAt(UPInt index, const char** offset) const
   1.927 +{
   1.928 +    DataDesc*   pdata = GetData();
   1.929 +    SPInt       i = (SPInt) index;
   1.930 +    const char* buf = pdata->Data;
   1.931 +    const char* end = buf + pdata->GetSize();
   1.932 +    UInt32      c;
   1.933 +
   1.934 +    do 
   1.935 +    {
   1.936 +        c = UTF8Util::DecodeNextChar_Advance0(&buf);
   1.937 +        i--;
   1.938 +
   1.939 +        if (buf >= end)
   1.940 +        {
   1.941 +            // We've hit the end of the string; don't go further.
   1.942 +            OVR_ASSERT(i == 0);
   1.943 +            return c;
   1.944 +        }
   1.945 +    } while (i >= 0);
   1.946 +
   1.947 +    *offset = buf;
   1.948 +
   1.949 +    return c;
   1.950 +}
   1.951 +
   1.952 +UInt32 String::GetNextChar(const char** offset) const
   1.953 +{
   1.954 +    return UTF8Util::DecodeNextChar(offset);
   1.955 +}
   1.956 +
   1.957 +
   1.958 +
   1.959 +void String::AppendChar(UInt32 ch)
   1.960 +{
   1.961 +    DataDesc*   pdata = GetData();
   1.962 +    UPInt       size = pdata->GetSize();
   1.963 +    char        buff[8];
   1.964 +    SPInt       encodeSize = 0;
   1.965 +
   1.966 +    // Converts ch into UTF8 string and fills it into buff.   
   1.967 +    UTF8Util::EncodeChar(buff, &encodeSize, ch);
   1.968 +    OVR_ASSERT(encodeSize >= 0);
   1.969 +
   1.970 +    SetData(AllocDataCopy2(size + (UPInt)encodeSize, 0,
   1.971 +                           pdata->Data, size, buff, (UPInt)encodeSize));
   1.972 +    pdata->Release();
   1.973 +}
   1.974 +
   1.975 +
   1.976 +void String::AppendString(const wchar_t* pstr, SPInt len)
   1.977 +{
   1.978 +    if (!pstr)
   1.979 +        return;
   1.980 +
   1.981 +    DataDesc*   pdata = GetData();
   1.982 +    UPInt       oldSize = pdata->GetSize();    
   1.983 +    UPInt       encodeSize = (UPInt)UTF8Util::GetEncodeStringSize(pstr, len);
   1.984 +
   1.985 +    DataDesc*   pnewData = AllocDataCopy1(oldSize + (UPInt)encodeSize, 0,
   1.986 +                                          pdata->Data, oldSize);
   1.987 +    UTF8Util::EncodeString(pnewData->Data + oldSize,  pstr, len);
   1.988 +
   1.989 +    SetData(pnewData);
   1.990 +    pdata->Release();
   1.991 +}
   1.992 +
   1.993 +
   1.994 +void String::AppendString(const char* putf8str, SPInt utf8StrSz)
   1.995 +{
   1.996 +    if (!putf8str || !utf8StrSz)
   1.997 +        return;
   1.998 +    if (utf8StrSz == -1)
   1.999 +        utf8StrSz = (SPInt)OVR_strlen(putf8str);
  1.1000 +
  1.1001 +    DataDesc*   pdata = GetData();
  1.1002 +    UPInt       oldSize = pdata->GetSize();
  1.1003 +
  1.1004 +    SetData(AllocDataCopy2(oldSize + (UPInt)utf8StrSz, 0,
  1.1005 +                           pdata->Data, oldSize, putf8str, (UPInt)utf8StrSz));
  1.1006 +    pdata->Release();
  1.1007 +}
  1.1008 +
  1.1009 +void    String::AssignString(const InitStruct& src, UPInt size)
  1.1010 +{
  1.1011 +    DataDesc*   poldData = GetData();
  1.1012 +    DataDesc*   pnewData = AllocData(size, 0);
  1.1013 +    src.InitString(pnewData->Data, size);
  1.1014 +    SetData(pnewData);
  1.1015 +    poldData->Release();
  1.1016 +}
  1.1017 +
  1.1018 +void    String::AssignString(const char* putf8str, UPInt size)
  1.1019 +{
  1.1020 +    DataDesc* poldData = GetData();
  1.1021 +    SetData(AllocDataCopy1(size, 0, putf8str, size));
  1.1022 +    poldData->Release();
  1.1023 +}
  1.1024 +
  1.1025 +void    String::operator = (const char* pstr)
  1.1026 +{
  1.1027 +    AssignString(pstr, pstr ? OVR_strlen(pstr) : 0);
  1.1028 +}
  1.1029 +
  1.1030 +void    String::operator = (const wchar_t* pwstr)
  1.1031 +{
  1.1032 +    DataDesc*   poldData = GetData();
  1.1033 +    UPInt       size = pwstr ? (UPInt)UTF8Util::GetEncodeStringSize(pwstr) : 0;
  1.1034 +
  1.1035 +    DataDesc*   pnewData = AllocData(size, 0);
  1.1036 +    UTF8Util::EncodeString(pnewData->Data, pwstr);
  1.1037 +    SetData(pnewData);
  1.1038 +    poldData->Release();
  1.1039 +}
  1.1040 +
  1.1041 +
  1.1042 +void    String::operator = (const String& src)
  1.1043 +{     
  1.1044 +    DataDesc*    psdata = src.GetData();
  1.1045 +    DataDesc*    pdata = GetData();    
  1.1046 +
  1.1047 +    SetData(psdata);
  1.1048 +    psdata->AddRef();
  1.1049 +    pdata->Release();
  1.1050 +}
  1.1051 +
  1.1052 +
  1.1053 +void    String::operator = (const StringBuffer& src)
  1.1054 +{ 
  1.1055 +    DataDesc* polddata = GetData();    
  1.1056 +    SetData(AllocDataCopy1(src.GetSize(), 0, src.ToCStr(), src.GetSize()));
  1.1057 +    polddata->Release();
  1.1058 +}
  1.1059 +
  1.1060 +void    String::operator += (const String& src)
  1.1061 +{
  1.1062 +    DataDesc   *pourData = GetData(),
  1.1063 +               *psrcData = src.GetData();
  1.1064 +    UPInt       ourSize  = pourData->GetSize(),
  1.1065 +                srcSize  = psrcData->GetSize();
  1.1066 +    UPInt       lflag    = pourData->GetLengthFlag() & psrcData->GetLengthFlag();
  1.1067 +
  1.1068 +    SetData(AllocDataCopy2(ourSize + srcSize, lflag,
  1.1069 +                           pourData->Data, ourSize, psrcData->Data, srcSize));
  1.1070 +    pourData->Release();
  1.1071 +}
  1.1072 +
  1.1073 +
  1.1074 +String   String::operator + (const char* str) const
  1.1075 +{   
  1.1076 +    String tmp1(*this);
  1.1077 +    tmp1 += (str ? str : "");
  1.1078 +    return tmp1;
  1.1079 +}
  1.1080 +
  1.1081 +String   String::operator + (const String& src) const
  1.1082 +{ 
  1.1083 +    String tmp1(*this);
  1.1084 +    tmp1 += src;
  1.1085 +    return tmp1;
  1.1086 +}
  1.1087 +
  1.1088 +void    String::Remove(UPInt posAt, SPInt removeLength)
  1.1089 +{
  1.1090 +    DataDesc*   pdata = GetData();
  1.1091 +    UPInt       oldSize = pdata->GetSize();    
  1.1092 +    // Length indicates the number of characters to remove. 
  1.1093 +    UPInt       length = GetLength();
  1.1094 +
  1.1095 +    // If index is past the string, nothing to remove.
  1.1096 +    if (posAt >= length)
  1.1097 +        return;
  1.1098 +    // Otherwise, cap removeLength to the length of the string.
  1.1099 +    if ((posAt + removeLength) > length)
  1.1100 +        removeLength = length - posAt;
  1.1101 +
  1.1102 +    // Get the byte position of the UTF8 char at position posAt.
  1.1103 +    SPInt bytePos    = UTF8Util::GetByteIndex(posAt, pdata->Data, oldSize);
  1.1104 +    SPInt removeSize = UTF8Util::GetByteIndex(removeLength, pdata->Data + bytePos, oldSize-bytePos);
  1.1105 +
  1.1106 +    SetData(AllocDataCopy2(oldSize - removeSize, pdata->GetLengthFlag(),
  1.1107 +                           pdata->Data, bytePos,
  1.1108 +                           pData->Data + bytePos + removeSize, (oldSize - bytePos - removeSize)));
  1.1109 +    pdata->Release();
  1.1110 +}
  1.1111 +
  1.1112 +
  1.1113 +String   String::Substring(UPInt start, UPInt end) const
  1.1114 +{
  1.1115 +    UPInt length = GetLength();
  1.1116 +    if ((start >= length) || (start >= end))
  1.1117 +        return String();   
  1.1118 +
  1.1119 +    DataDesc* pdata = GetData();
  1.1120 +    
  1.1121 +    // If size matches, we know the exact index range.
  1.1122 +    if (pdata->LengthIsSize())
  1.1123 +        return String(pdata->Data + start, end - start);
  1.1124 +    
  1.1125 +    // Get position of starting character.
  1.1126 +    SPInt byteStart = UTF8Util::GetByteIndex(start, pdata->Data, pdata->GetSize());
  1.1127 +    SPInt byteSize  = UTF8Util::GetByteIndex(end - start, pdata->Data + byteStart, pdata->GetSize()-byteStart);
  1.1128 +    return String(pdata->Data + byteStart, (UPInt)byteSize);
  1.1129 +}
  1.1130 +
  1.1131 +void String::Clear()
  1.1132 +{   
  1.1133 +    NullData.AddRef();
  1.1134 +    GetData()->Release();
  1.1135 +    SetData(&NullData);
  1.1136 +}
  1.1137 +
  1.1138 +
  1.1139 +String   String::ToUpper() const 
  1.1140 +{       
  1.1141 +    UInt32      c;
  1.1142 +    const char* psource = GetData()->Data;
  1.1143 +    const char* pend = psource + GetData()->GetSize();
  1.1144 +    String      str;
  1.1145 +    SPInt       bufferOffset = 0;
  1.1146 +    char        buffer[512];
  1.1147 +    
  1.1148 +    while(psource < pend)
  1.1149 +    {
  1.1150 +        do {            
  1.1151 +            c = UTF8Util::DecodeNextChar_Advance0(&psource);
  1.1152 +            UTF8Util::EncodeChar(buffer, &bufferOffset, OVR_towupper(wchar_t(c)));
  1.1153 +        } while ((psource < pend) && (bufferOffset < SPInt(sizeof(buffer)-8)));
  1.1154 +
  1.1155 +        // Append string a piece at a time.
  1.1156 +        str.AppendString(buffer, bufferOffset);
  1.1157 +        bufferOffset = 0;
  1.1158 +    }
  1.1159 +
  1.1160 +    return str;
  1.1161 +}
  1.1162 +
  1.1163 +String   String::ToLower() const 
  1.1164 +{
  1.1165 +    UInt32      c;
  1.1166 +    const char* psource = GetData()->Data;
  1.1167 +    const char* pend = psource + GetData()->GetSize();
  1.1168 +    String      str;
  1.1169 +    SPInt       bufferOffset = 0;
  1.1170 +    char        buffer[512];
  1.1171 +
  1.1172 +    while(psource < pend)
  1.1173 +    {
  1.1174 +        do {
  1.1175 +            c = UTF8Util::DecodeNextChar_Advance0(&psource);
  1.1176 +            UTF8Util::EncodeChar(buffer, &bufferOffset, OVR_towlower(wchar_t(c)));
  1.1177 +        } while ((psource < pend) && (bufferOffset < SPInt(sizeof(buffer)-8)));
  1.1178 +
  1.1179 +        // Append string a piece at a time.
  1.1180 +        str.AppendString(buffer, bufferOffset);
  1.1181 +        bufferOffset = 0;
  1.1182 +    }
  1.1183 +
  1.1184 +    return str;
  1.1185 +}
  1.1186 +
  1.1187 +
  1.1188 +
  1.1189 +String& String::Insert(const char* substr, UPInt posAt, SPInt strSize)
  1.1190 +{
  1.1191 +    DataDesc* poldData   = GetData();
  1.1192 +    UPInt     oldSize    = poldData->GetSize();
  1.1193 +    UPInt     insertSize = (strSize < 0) ? OVR_strlen(substr) : (UPInt)strSize;    
  1.1194 +    UPInt     byteIndex  =  (poldData->LengthIsSize()) ?
  1.1195 +                            posAt : (UPInt)UTF8Util::GetByteIndex(posAt, poldData->Data, oldSize);
  1.1196 +
  1.1197 +    OVR_ASSERT(byteIndex <= oldSize);
  1.1198 +    
  1.1199 +    DataDesc* pnewData = AllocDataCopy2(oldSize + insertSize, 0,
  1.1200 +                                        poldData->Data, byteIndex, substr, insertSize);
  1.1201 +    memcpy(pnewData->Data + byteIndex + insertSize,
  1.1202 +           poldData->Data + byteIndex, oldSize - byteIndex);
  1.1203 +    SetData(pnewData);
  1.1204 +    poldData->Release();
  1.1205 +    return *this;
  1.1206 +}
  1.1207 +
  1.1208 +/*
  1.1209 +String& String::Insert(const UInt32* substr, UPInt posAt, SPInt len)
  1.1210 +{
  1.1211 +    for (SPInt i = 0; i < len; ++i)
  1.1212 +    {
  1.1213 +        UPInt charw = InsertCharAt(substr[i], posAt);
  1.1214 +        posAt += charw;
  1.1215 +    }
  1.1216 +    return *this;
  1.1217 +}
  1.1218 +*/
  1.1219 +
  1.1220 +UPInt String::InsertCharAt(UInt32 c, UPInt posAt)
  1.1221 +{
  1.1222 +    char    buf[8];
  1.1223 +    SPInt   index = 0;
  1.1224 +    UTF8Util::EncodeChar(buf, &index, c);
  1.1225 +    OVR_ASSERT(index >= 0);
  1.1226 +    buf[(UPInt)index] = 0;
  1.1227 +
  1.1228 +    Insert(buf, posAt, index);
  1.1229 +    return (UPInt)index;
  1.1230 +}
  1.1231 +
  1.1232 +
  1.1233 +int String::CompareNoCase(const char* a, const char* b)
  1.1234 +{
  1.1235 +    return OVR_stricmp(a, b);
  1.1236 +}
  1.1237 +
  1.1238 +int String::CompareNoCase(const char* a, const char* b, SPInt len)
  1.1239 +{
  1.1240 +    if (len)
  1.1241 +    {
  1.1242 +        SPInt f,l;
  1.1243 +        SPInt slen = len;
  1.1244 +        const char *s = b;
  1.1245 +        do {
  1.1246 +            f = (SPInt)OVR_tolower((int)(*(a++)));
  1.1247 +            l = (SPInt)OVR_tolower((int)(*(b++)));
  1.1248 +        } while (--len && f && (f == l) && *b != 0);
  1.1249 +
  1.1250 +        if (f == l && (len != 0 || *b != 0))
  1.1251 +        {
  1.1252 +            f = (SPInt)slen;
  1.1253 +            l = (SPInt)OVR_strlen(s);
  1.1254 +            return int(f - l);
  1.1255 +        }
  1.1256 +
  1.1257 +        return int(f - l);
  1.1258 +    }
  1.1259 +    else
  1.1260 +        return (0-(int)OVR_strlen(b));
  1.1261 +}
  1.1262 +
  1.1263 +// ***** Implement hash static functions
  1.1264 +
  1.1265 +// Hash function
  1.1266 +UPInt String::BernsteinHashFunction(const void* pdataIn, UPInt size, UPInt seed)
  1.1267 +{
  1.1268 +    const UByte*    pdata   = (const UByte*) pdataIn;
  1.1269 +    UPInt           h       = seed;
  1.1270 +    while (size > 0)
  1.1271 +    {
  1.1272 +        size--;
  1.1273 +        h = ((h << 5) + h) ^ (unsigned) pdata[size];
  1.1274 +    }
  1.1275 +
  1.1276 +    return h;
  1.1277 +}
  1.1278 +
  1.1279 +// Hash function, case-insensitive
  1.1280 +UPInt String::BernsteinHashFunctionCIS(const void* pdataIn, UPInt size, UPInt seed)
  1.1281 +{
  1.1282 +    const UByte*    pdata = (const UByte*) pdataIn;
  1.1283 +    UPInt           h = seed;
  1.1284 +    while (size > 0)
  1.1285 +    {
  1.1286 +        size--;
  1.1287 +        h = ((h << 5) + h) ^ OVR_tolower(pdata[size]);
  1.1288 +    }
  1.1289 +
  1.1290 +    // Alternative: "sdbm" hash function, suggested at same web page above.
  1.1291 +    // h = 0;
  1.1292 +    // for bytes { h = (h << 16) + (h << 6) - hash + *p; }
  1.1293 +    return h;
  1.1294 +}
  1.1295 +
  1.1296 +
  1.1297 +
  1.1298 +// ***** String Buffer used for Building Strings
  1.1299 +
  1.1300 +
  1.1301 +#define OVR_SBUFF_DEFAULT_GROW_SIZE 512
  1.1302 +// Constructors / Destructor.
  1.1303 +StringBuffer::StringBuffer()
  1.1304 +    : pData(NULL), Size(0), BufferSize(0), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false)
  1.1305 +{
  1.1306 +}
  1.1307 +
  1.1308 +StringBuffer::StringBuffer(UPInt growSize)
  1.1309 +    : pData(NULL), Size(0), BufferSize(0), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false)
  1.1310 +{
  1.1311 +    SetGrowSize(growSize);
  1.1312 +}
  1.1313 +
  1.1314 +StringBuffer::StringBuffer(const char* data)
  1.1315 +    : pData(NULL), Size(0), BufferSize(0), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false)
  1.1316 +{
  1.1317 +    *this = data;
  1.1318 +}
  1.1319 +
  1.1320 +StringBuffer::StringBuffer(const char* data, UPInt dataSize)
  1.1321 +    : pData(NULL), Size(0), BufferSize(0), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false)
  1.1322 +{
  1.1323 +    AppendString(data, dataSize);
  1.1324 +}
  1.1325 +
  1.1326 +StringBuffer::StringBuffer(const String& src)
  1.1327 +    : pData(NULL), Size(0), BufferSize(0), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false)
  1.1328 +{
  1.1329 +    AppendString(src.ToCStr(), src.GetSize());
  1.1330 +}
  1.1331 +
  1.1332 +StringBuffer::StringBuffer(const StringBuffer& src)
  1.1333 +    : pData(NULL), Size(0), BufferSize(src.GetGrowSize()), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false)
  1.1334 +{
  1.1335 +    AppendString(src.ToCStr(), src.GetSize());
  1.1336 +    LengthIsSize = src.LengthIsSize;
  1.1337 +}
  1.1338 +
  1.1339 +StringBuffer::StringBuffer(const wchar_t* data)
  1.1340 +    : pData(NULL), Size(0), BufferSize(0), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false)
  1.1341 +{
  1.1342 +    *this = data;
  1.1343 +}
  1.1344 +
  1.1345 +StringBuffer::~StringBuffer()
  1.1346 +{
  1.1347 +    if (pData)
  1.1348 +        OVR_FREE(pData);
  1.1349 +}
  1.1350 +void StringBuffer::SetGrowSize(UPInt growSize) 
  1.1351 +{ 
  1.1352 +    if (growSize <= 16)
  1.1353 +        GrowSize = 16;
  1.1354 +    else
  1.1355 +    {
  1.1356 +        UByte bits = Alg::UpperBit(UInt32(growSize-1));
  1.1357 +        UPInt size = 1<<bits;
  1.1358 +        GrowSize = size == growSize ? growSize : size;
  1.1359 +    }
  1.1360 +}
  1.1361 +
  1.1362 +UPInt StringBuffer::GetLength() const
  1.1363 +{
  1.1364 +    UPInt length, size = GetSize();
  1.1365 +    if (LengthIsSize)
  1.1366 +        return size;
  1.1367 +
  1.1368 +    length = (UPInt)UTF8Util::GetLength(pData, (UPInt)GetSize());
  1.1369 +
  1.1370 +    if (length == GetSize())
  1.1371 +        LengthIsSize = true;
  1.1372 +    return length;
  1.1373 +}
  1.1374 +
  1.1375 +void    StringBuffer::Reserve(UPInt _size)
  1.1376 +{
  1.1377 +    if (_size >= BufferSize) // >= because of trailing zero! (!AB)
  1.1378 +    {
  1.1379 +        BufferSize = (_size + 1 + GrowSize - 1)& ~(GrowSize-1);
  1.1380 +        if (!pData)
  1.1381 +            pData = (char*)OVR_ALLOC(BufferSize);
  1.1382 +        else 
  1.1383 +            pData = (char*)OVR_REALLOC(pData, BufferSize);
  1.1384 +    }
  1.1385 +}
  1.1386 +void    StringBuffer::Resize(UPInt _size)
  1.1387 +{
  1.1388 +    Reserve(_size);
  1.1389 +    LengthIsSize = false;
  1.1390 +    Size = _size;
  1.1391 +    if (pData)
  1.1392 +        pData[Size] = 0;
  1.1393 +}
  1.1394 +
  1.1395 +void StringBuffer::Clear()
  1.1396 +{
  1.1397 +    Resize(0);
  1.1398 +    /*
  1.1399 +    if (pData != pEmptyNullData)
  1.1400 +    {
  1.1401 +        OVR_FREE(pHeap, pData);
  1.1402 +        pData = pEmptyNullData;
  1.1403 +        Size = BufferSize = 0;
  1.1404 +        LengthIsSize = false;
  1.1405 +    }
  1.1406 +    */
  1.1407 +}
  1.1408 +// Appends a character
  1.1409 +void     StringBuffer::AppendChar(UInt32 ch)
  1.1410 +{
  1.1411 +    char    buff[8];
  1.1412 +    UPInt   origSize = GetSize();
  1.1413 +
  1.1414 +    // Converts ch into UTF8 string and fills it into buff. Also increments index according to the number of bytes
  1.1415 +    // in the UTF8 string.
  1.1416 +    SPInt   srcSize = 0;
  1.1417 +    UTF8Util::EncodeChar(buff, &srcSize, ch);
  1.1418 +    OVR_ASSERT(srcSize >= 0);
  1.1419 +    
  1.1420 +    UPInt size = origSize + srcSize;
  1.1421 +    Resize(size);
  1.1422 +    memcpy(pData + origSize, buff, srcSize);
  1.1423 +}
  1.1424 +
  1.1425 +// Append a string
  1.1426 +void     StringBuffer::AppendString(const wchar_t* pstr, SPInt len)
  1.1427 +{
  1.1428 +    if (!pstr)
  1.1429 +        return;
  1.1430 +
  1.1431 +    SPInt   srcSize     = UTF8Util::GetEncodeStringSize(pstr, len);
  1.1432 +    UPInt   origSize    = GetSize();
  1.1433 +    UPInt   size        = srcSize + origSize;
  1.1434 +
  1.1435 +    Resize(size);
  1.1436 +    UTF8Util::EncodeString(pData + origSize,  pstr, len);
  1.1437 +}
  1.1438 +
  1.1439 +void      StringBuffer::AppendString(const char* putf8str, SPInt utf8StrSz)
  1.1440 +{
  1.1441 +    if (!putf8str || !utf8StrSz)
  1.1442 +        return;
  1.1443 +    if (utf8StrSz == -1)
  1.1444 +        utf8StrSz = (SPInt)OVR_strlen(putf8str);
  1.1445 +
  1.1446 +    UPInt   origSize    = GetSize();
  1.1447 +    UPInt   size        = utf8StrSz + origSize;
  1.1448 +
  1.1449 +    Resize(size);
  1.1450 +    memcpy(pData + origSize, putf8str, utf8StrSz);
  1.1451 +}
  1.1452 +
  1.1453 +
  1.1454 +void      StringBuffer::operator = (const char* pstr)
  1.1455 +{
  1.1456 +    pstr = pstr ? pstr : "";
  1.1457 +    UPInt size = OVR_strlen(pstr);
  1.1458 +    Resize(size);
  1.1459 +    memcpy(pData, pstr, size);
  1.1460 +}
  1.1461 +
  1.1462 +void      StringBuffer::operator = (const wchar_t* pstr)
  1.1463 +{
  1.1464 +    pstr = pstr ? pstr : L"";
  1.1465 +    UPInt size = (UPInt)UTF8Util::GetEncodeStringSize(pstr);
  1.1466 +    Resize(size);
  1.1467 +    UTF8Util::EncodeString(pData, pstr);
  1.1468 +}
  1.1469 +
  1.1470 +void      StringBuffer::operator = (const String& src)
  1.1471 +{
  1.1472 +    Resize(src.GetSize());
  1.1473 +    memcpy(pData, src.ToCStr(), src.GetSize());
  1.1474 +}
  1.1475 +
  1.1476 +
  1.1477 +// Inserts substr at posAt
  1.1478 +void      StringBuffer::Insert(const char* substr, UPInt posAt, SPInt len)
  1.1479 +{
  1.1480 +    UPInt     oldSize    = Size;
  1.1481 +    UPInt     insertSize = (len < 0) ? OVR_strlen(substr) : (UPInt)len;    
  1.1482 +    UPInt     byteIndex  = LengthIsSize ? posAt : 
  1.1483 +                           (UPInt)UTF8Util::GetByteIndex(posAt, pData, (SPInt)Size);
  1.1484 +
  1.1485 +    OVR_ASSERT(byteIndex <= oldSize);
  1.1486 +    Reserve(oldSize + insertSize);
  1.1487 +
  1.1488 +    memmove(pData + byteIndex + insertSize, pData + byteIndex, oldSize - byteIndex + 1);
  1.1489 +    memcpy (pData + byteIndex, substr, insertSize);
  1.1490 +    LengthIsSize = false;
  1.1491 +    Size = oldSize + insertSize;
  1.1492 +    pData[Size] = 0;
  1.1493 +}
  1.1494 +
  1.1495 +// Inserts character at posAt
  1.1496 +UPInt     StringBuffer::InsertCharAt(UInt32 c, UPInt posAt)
  1.1497 +{
  1.1498 +    char    buf[8];
  1.1499 +    SPInt   len = 0;
  1.1500 +    UTF8Util::EncodeChar(buf, &len, c);
  1.1501 +    OVR_ASSERT(len >= 0);
  1.1502 +    buf[(UPInt)len] = 0;
  1.1503 +
  1.1504 +    Insert(buf, posAt, len);
  1.1505 +    return (UPInt)len;
  1.1506 +}
  1.1507 +
  1.1508 +} // OVR