gwnavruntime/kernel/SF_String.h Source File

SF_String.h
Go to the documentation of this file.
1 /*
2 * Copyright 2015 Autodesk, Inc. All rights reserved.
3 * Use of this software is subject to the terms of the Autodesk license agreement and any attachments or Appendices thereto provided at the time of installation or download,
4 * or which otherwise accompanies this software in either electronic or hard copy form, or which is signed by you and accepted by Autodesk.
5 */
6 
7 /**************************************************************************
8 
9 PublicHeader: None
10 Filename : KY_String.h
11 Content : String UTF8 string implementation with copy-on
12  write semantics (thread-safe for assignment but not
13  modification).
14 Created : April 27, 2007
15 Authors : Ankur Mohan, Michael Antonov
16 
17 **************************************************************************/
18 
19 #ifndef INC_KY_Kernel_String_H
20 #define INC_KY_Kernel_String_H
21 
22 #include <string.h>
29 
30 namespace Kaim {
31 
32 // ***** Classes
33 
34 class String;
35 class StringLH;
36 class StringDH;
37 class StringBuffer;
38 class StringDataPtr;
39 
40 
41 // ***** String Class
42 
43 // String is UTF8 based string class with heap support. There are several
44 // versions of string used to manage different heaps:
45 //
46 // String - Allocates memory from global heap by default.
47 // StringLH - Allocates memory from local heap based on 'this' pointer,
48 // so it can only be constructed in allocated data structures.
49 // StringDH - Allocates from a heap explicitly specified in constructor
50 // argument; mostly used for temporaries which are later assigned
51 // to the local heap strings.
52 //
53 // String is a base to the other two classes, allowing all string argument
54 // passing to be done by String&, passing a specific derived class is not
55 // necessary. Strings do NOT mutate heaps on assignment, so a data copy will
56 // be made if a string is copied to a different heap; this copy and allocation
57 // is avoided if heaps on both sides of assignment do match.
58 
59 
60 class String
61 {
62  friend class StringLH;
63  friend class StringDH;
64 
65 protected:
66 
67  enum FlagConstants
68  {
69  //Flag_GetLength = 0x7FFFFFFF,
70  // This flag is set if GetLength() == GetSize() for a string.
71  // Avoid extra scanning is Substring and indexing logic.
72  Flag_LengthIsSizeShift = (sizeof(UPInt)*8 - 1)
73  };
74 
75 
76  // Internal structure to hold string data
77  struct DataDesc
78  {
79  // Number of bytes. Will be the same as the number of chars if the characters
80  // are ascii, may not be equal to number of chars in case string data is UTF8.
81  UPInt Size;
82  volatile SInt32 RefCount;
83  char Data[1];
84 
85  void AddRef()
86  {
87  AtomicOps<SInt32>::ExchangeAdd_NoSync(&RefCount, 1);
88  }
89  // Decrement ref count. This needs to be thread-safe, since
90  // a different thread could have also decremented the ref count.
91  // For example, if u start off with a ref count = 2. Now if u
92  // decrement the ref count and check against 0 in different
93  // statements, a different thread can also decrement the ref count
94  // in between our decrement and checking against 0 and will find
95  // the ref count = 0 and delete the object. This will lead to a crash
96  // when context switches to our thread and we'll be trying to delete
97  // an already deleted object. Hence decrementing the ref count and
98  // checking against 0 needs to made an atomic operation.
99  void Release()
100  {
101  if ((AtomicOps<SInt32>::ExchangeAdd_NoSync(&RefCount, -1) - 1) == 0)
102  KY_FREE(this);
103  }
104 
105  static UPInt GetLengthFlagBit() { return UPInt(1) << Flag_LengthIsSizeShift; }
106  UPInt GetSize() const { return Size & ~GetLengthFlagBit() ; }
107  UPInt GetLengthFlag() const { return Size & GetLengthFlagBit(); }
108  bool LengthIsSize() const { return GetLengthFlag() != 0; }
109  };
110 
111  // Heap type of the string is encoded in the lower bits.
112  enum HeapType
113  {
114  HT_Global = 0, // Heap is global.
115  HT_Local = 1, // SF::String_loc: Heap is determined based on string's address.
116  HT_Dynamic = 2, // SF::String_temp: Heap is stored as a part of the class.
117  HT_Mask = 3
118  };
119 
120  union {
121  DataDesc* pData;
122  UPInt HeapTypeBits;
123  };
124  typedef union {
125  DataDesc* pData;
126  UPInt HeapTypeBits;
127  } DataDescUnion;
128 
129  inline HeapType GetHeapType() const { return (HeapType) (HeapTypeBits & HT_Mask); }
130 
131  inline DataDesc* GetData() const
132  {
133  DataDescUnion u;
134  u.pData = pData;
135  u.HeapTypeBits = (u.HeapTypeBits & ~(UPInt)HT_Mask);
136  return u.pData;
137  }
138 
139  inline void SetData(DataDesc* pdesc)
140  {
141  HeapType ht = GetHeapType();
142  pData = pdesc;
143  KY_ASSERT((HeapTypeBits & HT_Mask) == 0);
144  HeapTypeBits |= ht;
145  }
146 
147 
148  DataDesc* AllocData(MemoryHeap* pheap, UPInt size, UPInt lengthIsSize);
149  DataDesc* AllocDataCopy1(MemoryHeap* pheap, UPInt size, UPInt lengthIsSize,
150  const char* pdata, UPInt copySize);
151  DataDesc* AllocDataCopy2(MemoryHeap* pheap, UPInt size, UPInt lengthIsSize,
152  const char* pdata1, UPInt copySize1,
153  const char* pdata2, UPInt copySize2);
154 
155  // Special constructor to avoid data initalization when used in derived class.
156  struct NoConstructor { };
157  String(const NoConstructor&) { }
158 
159 public:
160 
161  // For initializing string with dynamic buffer
162  struct InitStruct
163  {
164  virtual ~InitStruct() { }
165  virtual void InitString(char* pbuffer, UPInt size) const = 0;
166  };
167 
168 
169  // Constructors / Destructors.
170  String();
171  String(const char* data);
172  String(const char* data1, const char* pdata2, const char* pdata3 = 0);
173  String(const char* data, UPInt buflen);
174  String(const String& src);
175  String(const StringBuffer& src);
176  String(const StringDataPtr src);
177  String(const InitStruct& src, UPInt size);
178  explicit String(const wchar_t* data);
179 
180  // Destructor (Captain Obvious guarantees!)
181  ~String()
182  {
183  GetData()->Release();
184  }
185 
186  // Declaration of NullString
187  static DataDesc NullData;
188 
189  MemoryHeap* GetHeap() const;
190 
191 
192  // *** General Functions
193 
194  void Clear();
195 
196  // For casting to a pointer to char.
197  operator const char*() const { return GetData()->Data; }
198  // Pointer to raw buffer.
199  const char* ToCStr() const { return GetData()->Data; }
200 
201  // Returns number of bytes
202  UPInt GetSize() const { return GetData()->GetSize() ; }
203  // Tells whether or not the string is empty
204  bool IsEmpty() const { return GetSize() == 0; }
205 
206  // Returns number of characters
207  UPInt GetLength() const;
208 
209  // Returns character at the specified index
210  UInt32 GetCharAt(UPInt index) const;
211  UInt32 GetFirstCharAt(UPInt index, const char** offset) const;
212  UInt32 GetNextChar(const char** offset) const;
213 
214  // Appends a character
215  void AppendChar(UInt32 ch);
216 
217  // Append a string
218  void AppendString(const wchar_t* pstr, SPInt len = -1);
219  void AppendString(const char* putf8str, SPInt utf8StrSz = -1);
220 
221  // Assigned a string with dynamic data (copied through initializer).
222  void AssignString(const InitStruct& src, UPInt size);
223  // Assigns string with known size.
224  void AssignString(const char* putf8str, UPInt size);
225 
226  // Resize the string to the new size
227 // void Resize(UPInt _size);
228 
229  // Removes the character at posAt
230  void Remove(UPInt posAt, SPInt len = 1);
231 
232  // Returns a String that's a substring of this.
233  // -start is the index of the first UTF8 character you want to include.
234  // -end is the index one past the last UTF8 character you want to include.
235  String Substring(UPInt start, UPInt end) const;
236 
237  // Case-conversion
238  String ToUpper() const;
239  String ToLower() const;
240 
241  // Inserts substr at posAt
242  String& Insert (const char* substr, UPInt posAt, SPInt len = -1);
243 
244  // Inserts character at posAt
245  UPInt InsertCharAt(UInt32 c, UPInt posAt);
246 
247  // Inserts substr at posAt, which is an index of a character (not byte).
248  // Of size is specified, it is in bytes.
249 // String& Insert(const UInt32* substr, UPInt posAt, SPInt size = -1);
250 
251  // Get Byte index of the character at position = index
252  UPInt GetByteIndex(UPInt index) const { return (UPInt)UTF8Util::GetByteIndex(index, GetData()->Data); }
253 
254  // Utility: case-insensitive string compare. stricmp() & strnicmp() are not
255  // ANSI or POSIX, do not seem to appear in Linux.
256  static int KY_STDCALL CompareNoCase(const char* a, const char* b);
257  static int KY_STDCALL CompareNoCase(const char* a, const char* b, SPInt len);
258 
259  // Hash function, case-insensitive
260  static UPInt KY_STDCALL BernsteinHashFunctionCIS(const void* pdataIn, UPInt size, UPInt seed = 5381);
261 
262  // Hash function, case-sensitive
263  static UPInt KY_STDCALL BernsteinHashFunction(const void* pdataIn, UPInt size, UPInt seed = 5381);
264 
265  // Encode/decode special html chars
266  static void KY_STDCALL EscapeSpecialHTML(const char* psrc, UPInt length, String* pescapedStr);
267  static void KY_STDCALL UnescapeSpecialHTML(const char* psrc, UPInt length, String* punescapedStr);
268 
269 
270  // ***** File path parsing helper functions.
271  // Implemented in KY_String_FilePath.cpp.
272 
273  // Absolute paths can star with:
274  // - protocols: 'file://', 'http://'
275  // - windows drive: 'c:\'
276  // - UNC share name: '\\share'
277  // - unix root '/'
278  static bool HasAbsolutePath(const char* path);
279  static bool HasExtension(const char* path);
280  static bool HasProtocol(const char* path);
281 
282  bool HasAbsolutePath() const { return HasAbsolutePath(ToCStr()); }
283  bool HasExtension() const { return HasExtension(ToCStr()); }
284  bool HasProtocol() const { return HasProtocol(ToCStr()); }
285 
286  String GetProtocol() const; // Returns protocol, if any, with trailing '://'.
287  String GetPath() const; // Returns path with trailing '/'.
288  String GetFilename() const; // Returns filename, including extension.
289  String GetExtension() const; // Returns extension with a dot.
290 
291  String& StripProtocol(); // Strips front protocol, if any, from the string.
292  String& StripExtension(); // Strips off trailing extension.
293 
294 
295  // Operators
296  // Assignment
297  void operator = (const char* str);
298  void operator = (const wchar_t* str);
299  void operator = (const String& src);
300  void operator = (const StringBuffer& src);
301 
302  // Addition
303  void operator += (const String& src);
304  void operator += (const char* psrc) { AppendString(psrc); }
305  void operator += (const wchar_t* psrc) { AppendString(psrc); }
306  void operator += (char ch) { AppendChar(ch); }
307  String operator + (const char* str) const;
308  String operator + (const String& src) const;
309 
310  // Comparison
311  bool operator == (const String& str) const
312  {
313  return (SFstrcmp(GetData()->Data, str.GetData()->Data)== 0);
314  }
315 
316  bool operator != (const String& str) const
317  {
318  return !operator == (str);
319  }
320 
321  bool operator == (const char* str) const
322  {
323  return SFstrcmp(GetData()->Data, str) == 0;
324  }
325 
326  bool operator != (const char* str) const
327  {
328  return !operator == (str);
329  }
330 
331  bool operator < (const char* pstr) const
332  {
333  return SFstrcmp(GetData()->Data, pstr) < 0;
334  }
335 
336  bool operator < (const String& str) const
337  {
338  return *this < str.GetData()->Data;
339  }
340 
341  bool operator > (const char* pstr) const
342  {
343  return SFstrcmp(GetData()->Data, pstr) > 0;
344  }
345 
346  bool operator > (const String& str) const
347  {
348  return *this > str.GetData()->Data;
349  }
350 
351  int CompareNoCase(const char* pstr) const
352  {
353  return CompareNoCase(GetData()->Data, pstr);
354  }
355  int CompareNoCase(const String& str) const
356  {
357  return CompareNoCase(GetData()->Data, str.ToCStr());
358  }
359 
360  // Accesses raw bytes
361  const char& operator [] (int index) const
362  {
363  KY_ASSERT(index >= 0 && (UPInt)index < GetSize());
364  return GetData()->Data[index];
365  }
366  const char& operator [] (UPInt index) const
367  {
368  KY_ASSERT(index < GetSize());
369  return GetData()->Data[index];
370  }
371 
372 
373  // Case insensitive keys are used to look up insensitive string in hash tables
374  // for SWF files with version before SWF 7.
375  struct NoCaseKey
376  {
377  const String* pStr;
378  NoCaseKey(const String &str) : pStr(&str){};
379  };
380 
381  bool operator == (const NoCaseKey& strKey) const
382  {
383  return (CompareNoCase(ToCStr(), strKey.pStr->ToCStr()) == 0);
384  }
385  bool operator != (const NoCaseKey& strKey) const
386  {
387  return !(CompareNoCase(ToCStr(), strKey.pStr->ToCStr()) == 0);
388  }
389 
390  // Hash functor used for strings.
391  struct HashFunctor
392  {
393  UPInt operator()(const String& data) const
394  {
395  UPInt size = data.GetSize();
396  return String::BernsteinHashFunction((const char*)data, size);
397  }
398  };
399  // Case-insensitive hash functor used for strings. Supports additional
400  // lookup based on NoCaseKey.
401  struct NoCaseHashFunctor
402  {
403  UPInt operator()(const String& data) const
404  {
405  UPInt size = data.GetSize();
406  return String::BernsteinHashFunctionCIS((const char*)data, size);
407  }
408  UPInt operator()(const NoCaseKey& data) const
409  {
410  UPInt size = data.pStr->GetSize();
411  return String::BernsteinHashFunctionCIS((const char*)data.pStr->ToCStr(), size);
412  }
413  };
414 
415 };
416 
417 
418 
419 // ***** Local Heap String - StringLH
420 
421 // A structure-local version of String, which determined its own memory
422 // heap based on 'this' pointer location. This class can not be created on
423 // stack or outside of an allocated memory heap. If cross-heap string assignment
424 // takes place, a copy of string data may be created.
425 
426 class StringLH : public String
427 {
428  // Initializes pData with Local heap flag.
429  void SetDataLcl(DataDesc* pdesc)
430  {
431  pData = pdesc;
432  KY_ASSERT((HeapTypeBits & HT_Mask) == 0);
433  HeapTypeBits |= HT_Local;
434  }
435 
436  void CopyConstructHelper(const String& src);
437 
438 public:
439  // Constructors / Destructors.
440  StringLH();
441  StringLH(const char* data);
442  StringLH(const char* data, UPInt buflen);
443  // We MUST have copy constructor, or compiler will generate an incorrect one calling base.
444  StringLH(const StringLH& src) : String(NoConstructor()) { CopyConstructHelper(src); }
445  explicit StringLH(const String& src) : String(NoConstructor()) { CopyConstructHelper(src); }
446  explicit StringLH(const InitStruct& src, UPInt size);
447  explicit StringLH(const wchar_t* data);
448 
449  // Assignment
450  void operator = (const char* str) { String::operator = (str); }
451  void operator = (const wchar_t* str) { String::operator = (str); }
452  void operator = (const String& src) { String::operator = (src); }
453  void operator = (const StringBuffer& src) { String::operator = (src); }
454 };
455 
456 
457 // ***** Dynamic Heap String - StringDH
458 
459 // A dynamic heap version of String, which stores its memory heap in an
460 // internal pointer. Note that assigning the string does NOT copy the heap.
461 
462 class StringDH : public String
463 {
464  MemoryHeap* pHeap;
465 
466  // Initializes pData with Local heap flag.
467  void SetDataLcl(DataDesc* pdesc)
468  {
469  pData = pdesc;
470  KY_ASSERT((HeapTypeBits & HT_Mask) == 0);
471  HeapTypeBits |= HT_Dynamic;
472  }
473 
474  void CopyConstructHelper(const String& src, MemoryHeap* pheap);
475 
476 public:
477  // Constructors / Destructors.
478  StringDH(MemoryHeap* pheap = Memory::GetGlobalHeap());
479  StringDH(MemoryHeap* pheap, const char* data);
480  StringDH(MemoryHeap* pheap, const char* data1, const char* pdata2, const char* pdata3 = 0);
481  StringDH(MemoryHeap* pheap, const char* data, UPInt buflen);
482  StringDH(const StringDH& src) : String(NoConstructor()) { CopyConstructHelper(src, src.GetHeap()); }
483  explicit StringDH(const String& src) : String(NoConstructor()) { CopyConstructHelper(src, 0); }
484  explicit StringDH(MemoryHeap* pheap, const String& src) : String(NoConstructor()) { CopyConstructHelper(src, pheap); }
485  explicit StringDH(MemoryHeap* pheap, const InitStruct& src, UPInt size);
486  explicit StringDH(MemoryHeap* pheap, const wchar_t* data);
487 
488  void operator = (const char* str) { String::operator = (str); }
489  void operator = (const wchar_t* str) { String::operator = (str); }
490  void operator = (const String& src) { String::operator = (src); }
491  void operator = (const StringBuffer& src) { String::operator = (src); }
492 
493  MemoryHeap* GetHeap() const { return pHeap; }
494 };
495 
496 
497 
498 
499 // ***** String Buffer used for Building Strings
500 
501 class StringBuffer
502 {
503  char* pData;
504  UPInt Size;
505  UPInt BufferSize;
506  UPInt GrowSize;
507  mutable bool LengthIsSize;
508  MemoryHeap* pHeap;
509 
510 public:
511 
512  // Constructors / Destructor.
513  StringBuffer(MemoryHeap* pheap = Memory::GetGlobalHeap());
514  explicit StringBuffer(UPInt growSize, MemoryHeap* pheap = Memory::GetGlobalHeap());
515  StringBuffer(const char* data, MemoryHeap* pheap = Memory::GetGlobalHeap());
516  StringBuffer(const char* data, UPInt buflen, MemoryHeap* pheap = Memory::GetGlobalHeap());
517  StringBuffer(const String& src, MemoryHeap* pheap = Memory::GetGlobalHeap());
518  StringBuffer(const StringBuffer& src, MemoryHeap* pheap = Memory::GetGlobalHeap());
519  explicit StringBuffer(const wchar_t* data, MemoryHeap* pheap = Memory::GetGlobalHeap());
520  ~StringBuffer();
521 
522 
523  MemoryHeap* GetHeap() const { return pHeap; }
524 
525  // Modify grow size used for growing/shrinking the buffer.
526  UPInt GetGrowSize() const { return GrowSize; }
527  void SetGrowSize(UPInt growSize);
528 
529 
530  // *** General Functions
531  // Does not release memory, just sets Size to 0
532  void Clear();
533 
534  // For casting to a pointer to char.
535  operator const char*() const { return (pData) ? pData : ""; }
536  // Pointer to raw buffer.
537  const char* ToCStr() const { return (pData) ? pData : ""; }
538 
539  // Returns number of bytes.
540  UPInt GetSize() const { return Size ; }
541  // Tells whether or not the string is empty.
542  bool IsEmpty() const { return GetSize() == 0; }
543 
544  // Returns number of characters
545  UPInt GetLength() const;
546 
547  // Returns character at the specified index
548  UInt32 GetCharAt(UPInt index) const;
549  UInt32 GetFirstCharAt(UPInt index, const char** offset) const;
550  UInt32 GetNextChar(const char** offset) const;
551 
552 
553  // Resize the string to the new size
554  void Resize(UPInt _size);
555  void Reserve(UPInt _size);
556 
557  // Appends a character
558  void AppendChar(UInt32 ch);
559 
560  // Append a string
561  void AppendString(const wchar_t* pstr, SPInt len = -1);
562  void AppendString(const char* putf8str, SPInt utf8StrSz = -1);
563 
564  // Assigned a string with dynamic data (copied through initializer).
565  //void AssignString(const InitStruct& src, UPInt size);
566 
567  // Inserts substr at posAt
568  void Insert (const char* substr, UPInt posAt, SPInt len = -1);
569  // Inserts character at posAt
570  UPInt InsertCharAt(UInt32 c, UPInt posAt);
571 
572  // Assignment
573  void operator = (const char* str);
574  void operator = (const wchar_t* str);
575  void operator = (const String& src);
576  void operator = (const StringBuffer& src);
577 
578  // Addition
579  void operator += (const StringBuffer& buff) { AppendString(buff.ToCStr(), buff.GetSize()); }
580  void operator += (const String& src) { AppendString(src.ToCStr(),src.GetSize()); }
581  void operator += (const char* psrc) { AppendString(psrc); }
582  void operator += (const wchar_t* psrc) { AppendString(psrc); }
583  void operator += (char ch) { AppendChar(ch); }
584  //String operator + (const char* str) const ;
585  //String operator + (const String& src) const ;
586 
587  // Accesses raw bytes
588  char& operator [] (int index)
589  {
590  KY_ASSERT(((UPInt)index) < GetSize());
591  return pData[index];
592  }
593  char& operator [] (UPInt index)
594  {
595  KY_ASSERT(index < GetSize());
596  return pData[index];
597  }
598 
599  const char& operator [] (int index) const
600  {
601  KY_ASSERT(((UPInt)index) < GetSize());
602  return pData[index];
603  }
604  const char& operator [] (UPInt index) const
605  {
606  KY_ASSERT(index < GetSize());
607  return pData[index];
608  }
609 };
610 
611 
612 //
613 // Wrapper for string data. The data must have a guaranteed
614 // lifespan throughout the usage of the wrapper. Not intended for
615 // cached usage. Not thread safe.
616 //
617 class StringDataPtr
618 {
619 public:
620  StringDataPtr() : pStr(NULL), Size(0) {}
621  StringDataPtr(const StringDataPtr& p)
622  : pStr(p.pStr), Size(p.Size) {}
623  StringDataPtr(const char* pstr, UPInt sz)
624  : pStr(pstr), Size(sz) {}
625  StringDataPtr(const char* pstr)
626  : pStr(pstr), Size((pstr != NULL) ? SFstrlen(pstr) : 0) {}
627  explicit StringDataPtr(const String& str)
628  : pStr(str.ToCStr()), Size(str.GetSize()) {}
629  template <typename T, int N>
630  StringDataPtr(const T (&v)[N])
631  : pStr(v), Size(N) {}
632 
633 public:
634  // Accesses raw bytes
635  char operator [] (UPInt index) const
636  {
637  KY_ASSERT(index < GetSize());
638  return pStr[index];
639  }
640 
641  const char* ToCStr() const { return pStr; }
642  UPInt GetSize() const { return Size; }
643  bool IsEmpty() const { return GetSize() == 0; }
644 
645  // value is a prefix of this string
646  // Character's values are not compared.
647  bool IsPrefix(const StringDataPtr& value) const
648  {
649  return ToCStr() == value.ToCStr() && GetSize() >= value.GetSize();
650  }
651  // value is a suffix of this string
652  // Character's values are not compared.
653  bool IsSuffix(const StringDataPtr& value) const
654  {
655  return ToCStr() <= value.ToCStr() && (End()) == (value.End());
656  }
657 
658  // Find first character.
659  // init_ind - initial index.
660  SPInt FindChar(char c, UPInt init_ind = 0) const
661  {
662  for (UPInt i = init_ind; i < GetSize(); ++i)
663  if (pStr[i] == c)
664  return static_cast<SPInt>(i);
665 
666  return -1;
667  }
668 
669  // Find last character.
670  // init_ind - initial index.
671  SPInt FindLastChar(char c, UPInt init_ind = ~0) const;
672 
673  // Find first substring.
674  SPInt FindSubstring(const StringDataPtr& s, UPInt init_ind = 0) const;
675 
676  // Create new object and trim size bytes from the left.
677  StringDataPtr GetTrimLeft(UPInt size) const
678  {
679  // Limit trim size to the size of the string.
680  size = Alg::PMin(GetSize(), size);
681 
682  return StringDataPtr(ToCStr() + size, GetSize() - size);
683  }
684  // Create new object and trim size bytes from the right.
685  StringDataPtr GetTrimRight(UPInt size) const
686  {
687  // Limit trim to the size of the string.
688  size = Alg::PMin(GetSize(), size);
689 
690  return StringDataPtr(ToCStr(), GetSize() - size);
691  }
692 
693  // Create new object, which contains next token.
694  // Useful for parsing.
695  StringDataPtr GetNextToken(char separator = ':') const;
696 
697  // Trim size bytes from the left.
698  StringDataPtr& TrimLeft(UPInt size)
699  {
700  // Limit trim size to the size of the string.
701  size = Alg::PMin(GetSize(), size);
702  pStr += size;
703  Size -= size;
704 
705  return *this;
706  }
707  // Trim size bytes from the right.
708  StringDataPtr& TrimRight(UPInt size)
709  {
710  // Limit trim to the size of the string.
711  size = Alg::PMin(GetSize(), size);
712  Size -= size;
713 
714  return *this;
715  }
716 
717  // Create new object. Prefix of size "size".
718  StringDataPtr GetPrefix(UPInt size) const
719  {
720  // Limit prefix size to the size of the string.
721  size = Alg::PMin(GetSize(), size);
722 
723  return StringDataPtr(ToCStr(), size);
724  }
725  // Create new object. Suffix of size "size".
726  StringDataPtr GetSuffix(UPInt size) const
727  {
728  // Limit suffix to the size of the string.
729  size = Alg::PMin(GetSize(), size);
730 
731  return StringDataPtr(ToCStr() + GetSize() - size, size);
732  }
733 
734  // Prefix of size "size".
735  StringDataPtr& Prefix(UPInt size)
736  {
737  // Limit prefix size to the size of the string.
738  Size = Alg::PMin(GetSize(), size);
739 
740  return *this;
741  }
742  // Suffix of size "size".
743  StringDataPtr& Suffix(UPInt size)
744  {
745  // Limit suffix to the size of the string.
746  size = Alg::PMin(GetSize(), size);
747 
748  pStr = ToCStr() + GetSize() - size;
749  Size = size;
750 
751  return *this;
752  }
753 
754  static bool IsWhiteSpace(UInt32 c);
755 
756  StringDataPtr GetTruncateWhitespace() const;
757  StringDataPtr& TruncateWhitespace()
758  {
759  *this = GetTruncateWhitespace();
760  return *this;
761  }
762 
763  const char* Begin() const { return ToCStr(); }
764  const char* End() const { return ToCStr() + GetSize(); }
765 
766  // Hash functor used string data pointers
767  struct HashFunctor
768  {
769  UPInt operator()(const StringDataPtr& data) const
770  {
771  return String::BernsteinHashFunction(data.ToCStr(), data.GetSize());
772  }
773  };
774 
775  bool operator==(const StringDataPtr& other) const
776  {
777  return (other.Size == Size &&
778  (other.pStr == pStr ||
779  (pStr && other.pStr && SFstrncmp(pStr, other.pStr, Size) == 0)));
780  }
781  bool operator!=(const StringDataPtr& other) const
782  {
783  return !operator==(other);
784  }
785 
786 public:
787  static StringDataPtr Null;
788 
789 protected:
790  const char* pStr;
791  UPInt Size;
792 };
793 
794 } // Scaleform
795 
796 #endif
Definition: gamekitcrowddispersion.h:20