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