aboutsummaryrefslogtreecommitdiffstats
path: root/LibOVR/Src/Kernel/OVR_String.h
diff options
context:
space:
mode:
Diffstat (limited to 'LibOVR/Src/Kernel/OVR_String.h')
-rw-r--r--LibOVR/Src/Kernel/OVR_String.h1290
1 files changed, 645 insertions, 645 deletions
diff --git a/LibOVR/Src/Kernel/OVR_String.h b/LibOVR/Src/Kernel/OVR_String.h
index 112878c..794990f 100644
--- a/LibOVR/Src/Kernel/OVR_String.h
+++ b/LibOVR/Src/Kernel/OVR_String.h
@@ -1,645 +1,645 @@
-/************************************************************************************
-
-PublicHeader: OVR.h
-Filename : OVR_String.h
-Content : String UTF8 string implementation with copy-on-write semantics
- (thread-safe for assignment but not modification).
-Created : September 19, 2012
-Notes :
-
-Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved.
-
-Use of this software is subject to the terms of the Oculus license
-agreement provided at the time of installation or download, or which
-otherwise accompanies this software in either electronic or hard copy form.
-
-************************************************************************************/
-
-#ifndef OVR_String_h
-#define OVR_String_h
-
-#include "OVR_Types.h"
-#include "OVR_Allocator.h"
-#include "OVR_UTF8Util.h"
-#include "OVR_Atomic.h"
-#include "OVR_Std.h"
-#include "OVR_Alg.h"
-
-namespace OVR {
-
-// ***** Classes
-
-class String;
-class StringBuffer;
-
-
-//-----------------------------------------------------------------------------------
-// ***** String Class
-
-// String is UTF8 based string class with copy-on-write implementation
-// for assignment.
-
-class String
-{
-protected:
-
- enum FlagConstants
- {
- //Flag_GetLength = 0x7FFFFFFF,
- // This flag is set if GetLength() == GetSize() for a string.
- // Avoid extra scanning is Substring and indexing logic.
- Flag_LengthIsSizeShift = (sizeof(UPInt)*8 - 1)
- };
-
-
- // Internal structure to hold string data
- struct DataDesc
- {
- // Number of bytes. Will be the same as the number of chars if the characters
- // are ascii, may not be equal to number of chars in case string data is UTF8.
- UPInt Size;
- volatile SInt32 RefCount;
- char Data[1];
-
- void AddRef()
- {
- AtomicOps<SInt32>::ExchangeAdd_NoSync(&RefCount, 1);
- }
- // Decrement ref count. This needs to be thread-safe, since
- // a different thread could have also decremented the ref count.
- // For example, if u start off with a ref count = 2. Now if u
- // decrement the ref count and check against 0 in different
- // statements, a different thread can also decrement the ref count
- // in between our decrement and checking against 0 and will find
- // the ref count = 0 and delete the object. This will lead to a crash
- // when context switches to our thread and we'll be trying to delete
- // an already deleted object. Hence decrementing the ref count and
- // checking against 0 needs to made an atomic operation.
- void Release()
- {
- if ((AtomicOps<SInt32>::ExchangeAdd_NoSync(&RefCount, -1) - 1) == 0)
- OVR_FREE(this);
- }
-
- static UPInt GetLengthFlagBit() { return UPInt(1) << Flag_LengthIsSizeShift; }
- UPInt GetSize() const { return Size & ~GetLengthFlagBit() ; }
- UPInt GetLengthFlag() const { return Size & GetLengthFlagBit(); }
- bool LengthIsSize() const { return GetLengthFlag() != 0; }
- };
-
- // Heap type of the string is encoded in the lower bits.
- enum HeapType
- {
- HT_Global = 0, // Heap is global.
- HT_Local = 1, // SF::String_loc: Heap is determined based on string's address.
- HT_Dynamic = 2, // SF::String_temp: Heap is stored as a part of the class.
- HT_Mask = 3
- };
-
- union {
- DataDesc* pData;
- UPInt HeapTypeBits;
- };
- typedef union {
- DataDesc* pData;
- UPInt HeapTypeBits;
- } DataDescUnion;
-
- inline HeapType GetHeapType() const { return (HeapType) (HeapTypeBits & HT_Mask); }
-
- inline DataDesc* GetData() const
- {
- DataDescUnion u;
- u.pData = pData;
- u.HeapTypeBits = (u.HeapTypeBits & ~(UPInt)HT_Mask);
- return u.pData;
- }
-
- inline void SetData(DataDesc* pdesc)
- {
- HeapType ht = GetHeapType();
- pData = pdesc;
- OVR_ASSERT((HeapTypeBits & HT_Mask) == 0);
- HeapTypeBits |= ht;
- }
-
-
- DataDesc* AllocData(UPInt size, UPInt lengthIsSize);
- DataDesc* AllocDataCopy1(UPInt size, UPInt lengthIsSize,
- const char* pdata, UPInt copySize);
- DataDesc* AllocDataCopy2(UPInt size, UPInt lengthIsSize,
- const char* pdata1, UPInt copySize1,
- const char* pdata2, UPInt copySize2);
-
- // Special constructor to avoid data initalization when used in derived class.
- struct NoConstructor { };
- String(const NoConstructor&) { }
-
-public:
-
- // For initializing string with dynamic buffer
- struct InitStruct
- {
- virtual ~InitStruct() { }
- virtual void InitString(char* pbuffer, UPInt size) const = 0;
- };
-
-
- // Constructors / Destructors.
- String();
- String(const char* data);
- String(const char* data1, const char* pdata2, const char* pdata3 = 0);
- String(const char* data, UPInt buflen);
- String(const String& src);
- String(const StringBuffer& src);
- String(const InitStruct& src, UPInt size);
- explicit String(const wchar_t* data);
-
- // Destructor (Captain Obvious guarantees!)
- ~String()
- {
- GetData()->Release();
- }
-
- // Declaration of NullString
- static DataDesc NullData;
-
-
- // *** General Functions
-
- void Clear();
-
- // For casting to a pointer to char.
- operator const char*() const { return GetData()->Data; }
- // Pointer to raw buffer.
- const char* ToCStr() const { return GetData()->Data; }
-
- // Returns number of bytes
- UPInt GetSize() const { return GetData()->GetSize() ; }
- // Tells whether or not the string is empty
- bool IsEmpty() const { return GetSize() == 0; }
-
- // Returns number of characters
- UPInt GetLength() const;
-
- // Returns character at the specified index
- UInt32 GetCharAt(UPInt index) const;
- UInt32 GetFirstCharAt(UPInt index, const char** offset) const;
- UInt32 GetNextChar(const char** offset) const;
-
- // Appends a character
- void AppendChar(UInt32 ch);
-
- // Append a string
- void AppendString(const wchar_t* pstr, SPInt len = -1);
- void AppendString(const char* putf8str, SPInt utf8StrSz = -1);
-
- // Assigned a string with dynamic data (copied through initializer).
- void AssignString(const InitStruct& src, UPInt size);
- // Assigns string with known size.
- void AssignString(const char* putf8str, UPInt size);
-
- // Resize the string to the new size
-// void Resize(UPInt _size);
-
- // Removes the character at posAt
- void Remove(UPInt posAt, SPInt len = 1);
-
- // Returns a String that's a substring of this.
- // -start is the index of the first UTF8 character you want to include.
- // -end is the index one past the last UTF8 character you want to include.
- String Substring(UPInt start, UPInt end) const;
-
- // Case-conversion
- String ToUpper() const;
- String ToLower() const;
-
- // Inserts substr at posAt
- String& Insert (const char* substr, UPInt posAt, SPInt len = -1);
-
- // Inserts character at posAt
- UPInt InsertCharAt(UInt32 c, UPInt posAt);
-
- // Inserts substr at posAt, which is an index of a character (not byte).
- // Of size is specified, it is in bytes.
-// String& Insert(const UInt32* substr, UPInt posAt, SPInt size = -1);
-
- // Get Byte index of the character at position = index
- UPInt GetByteIndex(UPInt index) const { return (UPInt)UTF8Util::GetByteIndex(index, GetData()->Data); }
-
- // Utility: case-insensitive string compare. stricmp() & strnicmp() are not
- // ANSI or POSIX, do not seem to appear in Linux.
- static int OVR_STDCALL CompareNoCase(const char* a, const char* b);
- static int OVR_STDCALL CompareNoCase(const char* a, const char* b, SPInt len);
-
- // Hash function, case-insensitive
- static UPInt OVR_STDCALL BernsteinHashFunctionCIS(const void* pdataIn, UPInt size, UPInt seed = 5381);
-
- // Hash function, case-sensitive
- static UPInt OVR_STDCALL BernsteinHashFunction(const void* pdataIn, UPInt size, UPInt seed = 5381);
-
-
- // ***** File path parsing helper functions.
- // Implemented in OVR_String_FilePath.cpp.
-
- // Absolute paths can star with:
- // - protocols: 'file://', 'http://'
- // - windows drive: 'c:\'
- // - UNC share name: '\\share'
- // - unix root '/'
- static bool HasAbsolutePath(const char* path);
- static bool HasExtension(const char* path);
- static bool HasProtocol(const char* path);
-
- bool HasAbsolutePath() const { return HasAbsolutePath(ToCStr()); }
- bool HasExtension() const { return HasExtension(ToCStr()); }
- bool HasProtocol() const { return HasProtocol(ToCStr()); }
-
- String GetProtocol() const; // Returns protocol, if any, with trailing '://'.
- String GetPath() const; // Returns path with trailing '/'.
- String GetFilename() const; // Returns filename, including extension.
- String GetExtension() const; // Returns extension with a dot.
-
- void StripProtocol(); // Strips front protocol, if any, from the string.
- void StripExtension(); // Strips off trailing extension.
-
-
- // Operators
- // Assignment
- void operator = (const char* str);
- void operator = (const wchar_t* str);
- void operator = (const String& src);
- void operator = (const StringBuffer& src);
-
- // Addition
- void operator += (const String& src);
- void operator += (const char* psrc) { AppendString(psrc); }
- void operator += (const wchar_t* psrc) { AppendString(psrc); }
- void operator += (char ch) { AppendChar(ch); }
- String operator + (const char* str) const;
- String operator + (const String& src) const;
-
- // Comparison
- bool operator == (const String& str) const
- {
- return (OVR_strcmp(GetData()->Data, str.GetData()->Data)== 0);
- }
-
- bool operator != (const String& str) const
- {
- return !operator == (str);
- }
-
- bool operator == (const char* str) const
- {
- return OVR_strcmp(GetData()->Data, str) == 0;
- }
-
- bool operator != (const char* str) const
- {
- return !operator == (str);
- }
-
- bool operator < (const char* pstr) const
- {
- return OVR_strcmp(GetData()->Data, pstr) < 0;
- }
-
- bool operator < (const String& str) const
- {
- return *this < str.GetData()->Data;
- }
-
- bool operator > (const char* pstr) const
- {
- return OVR_strcmp(GetData()->Data, pstr) > 0;
- }
-
- bool operator > (const String& str) const
- {
- return *this > str.GetData()->Data;
- }
-
- int CompareNoCase(const char* pstr) const
- {
- return CompareNoCase(GetData()->Data, pstr);
- }
- int CompareNoCase(const String& str) const
- {
- return CompareNoCase(GetData()->Data, str.ToCStr());
- }
-
- // Accesses raw bytes
- const char& operator [] (int index) const
- {
- OVR_ASSERT(index >= 0 && (UPInt)index < GetSize());
- return GetData()->Data[index];
- }
- const char& operator [] (UPInt index) const
- {
- OVR_ASSERT(index < GetSize());
- return GetData()->Data[index];
- }
-
-
- // Case insensitive keys are used to look up insensitive string in hash tables
- // for SWF files with version before SWF 7.
- struct NoCaseKey
- {
- const String* pStr;
- NoCaseKey(const String &str) : pStr(&str){};
- };
-
- bool operator == (const NoCaseKey& strKey) const
- {
- return (CompareNoCase(ToCStr(), strKey.pStr->ToCStr()) == 0);
- }
- bool operator != (const NoCaseKey& strKey) const
- {
- return !(CompareNoCase(ToCStr(), strKey.pStr->ToCStr()) == 0);
- }
-
- // Hash functor used for strings.
- struct HashFunctor
- {
- UPInt operator()(const String& data) const
- {
- UPInt size = data.GetSize();
- return String::BernsteinHashFunction((const char*)data, size);
- }
- };
- // Case-insensitive hash functor used for strings. Supports additional
- // lookup based on NoCaseKey.
- struct NoCaseHashFunctor
- {
- UPInt operator()(const String& data) const
- {
- UPInt size = data.GetSize();
- return String::BernsteinHashFunctionCIS((const char*)data, size);
- }
- UPInt operator()(const NoCaseKey& data) const
- {
- UPInt size = data.pStr->GetSize();
- return String::BernsteinHashFunctionCIS((const char*)data.pStr->ToCStr(), size);
- }
- };
-
-};
-
-
-//-----------------------------------------------------------------------------------
-// ***** String Buffer used for Building Strings
-
-class StringBuffer
-{
- char* pData;
- UPInt Size;
- UPInt BufferSize;
- UPInt GrowSize;
- mutable bool LengthIsSize;
-
-public:
-
- // Constructors / Destructor.
- StringBuffer();
- explicit StringBuffer(UPInt growSize);
- StringBuffer(const char* data);
- StringBuffer(const char* data, UPInt buflen);
- StringBuffer(const String& src);
- StringBuffer(const StringBuffer& src);
- explicit StringBuffer(const wchar_t* data);
- ~StringBuffer();
-
-
- // Modify grow size used for growing/shrinking the buffer.
- UPInt GetGrowSize() const { return GrowSize; }
- void SetGrowSize(UPInt growSize);
-
-
- // *** General Functions
- // Does not release memory, just sets Size to 0
- void Clear();
-
- // For casting to a pointer to char.
- operator const char*() const { return (pData) ? pData : ""; }
- // Pointer to raw buffer.
- const char* ToCStr() const { return (pData) ? pData : ""; }
-
- // Returns number of bytes.
- UPInt GetSize() const { return Size ; }
- // Tells whether or not the string is empty.
- bool IsEmpty() const { return GetSize() == 0; }
-
- // Returns number of characters
- UPInt GetLength() const;
-
- // Returns character at the specified index
- UInt32 GetCharAt(UPInt index) const;
- UInt32 GetFirstCharAt(UPInt index, const char** offset) const;
- UInt32 GetNextChar(const char** offset) const;
-
-
- // Resize the string to the new size
- void Resize(UPInt _size);
- void Reserve(UPInt _size);
-
- // Appends a character
- void AppendChar(UInt32 ch);
-
- // Append a string
- void AppendString(const wchar_t* pstr, SPInt len = -1);
- void AppendString(const char* putf8str, SPInt utf8StrSz = -1);
- void AppendFormat(const char* format, ...);
-
- // Assigned a string with dynamic data (copied through initializer).
- //void AssignString(const InitStruct& src, UPInt size);
-
- // Inserts substr at posAt
- void Insert (const char* substr, UPInt posAt, SPInt len = -1);
- // Inserts character at posAt
- UPInt InsertCharAt(UInt32 c, UPInt posAt);
-
- // Assignment
- void operator = (const char* str);
- void operator = (const wchar_t* str);
- void operator = (const String& src);
-
- // Addition
- void operator += (const String& src) { AppendString(src.ToCStr(),src.GetSize()); }
- void operator += (const char* psrc) { AppendString(psrc); }
- void operator += (const wchar_t* psrc) { AppendString(psrc); }
- void operator += (char ch) { AppendChar(ch); }
- //String operator + (const char* str) const ;
- //String operator + (const String& src) const ;
-
- // Accesses raw bytes
- char& operator [] (int index)
- {
- OVR_ASSERT(((UPInt)index) < GetSize());
- return pData[index];
- }
- char& operator [] (UPInt index)
- {
- OVR_ASSERT(index < GetSize());
- return pData[index];
- }
-
- const char& operator [] (int index) const
- {
- OVR_ASSERT(((UPInt)index) < GetSize());
- return pData[index];
- }
- const char& operator [] (UPInt index) const
- {
- OVR_ASSERT(index < GetSize());
- return pData[index];
- }
-};
-
-
-//
-// Wrapper for string data. The data must have a guaranteed
-// lifespan throughout the usage of the wrapper. Not intended for
-// cached usage. Not thread safe.
-//
-class StringDataPtr
-{
-public:
- StringDataPtr() : pStr(NULL), Size(0) {}
- StringDataPtr(const StringDataPtr& p)
- : pStr(p.pStr), Size(p.Size) {}
- StringDataPtr(const char* pstr, UPInt sz)
- : pStr(pstr), Size(sz) {}
- StringDataPtr(const char* pstr)
- : pStr(pstr), Size((pstr != NULL) ? OVR_strlen(pstr) : 0) {}
- explicit StringDataPtr(const String& str)
- : pStr(str.ToCStr()), Size(str.GetSize()) {}
- template <typename T, int N>
- StringDataPtr(const T (&v)[N])
- : pStr(v), Size(N) {}
-
-public:
- const char* ToCStr() const { return pStr; }
- UPInt GetSize() const { return Size; }
- bool IsEmpty() const { return GetSize() == 0; }
-
- // value is a prefix of this string
- // Character's values are not compared.
- bool IsPrefix(const StringDataPtr& value) const
- {
- return ToCStr() == value.ToCStr() && GetSize() >= value.GetSize();
- }
- // value is a suffix of this string
- // Character's values are not compared.
- bool IsSuffix(const StringDataPtr& value) const
- {
- return ToCStr() <= value.ToCStr() && (End()) == (value.End());
- }
-
- // Find first character.
- // init_ind - initial index.
- SPInt FindChar(char c, UPInt init_ind = 0) const
- {
- for (UPInt i = init_ind; i < GetSize(); ++i)
- if (pStr[i] == c)
- return static_cast<SPInt>(i);
-
- return -1;
- }
-
- // Find last character.
- // init_ind - initial index.
- SPInt FindLastChar(char c, UPInt init_ind = ~0) const
- {
- if (init_ind == (UPInt)~0 || init_ind > GetSize())
- init_ind = GetSize();
- else
- ++init_ind;
-
- for (UPInt i = init_ind; i > 0; --i)
- if (pStr[i - 1] == c)
- return static_cast<SPInt>(i - 1);
-
- return -1;
- }
-
- // Create new object and trim size bytes from the left.
- StringDataPtr GetTrimLeft(UPInt size) const
- {
- // Limit trim size to the size of the string.
- size = Alg::PMin(GetSize(), size);
-
- return StringDataPtr(ToCStr() + size, GetSize() - size);
- }
- // Create new object and trim size bytes from the right.
- StringDataPtr GetTrimRight(UPInt size) const
- {
- // Limit trim to the size of the string.
- size = Alg::PMin(GetSize(), size);
-
- return StringDataPtr(ToCStr(), GetSize() - size);
- }
-
- // Create new object, which contains next token.
- // Useful for parsing.
- StringDataPtr GetNextToken(char separator = ':') const
- {
- UPInt cur_pos = 0;
- const char* cur_str = ToCStr();
-
- for (; cur_pos < GetSize() && cur_str[cur_pos]; ++cur_pos)
- {
- if (cur_str[cur_pos] == separator)
- {
- break;
- }
- }
-
- return StringDataPtr(ToCStr(), cur_pos);
- }
-
- // Trim size bytes from the left.
- StringDataPtr& TrimLeft(UPInt size)
- {
- // Limit trim size to the size of the string.
- size = Alg::PMin(GetSize(), size);
- pStr += size;
- Size -= size;
-
- return *this;
- }
- // Trim size bytes from the right.
- StringDataPtr& TrimRight(UPInt size)
- {
- // Limit trim to the size of the string.
- size = Alg::PMin(GetSize(), size);
- Size -= size;
-
- return *this;
- }
-
- const char* Begin() const { return ToCStr(); }
- const char* End() const { return ToCStr() + GetSize(); }
-
- // Hash functor used string data pointers
- struct HashFunctor
- {
- UPInt operator()(const StringDataPtr& data) const
- {
- return String::BernsteinHashFunction(data.ToCStr(), data.GetSize());
- }
- };
-
- bool operator== (const StringDataPtr& data) const
- {
- return (OVR_strncmp(pStr, data.pStr, data.Size) == 0);
- }
-
-protected:
- const char* pStr;
- UPInt Size;
-};
-
-} // OVR
-
-#endif
+/************************************************************************************
+
+PublicHeader: OVR.h
+Filename : OVR_String.h
+Content : String UTF8 string implementation with copy-on-write semantics
+ (thread-safe for assignment but not modification).
+Created : September 19, 2012
+Notes :
+
+Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved.
+
+Use of this software is subject to the terms of the Oculus license
+agreement provided at the time of installation or download, or which
+otherwise accompanies this software in either electronic or hard copy form.
+
+************************************************************************************/
+
+#ifndef OVR_String_h
+#define OVR_String_h
+
+#include "OVR_Types.h"
+#include "OVR_Allocator.h"
+#include "OVR_UTF8Util.h"
+#include "OVR_Atomic.h"
+#include "OVR_Std.h"
+#include "OVR_Alg.h"
+
+namespace OVR {
+
+// ***** Classes
+
+class String;
+class StringBuffer;
+
+
+//-----------------------------------------------------------------------------------
+// ***** String Class
+
+// String is UTF8 based string class with copy-on-write implementation
+// for assignment.
+
+class String
+{
+protected:
+
+ enum FlagConstants
+ {
+ //Flag_GetLength = 0x7FFFFFFF,
+ // This flag is set if GetLength() == GetSize() for a string.
+ // Avoid extra scanning is Substring and indexing logic.
+ Flag_LengthIsSizeShift = (sizeof(UPInt)*8 - 1)
+ };
+
+
+ // Internal structure to hold string data
+ struct DataDesc
+ {
+ // Number of bytes. Will be the same as the number of chars if the characters
+ // are ascii, may not be equal to number of chars in case string data is UTF8.
+ UPInt Size;
+ volatile SInt32 RefCount;
+ char Data[1];
+
+ void AddRef()
+ {
+ AtomicOps<SInt32>::ExchangeAdd_NoSync(&RefCount, 1);
+ }
+ // Decrement ref count. This needs to be thread-safe, since
+ // a different thread could have also decremented the ref count.
+ // For example, if u start off with a ref count = 2. Now if u
+ // decrement the ref count and check against 0 in different
+ // statements, a different thread can also decrement the ref count
+ // in between our decrement and checking against 0 and will find
+ // the ref count = 0 and delete the object. This will lead to a crash
+ // when context switches to our thread and we'll be trying to delete
+ // an already deleted object. Hence decrementing the ref count and
+ // checking against 0 needs to made an atomic operation.
+ void Release()
+ {
+ if ((AtomicOps<SInt32>::ExchangeAdd_NoSync(&RefCount, -1) - 1) == 0)
+ OVR_FREE(this);
+ }
+
+ static UPInt GetLengthFlagBit() { return UPInt(1) << Flag_LengthIsSizeShift; }
+ UPInt GetSize() const { return Size & ~GetLengthFlagBit() ; }
+ UPInt GetLengthFlag() const { return Size & GetLengthFlagBit(); }
+ bool LengthIsSize() const { return GetLengthFlag() != 0; }
+ };
+
+ // Heap type of the string is encoded in the lower bits.
+ enum HeapType
+ {
+ HT_Global = 0, // Heap is global.
+ HT_Local = 1, // SF::String_loc: Heap is determined based on string's address.
+ HT_Dynamic = 2, // SF::String_temp: Heap is stored as a part of the class.
+ HT_Mask = 3
+ };
+
+ union {
+ DataDesc* pData;
+ UPInt HeapTypeBits;
+ };
+ typedef union {
+ DataDesc* pData;
+ UPInt HeapTypeBits;
+ } DataDescUnion;
+
+ inline HeapType GetHeapType() const { return (HeapType) (HeapTypeBits & HT_Mask); }
+
+ inline DataDesc* GetData() const
+ {
+ DataDescUnion u;
+ u.pData = pData;
+ u.HeapTypeBits = (u.HeapTypeBits & ~(UPInt)HT_Mask);
+ return u.pData;
+ }
+
+ inline void SetData(DataDesc* pdesc)
+ {
+ HeapType ht = GetHeapType();
+ pData = pdesc;
+ OVR_ASSERT((HeapTypeBits & HT_Mask) == 0);
+ HeapTypeBits |= ht;
+ }
+
+
+ DataDesc* AllocData(UPInt size, UPInt lengthIsSize);
+ DataDesc* AllocDataCopy1(UPInt size, UPInt lengthIsSize,
+ const char* pdata, UPInt copySize);
+ DataDesc* AllocDataCopy2(UPInt size, UPInt lengthIsSize,
+ const char* pdata1, UPInt copySize1,
+ const char* pdata2, UPInt copySize2);
+
+ // Special constructor to avoid data initalization when used in derived class.
+ struct NoConstructor { };
+ String(const NoConstructor&) { }
+
+public:
+
+ // For initializing string with dynamic buffer
+ struct InitStruct
+ {
+ virtual ~InitStruct() { }
+ virtual void InitString(char* pbuffer, UPInt size) const = 0;
+ };
+
+
+ // Constructors / Destructors.
+ String();
+ String(const char* data);
+ String(const char* data1, const char* pdata2, const char* pdata3 = 0);
+ String(const char* data, UPInt buflen);
+ String(const String& src);
+ String(const StringBuffer& src);
+ String(const InitStruct& src, UPInt size);
+ explicit String(const wchar_t* data);
+
+ // Destructor (Captain Obvious guarantees!)
+ ~String()
+ {
+ GetData()->Release();
+ }
+
+ // Declaration of NullString
+ static DataDesc NullData;
+
+
+ // *** General Functions
+
+ void Clear();
+
+ // For casting to a pointer to char.
+ operator const char*() const { return GetData()->Data; }
+ // Pointer to raw buffer.
+ const char* ToCStr() const { return GetData()->Data; }
+
+ // Returns number of bytes
+ UPInt GetSize() const { return GetData()->GetSize() ; }
+ // Tells whether or not the string is empty
+ bool IsEmpty() const { return GetSize() == 0; }
+
+ // Returns number of characters
+ UPInt GetLength() const;
+
+ // Returns character at the specified index
+ UInt32 GetCharAt(UPInt index) const;
+ UInt32 GetFirstCharAt(UPInt index, const char** offset) const;
+ UInt32 GetNextChar(const char** offset) const;
+
+ // Appends a character
+ void AppendChar(UInt32 ch);
+
+ // Append a string
+ void AppendString(const wchar_t* pstr, SPInt len = -1);
+ void AppendString(const char* putf8str, SPInt utf8StrSz = -1);
+
+ // Assigned a string with dynamic data (copied through initializer).
+ void AssignString(const InitStruct& src, UPInt size);
+ // Assigns string with known size.
+ void AssignString(const char* putf8str, UPInt size);
+
+ // Resize the string to the new size
+// void Resize(UPInt _size);
+
+ // Removes the character at posAt
+ void Remove(UPInt posAt, SPInt len = 1);
+
+ // Returns a String that's a substring of this.
+ // -start is the index of the first UTF8 character you want to include.
+ // -end is the index one past the last UTF8 character you want to include.
+ String Substring(UPInt start, UPInt end) const;
+
+ // Case-conversion
+ String ToUpper() const;
+ String ToLower() const;
+
+ // Inserts substr at posAt
+ String& Insert (const char* substr, UPInt posAt, SPInt len = -1);
+
+ // Inserts character at posAt
+ UPInt InsertCharAt(UInt32 c, UPInt posAt);
+
+ // Inserts substr at posAt, which is an index of a character (not byte).
+ // Of size is specified, it is in bytes.
+// String& Insert(const UInt32* substr, UPInt posAt, SPInt size = -1);
+
+ // Get Byte index of the character at position = index
+ UPInt GetByteIndex(UPInt index) const { return (UPInt)UTF8Util::GetByteIndex(index, GetData()->Data); }
+
+ // Utility: case-insensitive string compare. stricmp() & strnicmp() are not
+ // ANSI or POSIX, do not seem to appear in Linux.
+ static int OVR_STDCALL CompareNoCase(const char* a, const char* b);
+ static int OVR_STDCALL CompareNoCase(const char* a, const char* b, SPInt len);
+
+ // Hash function, case-insensitive
+ static UPInt OVR_STDCALL BernsteinHashFunctionCIS(const void* pdataIn, UPInt size, UPInt seed = 5381);
+
+ // Hash function, case-sensitive
+ static UPInt OVR_STDCALL BernsteinHashFunction(const void* pdataIn, UPInt size, UPInt seed = 5381);
+
+
+ // ***** File path parsing helper functions.
+ // Implemented in OVR_String_FilePath.cpp.
+
+ // Absolute paths can star with:
+ // - protocols: 'file://', 'http://'
+ // - windows drive: 'c:\'
+ // - UNC share name: '\\share'
+ // - unix root '/'
+ static bool HasAbsolutePath(const char* path);
+ static bool HasExtension(const char* path);
+ static bool HasProtocol(const char* path);
+
+ bool HasAbsolutePath() const { return HasAbsolutePath(ToCStr()); }
+ bool HasExtension() const { return HasExtension(ToCStr()); }
+ bool HasProtocol() const { return HasProtocol(ToCStr()); }
+
+ String GetProtocol() const; // Returns protocol, if any, with trailing '://'.
+ String GetPath() const; // Returns path with trailing '/'.
+ String GetFilename() const; // Returns filename, including extension.
+ String GetExtension() const; // Returns extension with a dot.
+
+ void StripProtocol(); // Strips front protocol, if any, from the string.
+ void StripExtension(); // Strips off trailing extension.
+
+
+ // Operators
+ // Assignment
+ void operator = (const char* str);
+ void operator = (const wchar_t* str);
+ void operator = (const String& src);
+ void operator = (const StringBuffer& src);
+
+ // Addition
+ void operator += (const String& src);
+ void operator += (const char* psrc) { AppendString(psrc); }
+ void operator += (const wchar_t* psrc) { AppendString(psrc); }
+ void operator += (char ch) { AppendChar(ch); }
+ String operator + (const char* str) const;
+ String operator + (const String& src) const;
+
+ // Comparison
+ bool operator == (const String& str) const
+ {
+ return (OVR_strcmp(GetData()->Data, str.GetData()->Data)== 0);
+ }
+
+ bool operator != (const String& str) const
+ {
+ return !operator == (str);
+ }
+
+ bool operator == (const char* str) const
+ {
+ return OVR_strcmp(GetData()->Data, str) == 0;
+ }
+
+ bool operator != (const char* str) const
+ {
+ return !operator == (str);
+ }
+
+ bool operator < (const char* pstr) const
+ {
+ return OVR_strcmp(GetData()->Data, pstr) < 0;
+ }
+
+ bool operator < (const String& str) const
+ {
+ return *this < str.GetData()->Data;
+ }
+
+ bool operator > (const char* pstr) const
+ {
+ return OVR_strcmp(GetData()->Data, pstr) > 0;
+ }
+
+ bool operator > (const String& str) const
+ {
+ return *this > str.GetData()->Data;
+ }
+
+ int CompareNoCase(const char* pstr) const
+ {
+ return CompareNoCase(GetData()->Data, pstr);
+ }
+ int CompareNoCase(const String& str) const
+ {
+ return CompareNoCase(GetData()->Data, str.ToCStr());
+ }
+
+ // Accesses raw bytes
+ const char& operator [] (int index) const
+ {
+ OVR_ASSERT(index >= 0 && (UPInt)index < GetSize());
+ return GetData()->Data[index];
+ }
+ const char& operator [] (UPInt index) const
+ {
+ OVR_ASSERT(index < GetSize());
+ return GetData()->Data[index];
+ }
+
+
+ // Case insensitive keys are used to look up insensitive string in hash tables
+ // for SWF files with version before SWF 7.
+ struct NoCaseKey
+ {
+ const String* pStr;
+ NoCaseKey(const String &str) : pStr(&str){};
+ };
+
+ bool operator == (const NoCaseKey& strKey) const
+ {
+ return (CompareNoCase(ToCStr(), strKey.pStr->ToCStr()) == 0);
+ }
+ bool operator != (const NoCaseKey& strKey) const
+ {
+ return !(CompareNoCase(ToCStr(), strKey.pStr->ToCStr()) == 0);
+ }
+
+ // Hash functor used for strings.
+ struct HashFunctor
+ {
+ UPInt operator()(const String& data) const
+ {
+ UPInt size = data.GetSize();
+ return String::BernsteinHashFunction((const char*)data, size);
+ }
+ };
+ // Case-insensitive hash functor used for strings. Supports additional
+ // lookup based on NoCaseKey.
+ struct NoCaseHashFunctor
+ {
+ UPInt operator()(const String& data) const
+ {
+ UPInt size = data.GetSize();
+ return String::BernsteinHashFunctionCIS((const char*)data, size);
+ }
+ UPInt operator()(const NoCaseKey& data) const
+ {
+ UPInt size = data.pStr->GetSize();
+ return String::BernsteinHashFunctionCIS((const char*)data.pStr->ToCStr(), size);
+ }
+ };
+
+};
+
+
+//-----------------------------------------------------------------------------------
+// ***** String Buffer used for Building Strings
+
+class StringBuffer
+{
+ char* pData;
+ UPInt Size;
+ UPInt BufferSize;
+ UPInt GrowSize;
+ mutable bool LengthIsSize;
+
+public:
+
+ // Constructors / Destructor.
+ StringBuffer();
+ explicit StringBuffer(UPInt growSize);
+ StringBuffer(const char* data);
+ StringBuffer(const char* data, UPInt buflen);
+ StringBuffer(const String& src);
+ StringBuffer(const StringBuffer& src);
+ explicit StringBuffer(const wchar_t* data);
+ ~StringBuffer();
+
+
+ // Modify grow size used for growing/shrinking the buffer.
+ UPInt GetGrowSize() const { return GrowSize; }
+ void SetGrowSize(UPInt growSize);
+
+
+ // *** General Functions
+ // Does not release memory, just sets Size to 0
+ void Clear();
+
+ // For casting to a pointer to char.
+ operator const char*() const { return (pData) ? pData : ""; }
+ // Pointer to raw buffer.
+ const char* ToCStr() const { return (pData) ? pData : ""; }
+
+ // Returns number of bytes.
+ UPInt GetSize() const { return Size ; }
+ // Tells whether or not the string is empty.
+ bool IsEmpty() const { return GetSize() == 0; }
+
+ // Returns number of characters
+ UPInt GetLength() const;
+
+ // Returns character at the specified index
+ UInt32 GetCharAt(UPInt index) const;
+ UInt32 GetFirstCharAt(UPInt index, const char** offset) const;
+ UInt32 GetNextChar(const char** offset) const;
+
+
+ // Resize the string to the new size
+ void Resize(UPInt _size);
+ void Reserve(UPInt _size);
+
+ // Appends a character
+ void AppendChar(UInt32 ch);
+
+ // Append a string
+ void AppendString(const wchar_t* pstr, SPInt len = -1);
+ void AppendString(const char* putf8str, SPInt utf8StrSz = -1);
+ void AppendFormat(const char* format, ...);
+
+ // Assigned a string with dynamic data (copied through initializer).
+ //void AssignString(const InitStruct& src, UPInt size);
+
+ // Inserts substr at posAt
+ void Insert (const char* substr, UPInt posAt, SPInt len = -1);
+ // Inserts character at posAt
+ UPInt InsertCharAt(UInt32 c, UPInt posAt);
+
+ // Assignment
+ void operator = (const char* str);
+ void operator = (const wchar_t* str);
+ void operator = (const String& src);
+
+ // Addition
+ void operator += (const String& src) { AppendString(src.ToCStr(),src.GetSize()); }
+ void operator += (const char* psrc) { AppendString(psrc); }
+ void operator += (const wchar_t* psrc) { AppendString(psrc); }
+ void operator += (char ch) { AppendChar(ch); }
+ //String operator + (const char* str) const ;
+ //String operator + (const String& src) const ;
+
+ // Accesses raw bytes
+ char& operator [] (int index)
+ {
+ OVR_ASSERT(((UPInt)index) < GetSize());
+ return pData[index];
+ }
+ char& operator [] (UPInt index)
+ {
+ OVR_ASSERT(index < GetSize());
+ return pData[index];
+ }
+
+ const char& operator [] (int index) const
+ {
+ OVR_ASSERT(((UPInt)index) < GetSize());
+ return pData[index];
+ }
+ const char& operator [] (UPInt index) const
+ {
+ OVR_ASSERT(index < GetSize());
+ return pData[index];
+ }
+};
+
+
+//
+// Wrapper for string data. The data must have a guaranteed
+// lifespan throughout the usage of the wrapper. Not intended for
+// cached usage. Not thread safe.
+//
+class StringDataPtr
+{
+public:
+ StringDataPtr() : pStr(NULL), Size(0) {}
+ StringDataPtr(const StringDataPtr& p)
+ : pStr(p.pStr), Size(p.Size) {}
+ StringDataPtr(const char* pstr, UPInt sz)
+ : pStr(pstr), Size(sz) {}
+ StringDataPtr(const char* pstr)
+ : pStr(pstr), Size((pstr != NULL) ? OVR_strlen(pstr) : 0) {}
+ explicit StringDataPtr(const String& str)
+ : pStr(str.ToCStr()), Size(str.GetSize()) {}
+ template <typename T, int N>
+ StringDataPtr(const T (&v)[N])
+ : pStr(v), Size(N) {}
+
+public:
+ const char* ToCStr() const { return pStr; }
+ UPInt GetSize() const { return Size; }
+ bool IsEmpty() const { return GetSize() == 0; }
+
+ // value is a prefix of this string
+ // Character's values are not compared.
+ bool IsPrefix(const StringDataPtr& value) const
+ {
+ return ToCStr() == value.ToCStr() && GetSize() >= value.GetSize();
+ }
+ // value is a suffix of this string
+ // Character's values are not compared.
+ bool IsSuffix(const StringDataPtr& value) const
+ {
+ return ToCStr() <= value.ToCStr() && (End()) == (value.End());
+ }
+
+ // Find first character.
+ // init_ind - initial index.
+ SPInt FindChar(char c, UPInt init_ind = 0) const
+ {
+ for (UPInt i = init_ind; i < GetSize(); ++i)
+ if (pStr[i] == c)
+ return static_cast<SPInt>(i);
+
+ return -1;
+ }
+
+ // Find last character.
+ // init_ind - initial index.
+ SPInt FindLastChar(char c, UPInt init_ind = ~0) const
+ {
+ if (init_ind == (UPInt)~0 || init_ind > GetSize())
+ init_ind = GetSize();
+ else
+ ++init_ind;
+
+ for (UPInt i = init_ind; i > 0; --i)
+ if (pStr[i - 1] == c)
+ return static_cast<SPInt>(i - 1);
+
+ return -1;
+ }
+
+ // Create new object and trim size bytes from the left.
+ StringDataPtr GetTrimLeft(UPInt size) const
+ {
+ // Limit trim size to the size of the string.
+ size = Alg::PMin(GetSize(), size);
+
+ return StringDataPtr(ToCStr() + size, GetSize() - size);
+ }
+ // Create new object and trim size bytes from the right.
+ StringDataPtr GetTrimRight(UPInt size) const
+ {
+ // Limit trim to the size of the string.
+ size = Alg::PMin(GetSize(), size);
+
+ return StringDataPtr(ToCStr(), GetSize() - size);
+ }
+
+ // Create new object, which contains next token.
+ // Useful for parsing.
+ StringDataPtr GetNextToken(char separator = ':') const
+ {
+ UPInt cur_pos = 0;
+ const char* cur_str = ToCStr();
+
+ for (; cur_pos < GetSize() && cur_str[cur_pos]; ++cur_pos)
+ {
+ if (cur_str[cur_pos] == separator)
+ {
+ break;
+ }
+ }
+
+ return StringDataPtr(ToCStr(), cur_pos);
+ }
+
+ // Trim size bytes from the left.
+ StringDataPtr& TrimLeft(UPInt size)
+ {
+ // Limit trim size to the size of the string.
+ size = Alg::PMin(GetSize(), size);
+ pStr += size;
+ Size -= size;
+
+ return *this;
+ }
+ // Trim size bytes from the right.
+ StringDataPtr& TrimRight(UPInt size)
+ {
+ // Limit trim to the size of the string.
+ size = Alg::PMin(GetSize(), size);
+ Size -= size;
+
+ return *this;
+ }
+
+ const char* Begin() const { return ToCStr(); }
+ const char* End() const { return ToCStr() + GetSize(); }
+
+ // Hash functor used string data pointers
+ struct HashFunctor
+ {
+ UPInt operator()(const StringDataPtr& data) const
+ {
+ return String::BernsteinHashFunction(data.ToCStr(), data.GetSize());
+ }
+ };
+
+ bool operator== (const StringDataPtr& data) const
+ {
+ return (OVR_strncmp(pStr, data.pStr, data.Size) == 0);
+ }
+
+protected:
+ const char* pStr;
+ UPInt Size;
+};
+
+} // OVR
+
+#endif