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_Array.h"
24 #include "UT_Assert.h"
25 #include "UT_Format.h"
26 #include "UT_String.h"
27 #include "UT_Swap.h"
28 #include "UT_StringUtils.h"
29 
30 #include <SYS/SYS_AtomicInt.h>
31 #include <SYS/SYS_Compiler.h>
32 #include <SYS/SYS_Inline.h>
33 #include <SYS/SYS_Math.h>
34 #include <SYS/SYS_Pragma.h>
35 #include <SYS/SYS_StaticAssert.h>
36 #include <SYS/SYS_String.h>
37 #include <SYS/SYS_Types.h>
38 
39 #include <functional>
40 #include <iosfwd>
41 #include <string>
42 #include <utility>
43 
44 #include <stdint.h>
45 #include <string.h>
46 
47 class UT_IStream;
48 class UT_OStream;
49 class ut_PatternRecord;
50 class UT_StringHolder;
51 class UT_StringMMPattern;
52 class UT_StringRef;
53 class UT_StringView;
54 class UT_WorkBuffer;
55 
56 // Forward declare the UDSL so that we can friend it inside of UT_StringHolder.
57 namespace UT { inline namespace Literal {
58 UT_StringHolder operator"" _sh(const char *s, std::size_t const length);
59 } }
60 
61 /// A string literal with length and compile-time computed hash value.
62 /// @note This will only be compile-time when used in compile time expressions
63 /// like template parameters and constexpr variables.
64 /// @note String literals whose length requires more than 31 bits not supported
65 /// @see UT_StringRef
67 {
68 public:
69  constexpr SYS_FORCE_INLINE
71  : myData(nullptr)
72  , myLength(0)
73  , myHash(0)
74  {
75  }
76 
77  template <size_t N>
78  constexpr SYS_FORCE_INLINE
79  UT_StringLit(const char (&str)[N])
80  : myData(str)
81  , myLength(N-1)
82  , myHash(SYSstring_hash(str, myLength, /*allow_nulls*/true))
83  {
84  SYS_STATIC_ASSERT(N-1 < (((exint)1) << 31));
85  }
86 
87  SYS_FORCE_INLINE constexpr const char* buffer() const { return myData; }
88  SYS_FORCE_INLINE constexpr const char* data() const { return myData; }
89  SYS_FORCE_INLINE constexpr const char* c_str() const { return myData; }
90  SYS_FORCE_INLINE constexpr operator const char*() const { return myData; }
91 
92  SYS_FORCE_INLINE constexpr exint length() const { return myLength; }
93 
94  SYS_FORCE_INLINE constexpr uint32 hash() const { return myHash; }
95 
97  SYS_FORCE_INLINE const UT_StringRef& asRef() const;
98 
99  SYS_FORCE_INLINE constexpr bool operator==(const UT_StringLit &other) const
100  {
101  if (myLength != other.myLength)
102  return false;
103  for (int32 i = 0; i < myLength; ++i)
104  {
105  if (myData[i] != other.myData[i])
106  return false;
107  }
108  return true;
109  }
110  SYS_FORCE_INLINE constexpr bool operator!=(const UT_StringLit &other) const
111  {
112  return !(*this == other);
113  }
114  SYS_FORCE_INLINE constexpr bool operator==(const char *other) const
115  {
116  int32 i = 0;
117  for (i = 0; i < myLength; ++i)
118  {
119  if (other[i] == '\0' || myData[i] != other[i])
120  return false;
121  }
122  // have we reached the end of both strings?
123  if (other[i] == '\0')
124  return true;
125  return false;
126  }
127  SYS_FORCE_INLINE constexpr bool operator!=(const char *other) const
128  {
129  return !(*this == other);
130  }
131 
132 private:
133  const char* myData;
134  int32 myLength;
135  uint32 myHash;
136 
137  friend class UT_StringRef;
138 };
139 
140 /// A holder for a string, which stores the length and caches the hash value.
141 /// A UT_StringRef does not necessarily own the string, and it is therefore not
142 /// safe to e.g. store a UT_StringRef in a container or member variable.
143 /// @see UT_StringHolder
144 /// @see UTmakeUnsafeRef
146 {
147 public:
148  typedef char value_type;
149 
151  {
155  STORE_INLINE
156  };
157 
159  {
160  public:
162  : myRefCount(0), myStorageMode(STORE_INLINE),
163  myHash(0), myLength(0), myData(0)
164  {
165  }
166 
167  static Holder *build(const char *str,
169  static Holder *buildFromData(const char *str,
170  exint len,
172  int hash = 0);
173  static Holder *buildBuffer(
174  exint length,
176 
177  const char *c_str() const
178  {
179  if (myStorageMode == STORE_INLINE)
180  return myDataIfInline;
181 
182  return myData;
183  }
184 
185  void incref()
186  {
187  myRefCount.add(1);
188  }
189  void decref()
190  {
191  if (myRefCount.add(-1) == 0)
192  {
193  // We can't invoke delete as we were malloced.
194  // Further, we have custom behaviour on ownership!
195  switch (myStorageMode)
196  {
197  case STORE_EXTERNAL:
198  case STORE_INLINE:
199  // Do nothing.
200  break;
201  case STORE_NEW:
202  delete [] myData;
203  break;
204  case STORE_MALLOC:
205  if (myData)
206  free( (void*)SYSconst_cast(myData));
207  break;
208  }
211  free(this);
213  }
214  }
215 
216  exint length() const
217  {
218  return myLength;
219  }
220 
221  unsigned hash() const
222  {
223  if (!myHash)
224  {
225  myHash = hash_string(c_str(), length());
226  }
227  return myHash;
228  }
229 
230  int64 getMemoryUsage(bool inclusive) const
231  {
232  int64 mem = inclusive ? sizeof(*this) : 0;
233 
234  switch (myStorageMode)
235  {
236  case STORE_EXTERNAL:
237  // Nothing extra.
238  break;
239  case STORE_INLINE:
240  UT_ASSERT_MSG_P(inclusive,
241  "If a Holder is STORE_INLINE, it *really* can't be a "
242  "member variable, because the size isn't determined "
243  "at runtime.");
244  mem += myLength + 1 - sizeof(const char *);
245  break;
246  case STORE_NEW:
247  case STORE_MALLOC:
248  // External reference we own.
249  mem += myLength + 1;
250  break;
251  }
252  return mem;
253  }
254 
255  private:
256  char *bufferNC() const
257  {
258  if (myStorageMode == STORE_INLINE)
259  return SYSconst_cast(myDataIfInline);
260 
261  return SYSconst_cast(myData);
262  }
263 
264  friend class UT_StringHolder;
265  friend class UT_StringRef;
266 
267  private:
268  SYS_AtomicInt32 myRefCount;
269  StorageMode myStorageMode;
270  mutable int myHash;
271  exint myLength;
272 
273  // This union makes viewing in a debugger much easier.
274  union {
275  const char *myData;
276  char myDataIfInline[sizeof(const char *)];
277  };
278  };
279 
282  {
283  init();
284  }
285 
286  /// Will make a shallow reference.
288  UT_StringRef(const char *str)
289  {
290  init();
291  if (UTisstring(str))
292  {
293  reference(str);
294  }
295  }
296 
297  /// Construct from string literal
298  SYS_FORCE_INLINE explicit
300  : UT_StringRef(lit.asRef())
301  {
302  }
303 
304  /// This will make a shallow reference to the contents of the string.
307  {
308  init();
309  if (str.size())
310  {
311  const char *s = str.c_str();
312  fastReferenceWithStrlen(s, str.length());
313  }
314  }
315 
316  /// This will make a shallow reference to the contents of the string.
317  UT_StringRef(const UT_WorkBuffer &str);
318 
319  /// This will make a shallow reference to the contents of the string.
322  {
323  init();
324  if (str.isstring())
325  reference(str);
326  }
327 
328  /// Shares a reference with the source.
331  {
332  Holder *sh = s.getHolder();
333  if (!isSentinelOrNullPtr(sh))
334  sh->incref();
335  // Can now blindly copy.
336  copy(s);
337  }
338 
339  /// Move constructor. Steals the working data from the original.
342  {
343  copy(s);
344  s.init();
345  }
346 
349  {
350  Holder *h = getHolder();
351  if (!isSentinelOrNullPtr(h))
352  h->decref();
353  }
354 
355  /// Special sentinel value support
356  /// @{
357  enum UT_StringSentinelType { SENTINEL };
358 
359  SYS_FORCE_INLINE explicit
361  : myData((const void*)SENTINEL_DATA)
362  , myLength(0)
363  , myHash(SENTINEL_HASH)
364  {
365  }
366 
368  bool isSentinel() const
369  {
370  return uintptr_t(myData) == SENTINEL_DATA && myHash == SENTINEL_HASH && !myLength;
371  }
372 
375  {
376  Holder *h = getHolder();
377  if (!isSentinelOrNullPtr(h))
378  h->decref();
379  myData = (const void*)SENTINEL_DATA;
380  myLength = 0;
381  myHash = SENTINEL_HASH;
382  }
383  /// @}
384 
385  /// Returns true this object is the sole owner of the underlying string
386  bool isUnique() const
387  {
388  Holder *h = getHolder();
389  if (isSentinelOrNullPtr(h))
390  return false;
391  return (h->myRefCount.relaxedLoad() == 1);
392  }
393 
394  /// Shares a reference with the source.
396  {
397  Holder *sh = s.getHolder();
398  Holder *th = getHolder();
399 
400  if (!isSentinelOrNullPtr(sh))
401  sh->incref();
402  if (!isSentinelOrNullPtr(th))
403  th->decref();
404  // Can now blindly copy.
405  copy(s);
406  return *this;
407  }
408 
409  /// Move the contents of about-to-be-destructed string
410  /// s to this string.
413  {
414  // Can just swap, since s is about to be destructed.
415  swap(s);
416  return *this;
417  }
418 
419  bool operator==(const UT_StringRef &s) const
420  {
421  // It is sensible to fast-path this based on myData!
422  // If our two pointers are equal, we either are pointing to
423  // the same Holder or to the same const char *, so are good
424  // to call it equal.
425  if (myData == s.myData)
426  return true;
427  exint tl = length();
428  exint sl = s.length();
429  if (tl != sl)
430  return false;
431  if (tl == 0)
432  return (uintptr_t(myData) == SENTINEL_DATA) == (uintptr_t(s.myData) == SENTINEL_DATA);
433 
434  // If both strings have cached hashes with different values, the
435  // strings cannot be equal.
436  const unsigned h1 = cachedHash();
437  const unsigned h2 = s.cachedHash();
438  if (h1 && h2 && (h1 != h2))
439  return false;
440 
441  return ::memcmp(c_str(), s.c_str(), tl) == 0;
442  }
443  bool operator==(const char *s) const
444  {
445  // It is sensible to fast-path this based on myData!
446  // If our two pointers are equal, we either are pointing to
447  // the same Holder or to the same const char *, so are good
448  // to call it equal.
449  // We don't test for myData being a Holder because it should
450  // never alias a const char *.
451  if (myDataIfChars == s)
452  return true;
453  // Avoid comparison with null.
454  if (!s)
455  return !isstring();
456  return ::strcmp(c_str(), s) == 0;
457  }
458  bool operator==(const UT_String &s) const
459  { return operator==(s.buffer()); }
460 
461  bool operator!=(const UT_StringRef &s) const
462  { return !operator==(s); }
463  bool operator!=(const char *s) const
464  { return !operator==(s); }
465  bool operator!=(const UT_String &s) const
466  { return operator!=(s.buffer()); }
467 
468  /// Spaceship comparison returns:
469  /// - < 0 if *this < k
470  /// - == 0 if *this == k
471  /// - > 0 if *this > k
472  int spaceship(const UT_StringRef &k) const
473  {
474  exint minlen = SYSmin(length(), k.length());
475  int r = memcmp(c_str(), k.c_str(), minlen);
476  if (r != 0)
477  return r;
478  if (k.length() > minlen)
479  return -1;
480  return length() > minlen ? 1 : 0;
481  }
482 
483  bool operator<(const UT_StringRef &k) const
484  { return spaceship(k) < 0; }
485  bool operator<=(const UT_StringRef &k) const
486  { return spaceship(k) <= 0; }
487  bool operator>(const UT_StringRef &k) const
488  { return spaceship(k) > 0; }
489  bool operator>=(const UT_StringRef &k) const
490  { return spaceship(k) >= 0; }
491  int compare(const UT_StringRef &str,
492  bool ignore_case=false) const
493  {
494  return ignore_case
495  ? SYSstrcasecmp(c_str(), str.c_str())
496  : spaceship(str); }
497  bool equal(const UT_StringRef &str,
498  bool ignore_case=false) const
499  { return compare(str, ignore_case) == 0; }
500 
501  /// Test whether the string is defined or not
503  SYS_SAFE_BOOL operator bool() const { return isstring(); }
504 
505  /// Imported from UT_String.
506  bool startsWith(const UT_StringView &pfx, bool case_sense=true) const
507  {
508  return UTstringStartsWith(*this, pfx.data(), case_sense, pfx.length());
509  }
510  bool endsWith(const UT_StringView &suffix, bool case_sense=true) const
511  {
512  return UTstringEndsWith(*this, suffix.data(), case_sense, suffix.length());
513  }
514  unsigned match(const char *pattern, bool case_sensitive=true) const
515  { return UT_StringWrap(c_str()).match(pattern, case_sensitive); }
516 
517  bool contains(const char *pattern, bool case_sensitive=true) const
518  { return UT_StringWrap(c_str()).contains(pattern, case_sensitive); }
519  const char *fcontain(const char *pattern, bool case_sensitive=true) const
520  { return UT_StringWrap(c_str()).fcontain(pattern, case_sensitive); }
521  const char *findWord(const char *word) const
522  { return UT_StringWrap(c_str()).findWord(word); }
523 
524  unsigned multiMatch(const char *pattern, bool case_sensitive,
525  char separator) const
526  {
527  return UT_StringWrap(c_str()).multiMatch(
528  pattern, case_sensitive, separator);
529  }
530  unsigned multiMatch(const char *pattern, bool case_sensitive = true,
531  const char *separators = ", ",
532  bool *explicitly_excluded = 0,
533  int *match_index = 0,
534  ut_PatternRecord *pattern_record=nullptr) const
535  {
536  return UT_StringWrap(c_str()).multiMatch(
537  pattern, case_sensitive, separators, explicitly_excluded,
538  match_index, pattern_record);
539  }
541  bool *explicitly_excluded = 0,
542  int *match_index = 0,
543  ut_PatternRecord *pattern_record=nullptr) const
544  {
545  return UT_StringWrap(c_str()).multiMatch(
546  pattern, explicitly_excluded, match_index, pattern_record);
547  }
548 
549  /// Returns true if the entire string matches the provided regular
550  /// expression, false otherwise. See UT_Regex.
551  bool matchRegex(const char *expr) const;
552 
553  int toInt() const
554  { return UT_StringWrap(c_str()).toInt(); }
555  fpreal toFloat() const
556  { return UT_StringWrap(c_str()).toFloat(); }
557 
558  /// Determine if string can be seen as a single floating point number
559  unsigned isFloat(int skip_spaces = 0, int loose = 0) const
560  { return UTstringIsFloat(*this, skip_spaces, loose); }
561  /// Determine if string can be seen as a single integer number
562  unsigned isInteger(int skip_spaces = 0) const
563  { return UTstringIsInteger(*this, skip_spaces); }
564 
566  operator const char *() const
567  { return c_str(); }
568 
570  const char *buffer() const
571  { return c_str(); }
572  // We are always non-null by definition!
574  const char *nonNullBuffer() const
575  { return c_str(); }
576 
577  /// Iterators
578  typedef const char * const_iterator;
579 
582  { return c_str(); }
585  { return begin() + length(); }
586 
587 
588  /// Converts the contents of this UT_String to a std::string. Since
589  /// we are never null this is easy
591  { return std::string(c_str(), length()); }
592 
594  void swap( UT_StringRef &other )
595  {
596  UTswap(myData, other.myData);
597  UTswap(myLength, other.myLength);
598  UTswap(myHash, other.myHash);
599  }
600 
601  /// Friend specialization of std::swap() to use UT_StringRef::swap()
602  friend void swap(UT_StringRef& a, UT_StringRef& b) { a.swap(b); }
603 
605  bool isstring() const
606  {
607  // This test works for both references and inline.
608  return !isSentinelOrNullPtr(myData);
609  }
610 
612  bool
613  hasNonSpace() const
614  {
615  const char *ptr = c_str();
616  for (exint i = 0, n = length(); i < n; ++i)
617  if (!SYSisspace(ptr[i]))
618  return true;
619  return false;
620  }
621 
622  /// Find the location of the character @c (or -1 if not found)
624  exint
625  findCharIndex(char c) const
626  {
627  const void *ptr = ::memchr(c_str(), c, length());
628  return ptr ? (const char *)ptr - c_str() : -1;
629  }
630 
631  /// Find the first location of any of the characters in the @c str passed in
633  exint
634  findCharIndex(const char *str) const
635  {
636  if (UTisstring(str))
637  {
638  const char *found_char = strpbrk(c_str(), str);
639  if (found_char)
640  return found_char - c_str();
641  }
642  return -1;
643  }
644 
645  /// Find the location of the character @c (or -1 if not found)
647  exint
648  findCharIndex(char c, exint start_offset) const
649  {
650  if (start_offset < length())
651  {
652  const void *ptr = ::memchr(c_str()+start_offset, c,
653  length()-start_offset);
654  if (ptr)
655  return (const char *)ptr - c_str();
656  }
657  return -1;
658  }
659 
660  /// Find the first location of any of the characters in the @c str passed in
662  exint
663  findCharIndex(const char *str, exint start_offset) const
664  {
665  if (UTisstring(str) && start_offset < length())
666  {
667  const char *found_char = strpbrk(c_str()+start_offset, str);
668  if (found_char)
669  return found_char - c_str();
670  }
671  return -1;
672  }
673 
675  exint
676  lastCharIndex(char c, int occurrence_number = 1) const
677  {
678  exint n = length();
679  const void *start = SYSmemrchr(c_str(), c, n);
680  while (start)
681  {
682  n = (const char *)start - c_str();
683  occurrence_number--;
684  if (occurrence_number <= 0)
685  return n;
686  start = (n == 0) ? nullptr : SYSmemrchr(c_str(), c, n-1);
687  }
688  return -1;
689  }
690 
691  /// Count the number of times the character @c c occurs
693  exint
694  countChar(char c) const
695  {
696  return UTstringCountChar(*this, c);
697  }
698 
700  void clear()
701  {
702  if (myData)
703  {
704  Holder *h = getHolder();
705  if (!isSentinelOrNullPtr(h))
706  h->decref();
707  init();
708  }
709  }
710 
712  const char *c_str() const
713  {
714  UT_ASSERT_P(!isSentinel());
715  Holder *holder = getHolder();
716  if (!isSentinelOrNullPtr(holder))
717  return holder->c_str();
718  // Harden empty strings.
719  if (isSentinelOrNullPtr(myDataIfChars))
720  {
721 #if SYS_IS_GCC_GE(6, 0) && !SYS_IS_GCC_GE(8, 0)
722  // We need to do this to fix bad GCC warning:
723  // offset outside bounds of constant string
724  const char *volatile empty = "";
725  return empty;
726 #else
727  return "";
728 #endif
729  }
730  return myDataIfChars;
731  }
733  const char* data() const
734  {
735  return c_str();
736  }
737 
738  exint length() const
739  {
740  Holder *holder = getHolder();
741 
742  if (!isSentinelOrNullPtr(holder))
743  return holder->length();
744 
745  if (myLength >= 0)
746  return myLength;
747 
748  exint result = -myLength;
749  result <<= 31;
750  result += myHash;
751 
752  return result;
753  }
754 
755  bool isEmpty() const
756  {
757  return length() == 0;
758  }
759 
760  unsigned hash() const
761  {
762  Holder *holder = getHolder();
763  if (!isSentinelOrNullPtr(holder))
764  return holder->hash();
765  if (myLength >= 0)
766  {
767  if (!myLength)
768  return 0;
769  if (!myHash)
770  {
771  myHash = hash_string(c_str(), length());
772  }
773  return myHash;
774  }
775  return hash_string(c_str(), length());
776  }
777 
778  /// Make a light weight reference to the source.
779  /// Caller must make sure src lives for the duration of this object,
780  /// and any objects value copied from this!
781  void reference(const char *src)
782  {
783  Holder *h = getHolder();
784  if (!isSentinelOrNullPtr(h))
785  h->decref();
786 
787  if (!src || !*src)
788  {
789  init();
790  }
791  else
792  {
793  myDataIfChars = src;
794 
795  exint len = ::strlen(src);
796  if (len >= (((exint)1) << 31))
797  {
798  myLength = -(len >> 31);
799  myHash = len & (0x7fffffff);
800  }
801  else
802  {
803  myLength = len;
804  myHash = 0;
805  }
806  }
807  }
808  /// Fast reference that takes the length of the string.
809  /// This is NOT a string view, the string must actually null terminate
810  /// at the given length or later functions will be confused.
812  {
813  Holder *h = getHolder();
814  if (!isSentinelOrNullPtr(h))
815  h->decref();
816 
817  if (!src || length <= 0)
818  {
819  UT_ASSERT(length == 0);
820  init();
821  }
822  else
823  {
824  UT_ASSERT_P(!src[length]);
825  myDataIfChars = src;
826 
827  if (length >= (((exint)1) << 31))
828  {
829  myLength = -(length >> 31);
830  myHash = length & (0x7fffffff);
831  }
832  else
833  {
834  myLength = length;
835  myHash = 0;
836  }
837  }
838  }
839 
840  int64 getMemoryUsage(bool inclusive) const
841  {
842  int64 mem = inclusive ? sizeof(*this) : 0;
843 
844  const Holder *holder = getHolder();
845  if (!isSentinelOrNullPtr(holder))
846  mem += holder->getMemoryUsage(true);
847  return mem;
848  }
849 
850  // This hash function does not look for null termination, but
851  // instead goes directly for the length.
853  static unsigned hash_string(const char *str, exint len)
854  {
855  return SYSstring_hash(str, len, /*allow_nulls*/true);
856  }
857 
859 
860  /// A version of trimSpace() that only removes leading and following spaces
861  /// from a string, leaving any between words intact.
862  bool trimBoundingSpace();
863 
864  /// trimSpace() will remove all space characters (leading and following)
865  /// from a string. If the string consists of multiple words, the words
866  /// will be collapsed. To keep a single space between words, pass in true.
867  /// The function returns true if space was trimmed.
868  bool trimSpace(bool leave_single_space_between_words = false);
869 
870  /// Convert the string into a valid C style variable name.
871  /// All non-alpha numerics will be converted to _.
872  /// If the first letter is a digit, it is prefixed with an _.
873  /// If the string is already valid, the string itself is returned.
874  /// Note that this does NOT force the name to be non-zero in length.
875  /// The safechars parameter is a string containing extra characters
876  /// that should be considered safe. These characters are not
877  /// converted to underscores.
879  UT_StringRef forceValidVariableName(const char *safechars = nullptr) const;
880 
881  /// Convert to lower case. If the string is already lower case, the string
882  /// itself is returned.
884  UT_StringRef toLower() const;
885  /// Convert to upper case. If the string is already upper case, the string
886  /// itsef is returned.
888  UT_StringRef toUpper() const;
889 
890  /// Often people reflexively use this from UT_String days to
891  /// this increases code compataibility.
892  void harden(const char *src);
893 
894  // Steals the given string, gaining ownership of it.
895  // Will be freed by this when the reference count hits zero.
896  void adoptFromMalloc(const char *str, exint length=-1)
897  {
898  clear();
899 
900  if (length == 0 || !str)
901  return;
902  else
903  {
904  if (length < 0)
905  {
906  length = ::strlen(str);
907  if (length == 0)
908  return;
909  }
910  Holder *h = Holder::buildFromData(str, length, STORE_MALLOC);
911  h->incref();
912  myLength = 0;
913  myData = h;
914  }
915  }
916  void adoptFromNew(const char *str, exint length=-1)
917  {
918  clear();
919 
920  if (length == 0 || !str)
921  return;
922  else
923  {
924  if (length < 0)
925  {
926  length = ::strlen(str);
927  if (length == 0)
928  return;
929  }
930  Holder *h = Holder::buildFromData(str, length, STORE_NEW);
931  h->incref();
932  myLength = 0;
933  myData = h;
934  }
935  }
937  {
938  if (!str.isstring())
939  {
940  clear();
941  return;
942  }
943  // We want to steal from always deep strings as well.
944  // We will erase the data in the source string!
945  str.harden();
946 
947  // Clear after harden in case str refers to us!
948  clear();
949 
950  Holder *h = Holder::build(str.myData, STORE_MALLOC);
951  h->incref();
952  myLength = 0;
953  myData = h;
954 
955  str.myData = 0;
956  str.myIsReference = true;
957  // Leave always deep as it was.
958  }
960  {
961  if (data.size() <= 0)
962  {
963  clear();
964  return;
965  }
966 
967  // Make sure the string is null terminated.
968  if (data[data.size() - 1] != '\0')
969  {
970  data.emplace_back('\0');
971  }
972 
973  // NB: Make sure to not include the '\0' in the string length
974  adoptFromMalloc(data.data(), data.size() - 1);
975  data.unsafeClearData();
976  }
977 
978  // Extracts a string from ourself of the given allocation mode.
979  // The result can be freed with that allocation mode.
980  // Will always clear myself afterwards. This will return our
981  // own string without copying if reference count is 1.
982  // Will return 0 for empty strings.
983  char *stealAsMalloc();
984 
985  // Tests to see if UT_StringLit's memory layout is the same
986  static bool verifyStringLit();
987 
988  /// Does a "smart" string compare which will sort based on numbered names.
989  /// That is "text20" is bigger than "text3". In a strictly alphanumeric
990  /// comparison, this would not be the case.
992  {
993  bool operator()(const UT_StringRef &s1, const UT_StringRef &s2) const
994  {
995  return UT_String::compareNumberedString(s1.c_str(), s2.c_str()) < 0;
996  }
997  };
998 
999  /// Save string to binary stream.
1000  void saveBinary(std::ostream &os) const
1001  { UT_StringWrap(c_str()).saveBinary(os); }
1002 
1003  /// Save string to ASCII stream. This will add double quotes and escape to
1004  /// the stream if necessary (empty string or contains spaces).
1005  void saveAscii(std::ostream &os) const
1006  { UT_StringWrap(c_str()).saveAscii(os); }
1007 
1008 private:
1009  void init()
1010  {
1011  myData = nullptr;
1012  myLength = 0;
1013  myHash = 0;
1014  }
1015 
1016  void copy(const UT_StringRef &s)
1017  {
1018  myData = s.myData;
1019  myLength = s.myLength;
1020  myHash = s.myHash;
1021  }
1022 
1024  Holder *getHolder() const
1025  {
1026  if (!myLength)
1027  return myDataIfHolder;
1028  return nullptr;
1029  }
1030 
1031  /// Internal method to access the cached hash value if it exists.
1032  /// Returns 0 if the hash hasn't been computed yet.
1033  unsigned cachedHash() const
1034  {
1035  Holder *holder = getHolder();
1036  if (!isSentinelOrNullPtr(holder))
1037  return holder->myHash;
1038 
1039  return (myLength > 0) ? myHash : 0;
1040  }
1041 
1042  // This union makes viewing in a debugger much easier.
1043  union {
1044  const void *myData;
1045  const char *myDataIfChars;
1047  };
1048  int myLength;
1049  mutable int myHash;
1050 
1051  /// This operator saves the string to the stream via the string's
1052  /// saveAscii() method, protecting any whitespace (by adding quotes),
1053  /// backslashes or quotes in the string.
1054  friend UT_API std::ostream &operator<<(std::ostream &os, const UT_StringRef &d);
1055  friend UT_API UT_OStream &operator<<(UT_OStream &os, const UT_StringRef &d);
1056 
1057  // UT_StringHolder needs to be a friend class so that the
1058  // UT_StringHolder(const UT_StringRef &) constructor can access myHash and
1059  // getHolder() for the UT_StringRef that is passed in.
1060  friend class UT_StringHolder;
1061 
1062  static constexpr uintptr_t SENTINEL_DATA = 1;
1063  static constexpr uint32 SENTINEL_HASH = 0xdeadbeef;
1064 
1065  template<typename T>
1066  static SYS_FORCE_INLINE bool isSentinelOrNullPtr(const T *p)
1067  {
1068  return uintptr_t(p) <= SENTINEL_DATA;
1069  }
1070 };
1071 
1073 {
1074  return str.hash();
1075 }
1076 
1077 /// A holder for a string, which stores the length and caches the hash value.
1078 /// The lifetime of the string is >= the lifetime of the UT_StringHolder.
1080 {
1081 public:
1082  /// UT_StringHolder can be constructed with UT_StringHolder::REFERENCE to
1083  /// create a shallow reference to the const char *.
1084  enum UT_StringReferenceType { REFERENCE };
1085 
1088  : UT_StringRef()
1089  {
1090  }
1091 
1092  /// Will make a copy of the provided string.
1094  UT_StringHolder(const char *str)
1095  {
1096  if (UTisstring(str))
1097  {
1098  Holder *h = Holder::build(str, STORE_INLINE);
1099  h->incref();
1100  myLength = 0;
1101  myDataIfHolder = h;
1102  }
1103  }
1104 
1105  /// Will make a shallow reference.
1108  : UT_StringRef(str)
1109  {
1110  }
1111 
1112  /// Will make a copy of the provided string.
1115  {
1116  if (data && length > 0)
1117  {
1118  Holder *h = Holder::buildFromData(data, length, STORE_INLINE);
1119  h->incref();
1120  myLength = 0;
1121  myDataIfHolder = h;
1122  }
1123  }
1124 
1125  // Prohibit accidents when converting from UT_String like:
1126  // myStringHolder(buffer, /*deep*/true)
1127  UT_StringHolder(const char *data, bool bad) = delete;
1128 
1129  // Add back explicit conversions for the length parameter
1132  : UT_StringHolder(data, exint(length)) { }
1135  : UT_StringHolder(data, exint(length)) { }
1138  : UT_StringHolder(data, exint(length)) { }
1139 #if defined(MBSD)
1141  UT_StringHolder(const char *data, size_t length)
1142  : UT_StringHolder(data, exint(length)) { }
1144  UT_StringHolder(const char *data, ptrdiff_t length)
1145  : UT_StringHolder(data, exint(length)) { }
1146 #endif
1147 
1148  /// Will make a copy of the provided string.
1151  {
1152  if (str.size())
1153  {
1154  const char *s = str.c_str();
1155  Holder *h = Holder::buildFromData(s, str.length(), STORE_INLINE);
1156  h->incref();
1157  myLength = 0;
1158  myDataIfHolder = h;
1159  }
1160  }
1161 
1162  /// This will make a shallow reference to the contents of the string.
1165  : UT_StringRef(str)
1166  {
1167  }
1168 
1169  /// Will make a copy of the provided string.
1170  UT_StringHolder(const UT_WorkBuffer &str);
1171 
1172  /// This will make a shallow reference to the contents of the string.
1175  : UT_StringRef(str)
1176  {
1177  }
1178 
1179  /// Will make a copy of the provided string.
1182  {
1183  *this = UT_StringHolder(str.buffer());
1184  }
1185 
1186  /// This will make a shallow reference to the contents of the string.
1189  : UT_StringRef(str)
1190  {
1191  }
1192 
1193  /// Will make a copy of the provided string.
1194  UT_StringHolder(const UT_StringView &sv);
1195 
1196  /// Makes a shallow reference to the contents of the UT_StringRef.
1199  : UT_StringRef(ref)
1200  {
1201  }
1202 
1203  /// Makes a deep copy of the provided UT_StringRef.
1204  /// This constructor is not marked explicit since we often want this
1205  /// conversion (e.g. when inserting a UT_StringRef into a UT_StringMap, as
1206  /// with the const char* constructor).
1208 
1209  /// Construct as a sentinel value
1210  SYS_FORCE_INLINE explicit
1212  : UT_StringRef(sentinel)
1213  {
1214  }
1215 
1216  /// Makes a copy of the provided string.
1219  : UT_StringRef(str)
1220  {
1221  }
1222 
1223  /// Move constructor. Steals the working data from the original.
1226  : UT_StringRef(std::move(a))
1227  {
1228  }
1229 
1230  /// Move constructor. Steals the data from the work buffer.
1231  UT_StringHolder(UT_WorkBuffer &&buf) noexcept;
1232 
1233  /// Makes a bit-wise copy of the string and adjust the reference count.
1236  {
1238  return *this;
1239  }
1240 
1241  /// Move the contents of about-to-be-destructed string
1242  /// s to this string.
1245  {
1246  UT_StringRef::operator=(std::move(s));
1247  return *this;
1248  }
1249 
1250  /// Move the contents buffer into this string holder.
1252 
1254  void swap(UT_StringHolder &other)
1255  {
1256  UT_StringRef::swap(other);
1257  }
1258 
1260  void swap(UT_StringRef &other)
1261  {
1262  UT_StringRef::swap(other);
1263  // harden ourselves like UT_StringHolder::operator=(UT_StringRef&)
1264  Holder *h = getHolder();
1265  if (!isSentinelOrNullPtr(h))
1266  return; // already a holder
1267  if (!isSentinelOrNullPtr(myDataIfChars))
1268  {
1269  exint len = (myLength >= 0) ? myLength
1270  : (exint(-myLength) << 31) + myHash;
1271  h = Holder::buildFromData(myDataIfChars, len, STORE_INLINE, myHash);
1272  h->incref();
1273  myLength = 0;
1274  myData = h;
1275  }
1276  }
1277 
1278  /// Friend specialization of std::swap() to use UT_StringHolder::swap()
1279  /// @{
1280  friend void swap(UT_StringHolder& a, UT_StringRef& b) { a.swap(b); }
1281  friend void swap(UT_StringHolder& a, UT_StringHolder& b) { a.swap(b); }
1282  /// @}
1283 
1284  /// In some functions it's nice to be able to return a const-reference to a
1285  /// UT_StringHolder. However, in error cases, you likely want to return an
1286  /// empty string. This would mean that you'd have to return a real
1287  /// UT_StringHolder (not a const reference). This static lets you return a
1288  /// reference to an empty string.
1290 
1292 
1293  /// Format a string using the same formatting codes as @c UTformat.
1294  template<typename... Args>
1295  size_t format(const char *fmt, const Args &...args)
1296  {
1297  clear();
1298 
1299  using namespace UT::Format;
1300  Writer w;
1302  size_t nb_needed = f.format(w, fmt, {args...});
1303 
1304  auto h = Holder::buildBuffer(nb_needed, STORE_MALLOC);
1305  h->incref();
1306  myLength = 0;
1307  myData = h;
1308 
1309  w.setBuffer(h->bufferNC(), nb_needed);
1310  f.format(w, fmt, {args...});
1311  h->bufferNC()[nb_needed] = '\0';
1312 
1313  return nb_needed;
1314  }
1315 
1316  /// Format a string using the same formatting codes as @c UTprintf.
1317  template<typename... Args>
1318  size_t sprintf(const char *fmt, const Args &...args)
1319  {
1320  clear();
1321 
1322  using namespace UT::Format;
1323  Writer w;
1325  size_t nb_needed = f.printf(w, fmt, {args...});
1326 
1327  auto h = Holder::buildBuffer(nb_needed, STORE_MALLOC);
1328  h->incref();
1329  myLength = 0;
1330  myData = h;
1331 
1332  w.setBuffer(h->bufferNC(), nb_needed);
1333  f.printf(w, fmt, {args...});
1334  h->bufferNC()[nb_needed] = '\0';
1335 
1336  return nb_needed;
1337  }
1338 
1339  /// Replaces up to 'count' occurrences of 'find' with 'replacement',
1340  /// and returns the number of substitutions that occurred.
1341  /// If 'count' <= 0, all occurrences will be replaced.
1342  int substitute(const char *find, const char *replacement, int count)
1343  {
1344  UT_String s(buffer());
1345  int n = s.substitute(find, replacement, count);
1346  if (n > 0)
1347  adoptFromString(s);
1348  return n;
1349  }
1350 
1351  /// Convenience version of substitute() for all or single occurrence.
1352  int substitute(const char *find, const char *replacement, bool all = true)
1353  {
1354  return substitute(find, replacement, !all ? 1 : -1);
1355  }
1356 
1357  /// Load string from stream. Use is.eof() to check eof status
1358  bool load(UT_IStream &is)
1359  {
1360  UT_String s;
1361  if (s.load(is))
1362  {
1363  adoptFromString(s);
1364  return true;
1365  }
1366  return false;
1367  }
1368 
1369 protected:
1370  friend UT_StringHolder UT::Literal::operator"" _sh(
1371  const char *s, std::size_t const length);
1372  friend UT_StringHolder operator"" _UTsh(
1373  const char *s, std::size_t const length);
1374  friend UT_API std::istream &operator>>(std::istream& is, UT_StringHolder& s);
1375 
1376  /// A marker enum to use this constructor.
1377  enum UT_StringLiteralType { LITERAL };
1378 
1379  /// Only accepts string literals. Since there's no way to guarantee that
1380  /// a const char * argument is a string literal, we do this through the
1381  /// use of user-defined literal and *only* provide this constructor to our
1382  /// user-defined literal operator.
1384  {
1385  if (str && length)
1386  {
1387  myDataIfChars = str;
1388  myLength = length;
1389  // As of C++14, user defined literals don't support constexpr so
1390  // this hash computation here is actually done at run-time except
1391  // for in some cases where the compiler (clang?) is able to
1392  // optimize this. Therefore, disable this to avoid extraneous hash
1393  // computation in cases where we just want to use "foo"_sh to avoid
1394  // heap allocation but never use its hash.
1395  // Use UT_StringLit if you want to get compile time hashes
1396 #if 0
1397  myHash = SYSstring_hash_literal(str);
1398 #else
1399  myHash = 0;
1400 #endif
1401  }
1402  }
1403 };
1404 
1405 UT_EXTERN_TEMPLATE(UT_Array<UT_StringHolder>); // requires #include "UT_Array.h"
1406 
1407 /// Convert a UT_StringRef into a UT_StringHolder that is a shallow reference.
1409 {
1410  SYS_STATIC_ASSERT(sizeof(UT_StringRef) == sizeof(UT_StringHolder));
1411  return reinterpret_cast<const UT_StringHolder &>(ref);
1412 }
1413 
1414 /// Convert a UT_StringRef into a UT_StringHolder that is a shallow reference,
1415 /// and also precompute the hash. Use this for string literals
1416 /// that will be used repeatedly in hash tables.
1418 {
1419  SYS_STATIC_ASSERT(sizeof(UT_StringRef) == sizeof(UT_StringHolder));
1420  ref.hash();
1421  return reinterpret_cast<const UT_StringHolder &>(ref);
1422 }
1423 
1426 {
1427  SYS_STATIC_ASSERT(sizeof(UT_StringHolder) == sizeof(*this));
1428  return reinterpret_cast<const UT_StringHolder &>(*this);
1429 }
1430 
1433 {
1434  SYS_STATIC_ASSERT(sizeof(UT_StringRef) == sizeof(*this));
1435  return reinterpret_cast<const UT_StringRef &>(*this);
1436 }
1437 
1438 SYS_FORCE_INLINE size_t tbb_hasher(const UT_StringRef &s) { return s.hash(); }
1439 SYS_FORCE_INLINE size_t tbb_hasher(const UT_StringHolder &s) { return s.hash(); }
1440 
1441 /// A user-defined string literal to construct UT_StringHolder objects.
1442 /// E.g:
1443 /// @code
1444 /// auto lit = "This is my UT_StringHolder literal"_sh;
1445 /// @endcode
1446 namespace UT { inline namespace Literal {
1447 SYS_FORCE_INLINE UT_StringHolder operator"" _sh(const char *s, std::size_t const length)
1448 {
1449  return UT_StringHolder(UT_StringHolder::LITERAL, s, length);
1450 }
1451 } }
1452 
1453 /// A user-defined literal in the global namespace. Uglier, but allows the use
1454 /// of UT_StringHolder UDLs in headers.
1455 SYS_FORCE_INLINE UT_StringHolder operator"" _UTsh(const char *s, std::size_t const length)
1456 {
1457  return UT_StringHolder(UT_StringHolder::LITERAL, s, length);
1458 }
1459 
1460 
1461 namespace std
1462 {
1463  template<>
1464  struct hash<UT_StringRef>
1465  {
1466  size_t operator()(const UT_StringRef &s) const
1467  {
1468  return s.hash();
1469  }
1470  };
1471  template<>
1472  struct hash<UT_StringHolder>
1473  {
1474  size_t operator()(const UT_StringHolder &s) const
1475  {
1476  return s.hash();
1477  }
1478  };
1479 }
1480 
1481 // For UT::ArraySet.
1482 namespace UT
1483 {
1484 template <typename T>
1485 struct DefaultClearer;
1486 
1487 template <>
1489 {
1490  static void clear(UT_StringHolder &v) { v.makeSentinel(); }
1491  static bool isClear(const UT_StringHolder &v) { return v.isSentinel(); }
1493  {
1494  new ((void *)p) UT_StringHolder(UT_StringRef::SENTINEL);
1495  }
1496  static const bool clearNeedsDestruction = false;
1497 };
1498 } // namespace UT
1499 
1500 #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.
bool match(const char *pattern, bool case_sensitive=true) const
GLint ref
Definition: glcorearb.h:123
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.
GLboolean GLboolean GLboolean b
Definition: glcorearb.h:1221
SYS_FORCE_INLINE const_iterator begin() const
unsigned hash() const
SYS_FORCE_INLINE const char * nonNullBuffer() const
#define SYS_STATIC_ASSERT(expr)
const char * fcontain(const char *pattern, bool case_sensitive=true) const
int int32
Definition: SYS_Types.h:39
SYS_FORCE_INLINE exint findCharIndex(char c, exint start_offset) const
Find the location of the character (or -1 if not found)
#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()
SYS_FORCE_INLINE constexpr exint length() const
unsigned multiMatch(const char *pattern, bool case_sensitive=true, const char *separators=", ", bool *explicitly_excluded=0, int *match_index=0, ut_PatternRecord *pattern_record=nullptr) 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 constexpr bool operator==(const char *other) const
void
Definition: png.h:1083
SYS_FORCE_INLINE UT_StringHolder(const char *data, exint length)
Will make a copy of the provided string.
SYS_FORCE_INLINE UT_StringHolder()
SYS_NO_DISCARD_RESULT bool UTstringEndsWith(const T &str, const char *suffix, bool case_sensitive=true, exint len=-1)
UT_StringLiteralType
A marker enum to use this constructor.
SYS_FORCE_INLINE void clear()
GLuint start
Definition: glcorearb.h:474
HALF_EXPORT std::istream & operator>>(std::istream &is, half &h)
bool contains(const char *pattern, bool case_sensitive=true) const
fpreal toFloat() const
int toInt() const
const GLfloat * c
Definition: glew.h:16631
SYS_FORCE_INLINE T * SYSconst_cast(const T *foo)
Definition: SYS_Types.h:136
bool isEmpty() const
static void clear(UT_StringHolder &v)
GLenum const void GLuint GLint reference
Definition: glew.h:13927
int64 exint
Definition: SYS_Types.h:125
SYS_FORCE_INLINE UT_StringRef(const UT_StringRef &s)
Shares a reference with the source.
SYS_FORCE_INLINE void swap(UT_StringHolder &other)
void swap(T &lhs, T &rhs)
Definition: pugixml.cpp:7172
static void clearConstruct(UT_StringHolder *p)
fallback_uintptr uintptr_t
Definition: format.h:314
SYS_FORCE_INLINE UT_StringRef & operator=(UT_StringRef &&s)
bool endsWith(const UT_StringView &suffix, bool case_sense=true) const
void adoptFromMalloc(const char *str, exint length=-1)
#define UT_API
Definition: UT_API.h:14
bool equal(const UT_StringRef &str, bool ignore_case=false) const
SYS_FORCE_INLINE UT_StringHolder(const char *data, uint64 length)
SYS_FORCE_INLINE UT_StringRef(UT_StringRef &&s) noexcept
Move constructor. Steals the working data from the original.
SYS_FORCE_INLINE constexpr bool operator==(const UT_StringLit &other) const
bool operator!=(const char *s) const
SYS_FORCE_INLINE bool hasNonSpace() const
#define UT_ASSERT_MSG_P(ZZ,...)
Definition: UT_Assert.h:173
GLenum src
Definition: glcorearb.h:1792
unsigned long long uint64
Definition: SYS_Types.h:117
SYS_FORCE_INLINE exint findCharIndex(const char *str) const
Find the first location of any of the characters in the str passed in.
int substitute(const char *find, const char *replacement, int count)
UT_EXTERN_TEMPLATE(UT_Array< UT_StringHolder >)
unsigned multiMatch(const char *pattern, bool case_sensitive, char separator) const
void unsafeClearData()
Definition: UT_Array.h:902
exint size() const
Definition: UT_Array.h:479
SYS_FORCE_INLINE size_t tbb_hasher(const UT_StringRef &s)
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat s1
Definition: glew.h:12900
int substitute(const char *find, const char *replacement, bool all=true)
Convenience version of substitute() for all or single occurrence.
constexpr SYS_FORCE_INLINE UT_StringLit()
SYS_FORCE_INLINE const char * data() const
SYS_FORCE_INLINE constexpr uint32 hash() const
SYS_FORCE_INLINE UT_StringRef(const UT_StringLit &lit)
Construct from string literal.
PUGI__FN unsigned int hash_string(const char_t *str)
Definition: pugixml.cpp:8490
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
SYS_FORCE_INLINE constexpr bool operator!=(const char *other) const
GLubyte GLubyte GLubyte GLubyte w
Definition: glcorearb.h:856
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
SYS_NO_DISCARD_RESULT SYS_FORCE_INLINE const char * data() const noexcept
Returns a pointer to the first character of a view.
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.
const char * buffer() const
Definition: UT_String.h:499
SYS_FORCE_INLINE UT_StringRef(UT_StringSentinelType)
CompareResults OIIO_API compare(const ImageBuf &A, const ImageBuf &B, float failthresh, float warnthresh, ROI roi={}, int nthreads=0)
A utility class to do read-only operations on a subset of an existing string.
Definition: UT_StringView.h:40
size_t sprintf(const char *fmt, const Args &...args)
Format a string using the same formatting codes as UTprintf.
Format
Definition: oidn.hpp:16
SYS_FORCE_INLINE size_t hash_value(const UT_StringRef &str)
SYS_NO_DISCARD_RESULT SYS_FORCE_INLINE exint length() const
Returns the length of the string in bytes.
GLuint64EXT * result
Definition: glew.h:14311
void adoptFromCharArray(UT_Array< char > &data)
SYS_FORCE_INLINE UT_StringHolder(const std::string &str)
Will make a copy of the provided string.
exint emplace_back(S &&...s)
Definition: UT_ArrayImpl.h:179
bool operator==(const UT_StringRef &s) const
int compare(const UT_StringRef &str, bool ignore_case=false) const
exint length() const
OIIO_FORCEINLINE const vint4 & operator+=(vint4 &a, const vint4 &b)
Definition: simd.h:4347
int64 getMemoryUsage(bool inclusive) const
#define SYS_SAFE_BOOL
Definition: SYS_Compiler.h:55
exint length() const
SYS_FORCE_INLINE exint findCharIndex(char c) const
Find the location of the character (or -1 if not found)
SYS_FORCE_INLINE const char * buffer() const
SYS_NO_DISCARD_RESULT bool UTstringIsFloat(const StringT &str, bool skip_spaces=false, bool loose=false, bool allow_underscore=false)
friend void swap(UT_StringHolder &a, UT_StringHolder &b)
FMT_CONSTEXPR bool find(Ptr first, Ptr last, T value, Ptr &out)
Definition: format.h:2929
GLenum GLsizei len
Definition: glew.h:7782
#define UT_ASSERT_P(ZZ)
Definition: UT_Assert.h:170
SYS_FORCE_INLINE UT_StringHolder(const char *data, uint32 length)
static const UT_StringHolder theEmptyString
const GLdouble * v
Definition: glcorearb.h:836
int substitute(const char *find, const char *replacement, int count)
bool operator>=(const UT_StringRef &k) const
const char * findWord(const char *word) const
GLboolean GLboolean GLboolean GLboolean a
Definition: glcorearb.h:1221
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
GLsizei const GLchar *const * string
Definition: glcorearb.h:813
SYS_NO_DISCARD_RESULT int UTstringCountChar(const StringT &str, int c)
SYS_FORCE_INLINE UT_StringRef()
SYS_NO_DISCARD_RESULT bool UTstringStartsWith(const T &str, const char *prefix, bool case_sensitive=true, exint len=-1)
SYS_FORCE_INLINE UT_StringHolder & operator=(UT_StringHolder &&s)
void harden()
Take shallow copy and make it deep.
Definition: UT_String.h:206
SYS_FORCE_INLINE void makeSentinel()
void saveAscii(std::ostream &os) const
Definition: UT_String.h:291
SYS_FORCE_INLINE exint findCharIndex(const char *str, exint start_offset) const
Find the first location of any of the characters in the str passed in.
#define SYS_PRAGMA_DISABLE_FREE_NONHEAP_OBJECT()
Definition: SYS_Pragma.h:117
SYS_FORCE_INLINE UT_StringHolder(UT_StringHolder &&a) noexcept
Move constructor. Steals the working data from the original.
long long int64
Definition: SYS_Types.h:116
GLfloat GLfloat p
Definition: glew.h:16656
#define SYS_NO_DISCARD_RESULT
Definition: SYS_Compiler.h:93
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
int spaceship(const UT_StringRef &k) const
GLint GLsizei count
Definition: glcorearb.h:404
#define SYS_PRAGMA_POP_WARN()
Definition: SYS_Pragma.h:35
size_t format(const char *fmt, const Args &...args)
Format a string using the same formatting codes as UTformat.
SYS_FORCE_INLINE constexpr const char * c_str() const
bool operator<=(const UT_StringRef &k) const
const char * findWord(const char *word) const
bool operator<(const UT_StringRef &k) const
bool operator!=(const UT_StringRef &s) const
void fastReferenceWithStrlen(const char *src, exint length)
SYS_NO_DISCARD_RESULT bool UTstringIsInteger(const StringT &str, bool skip_spaces=false)
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:287
SYS_FORCE_INLINE constexpr bool operator!=(const UT_StringLit &other) const
GLdouble n
Definition: glcorearb.h:2007
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glcorearb.h:2539
GLubyte * pattern
Definition: glew.h:5741
SYS_FORCE_INLINE UT_StringHolder(UT_StringReferenceType, const UT_StringRef &ref)
Makes a shallow reference to the contents of the UT_StringRef.
GLboolean * data
Definition: glcorearb.h:130
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)
GLuint GLsizei GLsizei * length
Definition: glcorearb.h:794
GLfloat GLfloat GLfloat GLfloat h
Definition: glcorearb.h:2001
static Holder * buildFromData(const char *str, exint len, StorageMode storage, int hash=0)
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)
SYS_FORCE_INLINE ~UT_StringRef()
size_t operator()(const UT_StringHolder &s) const
bool operator==(const UT_String &s) const
const void * ptr(const T *p)
Definition: format.h:3603
bool load(UT_IStream &is)
Load string from stream. Use is.eof() to check eof status.
fpreal64 fpreal
Definition: SYS_Types.h:277
bool multiMatch(const char *pattern, bool case_sensitive, char separator) const
T * data()
Definition: UT_Array.h:655
SYS_FORCE_INLINE exint lastCharIndex(char c, int occurrence_number=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:220
friend class UT_StringHolder
int64 getMemoryUsage(bool inclusive) const
unsigned multiMatch(const UT_StringMMPattern &pattern, bool *explicitly_excluded=0, int *match_index=0, ut_PatternRecord *pattern_record=nullptr) const
SYS_FORCE_INLINE UT_StringHolder(UT_StringReferenceType, const char *str)
Will make a shallow reference.
SYS_FORCE_INLINE bool UTisstring(const char *s)
OIIO_API bool copy(string_view from, string_view to, std::string &err)
SYS_FORCE_INLINE const UT_StringHolder & asHolder() const
Type-safe formatting, modeled on the Python str.format function.
SYS_FORCE_INLINE exint countChar(char c) const
Count the number of times the character c occurs.
GA_API const UT_StringHolder N
const char * const_iterator
Iterators.
SYS_FORCE_INLINE UT_StringRef(const char *str)
Will make a shallow reference.
GLfloat f
Definition: glcorearb.h:1925
**If you just want to fire and args
Definition: thread.h:615
unsigned int uint32
Definition: SYS_Types.h:40
void reference(const char *src)
bool isstring() const
Definition: UT_String.h:681
getOption("OpenEXR.storage") storage
Definition: HDK_Image.dox:276
unsigned isInteger(int skip_spaces=0) const
Determine if string can be seen as a single integer number.
#define UT_ASSERT(ZZ)
Definition: UT_Assert.h:171
SYS_FORCE_INLINE constexpr const char * buffer() const
SYS_FORCE_INLINE void swap(UT_StringRef &other)
int toInt() const
unsigned match(const char *pattern, bool case_sensitive=true) const
bool operator!=(const BaseDimensions< T > &a, const BaseDimensions< Y > &b)
Definition: Dimensions.h:165
#define const
Definition: zconf.h:214
unsigned hash() const
bool startsWith(const UT_StringView &pfx, bool case_sense=true) const
Imported from UT_String.
GLboolean r
Definition: glcorearb.h:1221
#define SYSmin(a, b)
Definition: SYS_Math.h:1536
GLdouble s
Definition: glew.h:1395
SYS_FORCE_INLINE UT_StringHolder(const char *str)
Will make a copy of the provided string.
bool all(const vbool4 &v)
Definition: simd.h:3445
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
SYS_FORCE_INLINE T relaxedLoad() const
Definition: SYS_AtomicInt.h:59
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 isUnique() const
Returns true this object is the sole owner of the underlying string.
static const UT_StringHolder theSentinel
const char * fcontain(const char *pattern, bool case_sensitive=true) const
Definition: UT_String.h:987
SYS_FORCE_INLINE void swap(UT_StringRef &other)