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