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