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 #if __cplusplus >= 202002L
59  #include <concepts>
60 #endif
61 #include <iosfwd>
62 #include <string>
63 #include <utility>
64 
65 #include <stdint.h>
66 #include <string.h>
67 
68 template <typename T> class UT_Array;
69 class UT_IStream;
70 class UT_OStream;
71 class ut_PatternRecord;
72 class UT_StringHolder;
73 class UT_StringMMPattern;
74 class UT_StringRef;
75 class UT_StringView;
76 class UT_WorkBuffer;
77 
78 // Forward declare the UDSL so that we can friend it inside of UT_StringHolder.
79 namespace UT { inline namespace Literal {
80 UT_StringHolder operator""_sh(const char *s, std::size_t const length);
81 } }
82 
83 /// A string literal with length and compile-time computed hash value.
84 /// @note This will only be compile-time when used in compile time expressions
85 /// like template parameters and constexpr variables.
86 /// @note String literals whose length requires more than 31 bits not supported
87 /// @see UT_StringRef
89 {
90 public:
91  constexpr SYS_FORCE_INLINE
93  : myData(nullptr) // These must match UT_StringRef's default ctor
94  , myLength(0)
95  , myHash(0)
96  {
97  }
98 
99  template <size_t N>
100  constexpr SYS_FORCE_INLINE
101  UT_StringLit(const char (&str)[N])
102  : myData(str)
103  , myLength(N-1)
104  , myHash(SYSstring_hash(str, myLength, /*allow_nulls*/true))
105  {
106  SYS_STATIC_ASSERT(N-1 < (((exint)1) << 31));
107  }
108 
109  SYS_FORCE_INLINE constexpr const char* data() const
110  {
111  return myData ? myData : "";
112  }
113  SYS_FORCE_INLINE constexpr const char* buffer() const { return data(); }
114  SYS_FORCE_INLINE constexpr const char* c_str() const { return data(); }
115 #if __cplusplus >= 202002L
116  template <std::same_as<const char *> T>
117  SYS_FORCE_INLINE constexpr operator T() const noexcept { return data(); }
118 #else
119  SYS_FORCE_INLINE constexpr operator const char*() const { return data(); }
120 #endif
121 
123  explicit operator bool() const { return myLength > 0; }
124 
125 #if __cplusplus >= 202002L
127  const char & operator[](size_t i) const { return data()[i]; }
128 #endif
129 
130  SYS_FORCE_INLINE constexpr exint length() const { return myLength; }
131 
132  SYS_FORCE_INLINE constexpr uint32 hash() const { return myHash; }
133 
135  SYS_FORCE_INLINE const UT_StringRef& asRef() const;
136 
137  friend SYS_FORCE_INLINE constexpr
138  bool operator==(const UT_StringLit &str, const char *other)
139  {
140  // Treat nullptr as empty strings
141  if (other == nullptr)
142  return (str.myLength == 0);
143  if (str.myData == nullptr)
144  return *other == 0;
145 #if _MSC_VER
146  if (__builtin_is_constant_evaluated())
147  {
148  // compare up to myLength+1 to include terminating nul
149  for (int32 i = 0; i < str.myLength + 1; ++i)
150  {
151  if (str.myData[i] != other[i])
152  return false;
153  }
154  return true;
155  }
156  return !strcmp(str.myData, other);
157 #else
158  return !__builtin_strcmp(str.myData, other);
159 #endif
160  }
161  friend SYS_FORCE_INLINE constexpr
162  bool operator==(const char *other, const UT_StringLit &str)
163  {
164  return (str == other);
165  }
166  friend SYS_FORCE_INLINE constexpr
167  bool operator!=(const UT_StringLit &str, const char *other)
168  {
169  return !(str == other);
170  }
171  friend SYS_FORCE_INLINE constexpr
172  bool operator!=(const char *other, const UT_StringLit &str)
173  {
174  return !(str == other);
175  }
176 
177 private:
178  const char* myData;
179  int32 myLength;
180  uint32 myHash;
181 
182  friend class UT_StringRef;
183 
184  friend constexpr bool operator==(const UT_StringLit &a, const UT_StringLit &b);
185 };
186 
187 constexpr bool operator==(const UT_StringLit &a, const UT_StringLit &b)
188 {
189  if ((a.myLength != b.myLength) || (a.myHash != b.myHash))
190  {
191  return false;
192  }
193 
194  // we must check also b.myData for nullptr to avoid gcc error
195  if ((a.myData == nullptr) || (b.myData == nullptr))
196  {
197  return true;
198  }
199 
200  return ! SYSmemcmp(a.myData, b.myData, a.myLength);
201 }
202 
203 constexpr bool operator!=(const UT_StringLit &a, const UT_StringLit &b)
204 {
205  return ! (a == b);
206 }
207 
208 // Empty strings must have myData be nullptr, specialize for these
209 template <>
210 constexpr SYS_FORCE_INLINE
211 UT_StringLit::UT_StringLit(const char (&str)[1])
212  : myData(nullptr)
213  , myLength(0)
214  , myHash(0)
215 {
216 }
217 
218 /// A holder for a string, which stores the length and caches the hash value.
219 /// A UT_StringRef does not necessarily own the string, and it is therefore not
220 /// safe to e.g. store a UT_StringRef in a container or member variable.
221 /// @see UT_StringHolder
222 /// @see UTmakeUnsafeRef
224 {
225 public:
226  typedef char value_type;
227 
229  {
233  STORE_INLINE
234  };
235 
237  {
238  Holder() = delete;
239  public:
240  static Holder *buildFromData(const char *str, exint len, StorageMode storage);
241  static Holder *buildInline(const char* str, exint length);
242  static Holder *buildInline(exint length);
243 
244  const char *c_str() const
245  {
246  if (myStorageMode == STORE_INLINE)
247  return myDataIfInline;
248  else
249  return myData;
250  }
251 
252  exint length() const
253  {
254  return myLength;
255  }
256 
257  void incref()
258  {
259  myRefCount.add(1);
260  }
261 
262  void decref()
263  {
264  if (myRefCount.add(-1) == 0)
265  destroy();
266  }
267 
268  int64 getMemoryUsage(bool inclusive) const;
269 
270  bool isUnique() const
271  {
272  return myRefCount.relaxedLoad() == 1 && myStorageMode != STORE_EXTERNAL;
273  }
274 
275  char* inlineBufferNC() // used after buildInline(length) to get buffer to write
276  {
277  return myDataIfInline;
278  }
279 
281  {
282  if (myStorageMode == STORE_MALLOC && myRefCount.relaxedLoad() == 1)
283  {
284  myStorageMode = STORE_EXTERNAL; // make destroy not free the data
285  return (char*)myData;
286  }
287  return 0; // steal did not work
288  }
289 
290  private:
291  void destroy();
292 
293  SYS_AtomicInt32 myRefCount;
294  StorageMode myStorageMode;
295  exint myLength;
296 
297  // This union makes viewing in a debugger much easier.
298  union {
299  const char *myData;
300  char myDataIfInline[sizeof(const char *)];
301  };
302  };
303 
306  : myData(nullptr)
307  , myLength(0)
308  , myHash(0)
309  {
310  }
311 
312  /// Will make a shallow reference.
314  UT_StringRef(const char *str)
315  : UT_StringRef()
316  {
317  if (str)
318  _reference(str, strlen(str));
319  }
320 
321  /// Will make a shallow reference.
322  /// This is NOT a string view, the string must actually null terminate
325  : UT_StringRef()
326  {
327  _reference(data, length);
328  }
329 
330  /// Construct from string literal
331  SYS_FORCE_INLINE explicit
333  : UT_StringRef(lit.asRef())
334  {
335  }
336 
337  /// This will make a shallow reference to the contents of the string.
339  UT_StringRef(const std::string &str)
340  : UT_StringRef(str.c_str(), str.length())
341  {
342  }
343 
344  /// This will make a shallow reference to the contents of the string.
345  UT_StringRef(const UT_WorkBuffer &str);
346 
347  /// This will make a shallow reference to the contents of the string.
350  : UT_StringRef(str.buffer(), str.length())
351  {
352  }
353 
354  /// Shares a reference with the source.
356  UT_StringRef(const UT_StringRef &s) noexcept
357  : myData(s.myData)
358  , myLength(s.myLength)
359  , myHash(s.myHash)
360  {
361  incref();
362  }
363 
364  /// Move constructor. Steals the working data from the original.
367  : myData(s.myData)
368  , myLength(s.myLength)
369  , myHash(s.myHash)
370  {
371  s.myData = nullptr;
372  s.myLength = 0;
373  s.myHash = 0;
374  }
375 
378  {
379  decref();
380  }
381 
382  /// Special sentinel value support
383  /// @{
384  enum UT_StringSentinelType { SENTINEL };
385 
386  SYS_FORCE_INLINE explicit
388  : myData(nullptr)
389  , myLength(0)
390  , myHash(SENTINEL_HASH)
391  {
392  }
393 
394  /// str==nullptr turns into sentinel, otherwise act like UT_StringRef(str)
397  : myData(nullptr)
398  , myLength(0)
399  , myHash(str ? 0 : SENTINEL_HASH)
400  {
401  if (str)
402  _reference(str, strlen(str));
403  }
404 
406  bool isSentinel() const
407  {
408  return myHash == SENTINEL_HASH && !myLength;
409  }
410 
413  {
414  decref();
415  myData = nullptr;
416  myLength = 0;
417  myHash = SENTINEL_HASH;
418  }
419  /// @}
420 
421  /// Returns true this object is the sole owner of the underlying string
422  bool isUnique() const
423  {
424  return !myLength && myDataIfHolder && myDataIfHolder->isUnique();
425  }
426 
427  /// Shares a reference with the source.
429  {
430  s.incref();
431  decref();
432  myData = s.myData;
433  myLength = s.myLength;
434  myHash = s.myHash;
435  return *this;
436  }
437 
438  /// Move the contents of about-to-be-destructed string
439  /// s to this string.
442  {
443  // Can just swap, since s is about to be destructed.
444  swap(s);
445  return *this;
446  }
447 
448  bool operator==(const UT_StringRef &s) const
449  {
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  if (myData == s.myData)
455  {
456  if (!myData)
457  return myHash == s.myHash; // make sure sentinel != ""
458  return true;
459  }
460  // empty string cannot match non-empty string.
461  if (!myData || !s.myData)
462  return false;
463  // If both strings have cached hashes with different values, the
464  // strings cannot be equal.
465  if (myHash && s.myHash && myHash != s.myHash)
466  return false;
467  const exint tl = length();
468  return tl == s.length() && SYSmemcmp(c_str(), s.c_str(), tl) == 0;
469  }
470 
471  bool operator==(const char *s) const
472  {
473  if (!myDataIfChars)
474  return (!s || !*s) && !myHash; // make sure sentinel != ""
475  // It is sensible to fast-path this based on myData!
476  // If our two pointers are equal, we either are pointing to
477  // the same Holder or to the same const char *, so are good
478  // to call it equal.
479  // We don't test for myData being a Holder because it should
480  // never alias a const char *.
481  if (myDataIfChars == s)
482  return true;
483  // Avoid comparison with null.
484  if (!s)
485  return false;
486  return ::strcmp(c_str(), s) == 0;
487  }
488  bool operator==(const UT_String &s) const
489  { return operator==(s.buffer()); }
490 
491  bool operator!=(const UT_StringRef &s) const
492  { return !operator==(s); }
493  bool operator!=(const char *s) const
494  { return !operator==(s); }
495  bool operator!=(const UT_String &s) const
496  { return operator!=(s.buffer()); }
497 
498  /// Spaceship comparison returns:
499  /// - < 0 if *this < k
500  /// - == 0 if *this == k
501  /// - > 0 if *this > k
502  int spaceship(const UT_StringRef &k) const
503  {
504  const exint l = length();
505  const exint kl = k.length();
506  const exint minlen = SYSmin(l, kl);
507  int r = SYSmemcmp(c_str(), k.c_str(), minlen);
508  if (r != 0)
509  return r;
510  else if (kl > minlen)
511  return -1;
512  else if (l > minlen)
513  return 1;
514  else
515  return 0;
516  }
517 
518  bool operator<(const UT_StringRef &k) const
519  { return spaceship(k) < 0; }
520  bool operator<=(const UT_StringRef &k) const
521  { return spaceship(k) <= 0; }
522  bool operator>(const UT_StringRef &k) const
523  { return spaceship(k) > 0; }
524  bool operator>=(const UT_StringRef &k) const
525  { return spaceship(k) >= 0; }
526  int compare(const UT_StringRef &str,
527  bool ignore_case=false) const
528  {
529  return ignore_case
530  ? SYSstrcasecmp(c_str(), str.c_str())
531  : spaceship(str); }
532  bool equal(const UT_StringRef &str,
533  bool ignore_case=false) const
534  { return compare(str, ignore_case) == 0; }
535 
536  /// Test whether the string is defined or not
538  explicit operator bool() const { return isstring(); }
539 
540  /// Imported from UT_String.
541  bool startsWith(const UT_StringView &pfx, bool case_sense=true) const
542  {
543  return UTstringStartsWith(*this, pfx.data(), case_sense, pfx.length());
544  }
545  bool endsWith(const UT_StringView &suffix, bool case_sense=true) const
546  {
547  return UTstringEndsWith(*this, suffix.data(), case_sense, suffix.length());
548  }
549  bool match(const char *pattern, bool case_sensitive=true) const
550  { return UT_StringWrap(c_str()).match(pattern, case_sensitive); }
551 
552  bool contains(const char *pattern, bool case_sensitive=true) const
553  { return UT_StringWrap(c_str()).contains(pattern, case_sensitive); }
554  const char *fcontain(const char *pattern, bool case_sensitive=true) const
555  { return UT_StringWrap(c_str()).fcontain(pattern, case_sensitive); }
556  const char *findWord(const char *word) const
557  { return UT_StringWrap(c_str()).findWord(word); }
558 
559  bool multiMatch(const char *pattern, bool case_sensitive,
560  char separator) const
561  {
562  return UT_StringWrap(c_str()).multiMatch(
563  pattern, case_sensitive, separator);
564  }
565  bool multiMatch(const char *pattern, bool case_sensitive = true,
566  const char *separators = ", ",
567  bool *explicitly_excluded = 0,
568  int *match_index = 0,
569  ut_PatternRecord *pattern_record=nullptr) const
570  {
571  return UT_StringWrap(c_str()).multiMatch(
572  pattern, case_sensitive, separators, explicitly_excluded,
573  match_index, pattern_record);
574  }
576  bool *explicitly_excluded = 0,
577  int *match_index = 0,
578  ut_PatternRecord *pattern_record=nullptr) const
579  {
580  return UT_StringWrap(c_str()).multiMatch(
581  pattern, explicitly_excluded, match_index, pattern_record);
582  }
583 
584  /// Returns true if the entire string matches the provided regular
585  /// expression, false otherwise. See UT_Regex.
586  bool matchRegex(const char *expr) const;
587 
588  int toInt() const
589  { return UT_StringWrap(c_str()).toInt(); }
590  fpreal toFloat() const
591  { return UT_StringWrap(c_str()).toFloat(); }
592 
593  /// Determine if string can be seen as a single floating point number
594  bool isFloat(bool skip_spaces = false, bool loose = false) const
595  { return UTstringIsFloat(*this, skip_spaces, loose); }
596  /// Determine if string can be seen as a single integer number
597  bool isInteger(bool skip_spaces = false) const
598  { return UTstringIsInteger(*this, skip_spaces); }
599 
600 #if __cplusplus >= 202002L
601  template <std::same_as<const char *> T>
603  operator T() const noexcept
604  { return c_str(); }
605 #else
607  operator const char *() const
608  { return c_str(); }
609 #endif
610 
612  const char *buffer() const
613  { return c_str(); }
614  // We are always non-null by definition!
616  const char *nonNullBuffer() const
617  { return c_str(); }
618 
619 #if __cplusplus >= 202002L
621  const char &operator[](size_t i) const { return c_str()[i]; }
622 #endif
623 
624  /// Iterators
625  typedef const char * const_iterator;
626 
629  { return c_str(); }
632  { return begin() + length(); }
633 
634 
635  /// Converts the contents of this UT_String to a std::string. Since
636  /// we are never null this is easy
637  std::string toStdString() const
638  { return std::string(c_str(), length()); }
639 
641  void swap( UT_StringRef &other )
642  {
643  UTswap(myData, other.myData);
644  UTswap(myLength, other.myLength);
645  UTswap(myHash, other.myHash);
646  }
647 
648  /// Friend specialization of std::swap() to use UT_StringRef::swap()
649  friend void swap(UT_StringRef& a, UT_StringRef& b) { a.swap(b); }
650 
651  /// Equivalent to (length() != 0)
652  /// Returns false for isSentinel()
654  bool isstring() const
655  { return myData != nullptr; }
656 
657  /// Same as !isstring()
658  bool isEmpty() const
659  { return myData == nullptr; }
660 
661  /// method name that maches std::string
662  bool empty() const
663  { return myData == nullptr; }
664 
666  bool
667  hasNonSpace() const
668  {
669  const char *ptr = c_str();
670  for (exint i = 0, n = length(); i < n; ++i)
671  if (!SYSisspace(ptr[i]))
672  return true;
673  return false;
674  }
675 
676  /// Find the location of the character @c (or -1 if not found)
678  exint
679  findCharIndex(char c) const
680  {
681  const char *str = c_str();
682  const void *ptr = ::memchr(str, c, length());
683  return ptr ? (const char *)ptr - str : -1;
684  }
685 
686  /// Find the first location of any of the characters in the @c str passed in
688  exint
689  findCharIndex(const char *str) const
690  {
691  if (UTisstring(str))
692  {
693  const char *ptr = c_str();
694  const char *found_char = strpbrk(ptr, str);
695  if (found_char)
696  return found_char - ptr;
697  }
698  return -1;
699  }
700 
701  /// Find the location of the character @c (or -1 if not found)
703  exint
704  findCharIndex(char c, exint start_offset) const
705  {
706  if (start_offset < length())
707  {
708  const char *str = c_str();
709  const void *ptr = ::memchr(str+start_offset, c,
710  length()-start_offset);
711  if (ptr)
712  return (const char *)ptr - str;
713  }
714  return -1;
715  }
716 
717  /// Find the first location of any of the characters in the @c str passed in
719  exint
720  findCharIndex(const char *str, exint start_offset) const
721  {
722  if (UTisstring(str) && start_offset < length())
723  {
724  const char *ptr = c_str();
725  const char *found_char = strpbrk(ptr+start_offset, str);
726  if (found_char)
727  return found_char - ptr;
728  }
729  return -1;
730  }
731 
733  exint
734  lastCharIndex(char c, int occurrence_number = 1) const
735  {
736  const char *str = c_str();
737  exint n = length();
738  const void *start = SYSmemrchr(str, c, n);
739  while (start)
740  {
741  n = (const char *)start - str;
742  occurrence_number--;
743  if (occurrence_number <= 0)
744  return n;
745  start = (n == 0) ? nullptr : SYSmemrchr(str, c, n-1);
746  }
747  return -1;
748  }
749 
750  /// Count the number of times the character @c c occurs
752  exint
753  countChar(char c) const
754  {
755  return UTstringCountChar(*this, c);
756  }
757 
759  void clear()
760  {
761  decref();
762  myData = nullptr;
763  myLength = 0;
764  myHash = 0;
765  }
766 
768  const char *c_str() const
769  {
770  UT_ASSERT_P(!isSentinel());
771  if (myLength)
772  {
773  UT_ASSERT_P(myDataIfChars);
774  return myDataIfChars;
775  }
776  else if (myDataIfHolder)
777  return myDataIfHolder->c_str();
778  else
779  {
780 #if SYS_IS_GCC_GE(6, 0) && !SYS_IS_GCC_GE(8, 0)
781  // We need to do this to fix bad GCC warning:
782  // offset outside bounds of constant string
783  const char *volatile empty = "";
784  return empty;
785 #else
786  return "";
787 #endif
788  }
789  }
791  const char* data() const
792  {
793  return c_str();
794  }
795 
796  exint length() const
797  {
798  if (myLength)
799  return myLength;
800  else if (myDataIfHolder)
801  return myDataIfHolder->length();
802  else
803  return 0;
804  }
805 
806  unsigned hash() const
807  {
808  if (!myHash && myData)
809  myHash = hashString(c_str(), length());
810  return myHash;
811  }
812 
813  /// Make a light weight reference to the source.
814  /// Caller must make sure src lives for the duration of this object,
815  /// and any objects value copied from this!
816  void reference(const char *src)
817  {
818  reference(src, src ? strlen(src) : 0);
819  }
820 
821  /// Fast reference that takes the length of the string.
822  /// This is NOT a string view, the string must actually null terminate
823  /// at the given length or later functions will be confused.
824  void reference(const char *str, exint length);
825 
826  /// old name of method:
828  {
829  reference(src, length);
830  }
831 
832  int64 getMemoryUsage(bool inclusive) const
833  {
834  int64 mem = inclusive ? sizeof(*this) : 0;
835  if (!myLength && myDataIfHolder)
836  mem += myDataIfHolder->getMemoryUsage(true);
837  return mem;
838  }
839 
840  // This hash function does not look for null termination, but
841  // instead goes directly for the length.
843  static unsigned hashString(const char *str, exint len)
844  {
845  return SYSstring_hash(str, len, /*allow_nulls*/true);
846  }
847 
848  // This hash function does not look for null termination, but
849  // instead goes directly for the length.
852  static unsigned hash_string(const char *str, exint len)
853  {
854  return SYSstring_hash(str, len, /*allow_nulls*/true);
855  }
856 
857  /// Convert the string into a valid C style variable name.
858  /// All non-alpha numerics will be converted to _.
859  /// If the first letter is a digit, it is prefixed with an _.
860  /// If the string is already valid, the string itself is returned.
861  /// Note that this does NOT force the name to be non-zero in length.
862  /// The safechars parameter is a string containing extra characters
863  /// that should be considered safe. These characters are not
864  /// converted to underscores.
866  UT_StringRef forceValidVariableName(const char *safechars = nullptr) const;
867 
868  /// Convert to lower case. If the string is already lower case, the string
869  /// itself is returned.
871  UT_StringRef toLower() const;
872  /// Convert to upper case. If the string is already upper case, the string
873  /// itsef is returned.
875  UT_StringRef toUpper() const;
876 
877  /// Often people reflexively use this from UT_String days so
878  /// this increases code compataibility.
879  void harden(const char *src)
880  {
881  setHolder(Holder::buildInline(src, src ? strlen(src) : 0));
882  }
883 
884  // Steals the given string, gaining ownership of it.
885  // Will be freed by this when the reference count hits zero.
886  void adoptFromMalloc(const char *str, exint length);
887  void adoptFromNew(const char *str, exint length);
888 
890  {
891  if (!str.isstring())
892  {
893  clear();
894  return;
895  }
896  // We want to steal from always deep strings as well.
897  // We will erase the data in the source string!
898  str.harden();
899 
900  adoptFromMalloc(str.myData, strlen(str.myData));
901 
902  // Clear after harden in case str refers to us!
903  str.myData = 0;
904  str.myIsReference = true;
905  // Leave always deep as it was.
906  }
907  void adoptFromCharArray(UT_Array<char>& data);
908 
909  // Extracts a string from ourself of the given allocation mode.
910  // The result can be freed with that allocation mode.
911  // Will always clear myself afterwards. This will return our
912  // own string without copying if reference count is 1.
913  // Will return 0 for empty strings.
914  char *stealAsMalloc();
915 
916  // Tests to see if UT_StringLit's memory layout is the same
917  static bool verifyStringLit();
918 
919  /// Does a "smart" string compare which will sort based on numbered names.
920  /// That is "text20" is bigger than "text3". In a strictly alphanumeric
921  /// comparison, this would not be the case.
923  {
924  bool operator()(const UT_StringRef &s1, const UT_StringRef &s2) const
925  {
926  return UT_String::compareNumberedString(s1.c_str(), s2.c_str()) < 0;
927  }
928  };
929 
930  /// Save string to binary stream.
931  void saveBinary(std::ostream &os) const
932  { UT_StringWrap(c_str()).saveBinary(os); }
933 
934  /// Save string to ASCII stream. This will add double quotes and escape to
935  /// the stream if necessary (empty string or contains spaces).
936  void saveAscii(std::ostream &os) const
937  { UT_StringWrap(c_str()).saveAscii(os); }
938 
939 private:
941  void incref() const
942  {
943  if (!myLength && myDataIfHolder)
944  myDataIfHolder->incref();
945  }
946 
948  void decref()
949  {
950  if (!myLength && myDataIfHolder)
951  myDataIfHolder->decref();
952  }
953 
954  // this does not do holder->incref, and holder==nullptr is same as clear()
955  void setHolder(Holder* holder)
956  {
957  decref();
958  myDataIfHolder = holder;
959  myLength = 0;
960  myHash = 0;
961  }
962 
963  // same as reference() except string is assumed to be empty, used by constructors
964  void _reference(const char* str, exint length);
965 
966  void harden()
967  {
968  if (myLength)
969  {
970  myDataIfHolder = Holder::buildInline(myDataIfChars, myLength);
971  myLength = 0;
972  }
973  }
974 
975  // This union makes viewing in a debugger much easier.
976  union {
977  const void *myData;
978  const char *myDataIfChars;
980  };
981  int myLength;
982  mutable int myHash;
983 
984  /// This operator saves the string to the stream via the string's
985  /// saveAscii() method, protecting any whitespace (by adding quotes),
986  /// backslashes or quotes in the string.
987  friend UT_API std::ostream &operator<<(std::ostream &os, const UT_StringRef &d);
988  friend UT_API UT_OStream &operator<<(UT_OStream &os, const UT_StringRef &d);
989 
990  // UT_StringHolder needs to be a friend class so that the
991  // UT_StringHolder(const UT_StringRef &) constructor can access myHash and
992  // myDataIfHolder for the UT_StringRef that is passed in.
993  friend class UT_StringHolder;
994 
995  static constexpr uint32 SENTINEL_HASH = 0xdeadbeef;
996 };
997 
999 {
1000  return str.hash();
1001 }
1002 
1003 /// Equality operators for UT_StringLit with UT_StringRef
1004 /// @{
1005 static SYS_FORCE_INLINE bool
1006 operator==(const UT_StringRef &ref, const UT_StringLit &lit)
1007 {
1008  return ref.operator==(lit.asRef());
1009 }
1010 static SYS_FORCE_INLINE bool
1011 operator==(const UT_StringLit &lit, const UT_StringRef &ref)
1012 {
1013  return ref.operator==(lit.asRef());
1014 }
1015 static SYS_FORCE_INLINE bool
1016 operator!=(const UT_StringRef &ref, const UT_StringLit &lit)
1017 {
1018  return ref.operator!=(lit.asRef());
1019 }
1020 static SYS_FORCE_INLINE bool
1021 operator!=(const UT_StringLit &lit, const UT_StringRef &ref)
1022 {
1023  return ref.operator!=(lit.asRef());
1024 }
1025 /// @}
1026 
1027 /// Equality operators for UT_StringRef with const char*
1028 /// @{
1029 static SYS_FORCE_INLINE bool
1030 operator==(const char *buf, const UT_StringRef &ref)
1031 {
1032  return ref.operator==(buf);
1033 }
1034 static SYS_FORCE_INLINE bool
1035 operator!=(const char *buf, const UT_StringRef &ref)
1036 {
1037  return ref.operator!=(buf);
1038 }
1039 /// @}
1040 
1041 /// Equality operators for UT_StringLit with UT_String
1042 /// @{
1043 static SYS_FORCE_INLINE bool
1044 operator==(const UT_String &str, const UT_StringLit &lit)
1045 {
1046  return str.operator==(lit.asRef());
1047 }
1048 static SYS_FORCE_INLINE bool
1049 operator==(const UT_StringLit &lit, const UT_String &str)
1050 {
1051  return str.operator==(lit.asRef());
1052 }
1053 static SYS_FORCE_INLINE bool
1054 operator!=(const UT_String &str, const UT_StringLit &lit)
1055 {
1056  return str.operator!=(lit.asRef());
1057 }
1058 static SYS_FORCE_INLINE bool
1059 operator!=(const UT_StringLit &lit, const UT_String &str)
1060 {
1061  return str.operator!=(lit.asRef());
1062 }
1063 /// @}
1064 
1065 static SYS_FORCE_INLINE bool
1066 operator==(const char *buf, const UT_String &str)
1067 {
1068  return str.operator==(buf);
1069 }
1070 
1071 
1072 /// A holder for a string, which stores the length and caches the hash value.
1073 /// The lifetime of the string is >= the lifetime of the UT_StringHolder.
1075 {
1076 public:
1077  /// UT_StringHolder can be constructed with UT_StringHolder::REFERENCE to
1078  /// create a shallow reference to the const char *.
1079  enum UT_StringReferenceType { REFERENCE };
1080 
1083  : UT_StringRef()
1084  {
1085  }
1086 
1087  /// Will make a copy of the provided string.
1089  UT_StringHolder(const char *str)
1090  : UT_StringHolder(str, str ? strlen(str) : 0)
1091  {
1092  }
1093 
1094  /// Will make a shallow reference.
1097  : UT_StringRef(str)
1098  {
1099  }
1100 
1101  /// Will make a copy of the provided string.
1104  {
1105  myDataIfHolder = Holder::buildInline(data, length);
1106  }
1107 
1108  // Prohibit accidents when converting from UT_String like:
1109  // myStringHolder(buffer, /*deep*/true)
1110  UT_StringHolder(const char *data, bool bad) = delete;
1111 
1112  // Add back explicit conversions for the length parameter
1115  : UT_StringHolder(data, exint(length)) { }
1118  : UT_StringHolder(data, exint(length)) { }
1121  : UT_StringHolder(data, exint(length)) { }
1122 #if defined(MBSD)
1124  UT_StringHolder(const char *data, size_t length)
1125  : UT_StringHolder(data, exint(length)) { }
1127  UT_StringHolder(const char *data, ptrdiff_t length)
1128  : UT_StringHolder(data, exint(length)) { }
1129 #endif
1130 
1131  /// Will make a copy of the provided string.
1133  UT_StringHolder(const std::string &str)
1134  : UT_StringHolder(str.c_str(), str.length())
1135  {
1136  }
1137 
1138  /// This will make a shallow reference to the contents of the string.
1140  UT_StringHolder(UT_StringReferenceType, const std::string &str)
1141  : UT_StringRef(str)
1142  {
1143  }
1144 
1145  /// Will make a copy of the provided string.
1146  UT_StringHolder(const UT_WorkBuffer &str);
1147 
1148  /// This will make a shallow reference to the contents of the string.
1151  : UT_StringRef(str)
1152  {
1153  }
1154 
1155  /// Will make a copy of the provided string.
1158  : UT_StringHolder(str.buffer(), str.length())
1159  {
1160  }
1161 
1162  /// Attempts to steal the string's buffer
1164  : UT_StringHolder()
1165  {
1166  adoptFromString(str);
1167  }
1168 
1169  /// This will make a shallow reference to the contents of the string.
1172  : UT_StringRef(str)
1173  {
1174  }
1175 
1176  /// Will make a copy of the provided string.
1177  UT_StringHolder(const UT_StringView &sv);
1178 
1179  /// Makes a shallow reference to the contents of the UT_StringRef.
1182  : UT_StringRef(ref)
1183  {
1184  }
1185 
1186  /// Makes a deep copy of the provided UT_StringRef.
1187  /// This constructor is not marked explicit since we often want this
1188  /// conversion (e.g. when inserting a UT_StringRef into a UT_StringMap, as
1189  /// with the const char* constructor).
1191  : UT_StringRef(ref)
1192  {
1193  harden();
1194  }
1195 
1197  : UT_StringRef(std::move(ref))
1198  {
1199  harden();
1200  }
1201 
1202  /// Construct as a sentinel value
1203  SYS_FORCE_INLINE explicit
1205  : UT_StringRef(sentinel)
1206  {
1207  }
1208 
1209  /// Makes a copy of the provided string.
1212  : UT_StringRef(str)
1213  {
1214  }
1215 
1216  /// Move constructor. Steals the working data from the original.
1219  : UT_StringRef(std::move(a))
1220  {
1221  }
1222 
1223  /// Move constructor. Steals the data from the work buffer.
1224  UT_StringHolder(UT_WorkBuffer &&buf) noexcept;
1225 
1226  /// Makes a bit-wise copy of the string and adjust the reference count.
1228  UT_StringHolder &operator=(const UT_StringHolder &s)
1229  {
1231  return *this;
1232  }
1233 
1234  /// Move the contents of about-to-be-destructed string
1235  /// s to this string.
1238  {
1239  UT_StringRef::operator=(std::move(s));
1240  return *this;
1241  }
1242 
1243  /// Move the contents buffer into this string holder.
1245 
1247  void swap(UT_StringHolder &other)
1248  {
1249  UT_StringRef::swap(other);
1250  }
1251 
1253  void swap(UT_StringRef &other)
1254  {
1255  UT_StringRef::swap(other);
1256  // harden ourselves like UT_StringHolder::operator=(UT_StringRef&)
1257  harden();
1258  }
1259 
1260  /// Friend specialization of std::swap() to use UT_StringHolder::swap()
1261  /// @{
1262  friend void swap(UT_StringHolder& a, UT_StringRef& b) { a.swap(b); }
1263  friend void swap(UT_StringHolder& a, UT_StringHolder& b) { a.swap(b); }
1264  /// @}
1265 
1266  /// In some functions it's nice to be able to return a const-reference to a
1267  /// UT_StringHolder. However, in error cases, you likely want to return an
1268  /// empty string. This would mean that you'd have to return a real
1269  /// UT_StringHolder (not a const reference). This static lets you return a
1270  /// reference to an empty string.
1272 
1274 
1275  /// Format a string using the same formatting codes as @c UTformat.
1276  template<typename... Args>
1277  size_t format(const char *fmt, const Args &...args)
1278  {
1279  return format(fmt, {args...});
1280  }
1281  size_t format(const char *fmt, std::initializer_list<UT::Format::ArgValue> args);
1282 
1283  /// Format a string using the same formatting codes as @c UTprintf.
1284  template<typename... Args>
1285  SYS_DEPRECATED_HDK_REPLACE(19.5, UT_WorkBuffer::sprintf() to avoid string allocations)
1286  size_t sprintf(const char *fmt, const Args &...args)
1287  {
1288  return sprintf(fmt, {args...});
1289  }
1290  size_t sprintf(const char *fmt, std::initializer_list<UT::Format::ArgValue> args);
1291 
1292  /// Replaces up to 'count' occurrences of 'find' with 'replacement',
1293  /// and returns the number of substitutions that occurred.
1294  /// If 'count' <= 0, all occurrences will be replaced.
1295  int substitute(const char *find, const char *replacement, exint count = -1)
1296  {
1297  UT_String s(buffer());
1298  exint n = s.substitute(find, replacement, count);
1299  if (n > 0)
1300  adoptFromString(s);
1301  return n;
1302  }
1303 
1304  /// Strips out all characters found in 'chars'. The string length will be
1305  /// reduced by the number of characters removed. The number of characters
1306  /// removed is returned.
1307  int strip(const char *chars);
1308 
1309  /// Prepend a string
1310  // @{
1311  void prepend(const UT_StringRef &prefix);
1312  // @}
1313 
1314  /// Load string from stream. Use is.eof() to check eof status
1315  bool load(UT_IStream &is)
1316  {
1317  UT_String s;
1318  if (s.load(is))
1319  {
1320  adoptFromString(s);
1321  return true;
1322  }
1323  return false;
1324  }
1325 
1326  UT_StringHolder &operator+=(const UT_StringRef &src);
1327 
1328  /// A version of trimSpace() that only removes leading and following spaces
1329  /// from a string, leaving any between words intact.
1330  bool trimBoundingSpace();
1331 
1332  /// trimSpace() will remove all space characters (leading and following)
1333  /// from a string. If the string consists of multiple words, the words
1334  /// will be collapsed. To keep a single space between words, pass in true.
1335  /// The function returns true if space was trimmed.
1336  bool trimSpace(bool leave_single_space_between_words = false);
1337 
1338  // This function will calculate the relative path to get from src to dest.
1339  // If file_path is false, this method assume it is dealing with node paths.
1340  // If file_path is true, it will also deal with Windows drive letters and
1341  // UNC paths.
1342  //
1343  // If we are doing file path comparisons then the source and dest are
1344  // treated as files. So getting from /a/b to /a/c is just "c". But "/a/b/"
1345  // to "/a/c" is "../c", using the trailing slash on the source path to
1346  // indicate it specifies a directory instead of a file.
1347  void getRelativePath(const char *src_fullpath,
1348  const char *dest_fullpath,
1349  bool file_path = false,
1350  bool allow_relative_path_from_root = true);
1351 protected:
1352  friend UT_StringHolder UT::Literal::operator""_sh(
1353  const char *s, std::size_t const length);
1354  friend UT_StringHolder operator""_UTsh(
1355  const char *s, std::size_t const length);
1356  friend UT_API std::istream &operator>>(std::istream& is, UT_StringHolder& s);
1357 
1358  /// A marker enum to use this constructor.
1359  enum UT_StringLiteralType { LITERAL };
1360 
1361  /// Only accepts string literals. Since there's no way to guarantee that
1362  /// a const char * argument is a string literal, we do this through the
1363  /// use of user-defined literal and *only* provide this constructor to our
1364  /// user-defined literal operator.
1366  {
1367  if (str && length)
1368  {
1369  myDataIfChars = str;
1370  myLength = length;
1371  // As of C++14, user defined literals don't support constexpr so
1372  // this hash computation here is actually done at run-time except
1373  // for in some cases where the compiler (clang?) is able to
1374  // optimize this. Therefore, disable this to avoid extraneous hash
1375  // computation in cases where we just want to use "foo"_sh to avoid
1376  // heap allocation but never use its hash.
1377  // Use UT_StringLit if you want to get compile time hashes
1378 #if 0
1379  myHash = SYSstring_hash_literal(str);
1380 #else
1381  myHash = 0;
1382 #endif
1383  }
1384  }
1385 };
1386 
1387 SYS_FORCE_INLINE size_t
1389 {
1390  return str.hash();
1391 }
1392 
1393 /// Convert a UT_StringRef into a UT_StringHolder that is a shallow reference.
1395 {
1396  SYS_STATIC_ASSERT(sizeof(UT_StringRef) == sizeof(UT_StringHolder));
1397  return reinterpret_cast<const UT_StringHolder &>(ref);
1398 }
1399 
1400 /// Convert a UT_StringRef into a UT_StringHolder that is a shallow reference,
1401 /// and also precompute the hash. Use this for string literals
1402 /// that will be used repeatedly in hash tables.
1404 {
1405  SYS_STATIC_ASSERT(sizeof(UT_StringRef) == sizeof(UT_StringHolder));
1406  ref.hash();
1407  return reinterpret_cast<const UT_StringHolder &>(ref);
1408 }
1409 
1412 {
1413  SYS_STATIC_ASSERT(sizeof(UT_StringHolder) == sizeof(*this));
1414  return reinterpret_cast<const UT_StringHolder &>(*this);
1415 }
1416 
1419 {
1420  SYS_STATIC_ASSERT(sizeof(UT_StringRef) == sizeof(*this));
1421  return reinterpret_cast<const UT_StringRef &>(*this);
1422 }
1423 
1424 /// A user-defined string literal to construct UT_StringHolder objects.
1425 /// E.g:
1426 /// @code
1427 /// auto lit = "This is my UT_StringHolder literal"_sh;
1428 /// @endcode
1429 namespace UT { inline namespace Literal {
1430 SYS_FORCE_INLINE UT_StringHolder operator""_sh(const char *s, std::size_t const length)
1431 {
1432  return UT_StringHolder(UT_StringHolder::LITERAL, s, length);
1433 }
1434 } }
1435 
1436 /// A user-defined literal in the global namespace. Uglier, but allows the use
1437 /// of UT_StringHolder UDLs in headers.
1438 SYS_FORCE_INLINE UT_StringHolder operator""_UTsh(const char *s, std::size_t const length)
1439 {
1440  return UT_StringHolder(UT_StringHolder::LITERAL, s, length);
1441 }
1442 
1443 
1444 namespace std
1445 {
1446  template<>
1447  struct hash<UT_StringRef>
1448  {
1449  size_t operator()(const UT_StringRef &s) const
1450  {
1451  return s.hash();
1452  }
1453  };
1454  template<>
1455  struct hash<UT_StringHolder>
1456  {
1457  size_t operator()(const UT_StringHolder &s) const
1458  {
1459  return s.hash();
1460  }
1461  };
1462 }
1463 
1464 // For UT::ArraySet.
1465 namespace UT
1466 {
1467 template <typename T>
1468 struct DefaultClearer;
1469 
1470 template <>
1472 {
1473  static void clear(UT_StringHolder &v) { v.makeSentinel(); }
1474  static bool isClear(const UT_StringHolder &v) { return v.isSentinel(); }
1476  {
1477  new ((void *)p) UT_StringHolder(UT_StringRef::SENTINEL);
1478  }
1479  static const bool clearNeedsDestruction = false;
1480 };
1481 } // namespace UT
1482 
1483 #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.
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
#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:525
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
GLint ref
Definition: glcorearb.h:124
int64 getMemoryUsage(bool inclusive) const
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:164
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:225
SYS_FORCE_INLINE void makeSentinel()
void saveAscii(std::ostream &os) const
Definition: UT_String.h:310
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:86
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.
static SYS_FORCE_INLINE unsigned hashString(const char *str, exint len)
constexpr bool operator!=(const UT_StringLit &a, const UT_StringLit &b)
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
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:306
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)
PcpNodeRef_ChildrenIterator begin(const PcpNodeRef::child_const_range &r)
Support for range-based for loops for PcpNodeRef children ranges.
Definition: node.h:587
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:283
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:265
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:713
OIIO_UTIL_API const char * c_str(string_view str)
constexpr bool operator==(const UT_StringLit &a, const UT_StringLit &b)
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:1953
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:1031
SYS_FORCE_INLINE void swap(UT_StringRef &other)