ovr_sdk
diff LibOVR/Src/Kernel/OVR_String.cpp @ 0:1b39a1b46319
initial 0.4.4
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Wed, 14 Jan 2015 06:51:16 +0200 |
parents | |
children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/LibOVR/Src/Kernel/OVR_String.cpp Wed Jan 14 06:51:16 2015 +0200 1.3 @@ -0,0 +1,779 @@ 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 2014 Oculus VR, LLC All Rights reserved. 1.13 + 1.14 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 1.15 +you may not use the Oculus VR Rift SDK except in compliance with the License, 1.16 +which is provided at the time of installation or download, or which 1.17 +otherwise accompanies this software in either electronic or hard copy form. 1.18 + 1.19 +You may obtain a copy of the License at 1.20 + 1.21 +http://www.oculusvr.com/licenses/LICENSE-3.2 1.22 + 1.23 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 1.24 +distributed under the License is distributed on an "AS IS" BASIS, 1.25 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1.26 +See the License for the specific language governing permissions and 1.27 +limitations under the License. 1.28 + 1.29 +************************************************************************************/ 1.30 + 1.31 +#include "OVR_String.h" 1.32 + 1.33 +#include <stdlib.h> 1.34 +#include <ctype.h> 1.35 + 1.36 +#ifdef OVR_OS_QNX 1.37 +# include <strings.h> 1.38 +#endif 1.39 + 1.40 +namespace OVR { 1.41 + 1.42 +#define String_LengthIsSize (size_t(1) << String::Flag_LengthIsSizeShift) 1.43 + 1.44 +String::DataDesc String::NullData = {String_LengthIsSize, 1, {0} }; 1.45 + 1.46 + 1.47 +String::String() 1.48 +{ 1.49 + pData = &NullData; 1.50 + pData->AddRef(); 1.51 +}; 1.52 + 1.53 +String::String(const char* pdata) 1.54 +{ 1.55 + // Obtain length in bytes; it doesn't matter if _data is UTF8. 1.56 + size_t size = pdata ? OVR_strlen(pdata) : 0; 1.57 + pData = AllocDataCopy1(size, 0, pdata, size); 1.58 +}; 1.59 + 1.60 +String::String(const char* pdata1, const char* pdata2, const char* pdata3) 1.61 +{ 1.62 + // Obtain length in bytes; it doesn't matter if _data is UTF8. 1.63 + size_t size1 = pdata1 ? OVR_strlen(pdata1) : 0; 1.64 + size_t size2 = pdata2 ? OVR_strlen(pdata2) : 0; 1.65 + size_t size3 = pdata3 ? OVR_strlen(pdata3) : 0; 1.66 + 1.67 + DataDesc *pdataDesc = AllocDataCopy2(size1 + size2 + size3, 0, 1.68 + pdata1, size1, pdata2, size2); 1.69 + memcpy(pdataDesc->Data + size1 + size2, pdata3, size3); 1.70 + pData = pdataDesc; 1.71 +} 1.72 + 1.73 +String::String(const char* pdata, size_t size) 1.74 +{ 1.75 + OVR_ASSERT((size == 0) || (pdata != 0)); 1.76 + pData = AllocDataCopy1(size, 0, pdata, size); 1.77 +}; 1.78 + 1.79 + 1.80 +String::String(const InitStruct& src, size_t size) 1.81 +{ 1.82 + pData = AllocData(size, 0); 1.83 + src.InitString(GetData()->Data, size); 1.84 +} 1.85 + 1.86 +String::String(const String& src) 1.87 +{ 1.88 + pData = src.GetData(); 1.89 + pData->AddRef(); 1.90 +} 1.91 + 1.92 +String::String(const StringBuffer& src) 1.93 +{ 1.94 + pData = AllocDataCopy1(src.GetSize(), 0, src.ToCStr(), src.GetSize()); 1.95 +} 1.96 + 1.97 +String::String(const wchar_t* data) 1.98 +{ 1.99 + pData = &NullData; 1.100 + pData->AddRef(); 1.101 + // Simplified logic for wchar_t constructor. 1.102 + if (data) 1.103 + *this = data; 1.104 +} 1.105 + 1.106 + 1.107 +String::DataDesc* String::AllocData(size_t size, size_t lengthIsSize) 1.108 +{ 1.109 + String::DataDesc* pdesc; 1.110 + 1.111 + if (size == 0) 1.112 + { 1.113 + pdesc = &NullData; 1.114 + pdesc->AddRef(); 1.115 + return pdesc; 1.116 + } 1.117 + 1.118 + pdesc = (DataDesc*)OVR_ALLOC(sizeof(DataDesc)+ size); 1.119 + pdesc->Data[size] = 0; 1.120 + pdesc->RefCount = 1; 1.121 + pdesc->Size = size | lengthIsSize; 1.122 + return pdesc; 1.123 +} 1.124 + 1.125 + 1.126 +String::DataDesc* String::AllocDataCopy1(size_t size, size_t lengthIsSize, 1.127 + const char* pdata, size_t copySize) 1.128 +{ 1.129 + String::DataDesc* pdesc = AllocData(size, lengthIsSize); 1.130 + memcpy(pdesc->Data, pdata, copySize); 1.131 + return pdesc; 1.132 +} 1.133 + 1.134 +String::DataDesc* String::AllocDataCopy2(size_t size, size_t lengthIsSize, 1.135 + const char* pdata1, size_t copySize1, 1.136 + const char* pdata2, size_t copySize2) 1.137 +{ 1.138 + String::DataDesc* pdesc = AllocData(size, lengthIsSize); 1.139 + memcpy(pdesc->Data, pdata1, copySize1); 1.140 + memcpy(pdesc->Data + copySize1, pdata2, copySize2); 1.141 + return pdesc; 1.142 +} 1.143 + 1.144 + 1.145 +size_t String::GetLength() const 1.146 +{ 1.147 + // Optimize length accesses for non-UTF8 character strings. 1.148 + DataDesc* pdata = GetData(); 1.149 + size_t length, size = pdata->GetSize(); 1.150 + 1.151 + if (pdata->LengthIsSize()) 1.152 + return size; 1.153 + 1.154 + length = (size_t)UTF8Util::GetLength(pdata->Data, (size_t)size); 1.155 + 1.156 + if (length == size) 1.157 + pdata->Size |= String_LengthIsSize; 1.158 + 1.159 + return length; 1.160 +} 1.161 + 1.162 + 1.163 +//static uint32_t String_CharSearch(const char* buf, ) 1.164 + 1.165 + 1.166 +uint32_t String::GetCharAt(size_t index) const 1.167 +{ 1.168 + intptr_t i = (intptr_t) index; 1.169 + DataDesc* pdata = GetData(); 1.170 + const char* buf = pdata->Data; 1.171 + uint32_t c; 1.172 + 1.173 + if (pdata->LengthIsSize()) 1.174 + { 1.175 + OVR_ASSERT(index < pdata->GetSize()); 1.176 + buf += i; 1.177 + return UTF8Util::DecodeNextChar_Advance0(&buf); 1.178 + } 1.179 + 1.180 + c = UTF8Util::GetCharAt(index, buf, pdata->GetSize()); 1.181 + return c; 1.182 +} 1.183 + 1.184 +uint32_t String::GetFirstCharAt(size_t index, const char** offset) const 1.185 +{ 1.186 + DataDesc* pdata = GetData(); 1.187 + intptr_t i = (intptr_t) index; 1.188 + const char* buf = pdata->Data; 1.189 + const char* end = buf + pdata->GetSize(); 1.190 + uint32_t c; 1.191 + 1.192 + do 1.193 + { 1.194 + c = UTF8Util::DecodeNextChar_Advance0(&buf); 1.195 + i--; 1.196 + 1.197 + if (buf >= end) 1.198 + { 1.199 + // We've hit the end of the string; don't go further. 1.200 + OVR_ASSERT(i == 0); 1.201 + return c; 1.202 + } 1.203 + } while (i >= 0); 1.204 + 1.205 + *offset = buf; 1.206 + 1.207 + return c; 1.208 +} 1.209 + 1.210 +uint32_t String::GetNextChar(const char** offset) const 1.211 +{ 1.212 + return UTF8Util::DecodeNextChar(offset); 1.213 +} 1.214 + 1.215 + 1.216 + 1.217 +void String::AppendChar(uint32_t ch) 1.218 +{ 1.219 + DataDesc* pdata = GetData(); 1.220 + size_t size = pdata->GetSize(); 1.221 + char buff[8]; 1.222 + intptr_t encodeSize = 0; 1.223 + 1.224 + // Converts ch into UTF8 string and fills it into buff. 1.225 + UTF8Util::EncodeChar(buff, &encodeSize, ch); 1.226 + OVR_ASSERT(encodeSize >= 0); 1.227 + 1.228 + SetData(AllocDataCopy2(size + (size_t)encodeSize, 0, 1.229 + pdata->Data, size, buff, (size_t)encodeSize)); 1.230 + pdata->Release(); 1.231 +} 1.232 + 1.233 + 1.234 +void String::AppendString(const wchar_t* pstr, intptr_t len) 1.235 +{ 1.236 + if (!pstr) 1.237 + return; 1.238 + 1.239 + DataDesc* pdata = GetData(); 1.240 + size_t oldSize = pdata->GetSize(); 1.241 + size_t encodeSize = (size_t)UTF8Util::GetEncodeStringSize(pstr, len); 1.242 + 1.243 + DataDesc* pnewData = AllocDataCopy1(oldSize + (size_t)encodeSize, 0, 1.244 + pdata->Data, oldSize); 1.245 + UTF8Util::EncodeString(pnewData->Data + oldSize, pstr, len); 1.246 + 1.247 + SetData(pnewData); 1.248 + pdata->Release(); 1.249 +} 1.250 + 1.251 + 1.252 +void String::AppendString(const char* putf8str, intptr_t utf8StrSz) 1.253 +{ 1.254 + if (!putf8str || !utf8StrSz) 1.255 + return; 1.256 + if (utf8StrSz == -1) 1.257 + utf8StrSz = (intptr_t)OVR_strlen(putf8str); 1.258 + 1.259 + DataDesc* pdata = GetData(); 1.260 + size_t oldSize = pdata->GetSize(); 1.261 + 1.262 + SetData(AllocDataCopy2(oldSize + (size_t)utf8StrSz, 0, 1.263 + pdata->Data, oldSize, putf8str, (size_t)utf8StrSz)); 1.264 + pdata->Release(); 1.265 +} 1.266 + 1.267 +void String::AssignString(const InitStruct& src, size_t size) 1.268 +{ 1.269 + DataDesc* poldData = GetData(); 1.270 + DataDesc* pnewData = AllocData(size, 0); 1.271 + src.InitString(pnewData->Data, size); 1.272 + SetData(pnewData); 1.273 + poldData->Release(); 1.274 +} 1.275 + 1.276 +void String::AssignString(const char* putf8str, size_t size) 1.277 +{ 1.278 + DataDesc* poldData = GetData(); 1.279 + SetData(AllocDataCopy1(size, 0, putf8str, size)); 1.280 + poldData->Release(); 1.281 +} 1.282 + 1.283 +void String::operator = (const char* pstr) 1.284 +{ 1.285 + AssignString(pstr, pstr ? OVR_strlen(pstr) : 0); 1.286 +} 1.287 + 1.288 +void String::operator = (const wchar_t* pwstr) 1.289 +{ 1.290 + pwstr = pwstr ? pwstr : L""; 1.291 + 1.292 + DataDesc* poldData = GetData(); 1.293 + size_t size = (size_t)UTF8Util::GetEncodeStringSize(pwstr); 1.294 + 1.295 + DataDesc* pnewData = AllocData(size, 0); 1.296 + UTF8Util::EncodeString(pnewData->Data, pwstr); 1.297 + SetData(pnewData); 1.298 + poldData->Release(); 1.299 +} 1.300 + 1.301 + 1.302 +void String::operator = (const String& src) 1.303 +{ 1.304 + DataDesc* psdata = src.GetData(); 1.305 + DataDesc* pdata = GetData(); 1.306 + 1.307 + SetData(psdata); 1.308 + psdata->AddRef(); 1.309 + pdata->Release(); 1.310 +} 1.311 + 1.312 + 1.313 +void String::operator = (const StringBuffer& src) 1.314 +{ 1.315 + DataDesc* polddata = GetData(); 1.316 + SetData(AllocDataCopy1(src.GetSize(), 0, src.ToCStr(), src.GetSize())); 1.317 + polddata->Release(); 1.318 +} 1.319 + 1.320 +void String::operator += (const String& src) 1.321 +{ 1.322 + DataDesc *pourData = GetData(), 1.323 + *psrcData = src.GetData(); 1.324 + size_t ourSize = pourData->GetSize(), 1.325 + srcSize = psrcData->GetSize(); 1.326 + size_t lflag = pourData->GetLengthFlag() & psrcData->GetLengthFlag(); 1.327 + 1.328 + SetData(AllocDataCopy2(ourSize + srcSize, lflag, 1.329 + pourData->Data, ourSize, psrcData->Data, srcSize)); 1.330 + pourData->Release(); 1.331 +} 1.332 + 1.333 + 1.334 +String String::operator + (const char* str) const 1.335 +{ 1.336 + String tmp1(*this); 1.337 + tmp1 += (str ? str : ""); 1.338 + return tmp1; 1.339 +} 1.340 + 1.341 +String String::operator + (const String& src) const 1.342 +{ 1.343 + String tmp1(*this); 1.344 + tmp1 += src; 1.345 + return tmp1; 1.346 +} 1.347 + 1.348 +void String::Remove(size_t posAt, intptr_t removeLength) 1.349 +{ 1.350 + DataDesc* pdata = GetData(); 1.351 + size_t oldSize = pdata->GetSize(); 1.352 + // Length indicates the number of characters to remove. 1.353 + size_t length = GetLength(); 1.354 + 1.355 + // If index is past the string, nothing to remove. 1.356 + if (posAt >= length) 1.357 + return; 1.358 + // Otherwise, cap removeLength to the length of the string. 1.359 + if ((posAt + removeLength) > length) 1.360 + removeLength = length - posAt; 1.361 + 1.362 + // Get the byte position of the UTF8 char at position posAt. 1.363 + intptr_t bytePos = UTF8Util::GetByteIndex(posAt, pdata->Data, oldSize); 1.364 + intptr_t removeSize = UTF8Util::GetByteIndex(removeLength, pdata->Data + bytePos, oldSize-bytePos); 1.365 + 1.366 + SetData(AllocDataCopy2(oldSize - removeSize, pdata->GetLengthFlag(), 1.367 + pdata->Data, bytePos, 1.368 + pData->Data + bytePos + removeSize, (oldSize - bytePos - removeSize))); 1.369 + pdata->Release(); 1.370 +} 1.371 + 1.372 + 1.373 +String String::Substring(size_t start, size_t end) const 1.374 +{ 1.375 + size_t length = GetLength(); 1.376 + if ((start >= length) || (start >= end)) 1.377 + return String(); 1.378 + 1.379 + DataDesc* pdata = GetData(); 1.380 + 1.381 + // If size matches, we know the exact index range. 1.382 + if (pdata->LengthIsSize()) 1.383 + return String(pdata->Data + start, end - start); 1.384 + 1.385 + // Get position of starting character. 1.386 + intptr_t byteStart = UTF8Util::GetByteIndex(start, pdata->Data, pdata->GetSize()); 1.387 + intptr_t byteSize = UTF8Util::GetByteIndex(end - start, pdata->Data + byteStart, pdata->GetSize()-byteStart); 1.388 + return String(pdata->Data + byteStart, (size_t)byteSize); 1.389 +} 1.390 + 1.391 +void String::Clear() 1.392 +{ 1.393 + NullData.AddRef(); 1.394 + GetData()->Release(); 1.395 + SetData(&NullData); 1.396 +} 1.397 + 1.398 + 1.399 +String String::ToUpper() const 1.400 +{ 1.401 + uint32_t c; 1.402 + const char* psource = GetData()->Data; 1.403 + const char* pend = psource + GetData()->GetSize(); 1.404 + String str; 1.405 + intptr_t bufferOffset = 0; 1.406 + char buffer[512]; 1.407 + 1.408 + while(psource < pend) 1.409 + { 1.410 + do { 1.411 + c = UTF8Util::DecodeNextChar_Advance0(&psource); 1.412 + UTF8Util::EncodeChar(buffer, &bufferOffset, OVR_towupper(wchar_t(c))); 1.413 + } while ((psource < pend) && (bufferOffset < intptr_t(sizeof(buffer)-8))); 1.414 + 1.415 + // Append string a piece at a time. 1.416 + str.AppendString(buffer, bufferOffset); 1.417 + bufferOffset = 0; 1.418 + } 1.419 + 1.420 + return str; 1.421 +} 1.422 + 1.423 +String String::ToLower() const 1.424 +{ 1.425 + uint32_t c; 1.426 + const char* psource = GetData()->Data; 1.427 + const char* pend = psource + GetData()->GetSize(); 1.428 + String str; 1.429 + intptr_t bufferOffset = 0; 1.430 + char buffer[512]; 1.431 + 1.432 + while(psource < pend) 1.433 + { 1.434 + do { 1.435 + c = UTF8Util::DecodeNextChar_Advance0(&psource); 1.436 + UTF8Util::EncodeChar(buffer, &bufferOffset, OVR_towlower(wchar_t(c))); 1.437 + } while ((psource < pend) && (bufferOffset < intptr_t(sizeof(buffer)-8))); 1.438 + 1.439 + // Append string a piece at a time. 1.440 + str.AppendString(buffer, bufferOffset); 1.441 + bufferOffset = 0; 1.442 + } 1.443 + 1.444 + return str; 1.445 +} 1.446 + 1.447 + 1.448 + 1.449 +String& String::Insert(const char* substr, size_t posAt, intptr_t strSize) 1.450 +{ 1.451 + DataDesc* poldData = GetData(); 1.452 + size_t oldSize = poldData->GetSize(); 1.453 + size_t insertSize = (strSize < 0) ? OVR_strlen(substr) : (size_t)strSize; 1.454 + size_t byteIndex = (poldData->LengthIsSize()) ? 1.455 + posAt : (size_t)UTF8Util::GetByteIndex(posAt, poldData->Data, oldSize); 1.456 + 1.457 + OVR_ASSERT(byteIndex <= oldSize); 1.458 + 1.459 + DataDesc* pnewData = AllocDataCopy2(oldSize + insertSize, 0, 1.460 + poldData->Data, byteIndex, substr, insertSize); 1.461 + memcpy(pnewData->Data + byteIndex + insertSize, 1.462 + poldData->Data + byteIndex, oldSize - byteIndex); 1.463 + SetData(pnewData); 1.464 + poldData->Release(); 1.465 + return *this; 1.466 +} 1.467 + 1.468 +/* 1.469 +String& String::Insert(const uint32_t* substr, size_t posAt, intptr_t len) 1.470 +{ 1.471 + for (intptr_t i = 0; i < len; ++i) 1.472 + { 1.473 + size_t charw = InsertCharAt(substr[i], posAt); 1.474 + posAt += charw; 1.475 + } 1.476 + return *this; 1.477 +} 1.478 +*/ 1.479 + 1.480 +size_t String::InsertCharAt(uint32_t c, size_t posAt) 1.481 +{ 1.482 + char buf[8]; 1.483 + intptr_t index = 0; 1.484 + UTF8Util::EncodeChar(buf, &index, c); 1.485 + OVR_ASSERT(index >= 0); 1.486 + buf[(size_t)index] = 0; 1.487 + 1.488 + Insert(buf, posAt, index); 1.489 + return (size_t)index; 1.490 +} 1.491 + 1.492 + 1.493 +int String::CompareNoCase(const char* a, const char* b) 1.494 +{ 1.495 + return OVR_stricmp(a, b); 1.496 +} 1.497 + 1.498 +int String::CompareNoCase(const char* a, const char* b, intptr_t len) 1.499 +{ 1.500 + if (len) 1.501 + { 1.502 + intptr_t f,l; 1.503 + intptr_t slen = len; 1.504 + const char *s = b; 1.505 + do { 1.506 + f = (intptr_t)OVR_tolower((int)(*(a++))); 1.507 + l = (intptr_t)OVR_tolower((int)(*(b++))); 1.508 + } while (--len && f && (f == l) && *b != 0); 1.509 + 1.510 + if (f == l && (len != 0 || *b != 0)) 1.511 + { 1.512 + f = (intptr_t)slen; 1.513 + l = (intptr_t)OVR_strlen(s); 1.514 + return int(f - l); 1.515 + } 1.516 + 1.517 + return int(f - l); 1.518 + } 1.519 + else 1.520 + return (0-(int)OVR_strlen(b)); 1.521 +} 1.522 + 1.523 +// ***** Implement hash static functions 1.524 + 1.525 +// Hash function 1.526 +size_t String::BernsteinHashFunction(const void* pdataIn, size_t size, size_t seed) 1.527 +{ 1.528 + const uint8_t* pdata = (const uint8_t*) pdataIn; 1.529 + size_t h = seed; 1.530 + while (size > 0) 1.531 + { 1.532 + size--; 1.533 + h = ((h << 5) + h) ^ (unsigned) pdata[size]; 1.534 + } 1.535 + 1.536 + return h; 1.537 +} 1.538 + 1.539 +// Hash function, case-insensitive 1.540 +size_t String::BernsteinHashFunctionCIS(const void* pdataIn, size_t size, size_t seed) 1.541 +{ 1.542 + const uint8_t* pdata = (const uint8_t*) pdataIn; 1.543 + size_t h = seed; 1.544 + while (size > 0) 1.545 + { 1.546 + size--; 1.547 + h = ((h << 5) + h) ^ OVR_tolower(pdata[size]); 1.548 + } 1.549 + 1.550 + // Alternative: "sdbm" hash function, suggested at same web page above. 1.551 + // h = 0; 1.552 + // for bytes { h = (h << 16) + (h << 6) - hash + *p; } 1.553 + return h; 1.554 +} 1.555 + 1.556 + 1.557 + 1.558 +// ***** String Buffer used for Building Strings 1.559 + 1.560 + 1.561 +#define OVR_SBUFF_DEFAULT_GROW_SIZE 512 1.562 +// Constructors / Destructor. 1.563 +StringBuffer::StringBuffer() 1.564 + : pData(NULL), Size(0), BufferSize(0), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false) 1.565 +{ 1.566 +} 1.567 + 1.568 +StringBuffer::StringBuffer(size_t growSize) 1.569 + : pData(NULL), Size(0), BufferSize(0), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false) 1.570 +{ 1.571 + SetGrowSize(growSize); 1.572 +} 1.573 + 1.574 +StringBuffer::StringBuffer(const char* data) 1.575 + : pData(NULL), Size(0), BufferSize(0), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false) 1.576 +{ 1.577 + AppendString(data); 1.578 +} 1.579 + 1.580 +StringBuffer::StringBuffer(const char* data, size_t dataSize) 1.581 + : pData(NULL), Size(0), BufferSize(0), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false) 1.582 +{ 1.583 + AppendString(data, dataSize); 1.584 +} 1.585 + 1.586 +StringBuffer::StringBuffer(const String& src) 1.587 + : pData(NULL), Size(0), BufferSize(0), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false) 1.588 +{ 1.589 + AppendString(src.ToCStr(), src.GetSize()); 1.590 +} 1.591 + 1.592 +StringBuffer::StringBuffer(const StringBuffer& src) 1.593 + : pData(NULL), Size(0), BufferSize(0), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false) 1.594 +{ 1.595 + AppendString(src.ToCStr(), src.GetSize()); 1.596 +} 1.597 + 1.598 +StringBuffer::StringBuffer(const wchar_t* data) 1.599 + : pData(NULL), Size(0), BufferSize(0), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false) 1.600 +{ 1.601 + *this = data; 1.602 +} 1.603 + 1.604 +StringBuffer::~StringBuffer() 1.605 +{ 1.606 + if (pData) 1.607 + OVR_FREE(pData); 1.608 +} 1.609 +void StringBuffer::SetGrowSize(size_t growSize) 1.610 +{ 1.611 + if (growSize <= 16) 1.612 + GrowSize = 16; 1.613 + else 1.614 + { 1.615 + uint8_t bits = Alg::UpperBit(uint32_t(growSize-1)); 1.616 + size_t size = (size_t)1 << bits; 1.617 + GrowSize = size == growSize ? growSize : size; 1.618 + } 1.619 +} 1.620 + 1.621 +size_t StringBuffer::GetLength() const 1.622 +{ 1.623 + size_t length, size = GetSize(); 1.624 + if (LengthIsSize) 1.625 + return size; 1.626 + 1.627 + length = (size_t)UTF8Util::GetLength(pData, (size_t)GetSize()); 1.628 + 1.629 + if (length == GetSize()) 1.630 + LengthIsSize = true; 1.631 + return length; 1.632 +} 1.633 + 1.634 +void StringBuffer::Reserve(size_t _size) 1.635 +{ 1.636 + if (_size >= BufferSize) // >= because of trailing zero! (!AB) 1.637 + { 1.638 + BufferSize = (_size + 1 + GrowSize - 1)& ~(GrowSize-1); 1.639 + if (!pData) 1.640 + pData = (char*)OVR_ALLOC(BufferSize); 1.641 + else 1.642 + pData = (char*)OVR_REALLOC(pData, BufferSize); 1.643 + } 1.644 +} 1.645 +void StringBuffer::Resize(size_t _size) 1.646 +{ 1.647 + Reserve(_size); 1.648 + LengthIsSize = false; 1.649 + Size = _size; 1.650 + if (pData) 1.651 + pData[Size] = 0; 1.652 +} 1.653 + 1.654 +void StringBuffer::Clear() 1.655 +{ 1.656 + Resize(0); 1.657 + /* 1.658 + if (pData != pEmptyNullData) 1.659 + { 1.660 + OVR_FREE(pHeap, pData); 1.661 + pData = pEmptyNullData; 1.662 + Size = BufferSize = 0; 1.663 + LengthIsSize = false; 1.664 + } 1.665 + */ 1.666 +} 1.667 +// Appends a character 1.668 +void StringBuffer::AppendChar(uint32_t ch) 1.669 +{ 1.670 + char buff[8]; 1.671 + size_t origSize = GetSize(); 1.672 + 1.673 + // Converts ch into UTF8 string and fills it into buff. Also increments index according to the number of bytes 1.674 + // in the UTF8 string. 1.675 + intptr_t srcSize = 0; 1.676 + UTF8Util::EncodeChar(buff, &srcSize, ch); 1.677 + OVR_ASSERT(srcSize >= 0); 1.678 + 1.679 + size_t size = origSize + srcSize; 1.680 + Resize(size); 1.681 + OVR_ASSERT(pData != NULL); 1.682 + memcpy(pData + origSize, buff, srcSize); 1.683 +} 1.684 + 1.685 +// Append a string 1.686 +void StringBuffer::AppendString(const wchar_t* pstr, intptr_t len) 1.687 +{ 1.688 + if (!pstr || !len) 1.689 + return; 1.690 + 1.691 + intptr_t srcSize = UTF8Util::GetEncodeStringSize(pstr, len); 1.692 + size_t origSize = GetSize(); 1.693 + size_t size = srcSize + origSize; 1.694 + 1.695 + Resize(size); 1.696 + OVR_ASSERT(pData != NULL); 1.697 + UTF8Util::EncodeString(pData + origSize, pstr, len); 1.698 +} 1.699 + 1.700 +void StringBuffer::AppendString(const char* putf8str, intptr_t utf8StrSz) 1.701 +{ 1.702 + if (!putf8str || !utf8StrSz) 1.703 + return; 1.704 + if (utf8StrSz == -1) 1.705 + utf8StrSz = (intptr_t)OVR_strlen(putf8str); 1.706 + 1.707 + size_t origSize = GetSize(); 1.708 + size_t size = utf8StrSz + origSize; 1.709 + 1.710 + Resize(size); 1.711 + OVR_ASSERT(pData != NULL); 1.712 + memcpy(pData + origSize, putf8str, utf8StrSz); 1.713 +} 1.714 + 1.715 +// If pstr is NULL then the StringBuffer is cleared. 1.716 +void StringBuffer::operator = (const char* pstr) 1.717 +{ 1.718 + pstr = pstr ? pstr : ""; 1.719 + size_t size = OVR_strlen(pstr); 1.720 + Resize(size); 1.721 + OVR_ASSERT((pData != NULL) || (size == 0)); 1.722 + memcpy(pData, pstr, size); 1.723 +} 1.724 + 1.725 +// If pstr is NULL then the StringBuffer is cleared. 1.726 +void StringBuffer::operator = (const wchar_t* pstr) 1.727 +{ 1.728 + pstr = pstr ? pstr : L""; 1.729 + size_t size = (size_t)UTF8Util::GetEncodeStringSize(pstr); 1.730 + Resize(size); 1.731 + OVR_ASSERT((pData != NULL) || (size == 0)); 1.732 + UTF8Util::EncodeString(pData, pstr); 1.733 +} 1.734 + 1.735 +void StringBuffer::operator = (const String& src) 1.736 +{ 1.737 + const size_t size = src.GetSize(); 1.738 + Resize(size); 1.739 + OVR_ASSERT((pData != NULL) || (size == 0)); 1.740 + memcpy(pData, src.ToCStr(), size); 1.741 +} 1.742 + 1.743 +void StringBuffer::operator = (const StringBuffer& src) 1.744 +{ 1.745 + Clear(); 1.746 + AppendString(src.ToCStr(), src.GetSize()); 1.747 +} 1.748 + 1.749 + 1.750 +// Inserts substr at posAt 1.751 +void StringBuffer::Insert(const char* substr, size_t posAt, intptr_t len) 1.752 +{ 1.753 + size_t oldSize = Size; 1.754 + size_t insertSize = (len < 0) ? OVR_strlen(substr) : (size_t)len; 1.755 + size_t byteIndex = LengthIsSize ? posAt : 1.756 + (size_t)UTF8Util::GetByteIndex(posAt, pData, (intptr_t)Size); 1.757 + 1.758 + OVR_ASSERT(byteIndex <= oldSize); 1.759 + Reserve(oldSize + insertSize); 1.760 + 1.761 + OVR_ASSERT(pData != NULL); // pData is unilaterally written to below. 1.762 + memmove(pData + byteIndex + insertSize, pData + byteIndex, oldSize - byteIndex + 1); 1.763 + memcpy (pData + byteIndex, substr, insertSize); 1.764 + LengthIsSize = false; 1.765 + Size = oldSize + insertSize; 1.766 + pData[Size] = 0; 1.767 +} 1.768 + 1.769 +// Inserts character at posAt 1.770 +size_t StringBuffer::InsertCharAt(uint32_t c, size_t posAt) 1.771 +{ 1.772 + char buf[8]; 1.773 + intptr_t len = 0; 1.774 + UTF8Util::EncodeChar(buf, &len, c); 1.775 + OVR_ASSERT(len >= 0); 1.776 + buf[(size_t)len] = 0; 1.777 + 1.778 + Insert(buf, posAt, len); 1.779 + return (size_t)len; 1.780 +} 1.781 + 1.782 +} // OVR