oculus1

annotate libovr/Src/Kernel/OVR_String.h @ 6:d6dd6372add6

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