oculus1

annotate libovr/Src/Kernel/OVR_String.h @ 1:e2f9e4603129

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