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