gwnavruntime/kernel/SF_String.h Source File

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