ovr_sdk
diff LibOVR/Src/Kernel/OVR_String.h @ 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.h Wed Jan 14 06:51:16 2015 +0200 1.3 @@ -0,0 +1,658 @@ 1.4 +/************************************************************************************ 1.5 + 1.6 +PublicHeader: OVR_Kernel.h 1.7 +Filename : OVR_String.h 1.8 +Content : String UTF8 string implementation with copy-on-write semantics 1.9 + (thread-safe for assignment but not modification). 1.10 +Created : September 19, 2012 1.11 +Notes : 1.12 + 1.13 +Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved. 1.14 + 1.15 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 1.16 +you may not use the Oculus VR Rift SDK except in compliance with the License, 1.17 +which is provided at the time of installation or download, or which 1.18 +otherwise accompanies this software in either electronic or hard copy form. 1.19 + 1.20 +You may obtain a copy of the License at 1.21 + 1.22 +http://www.oculusvr.com/licenses/LICENSE-3.2 1.23 + 1.24 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 1.25 +distributed under the License is distributed on an "AS IS" BASIS, 1.26 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1.27 +See the License for the specific language governing permissions and 1.28 +limitations under the License. 1.29 + 1.30 +************************************************************************************/ 1.31 + 1.32 +#ifndef OVR_String_h 1.33 +#define OVR_String_h 1.34 + 1.35 +#include "OVR_Types.h" 1.36 +#include "OVR_Allocator.h" 1.37 +#include "OVR_UTF8Util.h" 1.38 +#include "OVR_Atomic.h" 1.39 +#include "OVR_Std.h" 1.40 +#include "OVR_Alg.h" 1.41 + 1.42 +namespace OVR { 1.43 + 1.44 +// ***** Classes 1.45 + 1.46 +class String; 1.47 +class StringBuffer; 1.48 + 1.49 + 1.50 +//----------------------------------------------------------------------------------- 1.51 +// ***** String Class 1.52 + 1.53 +// String is UTF8 based string class with copy-on-write implementation 1.54 +// for assignment. 1.55 + 1.56 +class String 1.57 +{ 1.58 +protected: 1.59 + 1.60 + enum FlagConstants 1.61 + { 1.62 + //Flag_GetLength = 0x7FFFFFFF, 1.63 + // This flag is set if GetLength() == GetSize() for a string. 1.64 + // Avoid extra scanning is Substring and indexing logic. 1.65 + Flag_LengthIsSizeShift = (sizeof(size_t)*8 - 1) 1.66 + }; 1.67 + 1.68 + 1.69 + // Internal structure to hold string data 1.70 + struct DataDesc 1.71 + { 1.72 + // Number of bytes. Will be the same as the number of chars if the characters 1.73 + // are ascii, may not be equal to number of chars in case string data is UTF8. 1.74 + size_t Size; 1.75 + volatile int32_t RefCount; 1.76 + char Data[1]; 1.77 + 1.78 + void AddRef() 1.79 + { 1.80 + AtomicOps<int32_t>::ExchangeAdd_NoSync(&RefCount, 1); 1.81 + } 1.82 + // Decrement ref count. This needs to be thread-safe, since 1.83 + // a different thread could have also decremented the ref count. 1.84 + // For example, if u start off with a ref count = 2. Now if u 1.85 + // decrement the ref count and check against 0 in different 1.86 + // statements, a different thread can also decrement the ref count 1.87 + // in between our decrement and checking against 0 and will find 1.88 + // the ref count = 0 and delete the object. This will lead to a crash 1.89 + // when context switches to our thread and we'll be trying to delete 1.90 + // an already deleted object. Hence decrementing the ref count and 1.91 + // checking against 0 needs to made an atomic operation. 1.92 + void Release() 1.93 + { 1.94 + if ((AtomicOps<int32_t>::ExchangeAdd_NoSync(&RefCount, -1) - 1) == 0) 1.95 + OVR_FREE(this); 1.96 + } 1.97 + 1.98 + static size_t GetLengthFlagBit() { return size_t(1) << Flag_LengthIsSizeShift; } 1.99 + size_t GetSize() const { return Size & ~GetLengthFlagBit() ; } 1.100 + size_t GetLengthFlag() const { return Size & GetLengthFlagBit(); } 1.101 + bool LengthIsSize() const { return GetLengthFlag() != 0; } 1.102 + }; 1.103 + 1.104 + // Heap type of the string is encoded in the lower bits. 1.105 + enum HeapType 1.106 + { 1.107 + HT_Global = 0, // Heap is global. 1.108 + HT_Local = 1, // SF::String_loc: Heap is determined based on string's address. 1.109 + HT_Dynamic = 2, // SF::String_temp: Heap is stored as a part of the class. 1.110 + HT_Mask = 3 1.111 + }; 1.112 + 1.113 + union { 1.114 + DataDesc* pData; 1.115 + size_t HeapTypeBits; 1.116 + }; 1.117 + typedef union { 1.118 + DataDesc* pData; 1.119 + size_t HeapTypeBits; 1.120 + } DataDescUnion; 1.121 + 1.122 + inline HeapType GetHeapType() const { return (HeapType) (HeapTypeBits & HT_Mask); } 1.123 + 1.124 + inline DataDesc* GetData() const 1.125 + { 1.126 + DataDescUnion u; 1.127 + u.pData = pData; 1.128 + u.HeapTypeBits = (u.HeapTypeBits & ~(size_t)HT_Mask); 1.129 + return u.pData; 1.130 + } 1.131 + 1.132 + inline void SetData(DataDesc* pdesc) 1.133 + { 1.134 + HeapType ht = GetHeapType(); 1.135 + pData = pdesc; 1.136 + OVR_ASSERT((HeapTypeBits & HT_Mask) == 0); 1.137 + HeapTypeBits |= ht; 1.138 + } 1.139 + 1.140 + 1.141 + DataDesc* AllocData(size_t size, size_t lengthIsSize); 1.142 + DataDesc* AllocDataCopy1(size_t size, size_t lengthIsSize, 1.143 + const char* pdata, size_t copySize); 1.144 + DataDesc* AllocDataCopy2(size_t size, size_t lengthIsSize, 1.145 + const char* pdata1, size_t copySize1, 1.146 + const char* pdata2, size_t copySize2); 1.147 + 1.148 + // Special constructor to avoid data initalization when used in derived class. 1.149 + struct NoConstructor { }; 1.150 + String(const NoConstructor&) { } 1.151 + 1.152 +public: 1.153 + 1.154 + // For initializing string with dynamic buffer 1.155 + struct InitStruct 1.156 + { 1.157 + virtual ~InitStruct() { } 1.158 + virtual void InitString(char* pbuffer, size_t size) const = 0; 1.159 + }; 1.160 + 1.161 + 1.162 + // Constructors / Destructors. 1.163 + String(); 1.164 + String(const char* data); 1.165 + String(const char* data1, const char* pdata2, const char* pdata3 = 0); 1.166 + String(const char* data, size_t buflen); 1.167 + String(const String& src); 1.168 + String(const StringBuffer& src); 1.169 + String(const InitStruct& src, size_t size); 1.170 + explicit String(const wchar_t* data); 1.171 + 1.172 + // Destructor (Captain Obvious guarantees!) 1.173 + ~String() 1.174 + { 1.175 + GetData()->Release(); 1.176 + } 1.177 + 1.178 + // Declaration of NullString 1.179 + static DataDesc NullData; 1.180 + 1.181 + 1.182 + // *** General Functions 1.183 + 1.184 + void Clear(); 1.185 + 1.186 + // For casting to a pointer to char. 1.187 + operator const char*() const { return GetData()->Data; } 1.188 + // Pointer to raw buffer. 1.189 + const char* ToCStr() const { return GetData()->Data; } 1.190 + 1.191 + // Returns number of bytes 1.192 + size_t GetSize() const { return GetData()->GetSize() ; } 1.193 + // Tells whether or not the string is empty 1.194 + bool IsEmpty() const { return GetSize() == 0; } 1.195 + 1.196 + // Returns number of characters 1.197 + size_t GetLength() const; 1.198 + int GetLengthI() const { return (int)GetLength(); } 1.199 + 1.200 + // Returns character at the specified index 1.201 + uint32_t GetCharAt(size_t index) const; 1.202 + uint32_t GetFirstCharAt(size_t index, const char** offset) const; 1.203 + uint32_t GetNextChar(const char** offset) const; 1.204 + 1.205 + // Appends a character 1.206 + void AppendChar(uint32_t ch); 1.207 + 1.208 + // Append a string 1.209 + void AppendString(const wchar_t* pstr, intptr_t len = -1); 1.210 + void AppendString(const char* putf8str, intptr_t utf8StrSz = -1); 1.211 + 1.212 + // Assigned a string with dynamic data (copied through initializer). 1.213 + void AssignString(const InitStruct& src, size_t size); 1.214 + // Assigns string with known size. 1.215 + void AssignString(const char* putf8str, size_t size); 1.216 + 1.217 + // Resize the string to the new size 1.218 +// void Resize(size_t _size); 1.219 + 1.220 + // Removes the character at posAt 1.221 + void Remove(size_t posAt, intptr_t len = 1); 1.222 + 1.223 + // Returns a String that's a substring of this. 1.224 + // -start is the index of the first UTF8 character you want to include. 1.225 + // -end is the index one past the last UTF8 character you want to include. 1.226 + String Substring(size_t start, size_t end) const; 1.227 + 1.228 + // Case-conversion 1.229 + String ToUpper() const; 1.230 + String ToLower() const; 1.231 + 1.232 + // Inserts substr at posAt 1.233 + String& Insert (const char* substr, size_t posAt, intptr_t len = -1); 1.234 + 1.235 + // Inserts character at posAt 1.236 + size_t InsertCharAt(uint32_t c, size_t posAt); 1.237 + 1.238 + // Inserts substr at posAt, which is an index of a character (not byte). 1.239 + // Of size is specified, it is in bytes. 1.240 +// String& Insert(const uint32_t* substr, size_t posAt, intptr_t size = -1); 1.241 + 1.242 + // Get Byte index of the character at position = index 1.243 + size_t GetByteIndex(size_t index) const { return (size_t)UTF8Util::GetByteIndex(index, GetData()->Data); } 1.244 + 1.245 + // Utility: case-insensitive string compare. stricmp() & strnicmp() are not 1.246 + // ANSI or POSIX, do not seem to appear in Linux. 1.247 + static int OVR_STDCALL CompareNoCase(const char* a, const char* b); 1.248 + static int OVR_STDCALL CompareNoCase(const char* a, const char* b, intptr_t len); 1.249 + 1.250 + // Hash function, case-insensitive 1.251 + static size_t OVR_STDCALL BernsteinHashFunctionCIS(const void* pdataIn, size_t size, size_t seed = 5381); 1.252 + 1.253 + // Hash function, case-sensitive 1.254 + static size_t OVR_STDCALL BernsteinHashFunction(const void* pdataIn, size_t size, size_t seed = 5381); 1.255 + 1.256 + 1.257 + // ***** File path parsing helper functions. 1.258 + // Implemented in OVR_String_FilePath.cpp. 1.259 + 1.260 + // Absolute paths can star with: 1.261 + // - protocols: 'file://', 'http://' 1.262 + // - windows drive: 'c:\' 1.263 + // - UNC share name: '\\share' 1.264 + // - unix root '/' 1.265 + static bool HasAbsolutePath(const char* path); 1.266 + static bool HasExtension(const char* path); 1.267 + static bool HasProtocol(const char* path); 1.268 + 1.269 + bool HasAbsolutePath() const { return HasAbsolutePath(ToCStr()); } 1.270 + bool HasExtension() const { return HasExtension(ToCStr()); } 1.271 + bool HasProtocol() const { return HasProtocol(ToCStr()); } 1.272 + 1.273 + String GetProtocol() const; // Returns protocol, if any, with trailing '://'. 1.274 + String GetPath() const; // Returns path with trailing '/'. 1.275 + String GetFilename() const; // Returns filename, including extension. 1.276 + String GetExtension() const; // Returns extension with a dot. 1.277 + 1.278 + void StripProtocol(); // Strips front protocol, if any, from the string. 1.279 + void StripExtension(); // Strips off trailing extension. 1.280 + 1.281 + 1.282 + // Operators 1.283 + // Assignment 1.284 + void operator = (const char* str); 1.285 + void operator = (const wchar_t* str); 1.286 + void operator = (const String& src); 1.287 + void operator = (const StringBuffer& src); 1.288 + 1.289 + // Addition 1.290 + void operator += (const String& src); 1.291 + void operator += (const char* psrc) { AppendString(psrc); } 1.292 + void operator += (const wchar_t* psrc) { AppendString(psrc); } 1.293 + void operator += (char ch) { AppendChar(ch); } 1.294 + String operator + (const char* str) const; 1.295 + String operator + (const String& src) const; 1.296 + 1.297 + // Comparison 1.298 + bool operator == (const String& str) const 1.299 + { 1.300 + return (OVR_strcmp(GetData()->Data, str.GetData()->Data)== 0); 1.301 + } 1.302 + 1.303 + bool operator != (const String& str) const 1.304 + { 1.305 + return !operator == (str); 1.306 + } 1.307 + 1.308 + bool operator == (const char* str) const 1.309 + { 1.310 + return OVR_strcmp(GetData()->Data, str) == 0; 1.311 + } 1.312 + 1.313 + bool operator != (const char* str) const 1.314 + { 1.315 + return !operator == (str); 1.316 + } 1.317 + 1.318 + bool operator < (const char* pstr) const 1.319 + { 1.320 + return OVR_strcmp(GetData()->Data, pstr) < 0; 1.321 + } 1.322 + 1.323 + bool operator < (const String& str) const 1.324 + { 1.325 + return *this < str.GetData()->Data; 1.326 + } 1.327 + 1.328 + bool operator > (const char* pstr) const 1.329 + { 1.330 + return OVR_strcmp(GetData()->Data, pstr) > 0; 1.331 + } 1.332 + 1.333 + bool operator > (const String& str) const 1.334 + { 1.335 + return *this > str.GetData()->Data; 1.336 + } 1.337 + 1.338 + int CompareNoCase(const char* pstr) const 1.339 + { 1.340 + return CompareNoCase(GetData()->Data, pstr); 1.341 + } 1.342 + int CompareNoCase(const String& str) const 1.343 + { 1.344 + return CompareNoCase(GetData()->Data, str.ToCStr()); 1.345 + } 1.346 + 1.347 + // Accesses raw bytes 1.348 + const char& operator [] (int index) const 1.349 + { 1.350 + OVR_ASSERT(index >= 0 && (size_t)index < GetSize()); 1.351 + return GetData()->Data[index]; 1.352 + } 1.353 + const char& operator [] (size_t index) const 1.354 + { 1.355 + OVR_ASSERT(index < GetSize()); 1.356 + return GetData()->Data[index]; 1.357 + } 1.358 + 1.359 + 1.360 + // Case insensitive keys are used to look up insensitive string in hash tables 1.361 + // for SWF files with version before SWF 7. 1.362 + struct NoCaseKey 1.363 + { 1.364 + const String* pStr; 1.365 + NoCaseKey(const String &str) : pStr(&str){}; 1.366 + }; 1.367 + 1.368 + bool operator == (const NoCaseKey& strKey) const 1.369 + { 1.370 + return (CompareNoCase(ToCStr(), strKey.pStr->ToCStr()) == 0); 1.371 + } 1.372 + bool operator != (const NoCaseKey& strKey) const 1.373 + { 1.374 + return !(CompareNoCase(ToCStr(), strKey.pStr->ToCStr()) == 0); 1.375 + } 1.376 + 1.377 + // Hash functor used for strings. 1.378 + struct HashFunctor 1.379 + { 1.380 + size_t operator()(const String& data) const 1.381 + { 1.382 + size_t size = data.GetSize(); 1.383 + return String::BernsteinHashFunction((const char*)data, size); 1.384 + } 1.385 + }; 1.386 + // Case-insensitive hash functor used for strings. Supports additional 1.387 + // lookup based on NoCaseKey. 1.388 + struct NoCaseHashFunctor 1.389 + { 1.390 + size_t operator()(const String& data) const 1.391 + { 1.392 + size_t size = data.GetSize(); 1.393 + return String::BernsteinHashFunctionCIS((const char*)data, size); 1.394 + } 1.395 + size_t operator()(const NoCaseKey& data) const 1.396 + { 1.397 + size_t size = data.pStr->GetSize(); 1.398 + return String::BernsteinHashFunctionCIS((const char*)data.pStr->ToCStr(), size); 1.399 + } 1.400 + }; 1.401 + 1.402 +}; 1.403 + 1.404 + 1.405 +//----------------------------------------------------------------------------------- 1.406 +// ***** String Buffer used for Building Strings 1.407 + 1.408 +class StringBuffer 1.409 +{ 1.410 + char* pData; 1.411 + size_t Size; 1.412 + size_t BufferSize; 1.413 + size_t GrowSize; 1.414 + mutable bool LengthIsSize; 1.415 + 1.416 +public: 1.417 + 1.418 + // Constructors / Destructor. 1.419 + StringBuffer(); 1.420 + explicit StringBuffer(size_t growSize); 1.421 + StringBuffer(const char* data); 1.422 + StringBuffer(const char* data, size_t buflen); 1.423 + StringBuffer(const String& src); 1.424 + StringBuffer(const StringBuffer& src); 1.425 + explicit StringBuffer(const wchar_t* data); 1.426 + ~StringBuffer(); 1.427 + 1.428 + 1.429 + // Modify grow size used for growing/shrinking the buffer. 1.430 + size_t GetGrowSize() const { return GrowSize; } 1.431 + void SetGrowSize(size_t growSize); 1.432 + 1.433 + 1.434 + // *** General Functions 1.435 + // Does not release memory, just sets Size to 0 1.436 + void Clear(); 1.437 + 1.438 + // For casting to a pointer to char. 1.439 + operator const char*() const { return (pData) ? pData : ""; } 1.440 + // Pointer to raw buffer. 1.441 + const char* ToCStr() const { return (pData) ? pData : ""; } 1.442 + 1.443 + // Returns number of bytes. 1.444 + size_t GetSize() const { return Size ; } 1.445 + // Tells whether or not the string is empty. 1.446 + bool IsEmpty() const { return GetSize() == 0; } 1.447 + 1.448 + // Returns number of characters 1.449 + size_t GetLength() const; 1.450 + 1.451 + // Returns character at the specified index 1.452 + uint32_t GetCharAt(size_t index) const; 1.453 + uint32_t GetFirstCharAt(size_t index, const char** offset) const; 1.454 + uint32_t GetNextChar(const char** offset) const; 1.455 + 1.456 + 1.457 + // Resize the string to the new size 1.458 + void Resize(size_t _size); 1.459 + void Reserve(size_t _size); 1.460 + 1.461 + // Appends a character 1.462 + void AppendChar(uint32_t ch); 1.463 + 1.464 + // Append a string 1.465 + void AppendString(const wchar_t* pstr, intptr_t len = -1); 1.466 + void AppendString(const char* putf8str, intptr_t utf8StrSz = -1); 1.467 + void AppendFormat(const char* format, ...); 1.468 + 1.469 + // Assigned a string with dynamic data (copied through initializer). 1.470 + //void AssignString(const InitStruct& src, size_t size); 1.471 + 1.472 + // Inserts substr at posAt 1.473 + void Insert (const char* substr, size_t posAt, intptr_t len = -1); 1.474 + // Inserts character at posAt 1.475 + size_t InsertCharAt(uint32_t c, size_t posAt); 1.476 + 1.477 + // Assignment 1.478 + void operator = (const char* str); 1.479 + void operator = (const wchar_t* str); 1.480 + void operator = (const String& src); 1.481 + void operator = (const StringBuffer& src); 1.482 + 1.483 + // Addition 1.484 + void operator += (const String& src) { AppendString(src.ToCStr(),src.GetSize()); } 1.485 + void operator += (const char* psrc) { AppendString(psrc); } 1.486 + void operator += (const wchar_t* psrc) { AppendString(psrc); } 1.487 + void operator += (char ch) { AppendChar(ch); } 1.488 + //String operator + (const char* str) const ; 1.489 + //String operator + (const String& src) const ; 1.490 + 1.491 + // Accesses raw bytes 1.492 + char& operator [] (int index) 1.493 + { 1.494 + OVR_ASSERT(((size_t)index) < GetSize()); 1.495 + return pData[index]; 1.496 + } 1.497 + char& operator [] (size_t index) 1.498 + { 1.499 + OVR_ASSERT(index < GetSize()); 1.500 + return pData[index]; 1.501 + } 1.502 + 1.503 + const char& operator [] (int index) const 1.504 + { 1.505 + OVR_ASSERT(((size_t)index) < GetSize()); 1.506 + return pData[index]; 1.507 + } 1.508 + const char& operator [] (size_t index) const 1.509 + { 1.510 + OVR_ASSERT(index < GetSize()); 1.511 + return pData[index]; 1.512 + } 1.513 +}; 1.514 + 1.515 + 1.516 +// 1.517 +// Wrapper for string data. The data must have a guaranteed 1.518 +// lifespan throughout the usage of the wrapper. Not intended for 1.519 +// cached usage. Not thread safe. 1.520 +// 1.521 +class StringDataPtr 1.522 +{ 1.523 +public: 1.524 + StringDataPtr() : pStr(NULL), Size(0) {} 1.525 + StringDataPtr(const StringDataPtr& p) 1.526 + : pStr(p.pStr), Size(p.Size) {} 1.527 + StringDataPtr(const char* pstr, size_t sz) 1.528 + : pStr(pstr), Size(sz) {} 1.529 + StringDataPtr(const char* pstr) 1.530 + : pStr(pstr), Size((pstr != NULL) ? OVR_strlen(pstr) : 0) {} 1.531 + explicit StringDataPtr(const String& str) 1.532 + : pStr(str.ToCStr()), Size(str.GetSize()) {} 1.533 + template <typename T, int N> 1.534 + StringDataPtr(const T (&v)[N]) 1.535 + : pStr(v), Size(N) {} 1.536 + 1.537 +public: 1.538 + const char* ToCStr() const { return pStr; } 1.539 + size_t GetSize() const { return Size; } 1.540 + bool IsEmpty() const { return GetSize() == 0; } 1.541 + 1.542 + // value is a prefix of this string 1.543 + // Character's values are not compared. 1.544 + bool IsPrefix(const StringDataPtr& value) const 1.545 + { 1.546 + return ToCStr() == value.ToCStr() && GetSize() >= value.GetSize(); 1.547 + } 1.548 + // value is a suffix of this string 1.549 + // Character's values are not compared. 1.550 + bool IsSuffix(const StringDataPtr& value) const 1.551 + { 1.552 + return ToCStr() <= value.ToCStr() && (End()) == (value.End()); 1.553 + } 1.554 + 1.555 + // Find first character. 1.556 + // init_ind - initial index. 1.557 + intptr_t FindChar(char c, size_t init_ind = 0) const 1.558 + { 1.559 + for (size_t i = init_ind; i < GetSize(); ++i) 1.560 + if (pStr[i] == c) 1.561 + return static_cast<intptr_t>(i); 1.562 + 1.563 + return -1; 1.564 + } 1.565 + 1.566 + // Find last character. 1.567 + // init_ind - initial index. 1.568 + intptr_t FindLastChar(char c, size_t init_ind = ~0) const 1.569 + { 1.570 + if (init_ind == (size_t)~0 || init_ind > GetSize()) 1.571 + init_ind = GetSize(); 1.572 + else 1.573 + ++init_ind; 1.574 + 1.575 + for (size_t i = init_ind; i > 0; --i) 1.576 + if (pStr[i - 1] == c) 1.577 + return static_cast<intptr_t>(i - 1); 1.578 + 1.579 + return -1; 1.580 + } 1.581 + 1.582 + // Create new object and trim size bytes from the left. 1.583 + StringDataPtr GetTrimLeft(size_t size) const 1.584 + { 1.585 + // Limit trim size to the size of the string. 1.586 + size = Alg::PMin(GetSize(), size); 1.587 + 1.588 + return StringDataPtr(ToCStr() + size, GetSize() - size); 1.589 + } 1.590 + // Create new object and trim size bytes from the right. 1.591 + StringDataPtr GetTrimRight(size_t size) const 1.592 + { 1.593 + // Limit trim to the size of the string. 1.594 + size = Alg::PMin(GetSize(), size); 1.595 + 1.596 + return StringDataPtr(ToCStr(), GetSize() - size); 1.597 + } 1.598 + 1.599 + // Create new object, which contains next token. 1.600 + // Useful for parsing. 1.601 + StringDataPtr GetNextToken(char separator = ':') const 1.602 + { 1.603 + size_t cur_pos = 0; 1.604 + const char* cur_str = ToCStr(); 1.605 + 1.606 + for (; cur_pos < GetSize() && cur_str[cur_pos]; ++cur_pos) 1.607 + { 1.608 + if (cur_str[cur_pos] == separator) 1.609 + { 1.610 + break; 1.611 + } 1.612 + } 1.613 + 1.614 + return StringDataPtr(ToCStr(), cur_pos); 1.615 + } 1.616 + 1.617 + // Trim size bytes from the left. 1.618 + StringDataPtr& TrimLeft(size_t size) 1.619 + { 1.620 + // Limit trim size to the size of the string. 1.621 + size = Alg::PMin(GetSize(), size); 1.622 + pStr += size; 1.623 + Size -= size; 1.624 + 1.625 + return *this; 1.626 + } 1.627 + // Trim size bytes from the right. 1.628 + StringDataPtr& TrimRight(size_t size) 1.629 + { 1.630 + // Limit trim to the size of the string. 1.631 + size = Alg::PMin(GetSize(), size); 1.632 + Size -= size; 1.633 + 1.634 + return *this; 1.635 + } 1.636 + 1.637 + const char* Begin() const { return ToCStr(); } 1.638 + const char* End() const { return ToCStr() + GetSize(); } 1.639 + 1.640 + // Hash functor used string data pointers 1.641 + struct HashFunctor 1.642 + { 1.643 + size_t operator()(const StringDataPtr& data) const 1.644 + { 1.645 + return String::BernsteinHashFunction(data.ToCStr(), data.GetSize()); 1.646 + } 1.647 + }; 1.648 + 1.649 + bool operator== (const StringDataPtr& data) const 1.650 + { 1.651 + return (OVR_strncmp(pStr, data.pStr, data.Size) == 0); 1.652 + } 1.653 + 1.654 +protected: 1.655 + const char* pStr; 1.656 + size_t Size; 1.657 +}; 1.658 + 1.659 +} // OVR 1.660 + 1.661 +#endif