ovr_sdk

annotate 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
rev   line source
nuclear@0 1 /************************************************************************************
nuclear@0 2
nuclear@0 3 PublicHeader: OVR_Kernel.h
nuclear@0 4 Filename : OVR_String.h
nuclear@0 5 Content : String UTF8 string implementation with copy-on-write semantics
nuclear@0 6 (thread-safe for assignment but not modification).
nuclear@0 7 Created : September 19, 2012
nuclear@0 8 Notes :
nuclear@0 9
nuclear@0 10 Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved.
nuclear@0 11
nuclear@0 12 Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License");
nuclear@0 13 you may not use the Oculus VR Rift SDK except in compliance with the License,
nuclear@0 14 which is provided at the time of installation or download, or which
nuclear@0 15 otherwise accompanies this software in either electronic or hard copy form.
nuclear@0 16
nuclear@0 17 You may obtain a copy of the License at
nuclear@0 18
nuclear@0 19 http://www.oculusvr.com/licenses/LICENSE-3.2
nuclear@0 20
nuclear@0 21 Unless required by applicable law or agreed to in writing, the Oculus VR SDK
nuclear@0 22 distributed under the License is distributed on an "AS IS" BASIS,
nuclear@0 23 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
nuclear@0 24 See the License for the specific language governing permissions and
nuclear@0 25 limitations under the License.
nuclear@0 26
nuclear@0 27 ************************************************************************************/
nuclear@0 28
nuclear@0 29 #ifndef OVR_String_h
nuclear@0 30 #define OVR_String_h
nuclear@0 31
nuclear@0 32 #include "OVR_Types.h"
nuclear@0 33 #include "OVR_Allocator.h"
nuclear@0 34 #include "OVR_UTF8Util.h"
nuclear@0 35 #include "OVR_Atomic.h"
nuclear@0 36 #include "OVR_Std.h"
nuclear@0 37 #include "OVR_Alg.h"
nuclear@0 38
nuclear@0 39 namespace OVR {
nuclear@0 40
nuclear@0 41 // ***** Classes
nuclear@0 42
nuclear@0 43 class String;
nuclear@0 44 class StringBuffer;
nuclear@0 45
nuclear@0 46
nuclear@0 47 //-----------------------------------------------------------------------------------
nuclear@0 48 // ***** String Class
nuclear@0 49
nuclear@0 50 // String is UTF8 based string class with copy-on-write implementation
nuclear@0 51 // for assignment.
nuclear@0 52
nuclear@0 53 class String
nuclear@0 54 {
nuclear@0 55 protected:
nuclear@0 56
nuclear@0 57 enum FlagConstants
nuclear@0 58 {
nuclear@0 59 //Flag_GetLength = 0x7FFFFFFF,
nuclear@0 60 // This flag is set if GetLength() == GetSize() for a string.
nuclear@0 61 // Avoid extra scanning is Substring and indexing logic.
nuclear@0 62 Flag_LengthIsSizeShift = (sizeof(size_t)*8 - 1)
nuclear@0 63 };
nuclear@0 64
nuclear@0 65
nuclear@0 66 // Internal structure to hold string data
nuclear@0 67 struct DataDesc
nuclear@0 68 {
nuclear@0 69 // Number of bytes. Will be the same as the number of chars if the characters
nuclear@0 70 // are ascii, may not be equal to number of chars in case string data is UTF8.
nuclear@0 71 size_t Size;
nuclear@0 72 volatile int32_t RefCount;
nuclear@0 73 char Data[1];
nuclear@0 74
nuclear@0 75 void AddRef()
nuclear@0 76 {
nuclear@0 77 AtomicOps<int32_t>::ExchangeAdd_NoSync(&RefCount, 1);
nuclear@0 78 }
nuclear@0 79 // Decrement ref count. This needs to be thread-safe, since
nuclear@0 80 // a different thread could have also decremented the ref count.
nuclear@0 81 // For example, if u start off with a ref count = 2. Now if u
nuclear@0 82 // decrement the ref count and check against 0 in different
nuclear@0 83 // statements, a different thread can also decrement the ref count
nuclear@0 84 // in between our decrement and checking against 0 and will find
nuclear@0 85 // the ref count = 0 and delete the object. This will lead to a crash
nuclear@0 86 // when context switches to our thread and we'll be trying to delete
nuclear@0 87 // an already deleted object. Hence decrementing the ref count and
nuclear@0 88 // checking against 0 needs to made an atomic operation.
nuclear@0 89 void Release()
nuclear@0 90 {
nuclear@0 91 if ((AtomicOps<int32_t>::ExchangeAdd_NoSync(&RefCount, -1) - 1) == 0)
nuclear@0 92 OVR_FREE(this);
nuclear@0 93 }
nuclear@0 94
nuclear@0 95 static size_t GetLengthFlagBit() { return size_t(1) << Flag_LengthIsSizeShift; }
nuclear@0 96 size_t GetSize() const { return Size & ~GetLengthFlagBit() ; }
nuclear@0 97 size_t GetLengthFlag() const { return Size & GetLengthFlagBit(); }
nuclear@0 98 bool LengthIsSize() const { return GetLengthFlag() != 0; }
nuclear@0 99 };
nuclear@0 100
nuclear@0 101 // Heap type of the string is encoded in the lower bits.
nuclear@0 102 enum HeapType
nuclear@0 103 {
nuclear@0 104 HT_Global = 0, // Heap is global.
nuclear@0 105 HT_Local = 1, // SF::String_loc: Heap is determined based on string's address.
nuclear@0 106 HT_Dynamic = 2, // SF::String_temp: Heap is stored as a part of the class.
nuclear@0 107 HT_Mask = 3
nuclear@0 108 };
nuclear@0 109
nuclear@0 110 union {
nuclear@0 111 DataDesc* pData;
nuclear@0 112 size_t HeapTypeBits;
nuclear@0 113 };
nuclear@0 114 typedef union {
nuclear@0 115 DataDesc* pData;
nuclear@0 116 size_t HeapTypeBits;
nuclear@0 117 } DataDescUnion;
nuclear@0 118
nuclear@0 119 inline HeapType GetHeapType() const { return (HeapType) (HeapTypeBits & HT_Mask); }
nuclear@0 120
nuclear@0 121 inline DataDesc* GetData() const
nuclear@0 122 {
nuclear@0 123 DataDescUnion u;
nuclear@0 124 u.pData = pData;
nuclear@0 125 u.HeapTypeBits = (u.HeapTypeBits & ~(size_t)HT_Mask);
nuclear@0 126 return u.pData;
nuclear@0 127 }
nuclear@0 128
nuclear@0 129 inline void SetData(DataDesc* pdesc)
nuclear@0 130 {
nuclear@0 131 HeapType ht = GetHeapType();
nuclear@0 132 pData = pdesc;
nuclear@0 133 OVR_ASSERT((HeapTypeBits & HT_Mask) == 0);
nuclear@0 134 HeapTypeBits |= ht;
nuclear@0 135 }
nuclear@0 136
nuclear@0 137
nuclear@0 138 DataDesc* AllocData(size_t size, size_t lengthIsSize);
nuclear@0 139 DataDesc* AllocDataCopy1(size_t size, size_t lengthIsSize,
nuclear@0 140 const char* pdata, size_t copySize);
nuclear@0 141 DataDesc* AllocDataCopy2(size_t size, size_t lengthIsSize,
nuclear@0 142 const char* pdata1, size_t copySize1,
nuclear@0 143 const char* pdata2, size_t copySize2);
nuclear@0 144
nuclear@0 145 // Special constructor to avoid data initalization when used in derived class.
nuclear@0 146 struct NoConstructor { };
nuclear@0 147 String(const NoConstructor&) { }
nuclear@0 148
nuclear@0 149 public:
nuclear@0 150
nuclear@0 151 // For initializing string with dynamic buffer
nuclear@0 152 struct InitStruct
nuclear@0 153 {
nuclear@0 154 virtual ~InitStruct() { }
nuclear@0 155 virtual void InitString(char* pbuffer, size_t size) const = 0;
nuclear@0 156 };
nuclear@0 157
nuclear@0 158
nuclear@0 159 // Constructors / Destructors.
nuclear@0 160 String();
nuclear@0 161 String(const char* data);
nuclear@0 162 String(const char* data1, const char* pdata2, const char* pdata3 = 0);
nuclear@0 163 String(const char* data, size_t buflen);
nuclear@0 164 String(const String& src);
nuclear@0 165 String(const StringBuffer& src);
nuclear@0 166 String(const InitStruct& src, size_t size);
nuclear@0 167 explicit String(const wchar_t* data);
nuclear@0 168
nuclear@0 169 // Destructor (Captain Obvious guarantees!)
nuclear@0 170 ~String()
nuclear@0 171 {
nuclear@0 172 GetData()->Release();
nuclear@0 173 }
nuclear@0 174
nuclear@0 175 // Declaration of NullString
nuclear@0 176 static DataDesc NullData;
nuclear@0 177
nuclear@0 178
nuclear@0 179 // *** General Functions
nuclear@0 180
nuclear@0 181 void Clear();
nuclear@0 182
nuclear@0 183 // For casting to a pointer to char.
nuclear@0 184 operator const char*() const { return GetData()->Data; }
nuclear@0 185 // Pointer to raw buffer.
nuclear@0 186 const char* ToCStr() const { return GetData()->Data; }
nuclear@0 187
nuclear@0 188 // Returns number of bytes
nuclear@0 189 size_t GetSize() const { return GetData()->GetSize() ; }
nuclear@0 190 // Tells whether or not the string is empty
nuclear@0 191 bool IsEmpty() const { return GetSize() == 0; }
nuclear@0 192
nuclear@0 193 // Returns number of characters
nuclear@0 194 size_t GetLength() const;
nuclear@0 195 int GetLengthI() const { return (int)GetLength(); }
nuclear@0 196
nuclear@0 197 // Returns character at the specified index
nuclear@0 198 uint32_t GetCharAt(size_t index) const;
nuclear@0 199 uint32_t GetFirstCharAt(size_t index, const char** offset) const;
nuclear@0 200 uint32_t GetNextChar(const char** offset) const;
nuclear@0 201
nuclear@0 202 // Appends a character
nuclear@0 203 void AppendChar(uint32_t ch);
nuclear@0 204
nuclear@0 205 // Append a string
nuclear@0 206 void AppendString(const wchar_t* pstr, intptr_t len = -1);
nuclear@0 207 void AppendString(const char* putf8str, intptr_t utf8StrSz = -1);
nuclear@0 208
nuclear@0 209 // Assigned a string with dynamic data (copied through initializer).
nuclear@0 210 void AssignString(const InitStruct& src, size_t size);
nuclear@0 211 // Assigns string with known size.
nuclear@0 212 void AssignString(const char* putf8str, size_t size);
nuclear@0 213
nuclear@0 214 // Resize the string to the new size
nuclear@0 215 // void Resize(size_t _size);
nuclear@0 216
nuclear@0 217 // Removes the character at posAt
nuclear@0 218 void Remove(size_t posAt, intptr_t len = 1);
nuclear@0 219
nuclear@0 220 // Returns a String that's a substring of this.
nuclear@0 221 // -start is the index of the first UTF8 character you want to include.
nuclear@0 222 // -end is the index one past the last UTF8 character you want to include.
nuclear@0 223 String Substring(size_t start, size_t end) const;
nuclear@0 224
nuclear@0 225 // Case-conversion
nuclear@0 226 String ToUpper() const;
nuclear@0 227 String ToLower() const;
nuclear@0 228
nuclear@0 229 // Inserts substr at posAt
nuclear@0 230 String& Insert (const char* substr, size_t posAt, intptr_t len = -1);
nuclear@0 231
nuclear@0 232 // Inserts character at posAt
nuclear@0 233 size_t InsertCharAt(uint32_t c, size_t posAt);
nuclear@0 234
nuclear@0 235 // Inserts substr at posAt, which is an index of a character (not byte).
nuclear@0 236 // Of size is specified, it is in bytes.
nuclear@0 237 // String& Insert(const uint32_t* substr, size_t posAt, intptr_t size = -1);
nuclear@0 238
nuclear@0 239 // Get Byte index of the character at position = index
nuclear@0 240 size_t GetByteIndex(size_t index) const { return (size_t)UTF8Util::GetByteIndex(index, GetData()->Data); }
nuclear@0 241
nuclear@0 242 // Utility: case-insensitive string compare. stricmp() & strnicmp() are not
nuclear@0 243 // ANSI or POSIX, do not seem to appear in Linux.
nuclear@0 244 static int OVR_STDCALL CompareNoCase(const char* a, const char* b);
nuclear@0 245 static int OVR_STDCALL CompareNoCase(const char* a, const char* b, intptr_t len);
nuclear@0 246
nuclear@0 247 // Hash function, case-insensitive
nuclear@0 248 static size_t OVR_STDCALL BernsteinHashFunctionCIS(const void* pdataIn, size_t size, size_t seed = 5381);
nuclear@0 249
nuclear@0 250 // Hash function, case-sensitive
nuclear@0 251 static size_t OVR_STDCALL BernsteinHashFunction(const void* pdataIn, size_t size, size_t seed = 5381);
nuclear@0 252
nuclear@0 253
nuclear@0 254 // ***** File path parsing helper functions.
nuclear@0 255 // Implemented in OVR_String_FilePath.cpp.
nuclear@0 256
nuclear@0 257 // Absolute paths can star with:
nuclear@0 258 // - protocols: 'file://', 'http://'
nuclear@0 259 // - windows drive: 'c:\'
nuclear@0 260 // - UNC share name: '\\share'
nuclear@0 261 // - unix root '/'
nuclear@0 262 static bool HasAbsolutePath(const char* path);
nuclear@0 263 static bool HasExtension(const char* path);
nuclear@0 264 static bool HasProtocol(const char* path);
nuclear@0 265
nuclear@0 266 bool HasAbsolutePath() const { return HasAbsolutePath(ToCStr()); }
nuclear@0 267 bool HasExtension() const { return HasExtension(ToCStr()); }
nuclear@0 268 bool HasProtocol() const { return HasProtocol(ToCStr()); }
nuclear@0 269
nuclear@0 270 String GetProtocol() const; // Returns protocol, if any, with trailing '://'.
nuclear@0 271 String GetPath() const; // Returns path with trailing '/'.
nuclear@0 272 String GetFilename() const; // Returns filename, including extension.
nuclear@0 273 String GetExtension() const; // Returns extension with a dot.
nuclear@0 274
nuclear@0 275 void StripProtocol(); // Strips front protocol, if any, from the string.
nuclear@0 276 void StripExtension(); // Strips off trailing extension.
nuclear@0 277
nuclear@0 278
nuclear@0 279 // Operators
nuclear@0 280 // Assignment
nuclear@0 281 void operator = (const char* str);
nuclear@0 282 void operator = (const wchar_t* str);
nuclear@0 283 void operator = (const String& src);
nuclear@0 284 void operator = (const StringBuffer& src);
nuclear@0 285
nuclear@0 286 // Addition
nuclear@0 287 void operator += (const String& src);
nuclear@0 288 void operator += (const char* psrc) { AppendString(psrc); }
nuclear@0 289 void operator += (const wchar_t* psrc) { AppendString(psrc); }
nuclear@0 290 void operator += (char ch) { AppendChar(ch); }
nuclear@0 291 String operator + (const char* str) const;
nuclear@0 292 String operator + (const String& src) const;
nuclear@0 293
nuclear@0 294 // Comparison
nuclear@0 295 bool operator == (const String& str) const
nuclear@0 296 {
nuclear@0 297 return (OVR_strcmp(GetData()->Data, str.GetData()->Data)== 0);
nuclear@0 298 }
nuclear@0 299
nuclear@0 300 bool operator != (const String& str) const
nuclear@0 301 {
nuclear@0 302 return !operator == (str);
nuclear@0 303 }
nuclear@0 304
nuclear@0 305 bool operator == (const char* str) const
nuclear@0 306 {
nuclear@0 307 return OVR_strcmp(GetData()->Data, str) == 0;
nuclear@0 308 }
nuclear@0 309
nuclear@0 310 bool operator != (const char* str) const
nuclear@0 311 {
nuclear@0 312 return !operator == (str);
nuclear@0 313 }
nuclear@0 314
nuclear@0 315 bool operator < (const char* pstr) const
nuclear@0 316 {
nuclear@0 317 return OVR_strcmp(GetData()->Data, pstr) < 0;
nuclear@0 318 }
nuclear@0 319
nuclear@0 320 bool operator < (const String& str) const
nuclear@0 321 {
nuclear@0 322 return *this < str.GetData()->Data;
nuclear@0 323 }
nuclear@0 324
nuclear@0 325 bool operator > (const char* pstr) const
nuclear@0 326 {
nuclear@0 327 return OVR_strcmp(GetData()->Data, pstr) > 0;
nuclear@0 328 }
nuclear@0 329
nuclear@0 330 bool operator > (const String& str) const
nuclear@0 331 {
nuclear@0 332 return *this > str.GetData()->Data;
nuclear@0 333 }
nuclear@0 334
nuclear@0 335 int CompareNoCase(const char* pstr) const
nuclear@0 336 {
nuclear@0 337 return CompareNoCase(GetData()->Data, pstr);
nuclear@0 338 }
nuclear@0 339 int CompareNoCase(const String& str) const
nuclear@0 340 {
nuclear@0 341 return CompareNoCase(GetData()->Data, str.ToCStr());
nuclear@0 342 }
nuclear@0 343
nuclear@0 344 // Accesses raw bytes
nuclear@0 345 const char& operator [] (int index) const
nuclear@0 346 {
nuclear@0 347 OVR_ASSERT(index >= 0 && (size_t)index < GetSize());
nuclear@0 348 return GetData()->Data[index];
nuclear@0 349 }
nuclear@0 350 const char& operator [] (size_t index) const
nuclear@0 351 {
nuclear@0 352 OVR_ASSERT(index < GetSize());
nuclear@0 353 return GetData()->Data[index];
nuclear@0 354 }
nuclear@0 355
nuclear@0 356
nuclear@0 357 // Case insensitive keys are used to look up insensitive string in hash tables
nuclear@0 358 // for SWF files with version before SWF 7.
nuclear@0 359 struct NoCaseKey
nuclear@0 360 {
nuclear@0 361 const String* pStr;
nuclear@0 362 NoCaseKey(const String &str) : pStr(&str){};
nuclear@0 363 };
nuclear@0 364
nuclear@0 365 bool operator == (const NoCaseKey& strKey) const
nuclear@0 366 {
nuclear@0 367 return (CompareNoCase(ToCStr(), strKey.pStr->ToCStr()) == 0);
nuclear@0 368 }
nuclear@0 369 bool operator != (const NoCaseKey& strKey) const
nuclear@0 370 {
nuclear@0 371 return !(CompareNoCase(ToCStr(), strKey.pStr->ToCStr()) == 0);
nuclear@0 372 }
nuclear@0 373
nuclear@0 374 // Hash functor used for strings.
nuclear@0 375 struct HashFunctor
nuclear@0 376 {
nuclear@0 377 size_t operator()(const String& data) const
nuclear@0 378 {
nuclear@0 379 size_t size = data.GetSize();
nuclear@0 380 return String::BernsteinHashFunction((const char*)data, size);
nuclear@0 381 }
nuclear@0 382 };
nuclear@0 383 // Case-insensitive hash functor used for strings. Supports additional
nuclear@0 384 // lookup based on NoCaseKey.
nuclear@0 385 struct NoCaseHashFunctor
nuclear@0 386 {
nuclear@0 387 size_t operator()(const String& data) const
nuclear@0 388 {
nuclear@0 389 size_t size = data.GetSize();
nuclear@0 390 return String::BernsteinHashFunctionCIS((const char*)data, size);
nuclear@0 391 }
nuclear@0 392 size_t operator()(const NoCaseKey& data) const
nuclear@0 393 {
nuclear@0 394 size_t size = data.pStr->GetSize();
nuclear@0 395 return String::BernsteinHashFunctionCIS((const char*)data.pStr->ToCStr(), size);
nuclear@0 396 }
nuclear@0 397 };
nuclear@0 398
nuclear@0 399 };
nuclear@0 400
nuclear@0 401
nuclear@0 402 //-----------------------------------------------------------------------------------
nuclear@0 403 // ***** String Buffer used for Building Strings
nuclear@0 404
nuclear@0 405 class StringBuffer
nuclear@0 406 {
nuclear@0 407 char* pData;
nuclear@0 408 size_t Size;
nuclear@0 409 size_t BufferSize;
nuclear@0 410 size_t GrowSize;
nuclear@0 411 mutable bool LengthIsSize;
nuclear@0 412
nuclear@0 413 public:
nuclear@0 414
nuclear@0 415 // Constructors / Destructor.
nuclear@0 416 StringBuffer();
nuclear@0 417 explicit StringBuffer(size_t growSize);
nuclear@0 418 StringBuffer(const char* data);
nuclear@0 419 StringBuffer(const char* data, size_t buflen);
nuclear@0 420 StringBuffer(const String& src);
nuclear@0 421 StringBuffer(const StringBuffer& src);
nuclear@0 422 explicit StringBuffer(const wchar_t* data);
nuclear@0 423 ~StringBuffer();
nuclear@0 424
nuclear@0 425
nuclear@0 426 // Modify grow size used for growing/shrinking the buffer.
nuclear@0 427 size_t GetGrowSize() const { return GrowSize; }
nuclear@0 428 void SetGrowSize(size_t growSize);
nuclear@0 429
nuclear@0 430
nuclear@0 431 // *** General Functions
nuclear@0 432 // Does not release memory, just sets Size to 0
nuclear@0 433 void Clear();
nuclear@0 434
nuclear@0 435 // For casting to a pointer to char.
nuclear@0 436 operator const char*() const { return (pData) ? pData : ""; }
nuclear@0 437 // Pointer to raw buffer.
nuclear@0 438 const char* ToCStr() const { return (pData) ? pData : ""; }
nuclear@0 439
nuclear@0 440 // Returns number of bytes.
nuclear@0 441 size_t GetSize() const { return Size ; }
nuclear@0 442 // Tells whether or not the string is empty.
nuclear@0 443 bool IsEmpty() const { return GetSize() == 0; }
nuclear@0 444
nuclear@0 445 // Returns number of characters
nuclear@0 446 size_t GetLength() const;
nuclear@0 447
nuclear@0 448 // Returns character at the specified index
nuclear@0 449 uint32_t GetCharAt(size_t index) const;
nuclear@0 450 uint32_t GetFirstCharAt(size_t index, const char** offset) const;
nuclear@0 451 uint32_t GetNextChar(const char** offset) const;
nuclear@0 452
nuclear@0 453
nuclear@0 454 // Resize the string to the new size
nuclear@0 455 void Resize(size_t _size);
nuclear@0 456 void Reserve(size_t _size);
nuclear@0 457
nuclear@0 458 // Appends a character
nuclear@0 459 void AppendChar(uint32_t ch);
nuclear@0 460
nuclear@0 461 // Append a string
nuclear@0 462 void AppendString(const wchar_t* pstr, intptr_t len = -1);
nuclear@0 463 void AppendString(const char* putf8str, intptr_t utf8StrSz = -1);
nuclear@0 464 void AppendFormat(const char* format, ...);
nuclear@0 465
nuclear@0 466 // Assigned a string with dynamic data (copied through initializer).
nuclear@0 467 //void AssignString(const InitStruct& src, size_t size);
nuclear@0 468
nuclear@0 469 // Inserts substr at posAt
nuclear@0 470 void Insert (const char* substr, size_t posAt, intptr_t len = -1);
nuclear@0 471 // Inserts character at posAt
nuclear@0 472 size_t InsertCharAt(uint32_t c, size_t posAt);
nuclear@0 473
nuclear@0 474 // Assignment
nuclear@0 475 void operator = (const char* str);
nuclear@0 476 void operator = (const wchar_t* str);
nuclear@0 477 void operator = (const String& src);
nuclear@0 478 void operator = (const StringBuffer& src);
nuclear@0 479
nuclear@0 480 // Addition
nuclear@0 481 void operator += (const String& src) { AppendString(src.ToCStr(),src.GetSize()); }
nuclear@0 482 void operator += (const char* psrc) { AppendString(psrc); }
nuclear@0 483 void operator += (const wchar_t* psrc) { AppendString(psrc); }
nuclear@0 484 void operator += (char ch) { AppendChar(ch); }
nuclear@0 485 //String operator + (const char* str) const ;
nuclear@0 486 //String operator + (const String& src) const ;
nuclear@0 487
nuclear@0 488 // Accesses raw bytes
nuclear@0 489 char& operator [] (int index)
nuclear@0 490 {
nuclear@0 491 OVR_ASSERT(((size_t)index) < GetSize());
nuclear@0 492 return pData[index];
nuclear@0 493 }
nuclear@0 494 char& operator [] (size_t index)
nuclear@0 495 {
nuclear@0 496 OVR_ASSERT(index < GetSize());
nuclear@0 497 return pData[index];
nuclear@0 498 }
nuclear@0 499
nuclear@0 500 const char& operator [] (int index) const
nuclear@0 501 {
nuclear@0 502 OVR_ASSERT(((size_t)index) < GetSize());
nuclear@0 503 return pData[index];
nuclear@0 504 }
nuclear@0 505 const char& operator [] (size_t index) const
nuclear@0 506 {
nuclear@0 507 OVR_ASSERT(index < GetSize());
nuclear@0 508 return pData[index];
nuclear@0 509 }
nuclear@0 510 };
nuclear@0 511
nuclear@0 512
nuclear@0 513 //
nuclear@0 514 // Wrapper for string data. The data must have a guaranteed
nuclear@0 515 // lifespan throughout the usage of the wrapper. Not intended for
nuclear@0 516 // cached usage. Not thread safe.
nuclear@0 517 //
nuclear@0 518 class StringDataPtr
nuclear@0 519 {
nuclear@0 520 public:
nuclear@0 521 StringDataPtr() : pStr(NULL), Size(0) {}
nuclear@0 522 StringDataPtr(const StringDataPtr& p)
nuclear@0 523 : pStr(p.pStr), Size(p.Size) {}
nuclear@0 524 StringDataPtr(const char* pstr, size_t sz)
nuclear@0 525 : pStr(pstr), Size(sz) {}
nuclear@0 526 StringDataPtr(const char* pstr)
nuclear@0 527 : pStr(pstr), Size((pstr != NULL) ? OVR_strlen(pstr) : 0) {}
nuclear@0 528 explicit StringDataPtr(const String& str)
nuclear@0 529 : pStr(str.ToCStr()), Size(str.GetSize()) {}
nuclear@0 530 template <typename T, int N>
nuclear@0 531 StringDataPtr(const T (&v)[N])
nuclear@0 532 : pStr(v), Size(N) {}
nuclear@0 533
nuclear@0 534 public:
nuclear@0 535 const char* ToCStr() const { return pStr; }
nuclear@0 536 size_t GetSize() const { return Size; }
nuclear@0 537 bool IsEmpty() const { return GetSize() == 0; }
nuclear@0 538
nuclear@0 539 // value is a prefix of this string
nuclear@0 540 // Character's values are not compared.
nuclear@0 541 bool IsPrefix(const StringDataPtr& value) const
nuclear@0 542 {
nuclear@0 543 return ToCStr() == value.ToCStr() && GetSize() >= value.GetSize();
nuclear@0 544 }
nuclear@0 545 // value is a suffix of this string
nuclear@0 546 // Character's values are not compared.
nuclear@0 547 bool IsSuffix(const StringDataPtr& value) const
nuclear@0 548 {
nuclear@0 549 return ToCStr() <= value.ToCStr() && (End()) == (value.End());
nuclear@0 550 }
nuclear@0 551
nuclear@0 552 // Find first character.
nuclear@0 553 // init_ind - initial index.
nuclear@0 554 intptr_t FindChar(char c, size_t init_ind = 0) const
nuclear@0 555 {
nuclear@0 556 for (size_t i = init_ind; i < GetSize(); ++i)
nuclear@0 557 if (pStr[i] == c)
nuclear@0 558 return static_cast<intptr_t>(i);
nuclear@0 559
nuclear@0 560 return -1;
nuclear@0 561 }
nuclear@0 562
nuclear@0 563 // Find last character.
nuclear@0 564 // init_ind - initial index.
nuclear@0 565 intptr_t FindLastChar(char c, size_t init_ind = ~0) const
nuclear@0 566 {
nuclear@0 567 if (init_ind == (size_t)~0 || init_ind > GetSize())
nuclear@0 568 init_ind = GetSize();
nuclear@0 569 else
nuclear@0 570 ++init_ind;
nuclear@0 571
nuclear@0 572 for (size_t i = init_ind; i > 0; --i)
nuclear@0 573 if (pStr[i - 1] == c)
nuclear@0 574 return static_cast<intptr_t>(i - 1);
nuclear@0 575
nuclear@0 576 return -1;
nuclear@0 577 }
nuclear@0 578
nuclear@0 579 // Create new object and trim size bytes from the left.
nuclear@0 580 StringDataPtr GetTrimLeft(size_t size) const
nuclear@0 581 {
nuclear@0 582 // Limit trim size to the size of the string.
nuclear@0 583 size = Alg::PMin(GetSize(), size);
nuclear@0 584
nuclear@0 585 return StringDataPtr(ToCStr() + size, GetSize() - size);
nuclear@0 586 }
nuclear@0 587 // Create new object and trim size bytes from the right.
nuclear@0 588 StringDataPtr GetTrimRight(size_t size) const
nuclear@0 589 {
nuclear@0 590 // Limit trim to the size of the string.
nuclear@0 591 size = Alg::PMin(GetSize(), size);
nuclear@0 592
nuclear@0 593 return StringDataPtr(ToCStr(), GetSize() - size);
nuclear@0 594 }
nuclear@0 595
nuclear@0 596 // Create new object, which contains next token.
nuclear@0 597 // Useful for parsing.
nuclear@0 598 StringDataPtr GetNextToken(char separator = ':') const
nuclear@0 599 {
nuclear@0 600 size_t cur_pos = 0;
nuclear@0 601 const char* cur_str = ToCStr();
nuclear@0 602
nuclear@0 603 for (; cur_pos < GetSize() && cur_str[cur_pos]; ++cur_pos)
nuclear@0 604 {
nuclear@0 605 if (cur_str[cur_pos] == separator)
nuclear@0 606 {
nuclear@0 607 break;
nuclear@0 608 }
nuclear@0 609 }
nuclear@0 610
nuclear@0 611 return StringDataPtr(ToCStr(), cur_pos);
nuclear@0 612 }
nuclear@0 613
nuclear@0 614 // Trim size bytes from the left.
nuclear@0 615 StringDataPtr& TrimLeft(size_t size)
nuclear@0 616 {
nuclear@0 617 // Limit trim size to the size of the string.
nuclear@0 618 size = Alg::PMin(GetSize(), size);
nuclear@0 619 pStr += size;
nuclear@0 620 Size -= size;
nuclear@0 621
nuclear@0 622 return *this;
nuclear@0 623 }
nuclear@0 624 // Trim size bytes from the right.
nuclear@0 625 StringDataPtr& TrimRight(size_t size)
nuclear@0 626 {
nuclear@0 627 // Limit trim to the size of the string.
nuclear@0 628 size = Alg::PMin(GetSize(), size);
nuclear@0 629 Size -= size;
nuclear@0 630
nuclear@0 631 return *this;
nuclear@0 632 }
nuclear@0 633
nuclear@0 634 const char* Begin() const { return ToCStr(); }
nuclear@0 635 const char* End() const { return ToCStr() + GetSize(); }
nuclear@0 636
nuclear@0 637 // Hash functor used string data pointers
nuclear@0 638 struct HashFunctor
nuclear@0 639 {
nuclear@0 640 size_t operator()(const StringDataPtr& data) const
nuclear@0 641 {
nuclear@0 642 return String::BernsteinHashFunction(data.ToCStr(), data.GetSize());
nuclear@0 643 }
nuclear@0 644 };
nuclear@0 645
nuclear@0 646 bool operator== (const StringDataPtr& data) const
nuclear@0 647 {
nuclear@0 648 return (OVR_strncmp(pStr, data.pStr, data.Size) == 0);
nuclear@0 649 }
nuclear@0 650
nuclear@0 651 protected:
nuclear@0 652 const char* pStr;
nuclear@0 653 size_t Size;
nuclear@0 654 };
nuclear@0 655
nuclear@0 656 } // OVR
nuclear@0 657
nuclear@0 658 #endif