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 // Empty strings must have myData be nullptr, specialize for these
184 template <>
185 constexpr SYS_FORCE_INLINE
186 UT_StringLit::UT_StringLit(const char (&str)[1])
187  : myData(nullptr)
188  , myLength(0)
189  , myHash(0)
190 {
191 }
192 
193 /// A holder for a string, which stores the length and caches the hash value.
194 /// A UT_StringRef does not necessarily own the string, and it is therefore not
195 /// safe to e.g. store a UT_StringRef in a container or member variable.
196 /// @see UT_StringHolder
197 /// @see UTmakeUnsafeRef
199 {
200 public:
201  typedef char value_type;
202 
204  {
208  STORE_INLINE
209  };
210 
212  {
213  Holder() = delete;
214  public:
215  static Holder *buildFromData(const char *str, exint len, StorageMode storage);
216  static Holder *buildInline(const char* str, exint length);
217  static Holder *buildInline(exint length);
218 
219  const char *c_str() const
220  {
221  if (myStorageMode == STORE_INLINE)
222  return myDataIfInline;
223  else
224  return myData;
225  }
226 
227  exint length() const
228  {
229  return myLength;
230  }
231 
232  void incref()
233  {
234  myRefCount.add(1);
235  }
236 
237  void decref()
238  {
239  if (myRefCount.add(-1) == 0)
240  destroy();
241  }
242 
243  int64 getMemoryUsage(bool inclusive) const;
244 
245  bool isUnique() const
246  {
247  return myRefCount.relaxedLoad() == 1 && myStorageMode != STORE_EXTERNAL;
248  }
249 
250  char* inlineBufferNC() // used after buildInline(length) to get buffer to write
251  {
252  return myDataIfInline;
253  }
254 
256  {
257  if (myStorageMode == STORE_MALLOC && myRefCount.relaxedLoad() == 1)
258  {
259  myStorageMode = STORE_EXTERNAL; // make destroy not free the data
260  return (char*)myData;
261  }
262  return 0; // steal did not work
263  }
264 
265  private:
266  void destroy();
267 
268  SYS_AtomicInt32 myRefCount;
269  StorageMode myStorageMode;
270  exint myLength;
271 
272  // This union makes viewing in a debugger much easier.
273  union {
274  const char *myData;
275  char myDataIfInline[sizeof(const char *)];
276  };
277  };
278 
281  : myData(nullptr)
282  , myLength(0)
283  , myHash(0)
284  {
285  }
286 
287  /// Will make a shallow reference.
289  UT_StringRef(const char *str)
290  : UT_StringRef()
291  {
292  if (str)
293  _reference(str, strlen(str));
294  }
295 
296  /// Will make a shallow reference.
297  /// This is NOT a string view, the string must actually null terminate
300  : UT_StringRef()
301  {
302  _reference(data, length);
303  }
304 
305  /// Construct from string literal
306  SYS_FORCE_INLINE explicit
308  : UT_StringRef(lit.asRef())
309  {
310  }
311 
312  /// This will make a shallow reference to the contents of the string.
314  UT_StringRef(const std::string &str)
315  : UT_StringRef(str.c_str(), str.length())
316  {
317  }
318 
319  /// This will make a shallow reference to the contents of the string.
320  UT_StringRef(const UT_WorkBuffer &str);
321 
322  /// This will make a shallow reference to the contents of the string.
325  : UT_StringRef(str.buffer(), str.length())
326  {
327  }
328 
329  /// Shares a reference with the source.
331  UT_StringRef(const UT_StringRef &s) noexcept
332  : myData(s.myData)
333  , myLength(s.myLength)
334  , myHash(s.myHash)
335  {
336  incref();
337  }
338 
339  /// Move constructor. Steals the working data from the original.
342  : myData(s.myData)
343  , myLength(s.myLength)
344  , myHash(s.myHash)
345  {
346  s.myData = nullptr;
347  s.myLength = 0;
348  s.myHash = 0;
349  }
350 
353  {
354  decref();
355  }
356 
357  /// Special sentinel value support
358  /// @{
359  enum UT_StringSentinelType { SENTINEL };
360 
361  SYS_FORCE_INLINE explicit
363  : myData(nullptr)
364  , myLength(0)
365  , myHash(SENTINEL_HASH)
366  {
367  }
368 
369  /// str==nullptr turns into sentinel, otherwise act like UT_StringRef(str)
372  : myData(nullptr)
373  , myLength(0)
374  , myHash(str ? 0 : SENTINEL_HASH)
375  {
376  if (str)
377  _reference(str, strlen(str));
378  }
379 
381  bool isSentinel() const
382  {
383  return myHash == SENTINEL_HASH && !myLength;
384  }
385 
388  {
389  decref();
390  myData = nullptr;
391  myLength = 0;
392  myHash = SENTINEL_HASH;
393  }
394  /// @}
395 
396  /// Returns true this object is the sole owner of the underlying string
397  bool isUnique() const
398  {
399  return !myLength && myDataIfHolder && myDataIfHolder->isUnique();
400  }
401 
402  /// Shares a reference with the source.
404  {
405  s.incref();
406  decref();
407  myData = s.myData;
408  myLength = s.myLength;
409  myHash = s.myHash;
410  return *this;
411  }
412 
413  /// Move the contents of about-to-be-destructed string
414  /// s to this string.
417  {
418  // Can just swap, since s is about to be destructed.
419  swap(s);
420  return *this;
421  }
422 
423  bool operator==(const UT_StringRef &s) const
424  {
425  // It is sensible to fast-path this based on myData!
426  // If our two pointers are equal, we either are pointing to
427  // the same Holder or to the same const char *, so are good
428  // to call it equal.
429  if (myData == s.myData)
430  {
431  if (!myData)
432  return myHash == s.myHash; // make sure sentinel != ""
433  return true;
434  }
435  // empty string cannot match non-empty string.
436  if (!myData || !s.myData)
437  return false;
438  // If both strings have cached hashes with different values, the
439  // strings cannot be equal.
440  if (myHash && s.myHash && myHash != s.myHash)
441  return false;
442  const exint tl = length();
443  return tl == s.length() && SYSmemcmp(c_str(), s.c_str(), tl) == 0;
444  }
445 
446  bool operator==(const char *s) const
447  {
448  if (!myDataIfChars)
449  return (!s || !*s) && !myHash; // make sure sentinel != ""
450  // It is sensible to fast-path this based on myData!
451  // If our two pointers are equal, we either are pointing to
452  // the same Holder or to the same const char *, so are good
453  // to call it equal.
454  // We don't test for myData being a Holder because it should
455  // never alias a const char *.
456  if (myDataIfChars == s)
457  return true;
458  // Avoid comparison with null.
459  if (!s)
460  return false;
461  return ::strcmp(c_str(), s) == 0;
462  }
463  bool operator==(const UT_String &s) const
464  { return operator==(s.buffer()); }
465 
466  bool operator!=(const UT_StringRef &s) const
467  { return !operator==(s); }
468  bool operator!=(const char *s) const
469  { return !operator==(s); }
470  bool operator!=(const UT_String &s) const
471  { return operator!=(s.buffer()); }
472 
473  /// Spaceship comparison returns:
474  /// - < 0 if *this < k
475  /// - == 0 if *this == k
476  /// - > 0 if *this > k
477  int spaceship(const UT_StringRef &k) const
478  {
479  const exint l = length();
480  const exint kl = k.length();
481  const exint minlen = SYSmin(l, kl);
482  int r = SYSmemcmp(c_str(), k.c_str(), minlen);
483  if (r != 0)
484  return r;
485  else if (kl > minlen)
486  return -1;
487  else if (l > minlen)
488  return 1;
489  else
490  return 0;
491  }
492 
493  bool operator<(const UT_StringRef &k) const
494  { return spaceship(k) < 0; }
495  bool operator<=(const UT_StringRef &k) const
496  { return spaceship(k) <= 0; }
497  bool operator>(const UT_StringRef &k) const
498  { return spaceship(k) > 0; }
499  bool operator>=(const UT_StringRef &k) const
500  { return spaceship(k) >= 0; }
501  int compare(const UT_StringRef &str,
502  bool ignore_case=false) const
503  {
504  return ignore_case
505  ? SYSstrcasecmp(c_str(), str.c_str())
506  : spaceship(str); }
507  bool equal(const UT_StringRef &str,
508  bool ignore_case=false) const
509  { return compare(str, ignore_case) == 0; }
510 
511  /// Test whether the string is defined or not
513  SYS_SAFE_BOOL operator bool() const { return isstring(); }
514 
515  /// Imported from UT_String.
516  bool startsWith(const UT_StringView &pfx, bool case_sense=true) const
517  {
518  return UTstringStartsWith(*this, pfx.data(), case_sense, pfx.length());
519  }
520  bool endsWith(const UT_StringView &suffix, bool case_sense=true) const
521  {
522  return UTstringEndsWith(*this, suffix.data(), case_sense, suffix.length());
523  }
524  bool match(const char *pattern, bool case_sensitive=true) const
525  { return UT_StringWrap(c_str()).match(pattern, case_sensitive); }
526 
527  bool contains(const char *pattern, bool case_sensitive=true) const
528  { return UT_StringWrap(c_str()).contains(pattern, case_sensitive); }
529  const char *fcontain(const char *pattern, bool case_sensitive=true) const
530  { return UT_StringWrap(c_str()).fcontain(pattern, case_sensitive); }
531  const char *findWord(const char *word) const
532  { return UT_StringWrap(c_str()).findWord(word); }
533 
534  bool multiMatch(const char *pattern, bool case_sensitive,
535  char separator) const
536  {
537  return UT_StringWrap(c_str()).multiMatch(
538  pattern, case_sensitive, separator);
539  }
540  bool multiMatch(const char *pattern, bool case_sensitive = true,
541  const char *separators = ", ",
542  bool *explicitly_excluded = 0,
543  int *match_index = 0,
544  ut_PatternRecord *pattern_record=nullptr) const
545  {
546  return UT_StringWrap(c_str()).multiMatch(
547  pattern, case_sensitive, separators, explicitly_excluded,
548  match_index, pattern_record);
549  }
551  bool *explicitly_excluded = 0,
552  int *match_index = 0,
553  ut_PatternRecord *pattern_record=nullptr) const
554  {
555  return UT_StringWrap(c_str()).multiMatch(
556  pattern, explicitly_excluded, match_index, pattern_record);
557  }
558 
559  /// Returns true if the entire string matches the provided regular
560  /// expression, false otherwise. See UT_Regex.
561  bool matchRegex(const char *expr) const;
562 
563  int toInt() const
564  { return UT_StringWrap(c_str()).toInt(); }
565  fpreal toFloat() const
566  { return UT_StringWrap(c_str()).toFloat(); }
567 
568  /// Determine if string can be seen as a single floating point number
569  bool isFloat(bool skip_spaces = false, bool loose = false) const
570  { return UTstringIsFloat(*this, skip_spaces, loose); }
571  /// Determine if string can be seen as a single integer number
572  bool isInteger(bool skip_spaces = false) const
573  { return UTstringIsInteger(*this, skip_spaces); }
574 
576  operator const char *() const
577  { return c_str(); }
578 
580  const char *buffer() const
581  { return c_str(); }
582  // We are always non-null by definition!
584  const char *nonNullBuffer() const
585  { return c_str(); }
586 
587  /// Iterators
588  typedef const char * const_iterator;
589 
592  { return c_str(); }
595  { return begin() + length(); }
596 
597 
598  /// Converts the contents of this UT_String to a std::string. Since
599  /// we are never null this is easy
600  std::string toStdString() const
601  { return std::string(c_str(), length()); }
602 
604  void swap( UT_StringRef &other )
605  {
606  UTswap(myData, other.myData);
607  UTswap(myLength, other.myLength);
608  UTswap(myHash, other.myHash);
609  }
610 
611  /// Friend specialization of std::swap() to use UT_StringRef::swap()
612  friend void swap(UT_StringRef& a, UT_StringRef& b) { a.swap(b); }
613 
614  /// Equivalent to (length() != 0)
615  /// Returns false for isSentinel()
617  bool isstring() const
618  { return myData != nullptr; }
619 
620  /// Same as !isstring()
621  bool isEmpty() const
622  { return myData == nullptr; }
623 
624  /// method name that maches std::string
625  bool empty() const
626  { return myData == nullptr; }
627 
629  bool
630  hasNonSpace() const
631  {
632  const char *ptr = c_str();
633  for (exint i = 0, n = length(); i < n; ++i)
634  if (!SYSisspace(ptr[i]))
635  return true;
636  return false;
637  }
638 
639  /// Find the location of the character @c (or -1 if not found)
641  exint
642  findCharIndex(char c) const
643  {
644  const char *str = c_str();
645  const void *ptr = ::memchr(str, c, length());
646  return ptr ? (const char *)ptr - str : -1;
647  }
648 
649  /// Find the first location of any of the characters in the @c str passed in
651  exint
652  findCharIndex(const char *str) const
653  {
654  if (UTisstring(str))
655  {
656  const char *ptr = c_str();
657  const char *found_char = strpbrk(ptr, str);
658  if (found_char)
659  return found_char - ptr;
660  }
661  return -1;
662  }
663 
664  /// Find the location of the character @c (or -1 if not found)
666  exint
667  findCharIndex(char c, exint start_offset) const
668  {
669  if (start_offset < length())
670  {
671  const char *str = c_str();
672  const void *ptr = ::memchr(str+start_offset, c,
673  length()-start_offset);
674  if (ptr)
675  return (const char *)ptr - str;
676  }
677  return -1;
678  }
679 
680  /// Find the first location of any of the characters in the @c str passed in
682  exint
683  findCharIndex(const char *str, exint start_offset) const
684  {
685  if (UTisstring(str) && start_offset < length())
686  {
687  const char *ptr = c_str();
688  const char *found_char = strpbrk(ptr+start_offset, str);
689  if (found_char)
690  return found_char - ptr;
691  }
692  return -1;
693  }
694 
696  exint
697  lastCharIndex(char c, int occurrence_number = 1) const
698  {
699  const char *str = c_str();
700  exint n = length();
701  const void *start = SYSmemrchr(str, c, n);
702  while (start)
703  {
704  n = (const char *)start - str;
705  occurrence_number--;
706  if (occurrence_number <= 0)
707  return n;
708  start = (n == 0) ? nullptr : SYSmemrchr(str, c, n-1);
709  }
710  return -1;
711  }
712 
713  /// Count the number of times the character @c c occurs
715  exint
716  countChar(char c) const
717  {
718  return UTstringCountChar(*this, c);
719  }
720 
722  void clear()
723  {
724  decref();
725  myData = nullptr;
726  myLength = 0;
727  myHash = 0;
728  }
729 
731  const char *c_str() const
732  {
733  UT_ASSERT_P(!isSentinel());
734  if (myLength)
735  {
736  UT_ASSERT_P(myDataIfChars);
737  return myDataIfChars;
738  }
739  else if (myDataIfHolder)
740  return myDataIfHolder->c_str();
741  else
742  {
743 #if SYS_IS_GCC_GE(6, 0) && !SYS_IS_GCC_GE(8, 0)
744  // We need to do this to fix bad GCC warning:
745  // offset outside bounds of constant string
746  const char *volatile empty = "";
747  return empty;
748 #else
749  return "";
750 #endif
751  }
752  }
754  const char* data() const
755  {
756  return c_str();
757  }
758 
759  exint length() const
760  {
761  if (myLength)
762  return myLength;
763  else if (myDataIfHolder)
764  return myDataIfHolder->length();
765  else
766  return 0;
767  }
768 
769  unsigned hash() const
770  {
771  if (!myHash && myData)
772  myHash = hash_string(c_str(), length());
773  return myHash;
774  }
775 
776  /// Make a light weight reference to the source.
777  /// Caller must make sure src lives for the duration of this object,
778  /// and any objects value copied from this!
779  void reference(const char *src)
780  {
781  reference(src, src ? strlen(src) : 0);
782  }
783 
784  /// Fast reference that takes the length of the string.
785  /// This is NOT a string view, the string must actually null terminate
786  /// at the given length or later functions will be confused.
787  void reference(const char *str, exint length);
788 
789  /// old name of method:
791  {
792  reference(src, length);
793  }
794 
795  int64 getMemoryUsage(bool inclusive) const
796  {
797  int64 mem = inclusive ? sizeof(*this) : 0;
798  if (!myLength && myDataIfHolder)
799  mem += myDataIfHolder->getMemoryUsage(true);
800  return mem;
801  }
802 
803  // This hash function does not look for null termination, but
804  // instead goes directly for the length.
806  static unsigned hash_string(const char *str, exint len)
807  {
808  return SYSstring_hash(str, len, /*allow_nulls*/true);
809  }
810 
811 
812  /// Convert the string into a valid C style variable name.
813  /// All non-alpha numerics will be converted to _.
814  /// If the first letter is a digit, it is prefixed with an _.
815  /// If the string is already valid, the string itself is returned.
816  /// Note that this does NOT force the name to be non-zero in length.
817  /// The safechars parameter is a string containing extra characters
818  /// that should be considered safe. These characters are not
819  /// converted to underscores.
821  UT_StringRef forceValidVariableName(const char *safechars = nullptr) const;
822 
823  /// Convert to lower case. If the string is already lower case, the string
824  /// itself is returned.
826  UT_StringRef toLower() const;
827  /// Convert to upper case. If the string is already upper case, the string
828  /// itsef is returned.
830  UT_StringRef toUpper() const;
831 
832  /// Often people reflexively use this from UT_String days so
833  /// this increases code compataibility.
834  void harden(const char *src)
835  {
836  setHolder(Holder::buildInline(src, src ? strlen(src) : 0));
837  }
838 
839  // Steals the given string, gaining ownership of it.
840  // Will be freed by this when the reference count hits zero.
841  void adoptFromMalloc(const char *str, exint length);
842  void adoptFromNew(const char *str, exint length);
843 
845  {
846  if (!str.isstring())
847  {
848  clear();
849  return;
850  }
851  // We want to steal from always deep strings as well.
852  // We will erase the data in the source string!
853  str.harden();
854 
855  adoptFromMalloc(str.myData, strlen(str.myData));
856 
857  // Clear after harden in case str refers to us!
858  str.myData = 0;
859  str.myIsReference = true;
860  // Leave always deep as it was.
861  }
862  void adoptFromCharArray(UT_Array<char>& data);
863 
864  // Extracts a string from ourself of the given allocation mode.
865  // The result can be freed with that allocation mode.
866  // Will always clear myself afterwards. This will return our
867  // own string without copying if reference count is 1.
868  // Will return 0 for empty strings.
869  char *stealAsMalloc();
870 
871  // Tests to see if UT_StringLit's memory layout is the same
872  static bool verifyStringLit();
873 
874  /// Does a "smart" string compare which will sort based on numbered names.
875  /// That is "text20" is bigger than "text3". In a strictly alphanumeric
876  /// comparison, this would not be the case.
878  {
879  bool operator()(const UT_StringRef &s1, const UT_StringRef &s2) const
880  {
881  return UT_String::compareNumberedString(s1.c_str(), s2.c_str()) < 0;
882  }
883  };
884 
885  /// Save string to binary stream.
886  void saveBinary(std::ostream &os) const
887  { UT_StringWrap(c_str()).saveBinary(os); }
888 
889  /// Save string to ASCII stream. This will add double quotes and escape to
890  /// the stream if necessary (empty string or contains spaces).
891  void saveAscii(std::ostream &os) const
892  { UT_StringWrap(c_str()).saveAscii(os); }
893 
894 private:
896  void incref() const
897  {
898  if (!myLength && myDataIfHolder)
899  myDataIfHolder->incref();
900  }
901 
903  void decref()
904  {
905  if (!myLength && myDataIfHolder)
906  myDataIfHolder->decref();
907  }
908 
909  // this does not do holder->incref, and holder==nullptr is same as clear()
910  void setHolder(Holder* holder)
911  {
912  decref();
913  myDataIfHolder = holder;
914  myLength = 0;
915  myHash = 0;
916  }
917 
918  // same as reference() except string is assumed to be empty, used by constructors
919  void _reference(const char* str, exint length);
920 
921  void harden()
922  {
923  if (myLength)
924  {
925  myDataIfHolder = Holder::buildInline(myDataIfChars, myLength);
926  myLength = 0;
927  }
928  }
929 
930  // This union makes viewing in a debugger much easier.
931  union {
932  const void *myData;
933  const char *myDataIfChars;
935  };
936  int myLength;
937  mutable int myHash;
938 
939  /// This operator saves the string to the stream via the string's
940  /// saveAscii() method, protecting any whitespace (by adding quotes),
941  /// backslashes or quotes in the string.
942  friend UT_API std::ostream &operator<<(std::ostream &os, const UT_StringRef &d);
943  friend UT_API UT_OStream &operator<<(UT_OStream &os, const UT_StringRef &d);
944 
945  // UT_StringHolder needs to be a friend class so that the
946  // UT_StringHolder(const UT_StringRef &) constructor can access myHash and
947  // myDataIfHolder for the UT_StringRef that is passed in.
948  friend class UT_StringHolder;
949 
950  static constexpr uint32 SENTINEL_HASH = 0xdeadbeef;
951 };
952 
954 {
955  return str.hash();
956 }
957 
958 /// Equality operators for UT_StringLit with UT_StringRef
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 static SYS_FORCE_INLINE bool
971 operator!=(const UT_StringRef &ref, const UT_StringLit &lit)
972 {
973  return ref.operator!=(lit.asRef());
974 }
975 static SYS_FORCE_INLINE bool
976 operator!=(const UT_StringLit &lit, const UT_StringRef &ref)
977 {
978  return ref.operator!=(lit.asRef());
979 }
980 /// @}
981 
982 /// Equality operators for UT_StringLit with UT_String
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 static SYS_FORCE_INLINE bool
995 operator!=(const UT_String &str, const UT_StringLit &lit)
996 {
997  return str.operator!=(lit.asRef());
998 }
999 static SYS_FORCE_INLINE bool
1000 operator!=(const UT_StringLit &lit, const UT_String &str)
1001 {
1002  return str.operator!=(lit.asRef());
1003 }
1004 /// @}
1005 
1006 
1007 /// A holder for a string, which stores the length and caches the hash value.
1008 /// The lifetime of the string is >= the lifetime of the UT_StringHolder.
1010 {
1011 public:
1012  /// UT_StringHolder can be constructed with UT_StringHolder::REFERENCE to
1013  /// create a shallow reference to the const char *.
1014  enum UT_StringReferenceType { REFERENCE };
1015 
1018  : UT_StringRef()
1019  {
1020  }
1021 
1022  /// Will make a copy of the provided string.
1024  UT_StringHolder(const char *str)
1025  : UT_StringHolder(str, str ? strlen(str) : 0)
1026  {
1027  }
1028 
1029  /// Will make a shallow reference.
1032  : UT_StringRef(str)
1033  {
1034  }
1035 
1036  /// Will make a copy of the provided string.
1039  {
1040  myDataIfHolder = Holder::buildInline(data, length);
1041  }
1042 
1043  // Prohibit accidents when converting from UT_String like:
1044  // myStringHolder(buffer, /*deep*/true)
1045  UT_StringHolder(const char *data, bool bad) = delete;
1046 
1047  // Add back explicit conversions for the length parameter
1050  : UT_StringHolder(data, exint(length)) { }
1053  : UT_StringHolder(data, exint(length)) { }
1056  : UT_StringHolder(data, exint(length)) { }
1057 #if defined(MBSD)
1059  UT_StringHolder(const char *data, size_t length)
1060  : UT_StringHolder(data, exint(length)) { }
1062  UT_StringHolder(const char *data, ptrdiff_t length)
1063  : UT_StringHolder(data, exint(length)) { }
1064 #endif
1065 
1066  /// Will make a copy of the provided string.
1068  UT_StringHolder(const std::string &str)
1069  : UT_StringHolder(str.c_str(), str.length())
1070  {
1071  }
1072 
1073  /// This will make a shallow reference to the contents of the string.
1075  UT_StringHolder(UT_StringReferenceType, const std::string &str)
1076  : UT_StringRef(str)
1077  {
1078  }
1079 
1080  /// Will make a copy of the provided string.
1081  UT_StringHolder(const UT_WorkBuffer &str);
1082 
1083  /// This will make a shallow reference to the contents of the string.
1086  : UT_StringRef(str)
1087  {
1088  }
1089 
1090  /// Will make a copy of the provided string.
1093  : UT_StringHolder(str.buffer(), str.length())
1094  {
1095  }
1096 
1097  /// Attempts to steal the string's buffer
1099  : UT_StringHolder()
1100  {
1101  adoptFromString(str);
1102  }
1103 
1104  /// This will make a shallow reference to the contents of the string.
1107  : UT_StringRef(str)
1108  {
1109  }
1110 
1111  /// Will make a copy of the provided string.
1112  UT_StringHolder(const UT_StringView &sv);
1113 
1114  /// Makes a shallow reference to the contents of the UT_StringRef.
1117  : UT_StringRef(ref)
1118  {
1119  }
1120 
1121  /// Makes a deep copy of the provided UT_StringRef.
1122  /// This constructor is not marked explicit since we often want this
1123  /// conversion (e.g. when inserting a UT_StringRef into a UT_StringMap, as
1124  /// with the const char* constructor).
1126  : UT_StringRef(ref)
1127  {
1128  harden();
1129  }
1130 
1132  : UT_StringRef(std::move(ref))
1133  {
1134  harden();
1135  }
1136 
1137  /// Construct as a sentinel value
1138  SYS_FORCE_INLINE explicit
1140  : UT_StringRef(sentinel)
1141  {
1142  }
1143 
1144  /// Makes a copy of the provided string.
1147  : UT_StringRef(str)
1148  {
1149  }
1150 
1151  /// Move constructor. Steals the working data from the original.
1154  : UT_StringRef(std::move(a))
1155  {
1156  }
1157 
1158  /// Move constructor. Steals the data from the work buffer.
1159  UT_StringHolder(UT_WorkBuffer &&buf) noexcept;
1160 
1161  /// Makes a bit-wise copy of the string and adjust the reference count.
1163  UT_StringHolder &operator=(const UT_StringHolder &s)
1164  {
1166  return *this;
1167  }
1168 
1169  /// Move the contents of about-to-be-destructed string
1170  /// s to this string.
1173  {
1174  UT_StringRef::operator=(std::move(s));
1175  return *this;
1176  }
1177 
1178  /// Move the contents buffer into this string holder.
1180 
1182  void swap(UT_StringHolder &other)
1183  {
1184  UT_StringRef::swap(other);
1185  }
1186 
1188  void swap(UT_StringRef &other)
1189  {
1190  UT_StringRef::swap(other);
1191  // harden ourselves like UT_StringHolder::operator=(UT_StringRef&)
1192  harden();
1193  }
1194 
1195  /// Friend specialization of std::swap() to use UT_StringHolder::swap()
1196  /// @{
1197  friend void swap(UT_StringHolder& a, UT_StringRef& b) { a.swap(b); }
1198  friend void swap(UT_StringHolder& a, UT_StringHolder& b) { a.swap(b); }
1199  /// @}
1200 
1201  /// In some functions it's nice to be able to return a const-reference to a
1202  /// UT_StringHolder. However, in error cases, you likely want to return an
1203  /// empty string. This would mean that you'd have to return a real
1204  /// UT_StringHolder (not a const reference). This static lets you return a
1205  /// reference to an empty string.
1207 
1209 
1210  /// Format a string using the same formatting codes as @c UTformat.
1211  template<typename... Args>
1212  size_t format(const char *fmt, const Args &...args)
1213  {
1214  return format(fmt, {args...});
1215  }
1216  size_t format(const char *fmt, std::initializer_list<UT::Format::ArgValue> args);
1217 
1218  /// Format a string using the same formatting codes as @c UTprintf.
1219  template<typename... Args>
1220  SYS_DEPRECATED_HDK_REPLACE(19.5, UT_WorkBuffer::sprintf() to avoid string allocations)
1221  size_t sprintf(const char *fmt, const Args &...args)
1222  {
1223  return sprintf(fmt, {args...});
1224  }
1225  size_t sprintf(const char *fmt, std::initializer_list<UT::Format::ArgValue> args);
1226 
1227  /// Replaces up to 'count' occurrences of 'find' with 'replacement',
1228  /// and returns the number of substitutions that occurred.
1229  /// If 'count' <= 0, all occurrences will be replaced.
1230  int substitute(const char *find, const char *replacement, exint count = -1)
1231  {
1232  UT_String s(buffer());
1233  exint n = s.substitute(find, replacement, count);
1234  if (n > 0)
1235  adoptFromString(s);
1236  return n;
1237  }
1238 
1239  /// Strips out all characters found in 'chars'. The string length will be
1240  /// reduced by the number of characters removed. The number of characters
1241  /// removed is returned.
1242  int strip(const char *chars);
1243 
1244  /// Prepend a string
1245  // @{
1246  void prepend(const UT_StringRef &prefix);
1247  // @}
1248 
1249  /// Load string from stream. Use is.eof() to check eof status
1250  bool load(UT_IStream &is)
1251  {
1252  UT_String s;
1253  if (s.load(is))
1254  {
1255  adoptFromString(s);
1256  return true;
1257  }
1258  return false;
1259  }
1260 
1262 
1263  /// A version of trimSpace() that only removes leading and following spaces
1264  /// from a string, leaving any between words intact.
1265  bool trimBoundingSpace();
1266 
1267  /// trimSpace() will remove all space characters (leading and following)
1268  /// from a string. If the string consists of multiple words, the words
1269  /// will be collapsed. To keep a single space between words, pass in true.
1270  /// The function returns true if space was trimmed.
1271  bool trimSpace(bool leave_single_space_between_words = false);
1272 
1273 protected:
1274  friend UT_StringHolder UT::Literal::operator""_sh(
1275  const char *s, std::size_t const length);
1276  friend UT_StringHolder operator""_UTsh(
1277  const char *s, std::size_t const length);
1278  friend UT_API std::istream &operator>>(std::istream& is, UT_StringHolder& s);
1279 
1280  /// A marker enum to use this constructor.
1281  enum UT_StringLiteralType { LITERAL };
1282 
1283  /// Only accepts string literals. Since there's no way to guarantee that
1284  /// a const char * argument is a string literal, we do this through the
1285  /// use of user-defined literal and *only* provide this constructor to our
1286  /// user-defined literal operator.
1288  {
1289  if (str && length)
1290  {
1291  myDataIfChars = str;
1292  myLength = length;
1293  // As of C++14, user defined literals don't support constexpr so
1294  // this hash computation here is actually done at run-time except
1295  // for in some cases where the compiler (clang?) is able to
1296  // optimize this. Therefore, disable this to avoid extraneous hash
1297  // computation in cases where we just want to use "foo"_sh to avoid
1298  // heap allocation but never use its hash.
1299  // Use UT_StringLit if you want to get compile time hashes
1300 #if 0
1301  myHash = SYSstring_hash_literal(str);
1302 #else
1303  myHash = 0;
1304 #endif
1305  }
1306  }
1307 };
1308 
1309 SYS_FORCE_INLINE size_t
1311 {
1312  return str.hash();
1313 }
1314 
1315 /// Convert a UT_StringRef into a UT_StringHolder that is a shallow reference.
1317 {
1318  SYS_STATIC_ASSERT(sizeof(UT_StringRef) == sizeof(UT_StringHolder));
1319  return reinterpret_cast<const UT_StringHolder &>(ref);
1320 }
1321 
1322 /// Convert a UT_StringRef into a UT_StringHolder that is a shallow reference,
1323 /// and also precompute the hash. Use this for string literals
1324 /// that will be used repeatedly in hash tables.
1326 {
1327  SYS_STATIC_ASSERT(sizeof(UT_StringRef) == sizeof(UT_StringHolder));
1328  ref.hash();
1329  return reinterpret_cast<const UT_StringHolder &>(ref);
1330 }
1331 
1334 {
1335  SYS_STATIC_ASSERT(sizeof(UT_StringHolder) == sizeof(*this));
1336  return reinterpret_cast<const UT_StringHolder &>(*this);
1337 }
1338 
1341 {
1342  SYS_STATIC_ASSERT(sizeof(UT_StringRef) == sizeof(*this));
1343  return reinterpret_cast<const UT_StringRef &>(*this);
1344 }
1345 
1346 /// A user-defined string literal to construct UT_StringHolder objects.
1347 /// E.g:
1348 /// @code
1349 /// auto lit = "This is my UT_StringHolder literal"_sh;
1350 /// @endcode
1351 namespace UT { inline namespace Literal {
1352 SYS_FORCE_INLINE UT_StringHolder operator""_sh(const char *s, std::size_t const length)
1353 {
1354  return UT_StringHolder(UT_StringHolder::LITERAL, s, length);
1355 }
1356 } }
1357 
1358 /// A user-defined literal in the global namespace. Uglier, but allows the use
1359 /// of UT_StringHolder UDLs in headers.
1360 SYS_FORCE_INLINE UT_StringHolder operator""_UTsh(const char *s, std::size_t const length)
1361 {
1362  return UT_StringHolder(UT_StringHolder::LITERAL, s, length);
1363 }
1364 
1365 
1366 namespace std
1367 {
1368  template<>
1369  struct hash<UT_StringRef>
1370  {
1371  size_t operator()(const UT_StringRef &s) const
1372  {
1373  return s.hash();
1374  }
1375  };
1376  template<>
1377  struct hash<UT_StringHolder>
1378  {
1379  size_t operator()(const UT_StringHolder &s) const
1380  {
1381  return s.hash();
1382  }
1383  };
1384 }
1385 
1386 // For UT::ArraySet.
1387 namespace UT
1388 {
1389 template <typename T>
1390 struct DefaultClearer;
1391 
1392 template <>
1394 {
1395  static void clear(UT_StringHolder &v) { v.makeSentinel(); }
1396  static bool isClear(const UT_StringHolder &v) { return v.isSentinel(); }
1398  {
1399  new ((void *)p) UT_StringHolder(UT_StringRef::SENTINEL);
1400  }
1401  static const bool clearNeedsDestruction = false;
1402 };
1403 } // namespace UT
1404 
1405 #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
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
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
bool contains(const char *pattern, bool case_sensitive=true) const
fpreal toFloat() const
int toInt() const
#define SYS_DEPRECATED_HDK_REPLACE(__V__, __R__)
CompareResults OIIO_API compare(const ImageBuf &A, const ImageBuf &B, float failthresh, float warnthresh, float failrelative, float warnrelative, ROI roi={}, int nthreads=0)
bool isEmpty() const
Same as !isstring()
static void clear(UT_StringHolder &v)
SYS_NO_DISCARD_RESULT bool UTstringStartsWith(const T &str, const char *prefix, bool case_sensitive=true, exint len=-1)
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:7440
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
PUGI__FN PUGI__UNSIGNED_OVERFLOW unsigned int hash_string(const char_t *str)
Definition: pugixml.cpp:8710
#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
FMT_CONSTEXPR auto find(Ptr first, Ptr last, T value, Ptr &out) -> bool
Definition: core.h:2138
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.
GLuint buffer
Definition: glcorearb.h:660
OutGridT const XformOp bool bool
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.
SYS_FORCE_INLINE const UT_StringHolder & UTmakeUnsafeRefHash(const UT_StringRef &ref)
bool load(UT_IStream &is)
Load string from stream. Use is.eof() to check eof status.
fpreal toFloat() const
const void * myData
bool contains(const char *pattern, bool case_sensitive=true) const
constexpr SYS_FORCE_INLINE UT_StringLit(const char(&str)[N])
std::ostream & operator<<(std::ostream &ostr, const DataType &a)
Definition: DataType.h:133
SYS_FORCE_INLINE const_iterator end() const
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:516
SYS_FORCE_INLINE UT_StringRef(UT_StringSentinelType)
A utility class to do read-only operations on a subset of an existing string.
Definition: UT_StringView.h:40
SYS_FORCE_INLINE size_t hash_value(const UT_StringRef &str)
int substitute(const char *find, const char *replacement, exint count=-1)
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.
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:4512
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_FORCE_INLINE UT_StringHolder & operator=(UT_StringHolder &&s)
void harden()
Take shallow copy and make it deep.
Definition: UT_String.h:222
SYS_FORCE_INLINE void makeSentinel()
void saveAscii(std::ostream &os) const
Definition: UT_String.h:307
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:4675
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:303
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
int substitute(const char *find, const char *replacement, exint count=-1)
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:278
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:4331
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:618
unsigned int uint32
Definition: SYS_Types.h:40
void reference(const char *src)
bool isstring() const
Definition: UT_String.h:698
OIIO_UTIL_API const char * c_str(string_view str)
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
auto sprintf(const S &fmt, const T &...args) -> std::basic_string< Char >
Definition: printf.h:617
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.
that also have some descendant prim *whose name begins with which in turn has a child named baz where *the predicate and *a name There is also one special expression reference
#define SYSmin(a, b)
Definition: SYS_Math.h:1583
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:1821
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
GLenum src
Definition: glcorearb.h:1793
const char * fcontain(const char *pattern, bool case_sensitive=true) const
Definition: UT_String.h:1016
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:566