HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
UT_StringHolder.h
Go to the documentation of this file.
1 /*
2  * PROPRIETARY INFORMATION. This software is proprietary to
3  * Side Effects Software Inc., and is not to be reproduced,
4  * transmitted, or disclosed in any way without written permission.
5  *
6  * NAME: UT_StringHolder.h
7  *
8  * COMMENTS: A simple holder for strings which acts like copy on
9  * write, but has special methods for minimizing memory
10  * copies when you know what you are doing.
11  *
12  * Has a trivial move constructor.
13  *
14  * c_str does not change when it moves.
15  */
16 
17 // #pragma once
18 
19 #ifndef __UT_StringHolder_h__
20 #define __UT_StringHolder_h__
21 
22 #include "UT_API.h"
23 #include "UT_Format.h"
24 #include "UT_String.h"
25 #include "UT_StringView.h"
26 #include "UT_Swap.h"
27 
28 #include <SYS/SYS_AtomicInt.h>
29 #include <SYS/SYS_Compiler.h>
30 #include <SYS/SYS_Inline.h>
31 #include <SYS/SYS_Pragma.h>
32 #include <SYS/SYS_StaticAssert.h>
33 #include <SYS/SYS_Types.h>
34 
35 #include <functional>
36 #include <iosfwd>
37 
38 #include <stdlib.h>
39 
40 class UT_IStream;
41 class UT_OStream;
42 class UT_StringHolder;
43 class UT_StringRef;
44 class UT_WorkBuffer;
45 
46 // Forward declare the UDSL so that we can friend it inside of UT_StringHolder.
47 namespace UT { inline namespace Literal {
48 UT_StringHolder operator"" _sh(const char *s, std::size_t const length);
49 } }
50 
51 /// A string literal with length and compile-time computed hash value.
52 /// @note This will only be compile-time when used in compile time expressions
53 /// like template parameters and constexpr variables.
54 /// @note String literals whose length requires more than 31 bits not supported
55 /// @see UT_StringRef
57 {
58 public:
59  constexpr SYS_FORCE_INLINE
61  : myData(nullptr)
62  , myLength(0)
63  , myHash(0)
64  {
65  }
66 
67  template <size_t N>
68  constexpr SYS_FORCE_INLINE
69  UT_StringLit(const char (&str)[N])
70  : myData(str)
71  , myLength(N-1)
72  , myHash(SYSstring_hash_inner(str, 0))
73  {
74  SYS_STATIC_ASSERT(N-1 < (((exint)1) << 31));
75  }
76 
77  SYS_FORCE_INLINE constexpr const char* buffer() const { return myData; }
78  SYS_FORCE_INLINE constexpr const char* data() const { return myData; }
79  SYS_FORCE_INLINE constexpr const char* c_str() const { return myData; }
80 
81  SYS_FORCE_INLINE constexpr exint length() const { return myLength; }
82 
83  SYS_FORCE_INLINE constexpr uint32 hash() const { return myHash; }
84 
86  SYS_FORCE_INLINE const UT_StringRef& asRef() const;
87 
88 private:
89  const char* myData;
90  int32 myLength;
91  uint32 myHash;
92 
93  friend class UT_StringRef;
94 };
95 
96 /// A holder for a string, which stores the length and caches the hash value.
97 /// A UT_StringRef does not necessarily own the string, and it is therefore not
98 /// safe to e.g. store a UT_StringRef in a container or member variable.
99 /// @see UT_StringHolder
100 /// @see UTmakeUnsafeRef
102 {
103 public:
104  typedef char value_type;
105 
107  {
111  STORE_INLINE
112  };
113 
115  {
116  public:
118  : myRefCount(0), myStorageMode(STORE_INLINE),
119  myHash(0), myLength(0), myData(0)
120  {
121  }
122 
123  static Holder *build(const char *str,
125  static Holder *buildFromData(const char *str,
126  exint len,
128  int hash = 0);
129  static Holder *buildBuffer(
130  exint length,
132 
133  const char *c_str() const
134  {
135  if (myStorageMode == STORE_INLINE)
136  return myDataIfInline;
137 
138  return myData;
139  }
140 
141  void incref()
142  {
143  myRefCount.add(1);
144  }
145  void decref()
146  {
147  if (myRefCount.add(-1) == 0)
148  {
149  // We can't invoke delete as we were malloced.
150  // Further, we have custom behaviour on ownership!
151  switch (myStorageMode)
152  {
153  case STORE_EXTERNAL:
154  case STORE_INLINE:
155  // Do nothing.
156  break;
157  case STORE_NEW:
158  delete [] myData;
159  break;
160  case STORE_MALLOC:
161  if (myData)
162  free( (void*)SYSconst_cast(myData));
163  break;
164  }
167  free(this);
169  }
170  }
171 
172  exint length() const
173  {
174  return myLength;
175  }
176 
177  unsigned hash() const
178  {
179  if (!myHash)
180  {
181  myHash = hash_string(c_str(), length());
182  }
183  return myHash;
184  }
185 
186  int64 getMemoryUsage(bool inclusive) const
187  {
188  int64 mem = inclusive ? sizeof(*this) : 0;
189 
190  switch (myStorageMode)
191  {
192  case STORE_EXTERNAL:
193  // Nothing extra.
194  break;
195  case STORE_INLINE:
196  UT_ASSERT_MSG_P(inclusive,
197  "If a Holder is STORE_INLINE, it *really* can't be a "
198  "member variable, because the size isn't determined "
199  "at runtime.");
200  mem += myLength + 1 - sizeof(const char *);
201  break;
202  case STORE_NEW:
203  case STORE_MALLOC:
204  // External reference we own.
205  mem += myLength + 1;
206  break;
207  }
208  return mem;
209  }
210 
211  private:
212  char *bufferNC() const
213  {
214  if (myStorageMode == STORE_INLINE)
215  return SYSconst_cast(myDataIfInline);
216 
217  return SYSconst_cast(myData);
218  }
219 
220  friend class UT_StringHolder;
221  friend class UT_StringRef;
222 
223  private:
224  SYS_AtomicInt32 myRefCount;
225  StorageMode myStorageMode;
226  mutable int myHash;
227  exint myLength;
228 
229  // This union makes viewing in a debugger much easier.
230  union {
231  const char *myData;
232  char myDataIfInline[sizeof(const char *)];
233  };
234  };
235 
238  {
239  init();
240  }
241 
242  /// Will make a shallow reference.
244  UT_StringRef(const char *str)
245  {
246  init();
247  if (UTisstring(str))
248  {
249  reference(str);
250  }
251  }
252 
253  /// Construct from string literal
254  SYS_FORCE_INLINE explicit
256  : UT_StringRef(lit.asRef())
257  {
258  }
259 
260  /// This will make a shallow reference to the contents of the string.
263  {
264  init();
265  const char *s = str.c_str();
266  if (UTisstring(s))
267  {
268  fastReferenceWithStrlen(s, str.length());
269  }
270  }
271 
272  /// This will make a shallow reference to the contents of the string.
273  UT_StringRef(const UT_WorkBuffer &str);
274 
275  /// This will make a shallow reference to the contents of the string.
278  {
279  init();
280  if (str.isstring())
281  reference(str);
282  }
283 
284  /// Shares a reference with the source.
287  {
288  Holder *sh = s.getHolder();
289  if (!isSentinelOrNullPtr(sh))
290  sh->incref();
291  // Can now blindly copy.
292  copy(s);
293  }
294 
295  /// Move constructor. Steals the working data from the original.
298  {
299  copy(s);
300  s.init();
301  }
302 
305  {
306  Holder *h = getHolder();
307  if (!isSentinelOrNullPtr(h))
308  h->decref();
309  }
310 
311  /// Special sentinel value support
312  /// @{
313  enum UT_StringSentinelType { SENTINEL };
314 
315  SYS_FORCE_INLINE explicit
317  : myData((const void*)SENTINEL_DATA)
318  , myLength(0)
319  , myHash(SENTINEL_HASH)
320  {
321  }
322 
324  bool isSentinel() const
325  {
326  return uintptr_t(myData) == SENTINEL_DATA && myHash == SENTINEL_HASH && !myLength;
327  }
328 
331  {
332  Holder *h = getHolder();
333  if (!isSentinelOrNullPtr(h))
334  h->decref();
335  myData = (const void*)SENTINEL_DATA;
336  myLength = 0;
337  myHash = SENTINEL_HASH;
338  }
339  /// @}
340 
341  /// Shares a reference with the source.
343  {
344  Holder *sh = s.getHolder();
345  Holder *th = getHolder();
346 
347  if (!isSentinelOrNullPtr(sh))
348  sh->incref();
349  if (!isSentinelOrNullPtr(th))
350  th->decref();
351  // Can now blindly copy.
352  copy(s);
353  return *this;
354  }
355 
356  /// Move the contents of about-to-be-destructed string
357  /// s to this string.
360  {
361  // Can just swap, since s is about to be destructed.
362  swap(s);
363  return *this;
364  }
365 
366  bool operator==(const UT_StringRef &s) const
367  {
368  // It is sensible to fast-path this based on myData!
369  // If our two pointers are equal, we either are pointing to
370  // the same Holder or to the same const char *, so are good
371  // to call it equal.
372  if (myData == s.myData)
373  return true;
374  exint tl = length();
375  exint sl = s.length();
376  if (tl != sl)
377  return false;
378  if (tl == 0)
379  return (uintptr_t(myData) == SENTINEL_DATA) == (uintptr_t(s.myData) == SENTINEL_DATA);
380  return ::memcmp(c_str(), s.c_str(), tl) == 0;
381  }
382  bool operator==(const char *s) const
383  {
384  // It is sensible to fast-path this based on myData!
385  // If our two pointers are equal, we either are pointing to
386  // the same Holder or to the same const char *, so are good
387  // to call it equal.
388  // We don't test for myData being a Holder because it should
389  // never alias a const char *.
390  if (myDataIfChars == s)
391  return true;
392  // Avoid comparison with null.
393  if (!s)
394  return !isstring();
395  return ::strcmp(c_str(), s) == 0;
396  }
397  bool operator==(const UT_String &s) const
398  { return operator==(s.buffer()); }
399 
400  bool operator!=(const UT_StringRef &s) const
401  { return !operator==(s); }
402  bool operator!=(const char *s) const
403  { return !operator==(s); }
404  bool operator!=(const UT_String &s) const
405  { return operator!=(s.buffer()); }
406 
407  bool operator<(const UT_StringRef &k) const
408  { return ::strcmp(c_str(), k.c_str()) < 0; }
409  bool operator<=(const UT_StringRef &k) const
410  { return ::strcmp(c_str(), k.c_str()) <= 0; }
411  bool operator>(const UT_StringRef &k) const
412  { return ::strcmp(c_str(), k.c_str()) > 0; }
413  bool operator>=(const UT_StringRef &k) const
414  { return ::strcmp(c_str(), k.c_str()) >= 0; }
415  int compare(const UT_StringRef &str,
416  bool ignore_case=false) const
417  { return ignore_case ?
418  SYSstrcasecmp(c_str(), str.c_str()) :
419  ::strcmp(c_str(), str.c_str()); }
420  bool equal(const UT_StringRef &str,
421  bool ignore_case=false) const
422  { return compare(str, ignore_case) == 0; }
423 
424  /// Test whether the string is defined or not
426  SYS_SAFE_BOOL operator bool() const { return isstring(); }
427 
428  /// Imported from UT_String.
429  bool startsWith(const char *prefix, bool case_sense = true,
430  exint len=-1) const
431  {
432  return UT_StringWrap(c_str()).startsWith(prefix, case_sense, len);
433  }
434  bool endsWith(const char *prefix, bool case_sense = true,
435  exint len=-1) const
436  {
437  return UT_StringWrap(c_str()).endsWith(prefix, case_sense, len);
438  }
439  unsigned match(const char *pattern, int caseSensitive=1) const
440  { return UT_StringWrap(c_str()).match(pattern, caseSensitive); }
441  bool contains(const char *pattern, bool case_sensitive=true) const
442  { return UT_StringWrap(c_str()).contains(pattern, case_sensitive); }
443  unsigned multiMatch(const char *pattern,
444  int caseSensitive, char separator) const
445  { return UT_StringWrap(c_str()).multiMatch(pattern, caseSensitive, separator); }
446  unsigned multiMatch(const char *pattern, int caseSensitive = 1,
447  const char *separators = ", ",
448  bool *explicitlyExcluded = 0,
449  int *matchIndex = 0,
450  ut_PatternRecord *pattern_record=NULL) const
451  { return UT_StringWrap(c_str()).multiMatch(pattern, caseSensitive, separators, explicitlyExcluded, matchIndex, pattern_record); }
452  unsigned multiMatch(const UT_StringMMPattern &pattern,
453  bool *explicitlyExcluded = 0,
454  int *matchIndex = 0,
455  ut_PatternRecord *pattern_record=NULL) const
456  { return UT_StringWrap(c_str()).multiMatch(pattern, explicitlyExcluded, matchIndex, pattern_record); }
457 
458  int toInt() const
459  { return UT_StringWrap(c_str()).toInt(); }
460  fpreal toFloat() const
461  { return UT_StringWrap(c_str()).toFloat(); }
462 
463  /// Determine if string can be seen as a single floating point number
464  unsigned isFloat(int skip_spaces = 0, int loose = 0) const
465  { return UT_StringWrap(c_str()).isFloat(skip_spaces, loose); }
466  /// Determine if string can be seen as a single integer number
467  unsigned isInteger(int skip_spaces = 0) const
468  { return UT_StringWrap(c_str()).isInteger(skip_spaces); }
469 
471  operator const char *() const
472  { return c_str(); }
473 
475  const char *buffer() const
476  { return c_str(); }
477  // We are always non-null by definition!
479  const char *nonNullBuffer() const
480  { return c_str(); }
481 
482  /// Iterators
483  typedef const char * const_iterator;
484 
487  { return c_str(); }
490  { return begin() + length(); }
491 
492 
493  /// Converts the contents of this UT_String to a std::string. Since
494  /// we are never null this is easy
496  { return std::string(c_str(), length()); }
497 
499  void swap( UT_StringRef &other )
500  {
501  UTswap(myData, other.myData);
502  UTswap(myLength, other.myLength);
503  UTswap(myHash, other.myHash);
504  }
505 
506  /// Friend specialization of std::swap() to use UT_StringRef::swap()
507  friend void swap(UT_StringRef& a, UT_StringRef& b) { a.swap(b); }
508 
510  bool isstring() const
511  {
512  // This test works for both references and inline.
513  return !isSentinelOrNullPtr(myData);
514  }
515 
517  bool
518  hasNonSpace() const
519  {
520  const char *ptr = c_str();
521  while (*ptr && SYSisspace(*ptr))
522  ptr++;
523  return (*ptr) ? true : false;
524  }
525 
527  int
528  findChar(char c) const
529  {
530  const char *ptr = c_str();
531  while (*ptr && *ptr != c)
532  ptr++;
533  return (*ptr) ? (ptr - c_str()) : -1;
534  }
535 
537  int
538  findChar(const char *str) const
539  {
540  const char *ptr = c_str();
541  const char *found_char = nullptr;
542 
543  if (UTisstring(ptr) && UTisstring(str))
544  {
545  found_char = strpbrk(ptr, str);
546 
547  if (found_char)
548  return (intptr_t)(found_char - ptr);
549  }
550 
551  return -1;
552  }
553 
555  int
556  findChar(char c, exint start_offset) const
557  {
558  const char *ptr = c_str() + start_offset;
559  while (*ptr && *ptr != c)
560  ptr++;
561  return (*ptr) ? (ptr - c_str()) : -1;
562  }
563 
565  int
566  findChar(const char *str, exint start_offset) const
567  {
568  const char *ptr = c_str() + start_offset;
569  const char *found_char = nullptr;
570 
571  if (UTisstring(ptr) && UTisstring(str))
572  {
573  found_char = strpbrk(ptr, str);
574 
575  if (found_char)
576  return (intptr_t)(found_char - c_str());
577  }
578 
579  return -1;
580  }
581 
583  int
584  lastChar(char c, int occurance_number = 1) const
585  {
586  const char *ptr = c_str();
587  for (int i = length(); i --> 0;)
588  {
589  if(c == ptr[i])
590  {
591  occurance_number--;
592  if(occurance_number <= 0)
593  return i;
594  }
595  }
596 
597  return -1;
598  }
599 
601  int
602  countChar(char c) const
603  {
604  const char *ptr = c_str();
605  int count = 0;
606  while (*ptr)
607  {
608  if (*ptr == c)
609  count++;
610  ptr++;
611  }
612  return count;
613  }
614 
616  void clear()
617  {
618  if (myData)
619  {
620  Holder *h = getHolder();
621  if (!isSentinelOrNullPtr(h))
622  h->decref();
623  init();
624  }
625  }
626 
628  const char *c_str() const
629  {
630  UT_ASSERT_P(!isSentinel());
631  Holder *holder = getHolder();
632  if (!isSentinelOrNullPtr(holder))
633  return holder->c_str();
634  // Harden empty strings.
635  if (isSentinelOrNullPtr(myDataIfChars))
636  {
637 #if SYS_IS_GCC_GE(6, 0) && !SYS_IS_GCC_GE(7, 0)
638  // We need to do this to fix bad GCC 6 warning:
639  // offset outside bounds of constant string
640  const char *volatile empty = "";
641  return empty;
642 #else
643  return "";
644 #endif
645  }
646  return myDataIfChars;
647  }
648 
649  exint length() const
650  {
651  Holder *holder = getHolder();
652 
653  if (!isSentinelOrNullPtr(holder))
654  return holder->length();
655 
656  if (myLength >= 0)
657  return myLength;
658 
659  exint result = -myLength;
660  result <<= 31;
661  result += myHash;
662 
663  return result;
664  }
665 
666  bool isEmpty() const
667  {
668  return length() == 0;
669  }
670 
671  unsigned hash() const
672  {
673  Holder *holder = getHolder();
674  if (!isSentinelOrNullPtr(holder))
675  return holder->hash();
676  if (myLength >= 0)
677  {
678  if (!myLength)
679  return 0;
680  if (!myHash)
681  {
682  myHash = hash_string(c_str(), length());
683  }
684  return myHash;
685  }
686  return hash_string(c_str(), length());
687  }
688 
689  /// Make a light weight reference to the source.
690  /// Caller must make sure src lives for the duration of this object,
691  /// and any objects value copied from this!
692  void reference(const char *src)
693  {
694  Holder *h = getHolder();
695  if (!isSentinelOrNullPtr(h))
696  h->decref();
697 
698  if (!src || !*src)
699  {
700  init();
701  }
702  else
703  {
704  myDataIfChars = src;
705 
706  exint len = ::strlen(src);
707  if (len >= (((exint)1) << 31))
708  {
709  myLength = -(len >> 31);
710  myHash = len & (0x7fffffff);
711  }
712  else
713  {
714  myLength = len;
715  myHash = 0;
716  }
717  }
718  }
719  /// Fast reference that takes the length of the string.
720  /// This is NOT a string view, the string must actually null terminate
721  /// at the given length or later functions will be confused.
723  {
724  Holder *h = getHolder();
725  if (!isSentinelOrNullPtr(h))
726  h->decref();
727 
728  if (!src || length <= 0)
729  {
730  UT_ASSERT(length == 0);
731  init();
732  }
733  else
734  {
735  UT_ASSERT_P(!src[length]);
736  myDataIfChars = src;
737 
738  if (length >= (((exint)1) << 31))
739  {
740  myLength = -(length >> 31);
741  myHash = length & (0x7fffffff);
742  }
743  else
744  {
745  myLength = length;
746  myHash = 0;
747  }
748  }
749  }
750 
751  int64 getMemoryUsage(bool inclusive) const
752  {
753  int64 mem = inclusive ? sizeof(*this) : 0;
754 
755  const Holder *holder = getHolder();
756  if (!isSentinelOrNullPtr(holder))
757  mem += holder->getMemoryUsage(true);
758  return mem;
759  }
760 
761  // This hash function does not look for null termination, but
762  // instead goes directly for the length.
764  static unsigned hash_string(const char *str, exint len)
765  {
766  return SYSstring_hash(str, len);
767  }
768 
769  UT_StringRef &operator+=(const UT_StringRef &src);
770 
771  /// A version of trimSpace() that only removes leading and following spaces
772  /// from a string, leaving any between words intact.
773  bool trimBoundingSpace();
774 
775  /// trimSpace() will remove all space characters (leading and following)
776  /// from a string. If the string consists of multiple words, the words
777  /// will be collapsed. To keep a single space between words, pass in true.
778  /// The function returns true if space was trimmed.
779  bool trimSpace(bool leave_single_space_between_words = false);
780 
781  /// Convert to lower case. If the string is already lower case, the string
782  /// itself is returned.
783  UT_StringRef toLower() const;
784 
785  /// Often people reflexively use this from UT_String days to
786  /// this increases code compataibility.
787  void harden(const char *src);
788 
789  // Steals the given string, gaining ownership of it.
790  // Will be freed by this when the reference count hits zero.
791  void adoptFromMalloc(const char *str, exint length=-1)
792  {
793  clear();
794 
795  if (length == 0 || !UTisstring(str))
796  return;
797  else
798  {
799  if (length < 0)
800  length = ::strlen(str);
801  Holder *h = Holder::buildFromData(str, length, STORE_MALLOC);
802  h->incref();
803  myLength = 0;
804  myData = h;
805  }
806  }
807  void adoptFromNew(const char *str, exint length=-1)
808  {
809  clear();
810 
811  if (length == 0 || !UTisstring(str))
812  return;
813  else
814  {
815  if (length < 0)
816  length = ::strlen(str);
817  Holder *h = Holder::buildFromData(str, length, STORE_NEW);
818  h->incref();
819  myLength = 0;
820  myData = h;
821  }
822  }
824  {
825  if (!str.isstring())
826  {
827  clear();
828  return;
829  }
830  // We want to steal from always deep strings as well.
831  // We will erase the data in the source string!
832  str.harden();
833 
834  // Clear after harden in case str refers to us!
835  clear();
836 
837  Holder *h = Holder::build(str.myData, STORE_MALLOC);
838  h->incref();
839  myLength = 0;
840  myData = h;
841 
842  str.myData = 0;
843  str.myIsReference = true;
844  // Leave always deep as it was.
845  }
846 
847  // Extracts a string from ourself of the given allocation mode.
848  // The result can be freed with that allocation mode.
849  // Will always clear myself afterwards. This will return our
850  // own string without copying if reference count is 1.
851  // Will return 0 for empty strings.
852  char *stealAsMalloc();
853 
854  // Tests to see if UT_StringLit's memory layout is the same
855  static bool verifyStringLit();
856 
857  /// Does a "smart" string compare which will sort based on numbered names.
858  /// That is "text20" is bigger than "text3". In a strictly alphanumeric
859  /// comparison, this would not be the case.
861  {
862  bool operator()(const UT_StringRef &s1, const UT_StringRef &s2) const
863  {
864  return UT_String::compareNumberedString(s1.c_str(), s2.c_str()) < 0;
865  }
866  };
867 
868  /// Save string to binary stream.
869  void saveBinary(std::ostream &os) const
870  { UT_StringWrap(c_str()).saveBinary(os); }
871 
872  /// Save string to ASCII stream. This will add double quotes and escape to
873  /// the stream if necessary (empty string or contains spaces).
874  void saveAscii(std::ostream &os) const
875  { UT_StringWrap(c_str()).saveAscii(os); }
876 
877 private:
878  void init()
879  {
880  myData = nullptr;
881  myLength = 0;
882  myHash = 0;
883  }
884 
885  void copy(const UT_StringRef &s)
886  {
887  myData = s.myData;
888  myLength = s.myLength;
889  myHash = s.myHash;
890  }
891 
893  Holder *getHolder() const
894  {
895  if (!myLength)
896  return myDataIfHolder;
897  return NULL;
898  }
899 
900  // This union makes viewing in a debugger much easier.
901  union {
902  const void *myData;
903  const char *myDataIfChars;
905  };
906  int myLength;
907  mutable int myHash;
908 
909  /// This operator saves the string to the stream via the string's
910  /// saveAscii() method, protecting any whitespace (by adding quotes),
911  /// backslashes or quotes in the string.
912  friend UT_API std::ostream &operator<<(std::ostream &os, const UT_StringRef &d);
913  friend UT_API UT_OStream &operator<<(UT_OStream &os, const UT_StringRef &d);
914 
915  // UT_StringHolder needs to be a friend class so that the
916  // UT_StringHolder(const UT_StringRef &) constructor can access myHash and
917  // getHolder() for the UT_StringRef that is passed in.
918  friend class UT_StringHolder;
919 
920  static constexpr uintptr_t SENTINEL_DATA = 1;
921  static constexpr uint32 SENTINEL_HASH = 0xdeadbeef;
922 
923  template<typename T>
924  static SYS_FORCE_INLINE bool isSentinelOrNullPtr(const T *p)
925  {
926  return uintptr_t(p) <= SENTINEL_DATA;
927  }
928 };
929 
931 {
932  return str.hash();
933 }
934 
935 /// A holder for a string, which stores the length and caches the hash value.
936 /// The lifetime of the string is >= the lifetime of the UT_StringHolder.
938 {
939 public:
940  /// UT_StringHolder can be constructed with UT_StringHolder::REFERENCE to
941  /// create a shallow reference to the const char *.
942  enum UT_StringReferenceType { REFERENCE };
943 
946  : UT_StringRef()
947  {
948  }
949 
950  /// Will make a copy of the provided string.
952  UT_StringHolder(const char *str)
953  {
954  if (UTisstring(str))
955  {
956  Holder *h = Holder::build(str, STORE_INLINE);
957  h->incref();
958  myLength = 0;
959  myDataIfHolder = h;
960  }
961  }
962 
963  /// Will make a shallow reference.
966  : UT_StringRef(str)
967  {
968  }
969 
970  /// Will make a copy of the provided string.
973  {
974  if (data && length > 0)
975  {
976  Holder *h = Holder::buildFromData(data, length, STORE_INLINE);
977  h->incref();
978  myLength = 0;
979  myDataIfHolder = h;
980  }
981  }
982 
983  // Prohibit accidents when converting from UT_String like:
984  // myStringHolder(buffer, /*deep*/true)
985  UT_StringHolder(const char *data, bool bad) = delete;
986 
987  // Add back explicit conversions for the length parameter
990  : UT_StringHolder(data, exint(length)) { }
993  : UT_StringHolder(data, exint(length)) { }
996  : UT_StringHolder(data, exint(length)) { }
997 #if defined(MBSD)
999  UT_StringHolder(const char *data, size_t length)
1000  : UT_StringHolder(data, exint(length)) { }
1001 #endif
1002 
1003  /// Will make a copy of the provided string.
1006  {
1007  const char *s = str.c_str();
1008  if (UTisstring(s))
1009  {
1010  Holder *h = Holder::buildFromData(s, str.length(), STORE_INLINE);
1011  h->incref();
1012  myLength = 0;
1013  myDataIfHolder = h;
1014  }
1015  }
1016 
1017  /// This will make a shallow reference to the contents of the string.
1020  : UT_StringRef(str)
1021  {
1022  }
1023 
1024  /// Will make a copy of the provided string.
1025  UT_StringHolder(const UT_WorkBuffer &str);
1026 
1027  /// This will make a shallow reference to the contents of the string.
1030  : UT_StringRef(str)
1031  {
1032  }
1033 
1034  /// Will make a copy of the provided string.
1037  {
1038  *this = UT_StringHolder(str.buffer());
1039  }
1040 
1041  /// This will make a shallow reference to the contents of the string.
1044  : UT_StringRef(str)
1045  {
1046  }
1047 
1048  /// Will make a copy of the provided string.
1051  {
1052  if (!sv.isEmpty())
1053  {
1054  Holder *h = Holder::buildFromData(sv.begin(), sv.length(),
1055  STORE_INLINE);
1056  h->incref();
1057  myLength = 0;
1058  myDataIfHolder = h;
1059  }
1060  }
1061 
1062  /// Makes a shallow reference to the contents of the UT_StringRef.
1065  : UT_StringRef(ref)
1066  {
1067  }
1068 
1069  /// Makes a deep copy of the provided UT_StringRef.
1070  /// This constructor is not marked explicit since we often want this
1071  /// conversion (e.g. when inserting a UT_StringRef into a UT_StringMap, as
1072  /// with the const char* constructor).
1074 
1075  /// Construct as a sentinel value
1076  SYS_FORCE_INLINE explicit
1078  : UT_StringRef(sentinel)
1079  {
1080  }
1081 
1082  /// Makes a copy of the provided string.
1085  : UT_StringRef(str)
1086  {
1087  }
1088 
1089  /// Move constructor. Steals the working data from the original.
1092  : UT_StringRef(std::move(a))
1093  {
1094  }
1095 
1096  /// Makes a bit-wise copy of the string and adjust the reference count.
1099  {
1101  return *this;
1102  }
1103 
1104  /// Move the contents of about-to-be-destructed string
1105  /// s to this string.
1108  {
1109  UT_StringRef::operator=(std::move(s));
1110  return *this;
1111  }
1112 
1114  void swap(UT_StringHolder &other)
1115  {
1116  UT_StringRef::swap(other);
1117  }
1118 
1120  void swap(UT_StringRef &other)
1121  {
1122  UT_StringRef::swap(other);
1123  // harden ourselves like UT_StringHolder::operator=(UT_StringRef&)
1124  Holder *h = getHolder();
1125  if (!isSentinelOrNullPtr(h))
1126  return; // already a holder
1127  if (!isSentinelOrNullPtr(myDataIfChars))
1128  {
1129  exint len = (myLength >= 0) ? myLength
1130  : (exint(-myLength) << 31) + myHash;
1131  h = Holder::buildFromData(myDataIfChars, len, STORE_INLINE, myHash);
1132  h->incref();
1133  myLength = 0;
1134  myData = h;
1135  }
1136  }
1137 
1138  /// Friend specialization of std::swap() to use UT_StringHolder::swap()
1139  /// @{
1140  friend void swap(UT_StringHolder& a, UT_StringRef& b) { a.swap(b); }
1141  friend void swap(UT_StringHolder& a, UT_StringHolder& b) { a.swap(b); }
1142  /// @}
1143 
1144  /// In some functions it's nice to be able to return a const-reference to a
1145  /// UT_StringHolder. However, in error cases, you likely want to return an
1146  /// empty string. This would mean that you'd have to return a real
1147  /// UT_StringHolder (not a const reference). This static lets you return a
1148  /// reference to an empty string.
1150 
1152 
1153  /// Format a string using the same formatting codes as @c UTformat.
1154  template<typename... Args>
1155  size_t format(const char *fmt, const Args &...args)
1156  {
1157  clear();
1158 
1159  using namespace UT::Format;
1160  Writer w;
1162  size_t nb_needed = f.format(w, fmt, {args...});
1163 
1164  auto h = Holder::buildBuffer(nb_needed, STORE_MALLOC);
1165  h->incref();
1166  myLength = 0;
1167  myData = h;
1168 
1169  w.setBuffer(h->bufferNC(), nb_needed);
1170  f.format(w, fmt, {args...});
1171  h->bufferNC()[nb_needed] = '\0';
1172 
1173  return nb_needed;
1174  }
1175 
1176  /// Format a string using the same formatting codes as @c UTprintf.
1177  template<typename... Args>
1178  size_t sprintf(const char *fmt, const Args &...args)
1179  {
1180  clear();
1181 
1182  using namespace UT::Format;
1183  Writer w;
1185  size_t nb_needed = f.printf(w, fmt, {args...});
1186 
1187  auto h = Holder::buildBuffer(nb_needed, STORE_MALLOC);
1188  h->incref();
1189  myLength = 0;
1190  myData = h;
1191 
1192  w.setBuffer(h->bufferNC(), nb_needed);
1193  f.printf(w, fmt, {args...});
1194  h->bufferNC()[nb_needed] = '\0';
1195 
1196  return nb_needed;
1197  }
1198 
1199  /// Replace all occurances of 'find' with 'replacement'.
1200  /// Returns number of replacements.
1201  int substitute(const char *find, const char *replacement, bool all = true)
1202  {
1203  UT_String s(buffer());
1204  int n = s.substitute(find, replacement, all);
1205  if (n > 0)
1206  adoptFromString(s);
1207  return n;
1208  }
1209 
1210  /// Load string from stream. Use is.eof() to check eof status
1211  bool load(UT_IStream &is)
1212  {
1213  UT_String s;
1214  if (s.load(is))
1215  {
1216  adoptFromString(s);
1217  return true;
1218  }
1219  return false;
1220  }
1221 
1222 protected:
1223  friend UT_StringHolder UT::Literal::operator"" _sh(
1224  const char *s, std::size_t const length);
1225  friend UT_StringHolder operator"" _UTsh(
1226  const char *s, std::size_t const length);
1227 
1228  /// A marker enum to use this constructor.
1229  enum UT_StringLiteralType { LITERAL };
1230 
1231  /// Only accepts string literals. Since there's no way to guarantee that
1232  /// a const char * argument is a string literal, we do this through the
1233  /// use of user-defined literal and *only* provide this constructor to our
1234  /// user-defined literal operator.
1236  {
1237  if (str && length)
1238  {
1239  myDataIfChars = str;
1240  myLength = length;
1241  // As of C++14, user defined literals don't support constexpr so
1242  // this hash computation here is actually done at run-time except
1243  // for in some cases where the compiler (clang?) is able to
1244  // optimize this. Therefore, disable this to avoid extraneous hash
1245  // computation in cases where we just want to use "foo"_sh to avoid
1246  // heap allocation but never use its hash.
1247  // Use UT_StringLit if you want to get compile time hashes
1248 #if 0
1249  myHash = SYSstring_hash_literal(str);
1250 #else
1251  myHash = 0;
1252 #endif
1253  }
1254  }
1255 };
1256 
1257 template <typename T> class UT_Array;
1259 
1260 /// Convert a UT_StringRef into a UT_StringHolder that is a shallow reference.
1262 {
1263  SYS_STATIC_ASSERT(sizeof(UT_StringRef) == sizeof(UT_StringHolder));
1264  return reinterpret_cast<const UT_StringHolder &>(ref);
1265 }
1266 
1267 /// Convert a UT_StringRef into a UT_StringHolder that is a shallow reference,
1268 /// and also precompute the hash. Use this for string literals
1269 /// that will be used repeatedly in hash tables.
1271 {
1272  SYS_STATIC_ASSERT(sizeof(UT_StringRef) == sizeof(UT_StringHolder));
1273  ref.hash();
1274  return reinterpret_cast<const UT_StringHolder &>(ref);
1275 }
1276 
1279 {
1280  SYS_STATIC_ASSERT(sizeof(UT_StringHolder) == sizeof(*this));
1281  return reinterpret_cast<const UT_StringHolder &>(*this);
1282 }
1283 
1286 {
1287  SYS_STATIC_ASSERT(sizeof(UT_StringRef) == sizeof(*this));
1288  return reinterpret_cast<const UT_StringRef &>(*this);
1289 }
1290 
1291 SYS_FORCE_INLINE size_t tbb_hasher(const UT_StringRef &s) { return s.hash(); }
1292 SYS_FORCE_INLINE size_t tbb_hasher(const UT_StringHolder &s) { return s.hash(); }
1293 
1294 /// A user-defined string literal to construct UT_StringHolder objects.
1295 /// E.g:
1296 /// @code
1297 /// auto lit = "This is my UT_StringHolder literal"_sh;
1298 /// @endcode
1299 namespace UT { inline namespace Literal {
1300 SYS_FORCE_INLINE UT_StringHolder operator"" _sh(const char *s, std::size_t const length)
1301 {
1302  return UT_StringHolder(UT_StringHolder::LITERAL, s, length);
1303 }
1304 } }
1305 
1306 /// A user-defined literal in the global namespace. Uglier, but allows the use
1307 /// of UT_StringHolder UDLs in headers.
1308 SYS_FORCE_INLINE UT_StringHolder operator"" _UTsh(const char *s, std::size_t const length)
1309 {
1310  return UT_StringHolder(UT_StringHolder::LITERAL, s, length);
1311 }
1312 
1313 
1314 namespace std
1315 {
1316  template<>
1317  struct hash<UT_StringRef>
1318  {
1319  size_t operator()(const UT_StringRef &s) const
1320  {
1321  return s.hash();
1322  }
1323  };
1324  template<>
1325  struct hash<UT_StringHolder>
1326  {
1327  size_t operator()(const UT_StringHolder &s) const
1328  {
1329  return s.hash();
1330  }
1331  };
1332 }
1333 
1334 // For UT::ArraySet.
1335 namespace UT
1336 {
1337 template <typename T>
1338 struct DefaultClearer;
1339 
1340 template <>
1342 {
1343  static void clear(UT_StringHolder &v) { v.makeSentinel(); }
1344  static bool isClear(const UT_StringHolder &v) { return v.isSentinel(); }
1346  {
1347  new ((void *)p) UT_StringHolder(UT_StringRef::SENTINEL);
1348  }
1349  static const bool clearNeedsDestruction = false;
1350 };
1351 } // namespace UT
1352 
1353 #endif // __UT_StringHolder_h__
SYS_FORCE_INLINE UT_StringHolder(UT_StringReferenceType, const UT_String &str)
This will make a shallow reference to the contents of the string.
std::string toStdString() const
static Holder * build(const char *str, StorageMode storage)
void adoptFromString(UT_String &str)
SYS_FORCE_INLINE UT_StringHolder(const UT_StringHolder &str)
Makes a copy of the provided string.
SYS_FORCE_INLINE const_iterator begin() const
unsigned hash() const
SYS_FORCE_INLINE const char * nonNullBuffer() const
#define SYS_STATIC_ASSERT(expr)
SYS_FORCE_INLINE bool isEmpty() const
Returns true if the string is empty.
Definition: UT_StringView.h:82
unsigned match(const char *pattern, int caseSensitive=1) const
unsigned multiMatch(const char *pattern, int caseSensitive, char separator) const
bool endsWith(const char *suffix, bool case_sensitive=true, exint len=-1) const
#define SYS_PRAGMA_PUSH_WARN()
Definition: SYS_Pragma.h:34
size_t operator()(const UT_StringRef &s) const
friend void swap(UT_StringRef &a, UT_StringRef &b)
Friend specialization of std::swap() to use UT_StringRef::swap()
png_voidp s1
Definition: png.h:2193
SYS_FORCE_INLINE constexpr exint length() const
void UTswap(T &a, T &b)
Definition: UT_Swap.h:35
SYS_FORCE_INLINE UT_StringHolder(UT_StringLiteralType, const char *str, size_t length)
SYS_FORCE_INLINE int findChar(char c) const
unsigned match(const char *pattern, int caseSensitive=1) const
SYS_FORCE_INLINE exint length() const
Returns the length of the string in bytes.
Definition: UT_StringView.h:78
SYS_FORCE_INLINE UT_StringHolder(const char *data, exint length)
Will make a copy of the provided string.
SYS_FORCE_INLINE UT_StringHolder()
const GLdouble * v
Definition: glcorearb.h:836
UT_StringLiteralType
A marker enum to use this constructor.
SYS_FORCE_INLINE void clear()
GLsizei const GLchar *const * string
Definition: glcorearb.h:813
png_voidp ptr
Definition: png.h:2145
bool contains(const char *pattern, bool case_sensitive=true) const
fpreal toFloat() const
typedef void(APIENTRYP PFNGLCULLFACEPROC)(GLenum mode)
int toInt() const
SYS_FORCE_INLINE T * SYSconst_cast(const T *foo)
Definition: SYS_Types.h:127
bool isEmpty() const
static void clear(UT_StringHolder &v)
SYS_FORCE_INLINE UT_StringRef(const UT_StringRef &s)
Shares a reference with the source.
SYS_FORCE_INLINE void swap(UT_StringHolder &other)
GLboolean GLboolean GLboolean GLboolean a
Definition: glcorearb.h:1221
bool startsWith(const char *prefix, bool case_sense=true, exint len=-1) const
Imported from UT_String.
static void clearConstruct(UT_StringHolder *p)
SYS_FORCE_INLINE UT_StringRef & operator=(UT_StringRef &&s)
void adoptFromMalloc(const char *str, exint length=-1)
#define UT_API
Definition: UT_API.h:13
bool equal(const UT_StringRef &str, bool ignore_case=false) const
SYS_FORCE_INLINE UT_StringHolder(const char *data, uint64 length)
bool operator!=(const char *s) const
SYS_FORCE_INLINE bool hasNonSpace() const
SYS_FORCE_INLINE const_iterator begin() const
Returns a constant iterator pointing to the beginning of the string.
unsigned multiMatch(const char *pattern, int caseSensitive=1, const char *separators=", ", bool *explicitlyExcluded=0, int *matchIndex=0, ut_PatternRecord *pattern_record=NULL) const
SYS_FORCE_INLINE int findChar(const char *str, exint start_offset) const
unsigned isInteger(int skip_spaces=0) const
Determine if string can be seen as a single integer number.
UT_EXTERN_TEMPLATE(UT_Array< UT_StringHolder >)
png_uint_32 i
Definition: png.h:2877
SYS_FORCE_INLINE size_t tbb_hasher(const UT_StringRef &s)
int substitute(const char *find, const char *replacement, bool all=true)
constexpr SYS_FORCE_INLINE UT_StringLit()
SYS_FORCE_INLINE constexpr uint32 hash() const
SYS_FORCE_INLINE UT_StringRef(const UT_StringLit &lit)
Construct from string literal.
SYS_FORCE_INLINE const UT_StringHolder & UTmakeUnsafeRefHash(const UT_StringRef &ref)
bool load(UT_IStream &is)
Load string from stream. Use is.eof() to check eof status.
fpreal toFloat() const
const void * myData
bool contains(const char *pattern, bool case_sensitive=true) const
constexpr SYS_FORCE_INLINE UT_StringLit(const char(&str)[N])
std::ostream & operator<<(std::ostream &ostr, const DataType &a)
Definition: DataType.h:133
SYS_FORCE_INLINE const_iterator end() const
void saveAscii(std::ostream &os) const
bool operator==(const BaseDimensions< T > &a, const BaseDimensions< Y > &b)
Definition: Dimensions.h:137
UT_StringRef & operator=(const UT_StringRef &s)
Shares a reference with the source.
SYS_FORCE_INLINE UT_StringHolder(const UT_String &str)
Will make a copy of the provided string.
long long int64
Definition: SYS_Types.h:107
const char * buffer() const
Definition: UT_String.h:503
SYS_FORCE_INLINE UT_StringRef(UT_StringSentinelType)
unsigned multiMatch(const char *pattern, int caseSensitive, char separator) const
A utility class to do read-only operations on a subset of an existing string.
Definition: UT_StringView.h:31
size_t sprintf(const char *fmt, const Args &...args)
Format a string using the same formatting codes as UTprintf.
SYS_FORCE_INLINE size_t hash_value(const UT_StringRef &str)
GLdouble n
Definition: glcorearb.h:2007
GLfloat f
Definition: glcorearb.h:1925
SYS_FORCE_INLINE UT_StringRef(UT_StringRef &&s) SYS_NOEXCEPT
Move constructor. Steals the working data from the original.
SYS_FORCE_INLINE int findChar(const char *str) const
unsigned long long uint64
Definition: SYS_Types.h:108
SYS_FORCE_INLINE UT_StringHolder(const std::string &str)
Will make a copy of the provided string.
bool operator==(const UT_StringRef &s) const
int compare(const UT_StringRef &str, bool ignore_case=false) const
exint length() const
GLint ref
Definition: glcorearb.h:123
int64 getMemoryUsage(bool inclusive) const
#define SYS_SAFE_BOOL
Definition: SYS_Compiler.h:62
exint length() const
SYS_FORCE_INLINE const char * buffer() const
SYS_FORCE_INLINE UT_StringHolder(const UT_StringView &sv)
Will make a copy of the provided string.
int64 exint
Definition: SYS_Types.h:116
friend void swap(UT_StringHolder &a, UT_StringHolder &b)
#define UT_ASSERT_P(ZZ)
Definition: UT_Assert.h:125
SYS_FORCE_INLINE UT_StringHolder(const char *data, uint32 length)
static const UT_StringHolder theEmptyString
bool operator>=(const UT_StringRef &k) const
SYS_FORCE_INLINE const UT_StringHolder & UTmakeUnsafeRef(const UT_StringRef &ref)
Convert a UT_StringRef into a UT_StringHolder that is a shallow reference.
#define SYS_FORCE_INLINE
Definition: SYS_Inline.h:45
SYS_FORCE_INLINE UT_StringRef()
SYS_FORCE_INLINE UT_StringHolder & operator=(UT_StringHolder &&s)
void harden()
Take shallow copy and make it deep.
Definition: UT_String.h:213
SYS_FORCE_INLINE void makeSentinel()
void saveAscii(std::ostream &os) const
Definition: UT_String.h:298
#define SYS_PRAGMA_DISABLE_FREE_NONHEAP_OBJECT()
Definition: SYS_Pragma.h:114
static SYS_FORCE_INLINE unsigned hash_string(const char *str, exint len)
SYS_FORCE_INLINE const char * c_str() const
SYS_FORCE_INLINE bool isSentinel() const
SYS_FORCE_INLINE constexpr const char * data() const
#define SYS_PRAGMA_POP_WARN()
Definition: SYS_Pragma.h:35
GLboolean * data
Definition: glcorearb.h:130
size_t format(const char *fmt, const Args &...args)
Format a string using the same formatting codes as UTformat.
SYS_FORCE_INLINE UT_StringHolder & operator=(const UT_StringHolder &s)
Makes a bit-wise copy of the string and adjust the reference count.
int int32
Definition: SYS_Types.h:35
SYS_FORCE_INLINE constexpr const char * c_str() const
bool operator<=(const UT_StringRef &k) const
GLboolean GLboolean GLboolean b
Definition: glcorearb.h:1221
bool operator<(const UT_StringRef &k) const
bool operator!=(const UT_StringRef &s) const
SYS_FORCE_INLINE int findChar(char c, exint start_offset) const
void fastReferenceWithStrlen(const char *src, exint length)
GLint GLsizei count
Definition: glcorearb.h:404
SYS_FORCE_INLINE UT_StringHolder(const char *data, int32 length)
void saveBinary(std::ostream &os) const
Save string to binary stream.
Definition: UT_String.h:294
SYS_FORCE_INLINE UT_StringHolder(UT_StringReferenceType, const UT_StringRef &ref)
Makes a shallow reference to the contents of the UT_StringRef.
void saveBinary(std::ostream &os) const
Save string to binary stream.
friend void swap(UT_StringHolder &a, UT_StringRef &b)
SYS_FORCE_INLINE UT_StringHolder(UT_StringSentinelType sentinel)
Construct as a sentinel value.
SYS_FORCE_INLINE const UT_StringRef & asRef() const
static int compareNumberedString(const char *s1, const char *s2, bool case_sensitive=true, bool allow_negatives=false)
GLfloat GLfloat GLfloat GLfloat h
Definition: glcorearb.h:2001
static Holder * buildFromData(const char *str, exint len, StorageMode storage, int hash=0)
double fpreal
Definition: SYS_Types.h:270
png_voidp png_voidp s2
Definition: png.h:2193
SYS_FORCE_INLINE UT_StringRef(const UT_String &str)
This will make a shallow reference to the contents of the string.
void adoptFromNew(const char *str, exint length=-1)
bool operator>(const UT_StringRef &k) const
static bool isClear(const UT_StringHolder &v)
unsigned multiMatch(const UT_StringMMPattern &pattern, bool *explicitlyExcluded=0, int *matchIndex=0, ut_PatternRecord *pattern_record=NULL) const
SYS_FORCE_INLINE ~UT_StringRef()
size_t operator()(const UT_StringHolder &s) const
SYS_FORCE_INLINE bool UTisstring(const char *s)
Definition: UT_String.h:57
bool operator==(const UT_String &s) const
int substitute(const char *find, const char *replacement, bool all=true)
bool load(UT_IStream &is)
Load string from stream. Use is.eof() to check eof status.
#define SYS_NOEXCEPT
Definition: SYS_Compiler.h:55
bool endsWith(const char *prefix, bool case_sense=true, exint len=-1) const
bool operator()(const UT_StringRef &s1, const UT_StringRef &s2) const
int SYSstrcasecmp(const char *a, const char *b)
Definition: SYS_String.h:227
SYS_FORCE_INLINE int countChar(char c) const
friend class UT_StringHolder
int64 getMemoryUsage(bool inclusive) const
SYS_FORCE_INLINE UT_StringHolder(UT_StringReferenceType, const char *str)
Will make a shallow reference.
SYS_FORCE_INLINE const UT_StringHolder & asHolder() const
Type-safe formatting, modeled on the Python str.format function.
GA_API const UT_StringHolder N
const char * const_iterator
Iterators.
SYS_FORCE_INLINE UT_StringRef(const char *str)
Will make a shallow reference.
void reference(const char *src)
bool isstring() const
Definition: UT_String.h:689
getOption("OpenEXR.storage") storage
Definition: HDK_Image.dox:276
void swap(TfErrorTransport &l, TfErrorTransport &r)
unsigned isInteger(int skip_spaces=0) const
Determine if string can be seen as a single integer number.
GLubyte GLubyte GLubyte GLubyte w
Definition: glcorearb.h:856
#define UT_ASSERT(ZZ)
Definition: UT_Assert.h:126
SYS_FORCE_INLINE constexpr const char * buffer() const
SYS_FORCE_INLINE void swap(UT_StringRef &other)
int toInt() const
bool operator!=(const BaseDimensions< T > &a, const BaseDimensions< Y > &b)
Definition: Dimensions.h:165
#define const
Definition: zconf.h:214
unsigned hash() const
SYS_FORCE_INLINE int lastChar(char c, int occurance_number=1) const
unsigned isFloat(int skip_spaces=0, int loose=0, bool allow_underscore=false) const
Determine if string can be seen as a single floating point number.
SYS_FORCE_INLINE UT_StringHolder(UT_StringHolder &&a) SYS_NOEXCEPT
Move constructor. Steals the working data from the original.
SYS_FORCE_INLINE UT_StringHolder(const char *str)
Will make a copy of the provided string.
const char * c_str() const
const char * myDataIfChars
SYS_FORCE_INLINE UT_StringRef(const std::string &str)
This will make a shallow reference to the contents of the string.
unsigned isFloat(int skip_spaces=0, int loose=0) const
Determine if string can be seen as a single floating point number.
bool operator!=(const UT_String &s) const
SYS_FORCE_INLINE bool isstring() const
Holder * myDataIfHolder
bool operator==(const char *s) const
SYS_FORCE_INLINE UT_StringHolder(UT_StringReferenceType, const UT_WorkBuffer &str)
This will make a shallow reference to the contents of the string.
SYS_FORCE_INLINE UT_StringHolder(UT_StringReferenceType, const std::string &str)
This will make a shallow reference to the contents of the string.
bool startsWith(const char *prefix, bool case_sensitive=true, exint len=-1) const
static const UT_StringHolder theSentinel
#define UT_ASSERT_MSG_P(ZZ, MM)
Definition: UT_Assert.h:128
GLuint GLsizei GLsizei * length
Definition: glcorearb.h:794
GLenum src
Definition: glcorearb.h:1792
unsigned int uint32
Definition: SYS_Types.h:36
SYS_FORCE_INLINE void swap(UT_StringRef &other)