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  * RELATION TO THE STL:
17  *
18  * Use UT_StringHolder, UT_WorkBuffer, etc. instead of std::string
19  *
20  * Reasoning to not use std::string:
21  *
22  * - Performance: The specification prohibits copy-on-write, so we
23  * can’t do a COW implementation, that we often rely on to
24  * minimize allocations. 
25  *
26  * - Bugs: It uses internal pointers so is not trivially
27  * relocatable, making arrays of strings expensive to resize.
28  *
29  * - Aesthetics: We have too many string types already to manage
30  * in Houdini without making yet another one common.
31  *
32  * See also:
33  * https://internal.sidefx.com/wiki/index.php/StringClasses 
34  *
35  */
36 
37 // #pragma once
38 
39 #ifndef __UT_StringHolder_h__
40 #define __UT_StringHolder_h__
41 
42 #include "UT_API.h"
43 #include "UT_Assert.h"
44 #include "UT_Format.h"
45 #include "UT_String.h"
46 #include "UT_Swap.h"
47 #include "UT_StringUtils.h"
48 
49 #include <SYS/SYS_AtomicInt.h>
50 #include <SYS/SYS_Compiler.h>
51 #include <SYS/SYS_Inline.h>
52 #include <SYS/SYS_Math.h>
53 #include <SYS/SYS_Pragma.h>
54 #include <SYS/SYS_StaticAssert.h>
55 #include <SYS/SYS_String.h>
56 #include <SYS/SYS_Types.h>
57 
58 #include <iosfwd>
59 #include <string>
60 #include <utility>
61 
62 #include <stdint.h>
63 #include <string.h>
64 
65 template <typename T> class UT_Array;
66 class UT_IStream;
67 class UT_OStream;
68 class ut_PatternRecord;
69 class UT_StringHolder;
70 class UT_StringMMPattern;
71 class UT_StringRef;
72 class UT_StringView;
73 class UT_WorkBuffer;
74 
75 // Forward declare the UDSL so that we can friend it inside of UT_StringHolder.
76 namespace UT { inline namespace Literal {
77 UT_StringHolder operator"" _sh(const char *s, std::size_t const length);
78 } }
79 
80 /// A string literal with length and compile-time computed hash value.
81 /// @note This will only be compile-time when used in compile time expressions
82 /// like template parameters and constexpr variables.
83 /// @note String literals whose length requires more than 31 bits not supported
84 /// @see UT_StringRef
86 {
87 public:
88  constexpr SYS_FORCE_INLINE
90  : myData(nullptr) // These must match UT_StringRef's default ctor
91  , myLength(0)
92  , myHash(0)
93  {
94  }
95 
96  template <size_t N>
97  constexpr SYS_FORCE_INLINE
98  UT_StringLit(const char (&str)[N])
99  : myData(str)
100  , myLength(N-1)
101  , myHash(SYSstring_hash(str, myLength, /*allow_nulls*/true))
102  {
103  SYS_STATIC_ASSERT(N-1 < (((exint)1) << 31));
104  }
105 
106  SYS_FORCE_INLINE constexpr const char* data() const
107  {
108  return myData ? myData : "";
109  }
110  SYS_FORCE_INLINE constexpr const char* buffer() const { return data(); }
111  SYS_FORCE_INLINE constexpr const char* c_str() const { return data(); }
112  SYS_FORCE_INLINE constexpr operator const char*() const { return data(); }
113 
114  SYS_FORCE_INLINE constexpr exint length() const { return myLength; }
115 
116  SYS_FORCE_INLINE constexpr uint32 hash() const { return myHash; }
117 
119  SYS_FORCE_INLINE const UT_StringRef& asRef() const;
120 
121  SYS_FORCE_INLINE constexpr bool operator==(const UT_StringLit &other) const
122  {
123  if (myLength != other.myLength || myHash != other.myHash)
124  return false;
125  // we must check also other.myData for nullptr to avoid gcc error
126  if (myData == nullptr || other.myData == nullptr)
127  return true;
128  return !SYSmemcmp(myData, other.myData, myLength);
129  }
130  SYS_FORCE_INLINE constexpr bool operator!=(const UT_StringLit &other) const
131  {
132  return !(*this == other);
133  }
134 
135  friend SYS_FORCE_INLINE constexpr
136  bool operator==(const UT_StringLit &str, const char *other)
137  {
138  // Treat nullptr as empty strings
139  if (other == nullptr)
140  return (str.myLength == 0);
141  if (str.myData == nullptr)
142  return *other == 0;
143 #if _MSC_VER
144  if (__builtin_is_constant_evaluated())
145  {
146  // compare up to myLength+1 to include terminating nul
147  for (int32 i = 0; i < str.myLength + 1; ++i)
148  {
149  if (str.myData[i] != other[i])
150  return false;
151  }
152  return true;
153  }
154  return !strcmp(str.myData, other);
155 #else
156  return !__builtin_strcmp(str.myData, other);
157 #endif
158  }
159  friend SYS_FORCE_INLINE constexpr
160  bool operator==(const char *other, const UT_StringLit &str)
161  {
162  return (str == other);
163  }
164  friend SYS_FORCE_INLINE constexpr
165  bool operator!=(const UT_StringLit &str, const char *other)
166  {
167  return !(str == other);
168  }
169  friend SYS_FORCE_INLINE constexpr
170  bool operator!=(const char *other, const UT_StringLit &str)
171  {
172  return !(str == other);
173  }
174 
175 private:
176  const char* myData;
177  int32 myLength;
178  uint32 myHash;
179 
180  friend class UT_StringRef;
181 };
182 
183 /// A holder for a string, which stores the length and caches the hash value.
184 /// A UT_StringRef does not necessarily own the string, and it is therefore not
185 /// safe to e.g. store a UT_StringRef in a container or member variable.
186 /// @see UT_StringHolder
187 /// @see UTmakeUnsafeRef
189 {
190 public:
191  typedef char value_type;
192 
194  {
198  STORE_INLINE
199  };
200 
202  {
203  Holder() = delete;
204  public:
205  static Holder *buildFromData(const char *str, exint len, StorageMode storage);
206  static Holder *buildInline(const char* str, exint length);
207  static Holder *buildInline(exint length);
208 
209  const char *c_str() const
210  {
211  if (myStorageMode == STORE_INLINE)
212  return myDataIfInline;
213  else
214  return myData;
215  }
216 
217  exint length() const
218  {
219  return myLength;
220  }
221 
222  void incref()
223  {
224  myRefCount.add(1);
225  }
226 
227  void decref()
228  {
229  if (myRefCount.add(-1) == 0)
230  destroy();
231  }
232 
233  int64 getMemoryUsage(bool inclusive) const;
234 
235  bool isUnique() const
236  {
237  return myRefCount.relaxedLoad() == 1 && myStorageMode != STORE_EXTERNAL;
238  }
239 
240  char* inlineBufferNC() // used after buildInline(length) to get buffer to write
241  {
242  return myDataIfInline;
243  }
244 
246  {
247  if (myStorageMode == STORE_MALLOC && myRefCount.relaxedLoad() == 1)
248  {
249  myStorageMode = STORE_EXTERNAL; // make destroy not free the data
250  return (char*)myData;
251  }
252  return 0; // steal did not work
253  }
254 
255  private:
256  void destroy();
257 
258  SYS_AtomicInt32 myRefCount;
259  StorageMode myStorageMode;
260  exint myLength;
261 
262  // This union makes viewing in a debugger much easier.
263  union {
264  const char *myData;
265  char myDataIfInline[sizeof(const char *)];
266  };
267  };
268 
271  : myData(nullptr)
272  , myLength(0)
273  , myHash(0)
274  {
275  }
276 
277  /// Will make a shallow reference.
279  UT_StringRef(const char *str)
280  : UT_StringRef()
281  {
282  if (str)
283  _reference(str, strlen(str));
284  }
285 
286  /// Will make a shallow reference.
287  /// This is NOT a string view, the string must actually null terminate
290  : UT_StringRef()
291  {
292  _reference(data, length);
293  }
294 
295  /// Construct from string literal
296  SYS_FORCE_INLINE explicit
298  : UT_StringRef(lit.asRef())
299  {
300  }
301 
302  /// This will make a shallow reference to the contents of the string.
305  : UT_StringRef(str.c_str(), str.length())
306  {
307  }
308 
309  /// This will make a shallow reference to the contents of the string.
310  UT_StringRef(const UT_WorkBuffer &str);
311 
312  /// This will make a shallow reference to the contents of the string.
315  : UT_StringRef(str.buffer(), str.length())
316  {
317  }
318 
319  /// Shares a reference with the source.
321  UT_StringRef(const UT_StringRef &s) noexcept
322  : myData(s.myData)
323  , myLength(s.myLength)
324  , myHash(s.myHash)
325  {
326  incref();
327  }
328 
329  /// Move constructor. Steals the working data from the original.
332  : myData(s.myData)
333  , myLength(s.myLength)
334  , myHash(s.myHash)
335  {
336  s.myData = nullptr;
337  s.myLength = 0;
338  s.myHash = 0;
339  }
340 
343  {
344  decref();
345  }
346 
347  /// Special sentinel value support
348  /// @{
349  enum UT_StringSentinelType { SENTINEL };
350 
351  SYS_FORCE_INLINE explicit
353  : myData(nullptr)
354  , myLength(0)
355  , myHash(SENTINEL_HASH)
356  {
357  }
358 
359  /// str==nullptr turns into sentinel, otherwise act like UT_StringRef(str)
362  : myData(nullptr)
363  , myLength(0)
364  , myHash(str ? 0 : SENTINEL_HASH)
365  {
366  if (str)
367  _reference(str, strlen(str));
368  }
369 
371  bool isSentinel() const
372  {
373  return myHash == SENTINEL_HASH && !myLength;
374  }
375 
378  {
379  decref();
380  myData = nullptr;
381  myLength = 0;
382  myHash = SENTINEL_HASH;
383  }
384  /// @}
385 
386  /// Returns true this object is the sole owner of the underlying string
387  bool isUnique() const
388  {
389  return !myLength && myDataIfHolder && myDataIfHolder->isUnique();
390  }
391 
392  /// Shares a reference with the source.
394  {
395  s.incref();
396  decref();
397  myData = s.myData;
398  myLength = s.myLength;
399  myHash = s.myHash;
400  return *this;
401  }
402 
403  /// Move the contents of about-to-be-destructed string
404  /// s to this string.
407  {
408  // Can just swap, since s is about to be destructed.
409  swap(s);
410  return *this;
411  }
412 
413  bool operator==(const UT_StringRef &s) const
414  {
415  // It is sensible to fast-path this based on myData!
416  // If our two pointers are equal, we either are pointing to
417  // the same Holder or to the same const char *, so are good
418  // to call it equal.
419  if (myData == s.myData)
420  {
421  if (!myData)
422  return myHash == s.myHash; // make sure sentinel != ""
423  return true;
424  }
425  // empty string cannot match non-empty string.
426  if (!myData || !s.myData)
427  return false;
428  // If both strings have cached hashes with different values, the
429  // strings cannot be equal.
430  if (myHash && s.myHash && myHash != s.myHash)
431  return false;
432  const exint tl = length();
433  return tl == s.length() && SYSmemcmp(c_str(), s.c_str(), tl) == 0;
434  }
435 
436  bool operator==(const char *s) const
437  {
438  if (!myDataIfChars)
439  return (!s || !*s) && !myHash; // make sure sentinel != ""
440  // It is sensible to fast-path this based on myData!
441  // If our two pointers are equal, we either are pointing to
442  // the same Holder or to the same const char *, so are good
443  // to call it equal.
444  // We don't test for myData being a Holder because it should
445  // never alias a const char *.
446  if (myDataIfChars == s)
447  return true;
448  // Avoid comparison with null.
449  if (!s)
450  return false;
451  return ::strcmp(c_str(), s) == 0;
452  }
453  bool operator==(const UT_String &s) const
454  { return operator==(s.buffer()); }
455 
456  bool operator!=(const UT_StringRef &s) const
457  { return !operator==(s); }
458  bool operator!=(const char *s) const
459  { return !operator==(s); }
460  bool operator!=(const UT_String &s) const
461  { return operator!=(s.buffer()); }
462 
463  /// Spaceship comparison returns:
464  /// - < 0 if *this < k
465  /// - == 0 if *this == k
466  /// - > 0 if *this > k
467  int spaceship(const UT_StringRef &k) const
468  {
469  const exint l = length();
470  const exint kl = k.length();
471  const exint minlen = SYSmin(l, kl);
472  int r = SYSmemcmp(c_str(), k.c_str(), minlen);
473  if (r != 0)
474  return r;
475  else if (kl > minlen)
476  return -1;
477  else if (l > minlen)
478  return 1;
479  else
480  return 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  bool 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  bool 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  bool 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  bool isFloat(bool skip_spaces = false, bool loose = false) const
560  { return UTstringIsFloat(*this, skip_spaces, loose); }
561  /// Determine if string can be seen as a single integer number
562  bool isInteger(bool skip_spaces = false) 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 
604  /// Equivalent to (length() != 0)
605  /// Returns false for isSentinel()
607  bool isstring() const
608  { return myData != nullptr; }
609 
610  /// Same as !isstring()
611  bool isEmpty() const
612  { return myData == nullptr; }
613 
614  /// method name that maches std::string
615  bool empty() const
616  { return myData == nullptr; }
617 
619  bool
620  hasNonSpace() const
621  {
622  const char *ptr = c_str();
623  for (exint i = 0, n = length(); i < n; ++i)
624  if (!SYSisspace(ptr[i]))
625  return true;
626  return false;
627  }
628 
629  /// Find the location of the character @c (or -1 if not found)
631  exint
632  findCharIndex(char c) const
633  {
634  const char *str = c_str();
635  const void *ptr = ::memchr(str, c, length());
636  return ptr ? (const char *)ptr - str : -1;
637  }
638 
639  /// Find the first location of any of the characters in the @c str passed in
641  exint
642  findCharIndex(const char *str) const
643  {
644  if (UTisstring(str))
645  {
646  const char *ptr = c_str();
647  const char *found_char = strpbrk(ptr, str);
648  if (found_char)
649  return found_char - ptr;
650  }
651  return -1;
652  }
653 
654  /// Find the location of the character @c (or -1 if not found)
656  exint
657  findCharIndex(char c, exint start_offset) const
658  {
659  if (start_offset < length())
660  {
661  const char *str = c_str();
662  const void *ptr = ::memchr(str+start_offset, c,
663  length()-start_offset);
664  if (ptr)
665  return (const char *)ptr - str;
666  }
667  return -1;
668  }
669 
670  /// Find the first location of any of the characters in the @c str passed in
672  exint
673  findCharIndex(const char *str, exint start_offset) const
674  {
675  if (UTisstring(str) && start_offset < length())
676  {
677  const char *ptr = c_str();
678  const char *found_char = strpbrk(ptr+start_offset, str);
679  if (found_char)
680  return found_char - ptr;
681  }
682  return -1;
683  }
684 
686  exint
687  lastCharIndex(char c, int occurrence_number = 1) const
688  {
689  const char *str = c_str();
690  exint n = length();
691  const void *start = SYSmemrchr(str, c, n);
692  while (start)
693  {
694  n = (const char *)start - str;
695  occurrence_number--;
696  if (occurrence_number <= 0)
697  return n;
698  start = (n == 0) ? nullptr : SYSmemrchr(str, c, n-1);
699  }
700  return -1;
701  }
702 
703  /// Count the number of times the character @c c occurs
705  exint
706  countChar(char c) const
707  {
708  return UTstringCountChar(*this, c);
709  }
710 
712  void clear()
713  {
714  decref();
715  myData = nullptr;
716  myLength = 0;
717  myHash = 0;
718  }
719 
721  const char *c_str() const
722  {
723  UT_ASSERT_P(!isSentinel());
724  if (myLength)
725  {
726  UT_ASSERT_P(myDataIfChars);
727  return myDataIfChars;
728  }
729  else if (myDataIfHolder)
730  return myDataIfHolder->c_str();
731  else
732  {
733 #if SYS_IS_GCC_GE(6, 0) && !SYS_IS_GCC_GE(8, 0)
734  // We need to do this to fix bad GCC warning:
735  // offset outside bounds of constant string
736  const char *volatile empty = "";
737  return empty;
738 #else
739  return "";
740 #endif
741  }
742  }
744  const char* data() const
745  {
746  return c_str();
747  }
748 
749  exint length() const
750  {
751  if (myLength)
752  return myLength;
753  else if (myDataIfHolder)
754  return myDataIfHolder->length();
755  else
756  return 0;
757  }
758 
759  unsigned hash() const
760  {
761  if (!myHash && myData)
762  myHash = hash_string(c_str(), length());
763  return myHash;
764  }
765 
766  /// Make a light weight reference to the source.
767  /// Caller must make sure src lives for the duration of this object,
768  /// and any objects value copied from this!
769  void reference(const char *src)
770  {
771  reference(src, src ? strlen(src) : 0);
772  }
773 
774  /// Fast reference that takes the length of the string.
775  /// This is NOT a string view, the string must actually null terminate
776  /// at the given length or later functions will be confused.
777  void reference(const char *str, exint length);
778 
779  /// old name of method:
781  {
782  reference(src, length);
783  }
784 
785  int64 getMemoryUsage(bool inclusive) const
786  {
787  int64 mem = inclusive ? sizeof(*this) : 0;
788  if (!myLength && myDataIfHolder)
789  mem += myDataIfHolder->getMemoryUsage(true);
790  return mem;
791  }
792 
793  // This hash function does not look for null termination, but
794  // instead goes directly for the length.
796  static unsigned hash_string(const char *str, exint len)
797  {
798  return SYSstring_hash(str, len, /*allow_nulls*/true);
799  }
800 
801 
802  /// Convert the string into a valid C style variable name.
803  /// All non-alpha numerics will be converted to _.
804  /// If the first letter is a digit, it is prefixed with an _.
805  /// If the string is already valid, the string itself is returned.
806  /// Note that this does NOT force the name to be non-zero in length.
807  /// The safechars parameter is a string containing extra characters
808  /// that should be considered safe. These characters are not
809  /// converted to underscores.
811  UT_StringRef forceValidVariableName(const char *safechars = nullptr) const;
812 
813  /// Convert to lower case. If the string is already lower case, the string
814  /// itself is returned.
816  UT_StringRef toLower() const;
817  /// Convert to upper case. If the string is already upper case, the string
818  /// itsef is returned.
820  UT_StringRef toUpper() const;
821 
822  /// Often people reflexively use this from UT_String days so
823  /// this increases code compataibility.
824  void harden(const char *src)
825  {
826  setHolder(Holder::buildInline(src, src ? strlen(src) : 0));
827  }
828 
829  // Steals the given string, gaining ownership of it.
830  // Will be freed by this when the reference count hits zero.
831  void adoptFromMalloc(const char *str, exint length);
832  void adoptFromNew(const char *str, exint length);
833 
835  {
836  if (!str.isstring())
837  {
838  clear();
839  return;
840  }
841  // We want to steal from always deep strings as well.
842  // We will erase the data in the source string!
843  str.harden();
844 
845  adoptFromMalloc(str.myData, strlen(str.myData));
846 
847  // Clear after harden in case str refers to us!
848  str.myData = 0;
849  str.myIsReference = true;
850  // Leave always deep as it was.
851  }
852  void adoptFromCharArray(UT_Array<char>& data);
853 
854  // Extracts a string from ourself of the given allocation mode.
855  // The result can be freed with that allocation mode.
856  // Will always clear myself afterwards. This will return our
857  // own string without copying if reference count is 1.
858  // Will return 0 for empty strings.
859  char *stealAsMalloc();
860 
861  // Tests to see if UT_StringLit's memory layout is the same
862  static bool verifyStringLit();
863 
864  /// Does a "smart" string compare which will sort based on numbered names.
865  /// That is "text20" is bigger than "text3". In a strictly alphanumeric
866  /// comparison, this would not be the case.
868  {
869  bool operator()(const UT_StringRef &s1, const UT_StringRef &s2) const
870  {
871  return UT_String::compareNumberedString(s1.c_str(), s2.c_str()) < 0;
872  }
873  };
874 
875  /// Save string to binary stream.
876  void saveBinary(std::ostream &os) const
877  { UT_StringWrap(c_str()).saveBinary(os); }
878 
879  /// Save string to ASCII stream. This will add double quotes and escape to
880  /// the stream if necessary (empty string or contains spaces).
881  void saveAscii(std::ostream &os) const
882  { UT_StringWrap(c_str()).saveAscii(os); }
883 
884 private:
886  void incref() const
887  {
888  if (!myLength && myDataIfHolder)
889  myDataIfHolder->incref();
890  }
891 
893  void decref()
894  {
895  if (!myLength && myDataIfHolder)
896  myDataIfHolder->decref();
897  }
898 
899  // this does not do holder->incref, and holder==nullptr is same as clear()
900  void setHolder(Holder* holder)
901  {
902  decref();
903  myDataIfHolder = holder;
904  myLength = 0;
905  myHash = 0;
906  }
907 
908  // same as reference() except string is assumed to be empty, used by constructors
909  void _reference(const char* str, exint length);
910 
911  void harden()
912  {
913  if (myLength)
914  {
915  myDataIfHolder = Holder::buildInline(myDataIfChars, myLength);
916  myLength = 0;
917  }
918  }
919 
920  // This union makes viewing in a debugger much easier.
921  union {
922  const void *myData;
923  const char *myDataIfChars;
925  };
926  int myLength;
927  mutable int myHash;
928 
929  /// This operator saves the string to the stream via the string's
930  /// saveAscii() method, protecting any whitespace (by adding quotes),
931  /// backslashes or quotes in the string.
932  friend UT_API std::ostream &operator<<(std::ostream &os, const UT_StringRef &d);
933  friend UT_API UT_OStream &operator<<(UT_OStream &os, const UT_StringRef &d);
934 
935  // UT_StringHolder needs to be a friend class so that the
936  // UT_StringHolder(const UT_StringRef &) constructor can access myHash and
937  // myDataIfHolder for the UT_StringRef that is passed in.
938  friend class UT_StringHolder;
939 
940  static constexpr uint32 SENTINEL_HASH = 0xdeadbeef;
941 };
942 
944 {
945  return str.hash();
946 }
947 
948 /// Equality operators for UT_StringLit with UT_StringRef
949 /// @{
950 static SYS_FORCE_INLINE bool
951 operator==(const UT_StringRef &ref, const UT_StringLit &lit)
952 {
953  return ref.operator==(lit.asRef());
954 }
955 static SYS_FORCE_INLINE bool
956 operator==(const UT_StringLit &lit, const UT_StringRef &ref)
957 {
958  return ref.operator==(lit.asRef());
959 }
960 static SYS_FORCE_INLINE bool
961 operator!=(const UT_StringRef &ref, const UT_StringLit &lit)
962 {
963  return ref.operator!=(lit.asRef());
964 }
965 static SYS_FORCE_INLINE bool
966 operator!=(const UT_StringLit &lit, const UT_StringRef &ref)
967 {
968  return ref.operator!=(lit.asRef());
969 }
970 /// @}
971 
972 /// Equality operators for UT_StringLit with UT_String
973 /// @{
974 static SYS_FORCE_INLINE bool
975 operator==(const UT_String &str, const UT_StringLit &lit)
976 {
977  return str.operator==(lit.asRef());
978 }
979 static SYS_FORCE_INLINE bool
980 operator==(const UT_StringLit &lit, const UT_String &str)
981 {
982  return str.operator==(lit.asRef());
983 }
984 static SYS_FORCE_INLINE bool
985 operator!=(const UT_String &str, const UT_StringLit &lit)
986 {
987  return str.operator!=(lit.asRef());
988 }
989 static SYS_FORCE_INLINE bool
990 operator!=(const UT_StringLit &lit, const UT_String &str)
991 {
992  return str.operator!=(lit.asRef());
993 }
994 /// @}
995 
996 
997 /// A holder for a string, which stores the length and caches the hash value.
998 /// The lifetime of the string is >= the lifetime of the UT_StringHolder.
1000 {
1001 public:
1002  /// UT_StringHolder can be constructed with UT_StringHolder::REFERENCE to
1003  /// create a shallow reference to the const char *.
1004  enum UT_StringReferenceType { REFERENCE };
1005 
1008  : UT_StringRef()
1009  {
1010  }
1011 
1012  /// Will make a copy of the provided string.
1014  UT_StringHolder(const char *str)
1015  : UT_StringHolder(str, str ? strlen(str) : 0)
1016  {
1017  }
1018 
1019  /// Will make a shallow reference.
1022  : UT_StringRef(str)
1023  {
1024  }
1025 
1026  /// Will make a copy of the provided string.
1029  {
1030  myDataIfHolder = Holder::buildInline(data, length);
1031  }
1032 
1033  // Prohibit accidents when converting from UT_String like:
1034  // myStringHolder(buffer, /*deep*/true)
1035  UT_StringHolder(const char *data, bool bad) = delete;
1036 
1037  // Add back explicit conversions for the length parameter
1040  : UT_StringHolder(data, exint(length)) { }
1043  : UT_StringHolder(data, exint(length)) { }
1046  : UT_StringHolder(data, exint(length)) { }
1047 #if defined(MBSD)
1049  UT_StringHolder(const char *data, size_t length)
1050  : UT_StringHolder(data, exint(length)) { }
1052  UT_StringHolder(const char *data, ptrdiff_t length)
1053  : UT_StringHolder(data, exint(length)) { }
1054 #endif
1055 
1056  /// Will make a copy of the provided string.
1059  : UT_StringHolder(str.c_str(), str.length())
1060  {
1061  }
1062 
1063  /// This will make a shallow reference to the contents of the string.
1066  : UT_StringRef(str)
1067  {
1068  }
1069 
1070  /// Will make a copy of the provided string.
1071  UT_StringHolder(const UT_WorkBuffer &str);
1072 
1073  /// This will make a shallow reference to the contents of the string.
1076  : UT_StringRef(str)
1077  {
1078  }
1079 
1080  /// Will make a copy of the provided string.
1083  : UT_StringHolder(str.buffer(), str.length())
1084  {
1085  }
1086 
1087  /// Attempts to steal the string's buffer
1089  : UT_StringHolder()
1090  {
1091  adoptFromString(str);
1092  }
1093 
1094  /// This will make a shallow reference to the contents of the string.
1097  : UT_StringRef(str)
1098  {
1099  }
1100 
1101  /// Will make a copy of the provided string.
1102  UT_StringHolder(const UT_StringView &sv);
1103 
1104  /// Makes a shallow reference to the contents of the UT_StringRef.
1107  : UT_StringRef(ref)
1108  {
1109  }
1110 
1111  /// Makes a deep copy of the provided UT_StringRef.
1112  /// This constructor is not marked explicit since we often want this
1113  /// conversion (e.g. when inserting a UT_StringRef into a UT_StringMap, as
1114  /// with the const char* constructor).
1116  : UT_StringRef(ref)
1117  {
1118  harden();
1119  }
1120 
1122  : UT_StringRef(std::move(ref))
1123  {
1124  harden();
1125  }
1126 
1127  /// Construct as a sentinel value
1128  SYS_FORCE_INLINE explicit
1130  : UT_StringRef(sentinel)
1131  {
1132  }
1133 
1134  /// Makes a copy of the provided string.
1137  : UT_StringRef(str)
1138  {
1139  }
1140 
1141  /// Move constructor. Steals the working data from the original.
1144  : UT_StringRef(std::move(a))
1145  {
1146  }
1147 
1148  /// Move constructor. Steals the data from the work buffer.
1149  UT_StringHolder(UT_WorkBuffer &&buf) noexcept;
1150 
1151  /// Makes a bit-wise copy of the string and adjust the reference count.
1154  {
1156  return *this;
1157  }
1158 
1159  /// Move the contents of about-to-be-destructed string
1160  /// s to this string.
1163  {
1164  UT_StringRef::operator=(std::move(s));
1165  return *this;
1166  }
1167 
1168  /// Move the contents buffer into this string holder.
1170 
1172  void swap(UT_StringHolder &other)
1173  {
1174  UT_StringRef::swap(other);
1175  }
1176 
1178  void swap(UT_StringRef &other)
1179  {
1180  UT_StringRef::swap(other);
1181  // harden ourselves like UT_StringHolder::operator=(UT_StringRef&)
1182  harden();
1183  }
1184 
1185  /// Friend specialization of std::swap() to use UT_StringHolder::swap()
1186  /// @{
1187  friend void swap(UT_StringHolder& a, UT_StringRef& b) { a.swap(b); }
1188  friend void swap(UT_StringHolder& a, UT_StringHolder& b) { a.swap(b); }
1189  /// @}
1190 
1191  /// In some functions it's nice to be able to return a const-reference to a
1192  /// UT_StringHolder. However, in error cases, you likely want to return an
1193  /// empty string. This would mean that you'd have to return a real
1194  /// UT_StringHolder (not a const reference). This static lets you return a
1195  /// reference to an empty string.
1197 
1199 
1200  /// Format a string using the same formatting codes as @c UTformat.
1201  template<typename... Args>
1202  size_t format(const char *fmt, const Args &...args)
1203  {
1204  return format(fmt, {args...});
1205  }
1206  size_t format(const char *fmt, std::initializer_list<UT::Format::ArgValue> args);
1207 
1208  /// Format a string using the same formatting codes as @c UTprintf.
1209  template<typename... Args>
1210  SYS_DEPRECATED_HDK_REPLACE(19.5, UT_WorkBuffer::sprintf() to avoid string allocations)
1211  size_t sprintf(const char *fmt, const Args &...args)
1212  {
1213  return sprintf(fmt, {args...});
1214  }
1215  size_t sprintf(const char *fmt, std::initializer_list<UT::Format::ArgValue> args);
1216 
1217  /// Replaces up to 'count' occurrences of 'find' with 'replacement',
1218  /// and returns the number of substitutions that occurred.
1219  /// If 'count' <= 0, all occurrences will be replaced.
1220  int substitute(const char *find, const char *replacement, int count = -1)
1221  {
1222  UT_String s(buffer());
1223  int n = s.substitute(find, replacement, count);
1224  if (n > 0)
1225  adoptFromString(s);
1226  return n;
1227  }
1228 
1229  /// Convenience version of substitute() for all or single occurrence.
1230  SYS_DEPRECATED_REPLACE(19.5, "Use 'count' variant")
1231  int substitute(const char *find, const char *replacement, bool all)
1232  {
1233  return substitute(find, replacement, !all ? 1 : -1);
1234  }
1235 
1236  /// Strips out all characters found in 'chars'. The string length will be
1237  /// reduced by the number of characters removed. The number of characters
1238  /// removed is returned.
1239  int strip(const char *chars);
1240 
1241  /// Prepend a string
1242  // @{
1243  void prepend(const UT_StringRef &prefix);
1244  // @}
1245 
1246  /// Load string from stream. Use is.eof() to check eof status
1247  bool load(UT_IStream &is)
1248  {
1249  UT_String s;
1250  if (s.load(is))
1251  {
1252  adoptFromString(s);
1253  return true;
1254  }
1255  return false;
1256  }
1257 
1259 
1260  /// A version of trimSpace() that only removes leading and following spaces
1261  /// from a string, leaving any between words intact.
1262  bool trimBoundingSpace();
1263 
1264  /// trimSpace() will remove all space characters (leading and following)
1265  /// from a string. If the string consists of multiple words, the words
1266  /// will be collapsed. To keep a single space between words, pass in true.
1267  /// The function returns true if space was trimmed.
1268  bool trimSpace(bool leave_single_space_between_words = false);
1269 
1270 protected:
1271  friend UT_StringHolder UT::Literal::operator"" _sh(
1272  const char *s, std::size_t const length);
1273  friend UT_StringHolder operator"" _UTsh(
1274  const char *s, std::size_t const length);
1275  friend UT_API std::istream &operator>>(std::istream& is, UT_StringHolder& s);
1276 
1277  /// A marker enum to use this constructor.
1278  enum UT_StringLiteralType { LITERAL };
1279 
1280  /// Only accepts string literals. Since there's no way to guarantee that
1281  /// a const char * argument is a string literal, we do this through the
1282  /// use of user-defined literal and *only* provide this constructor to our
1283  /// user-defined literal operator.
1285  {
1286  if (str && length)
1287  {
1288  myDataIfChars = str;
1289  myLength = length;
1290  // As of C++14, user defined literals don't support constexpr so
1291  // this hash computation here is actually done at run-time except
1292  // for in some cases where the compiler (clang?) is able to
1293  // optimize this. Therefore, disable this to avoid extraneous hash
1294  // computation in cases where we just want to use "foo"_sh to avoid
1295  // heap allocation but never use its hash.
1296  // Use UT_StringLit if you want to get compile time hashes
1297 #if 0
1298  myHash = SYSstring_hash_literal(str);
1299 #else
1300  myHash = 0;
1301 #endif
1302  }
1303  }
1304 };
1305 
1306 /// Convert a UT_StringRef into a UT_StringHolder that is a shallow reference.
1308 {
1309  SYS_STATIC_ASSERT(sizeof(UT_StringRef) == sizeof(UT_StringHolder));
1310  return reinterpret_cast<const UT_StringHolder &>(ref);
1311 }
1312 
1313 /// Convert a UT_StringRef into a UT_StringHolder that is a shallow reference,
1314 /// and also precompute the hash. Use this for string literals
1315 /// that will be used repeatedly in hash tables.
1317 {
1318  SYS_STATIC_ASSERT(sizeof(UT_StringRef) == sizeof(UT_StringHolder));
1319  ref.hash();
1320  return reinterpret_cast<const UT_StringHolder &>(ref);
1321 }
1322 
1325 {
1326  SYS_STATIC_ASSERT(sizeof(UT_StringHolder) == sizeof(*this));
1327  return reinterpret_cast<const UT_StringHolder &>(*this);
1328 }
1329 
1332 {
1333  SYS_STATIC_ASSERT(sizeof(UT_StringRef) == sizeof(*this));
1334  return reinterpret_cast<const UT_StringRef &>(*this);
1335 }
1336 
1337 SYS_FORCE_INLINE size_t tbb_hasher(const UT_StringRef &s) { return s.hash(); }
1338 SYS_FORCE_INLINE size_t tbb_hasher(const UT_StringHolder &s) { return s.hash(); }
1339 
1340 /// A user-defined string literal to construct UT_StringHolder objects.
1341 /// E.g:
1342 /// @code
1343 /// auto lit = "This is my UT_StringHolder literal"_sh;
1344 /// @endcode
1345 namespace UT { inline namespace Literal {
1346 SYS_FORCE_INLINE UT_StringHolder operator"" _sh(const char *s, std::size_t const length)
1347 {
1348  return UT_StringHolder(UT_StringHolder::LITERAL, s, length);
1349 }
1350 } }
1351 
1352 /// A user-defined literal in the global namespace. Uglier, but allows the use
1353 /// of UT_StringHolder UDLs in headers.
1354 SYS_FORCE_INLINE UT_StringHolder operator"" _UTsh(const char *s, std::size_t const length)
1355 {
1356  return UT_StringHolder(UT_StringHolder::LITERAL, s, length);
1357 }
1358 
1359 
1360 namespace std
1361 {
1362  template<>
1363  struct hash<UT_StringRef>
1364  {
1365  size_t operator()(const UT_StringRef &s) const
1366  {
1367  return s.hash();
1368  }
1369  };
1370  template<>
1371  struct hash<UT_StringHolder>
1372  {
1373  size_t operator()(const UT_StringHolder &s) const
1374  {
1375  return s.hash();
1376  }
1377  };
1378 }
1379 
1380 // For UT::ArraySet.
1381 namespace UT
1382 {
1383 template <typename T>
1384 struct DefaultClearer;
1385 
1386 template <>
1388 {
1389  static void clear(UT_StringHolder &v) { v.makeSentinel(); }
1390  static bool isClear(const UT_StringHolder &v) { return v.isSentinel(); }
1392  {
1393  new ((void *)p) UT_StringHolder(UT_StringRef::SENTINEL);
1394  }
1395  static const bool clearNeedsDestruction = false;
1396 };
1397 } // namespace UT
1398 
1399 #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
std::string toStdString() const
typedef int(APIENTRYP RE_PFNGLXSWAPINTERVALSGIPROC)(int)
void adoptFromString(UT_String &str)
SYS_FORCE_INLINE UT_StringHolder(const UT_StringHolder &str)
Makes a copy of the provided string.
std::string ignore_case(std::string item)
Helper function to allow ignore_case to be passed to IsMember or Transform.
Definition: CLI11.h:3456
SYS_FORCE_INLINE const_iterator begin() const
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glcorearb.h:2540
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)
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 UT_StringRef(const char *data, exint length)
SYS_FORCE_INLINE constexpr exint length() const
bool multiMatch(const char *pattern, bool case_sensitive, char separator) 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)
void harden(const char *src)
getFileOption("OpenEXR:storage") storage
Definition: HDK_Image.dox:276
int substitute(const char *find, const char *replacement, int count=-1)
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:837
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:475
GLsizei const GLchar *const * string
Definition: glcorearb.h:814
bool contains(const char *pattern, bool case_sensitive=true) const
fpreal toFloat() const
int toInt() const
#define SYS_DEPRECATED_HDK_REPLACE(__V__, __R__)
bool isEmpty() const
Same as !isstring()
static void clear(UT_StringHolder &v)
bool isFloat(bool skip_spaces=false, bool loose=false) const
Determine if string can be seen as a single floating point number.
bool 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
int64 exint
Definition: SYS_Types.h:125
SYS_FORCE_INLINE void swap(UT_StringHolder &other)
GLboolean GLboolean GLboolean GLboolean a
Definition: glcorearb.h:1222
GLdouble s
Definition: glad.h:3009
void swap(T &lhs, T &rhs)
Definition: pugixml.cpp:7172
GLuint GLsizei GLsizei * length
Definition: glcorearb.h:795
static void clearConstruct(UT_StringHolder *p)
SYS_FORCE_INLINE UT_StringRef & operator=(UT_StringRef &&s)
bool endsWith(const UT_StringView &suffix, bool case_sense=true) const
#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
unsigned long long uint64
Definition: SYS_Types.h:117
bool match(const char *pattern, bool case_sensitive=true) const
SYS_FORCE_INLINE exint findCharIndex(const char *str) const
Find the first location of any of the characters in the str passed in.
SYS_FORCE_INLINE size_t tbb_hasher(const UT_StringRef &s)
SIM_API const UT_StringHolder all
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.
int substitute(const char *find, const char *replacement, int count=-1)
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
const void * myData
bool contains(const char *pattern, bool case_sensitive=true) const
#define SYS_DEPRECATED_REPLACE(__V__, __R__)
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
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.
bool isInteger(bool skip_spaces=false) const
Determine if string can be seen as a single integer number.
const char * buffer() const
Definition: UT_String.h:509
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:39
SYS_FORCE_INLINE size_t hash_value(const UT_StringRef &str)
UT_StringHolder(UT_String &&str)
Attempts to steal the string's buffer.
GLdouble n
Definition: glcorearb.h:2008
SYS_NO_DISCARD_RESULT SYS_FORCE_INLINE exint length() const
Returns the length of the string in bytes.
SYS_FORCE_INLINE UT_StringHolder(const std::string &str)
Will make a copy of the provided string.
Definition: core.h:760
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:4369
GLint ref
Definition: glcorearb.h:124
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)
SYS_FORCE_INLINE UT_StringRef(UT_StringSentinelType, const char *str)
str==nullptr turns into sentinel, otherwise act like UT_StringRef(str)
#define UT_ASSERT_P(ZZ)
Definition: UT_Assert.h:155
SYS_FORCE_INLINE UT_StringHolder(const char *data, uint32 length)
static const UT_StringHolder theEmptyString
SYS_FORCE_INLINE UT_StringRef(const UT_StringRef &s) noexcept
Shares a reference with the source.
bool operator>=(const UT_StringRef &k) const
const char * findWord(const char *word) 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
GLint GLint GLsizei GLint GLenum format
Definition: glcorearb.h:108
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:215
SYS_FORCE_INLINE void makeSentinel()
void saveAscii(std::ostream &os) const
Definition: UT_String.h:300
bool operator!=(const Mat3< T0 > &m0, const Mat3< T1 > &m1)
Inequality operator, does exact floating point comparisons.
Definition: Mat3.h:556
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.
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
#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
UT_StringHolder(UT_StringRef &&ref)
int spaceship(const UT_StringRef &k) const
friend SYS_FORCE_INLINE constexpr bool operator!=(const UT_StringLit &str, const char *other)
size_t format(const char *fmt, const Args &...args)
Format a string using the same formatting codes as UTformat.
friend SYS_FORCE_INLINE constexpr bool operator==(const char *other, const UT_StringLit &str)
SYS_FORCE_INLINE constexpr const char * c_str() const
GLushort pattern
Definition: glad.h:2583
bool operator<=(const UT_StringRef &k) const
OIIO_FORCEINLINE vint4 operator>>(const vint4 &a, const unsigned int bits)
Definition: simd.h:4524
GLboolean GLboolean GLboolean b
Definition: glcorearb.h:1222
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)
old name of method:
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:296
SYS_FORCE_INLINE constexpr bool operator!=(const UT_StringLit &other) const
int sprintf(const char *fmt,...) SYS_PRINTF_CHECK_ATTRIBUTE(2
bool empty() const
method name that maches std::string
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
bool isUnique() const
static int compareNumberedString(const char *s1, const char *s2, bool case_sensitive=true, bool allow_negatives=false)
SYS_FORCE_INLINE UT_StringRef(const UT_String &str)
This will make a shallow reference to the contents of the string.
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
friend SYS_FORCE_INLINE constexpr bool operator!=(const char *other, const UT_StringLit &str)
bool operator==(const UT_String &s) const
bool load(UT_IStream &is)
Load string from stream. Use is.eof() to check eof status.
UT_StringHolder(const UT_StringRef &ref)
fpreal64 fpreal
Definition: SYS_Types.h:277
bool multiMatch(const char *pattern, bool case_sensitive, char separator) const
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
SYS_FORCE_INLINE UT_StringHolder(UT_StringReferenceType, const char *str)
Will make a shallow reference.
SYS_FORCE_INLINE bool UTisstring(const char *s)
SYS_FORCE_INLINE const UT_StringHolder & asHolder() const
auto ptr(T p) -> const void *
Definition: format.h:2448
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.
**If you just want to fire and args
Definition: thread.h:609
unsigned int uint32
Definition: SYS_Types.h:40
void reference(const char *src)
bool isstring() const
Definition: UT_String.h:691
SYS_FORCE_INLINE constexpr const char * buffer() const
SYS_FORCE_INLINE void swap(UT_StringRef &other)
int toInt() const
GLboolean r
Definition: glcorearb.h:1222
#define const
Definition: zconf.h:214
auto sprintf(const S &fmt, const T &...args) -> std::basic_string< Char >
Definition: printf.h:574
string_view OIIO_UTIL_API strip(string_view str, string_view chars=string_view())
friend SYS_FORCE_INLINE constexpr bool operator==(const UT_StringLit &str, const char *other)
bool startsWith(const UT_StringView &pfx, bool case_sense=true) const
Imported from UT_String.
#define SYSmin(a, b)
Definition: SYS_Math.h:1539
static Holder * buildInline(const char *str, exint length)
SYS_FORCE_INLINE UT_StringHolder(const char *str)
Will make a copy of the provided string.
const char * c_str() const
bool operator==(const Mat3< T0 > &m0, const Mat3< T1 > &m1)
Equality operator, does exact floating point comparisons.
Definition: Mat3.h:542
const char * myDataIfChars
SYS_FORCE_INLINE UT_StringRef(const std::string &str)
This will make a shallow reference to the contents of the string.
GLint GLsizei count
Definition: glcorearb.h:405
bool operator!=(const UT_String &s) const
SYS_FORCE_INLINE bool isstring() const
Definition: format.h:895
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.
bool 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 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
FMT_CONSTEXPR auto find(Ptr first, Ptr last, T value, Ptr &out) -> bool
Definition: core.h:2089
GLenum src
Definition: glcorearb.h:1793
const char * fcontain(const char *pattern, bool case_sensitive=true) const
Definition: UT_String.h:997
SYS_FORCE_INLINE void swap(UT_StringRef &other)
PcpNodeRef_ChildrenIterator begin(const PcpNodeRef::child_const_range &r)
Support for range-based for loops for PcpNodeRef children ranges.
Definition: node.h:483