HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
UT_StringHolder.h
Go to the documentation of this file.
1 /*
2  * PROPRIETARY INFORMATION. This software is proprietary to
3  * Side Effects Software Inc., and is not to be reproduced,
4  * transmitted, or disclosed in any way without written permission.
5  *
6  * NAME: UT_StringHolder.h
7  *
8  * COMMENTS: A simple holder for strings which acts like copy on
9  * write, but has special methods for minimizing memory
10  * copies when you know what you are doing.
11  *
12  * Has a trivial move constructor.
13  *
14  * c_str does not change when it moves.
15  */
16 
17 // #pragma once
18 
19 #ifndef __UT_StringHolder_h__
20 #define __UT_StringHolder_h__
21 
22 #include "UT_API.h"
23 #include "UT_Array.h"
24 #include "UT_Format.h"
25 #include "UT_String.h"
26 #include "UT_Swap.h"
27 
28 #include <SYS/SYS_AtomicInt.h>
29 #include <SYS/SYS_Compiler.h>
30 #include <SYS/SYS_Inline.h>
31 #include <SYS/SYS_Pragma.h>
32 #include <SYS/SYS_StaticAssert.h>
33 #include <SYS/SYS_Types.h>
34 
35 #include <functional>
36 #include <iosfwd>
37 
38 #include <stdlib.h>
39 
40 class UT_IStream;
41 class UT_OStream;
42 class UT_StringHolder;
43 class UT_StringRef;
44 class UT_StringView;
45 class UT_WorkBuffer;
46 
47 // Forward declare the UDSL so that we can friend it inside of UT_StringHolder.
48 namespace UT { inline namespace Literal {
49 UT_StringHolder operator"" _sh(const char *s, std::size_t const length);
50 } }
51 
52 /// A string literal with length and compile-time computed hash value.
53 /// @note This will only be compile-time when used in compile time expressions
54 /// like template parameters and constexpr variables.
55 /// @note String literals whose length requires more than 31 bits not supported
56 /// @see UT_StringRef
58 {
59 public:
60  constexpr SYS_FORCE_INLINE
62  : myData(nullptr)
63  , myLength(0)
64  , myHash(0)
65  {
66  }
67 
68  template <size_t N>
69  constexpr SYS_FORCE_INLINE
70  UT_StringLit(const char (&str)[N])
71  : myData(str)
72  , myLength(N-1)
73  , myHash(SYSstring_hash_inner(str, 0))
74  {
75  SYS_STATIC_ASSERT(N-1 < (((exint)1) << 31));
76  }
77 
78  SYS_FORCE_INLINE constexpr const char* buffer() const { return myData; }
79  SYS_FORCE_INLINE constexpr const char* data() const { return myData; }
80  SYS_FORCE_INLINE constexpr const char* c_str() const { return myData; }
81  SYS_FORCE_INLINE constexpr operator const char*() const { return myData; }
82 
83  SYS_FORCE_INLINE constexpr exint length() const { return myLength; }
84 
85  SYS_FORCE_INLINE constexpr uint32 hash() const { return myHash; }
86 
88  SYS_FORCE_INLINE const UT_StringRef& asRef() const;
89 
90 private:
91  const char* myData;
92  int32 myLength;
93  uint32 myHash;
94 
95  friend class UT_StringRef;
96 };
97 
98 /// A holder for a string, which stores the length and caches the hash value.
99 /// A UT_StringRef does not necessarily own the string, and it is therefore not
100 /// safe to e.g. store a UT_StringRef in a container or member variable.
101 /// @see UT_StringHolder
102 /// @see UTmakeUnsafeRef
104 {
105 public:
106  typedef char value_type;
107 
109  {
113  STORE_INLINE
114  };
115 
117  {
118  public:
120  : myRefCount(0), myStorageMode(STORE_INLINE),
121  myHash(0), myLength(0), myData(0)
122  {
123  }
124 
125  static Holder *build(const char *str,
127  static Holder *buildFromData(const char *str,
128  exint len,
130  int hash = 0);
131  static Holder *buildBuffer(
132  exint length,
134 
135  const char *c_str() const
136  {
137  if (myStorageMode == STORE_INLINE)
138  return myDataIfInline;
139 
140  return myData;
141  }
142 
143  void incref()
144  {
145  myRefCount.add(1);
146  }
147  void decref()
148  {
149  if (myRefCount.add(-1) == 0)
150  {
151  // We can't invoke delete as we were malloced.
152  // Further, we have custom behaviour on ownership!
153  switch (myStorageMode)
154  {
155  case STORE_EXTERNAL:
156  case STORE_INLINE:
157  // Do nothing.
158  break;
159  case STORE_NEW:
160  delete [] myData;
161  break;
162  case STORE_MALLOC:
163  if (myData)
164  free( (void*)SYSconst_cast(myData));
165  break;
166  }
169  free(this);
171  }
172  }
173 
174  exint length() const
175  {
176  return myLength;
177  }
178 
179  unsigned hash() const
180  {
181  if (!myHash)
182  {
183  myHash = hash_string(c_str(), length());
184  }
185  return myHash;
186  }
187 
188  int64 getMemoryUsage(bool inclusive) const
189  {
190  int64 mem = inclusive ? sizeof(*this) : 0;
191 
192  switch (myStorageMode)
193  {
194  case STORE_EXTERNAL:
195  // Nothing extra.
196  break;
197  case STORE_INLINE:
198  UT_ASSERT_MSG_P(inclusive,
199  "If a Holder is STORE_INLINE, it *really* can't be a "
200  "member variable, because the size isn't determined "
201  "at runtime.");
202  mem += myLength + 1 - sizeof(const char *);
203  break;
204  case STORE_NEW:
205  case STORE_MALLOC:
206  // External reference we own.
207  mem += myLength + 1;
208  break;
209  }
210  return mem;
211  }
212 
213  private:
214  char *bufferNC() const
215  {
216  if (myStorageMode == STORE_INLINE)
217  return SYSconst_cast(myDataIfInline);
218 
219  return SYSconst_cast(myData);
220  }
221 
222  friend class UT_StringHolder;
223  friend class UT_StringRef;
224 
225  private:
226  SYS_AtomicInt32 myRefCount;
227  StorageMode myStorageMode;
228  mutable int myHash;
229  exint myLength;
230 
231  // This union makes viewing in a debugger much easier.
232  union {
233  const char *myData;
234  char myDataIfInline[sizeof(const char *)];
235  };
236  };
237 
240  {
241  init();
242  }
243 
244  /// Will make a shallow reference.
246  UT_StringRef(const char *str)
247  {
248  init();
249  if (UTisstring(str))
250  {
251  reference(str);
252  }
253  }
254 
255  /// Construct from string literal
256  SYS_FORCE_INLINE explicit
258  : UT_StringRef(lit.asRef())
259  {
260  }
261 
262  /// This will make a shallow reference to the contents of the string.
265  {
266  init();
267  const char *s = str.c_str();
268  if (UTisstring(s))
269  {
270  fastReferenceWithStrlen(s, str.length());
271  }
272  }
273 
274  /// This will make a shallow reference to the contents of the string.
275  UT_StringRef(const UT_WorkBuffer &str);
276 
277  /// This will make a shallow reference to the contents of the string.
280  {
281  init();
282  if (str.isstring())
283  reference(str);
284  }
285 
286  /// Shares a reference with the source.
289  {
290  Holder *sh = s.getHolder();
291  if (!isSentinelOrNullPtr(sh))
292  sh->incref();
293  // Can now blindly copy.
294  copy(s);
295  }
296 
297  /// Move constructor. Steals the working data from the original.
300  {
301  copy(s);
302  s.init();
303  }
304 
307  {
308  Holder *h = getHolder();
309  if (!isSentinelOrNullPtr(h))
310  h->decref();
311  }
312 
313  /// Special sentinel value support
314  /// @{
315  enum UT_StringSentinelType { SENTINEL };
316 
317  SYS_FORCE_INLINE explicit
319  : myData((const void*)SENTINEL_DATA)
320  , myLength(0)
321  , myHash(SENTINEL_HASH)
322  {
323  }
324 
326  bool isSentinel() const
327  {
328  return uintptr_t(myData) == SENTINEL_DATA && myHash == SENTINEL_HASH && !myLength;
329  }
330 
333  {
334  Holder *h = getHolder();
335  if (!isSentinelOrNullPtr(h))
336  h->decref();
337  myData = (const void*)SENTINEL_DATA;
338  myLength = 0;
339  myHash = SENTINEL_HASH;
340  }
341  /// @}
342 
343  /// Returns true this object is the sole owner of the underlying string
344  bool isUnique() const
345  {
346  Holder *h = getHolder();
347  if (isSentinelOrNullPtr(h))
348  return false;
349  return (h->myRefCount.relaxedLoad() == 1);
350  }
351 
352  /// Shares a reference with the source.
354  {
355  Holder *sh = s.getHolder();
356  Holder *th = getHolder();
357 
358  if (!isSentinelOrNullPtr(sh))
359  sh->incref();
360  if (!isSentinelOrNullPtr(th))
361  th->decref();
362  // Can now blindly copy.
363  copy(s);
364  return *this;
365  }
366 
367  /// Move the contents of about-to-be-destructed string
368  /// s to this string.
371  {
372  // Can just swap, since s is about to be destructed.
373  swap(s);
374  return *this;
375  }
376 
377  bool operator==(const UT_StringRef &s) const
378  {
379  // It is sensible to fast-path this based on myData!
380  // If our two pointers are equal, we either are pointing to
381  // the same Holder or to the same const char *, so are good
382  // to call it equal.
383  if (myData == s.myData)
384  return true;
385  exint tl = length();
386  exint sl = s.length();
387  if (tl != sl)
388  return false;
389  if (tl == 0)
390  return (uintptr_t(myData) == SENTINEL_DATA) == (uintptr_t(s.myData) == SENTINEL_DATA);
391  return ::memcmp(c_str(), s.c_str(), tl) == 0;
392  }
393  bool operator==(const char *s) const
394  {
395  // It is sensible to fast-path this based on myData!
396  // If our two pointers are equal, we either are pointing to
397  // the same Holder or to the same const char *, so are good
398  // to call it equal.
399  // We don't test for myData being a Holder because it should
400  // never alias a const char *.
401  if (myDataIfChars == s)
402  return true;
403  // Avoid comparison with null.
404  if (!s)
405  return !isstring();
406  return ::strcmp(c_str(), s) == 0;
407  }
408  bool operator==(const UT_String &s) const
409  { return operator==(s.buffer()); }
410 
411  bool operator!=(const UT_StringRef &s) const
412  { return !operator==(s); }
413  bool operator!=(const char *s) const
414  { return !operator==(s); }
415  bool operator!=(const UT_String &s) const
416  { return operator!=(s.buffer()); }
417 
418  bool operator<(const UT_StringRef &k) const
419  { return ::strcmp(c_str(), k.c_str()) < 0; }
420  bool operator<=(const UT_StringRef &k) const
421  { return ::strcmp(c_str(), k.c_str()) <= 0; }
422  bool operator>(const UT_StringRef &k) const
423  { return ::strcmp(c_str(), k.c_str()) > 0; }
424  bool operator>=(const UT_StringRef &k) const
425  { return ::strcmp(c_str(), k.c_str()) >= 0; }
426  int compare(const UT_StringRef &str,
427  bool ignore_case=false) const
428  { return ignore_case ?
429  SYSstrcasecmp(c_str(), str.c_str()) :
430  ::strcmp(c_str(), str.c_str()); }
431  bool equal(const UT_StringRef &str,
432  bool ignore_case=false) const
433  { return compare(str, ignore_case) == 0; }
434 
435  /// Test whether the string is defined or not
437  SYS_SAFE_BOOL operator bool() const { return isstring(); }
438 
439  /// Imported from UT_String.
440  bool startsWith(const char *prefix, bool case_sense = true,
441  exint len=-1) const
442  {
443  return UT_StringWrap(c_str()).startsWith(prefix, case_sense, len);
444  }
445  bool endsWith(const char *prefix, bool case_sense = true,
446  exint len=-1) const
447  {
448  return UT_StringWrap(c_str()).endsWith(prefix, case_sense, len);
449  }
450  unsigned match(const char *pattern, int caseSensitive=1) const
451  { return UT_StringWrap(c_str()).match(pattern, caseSensitive); }
452  bool contains(const char *pattern, bool case_sensitive=true) const
453  { return UT_StringWrap(c_str()).contains(pattern, case_sensitive); }
454  unsigned multiMatch(const char *pattern,
455  int caseSensitive, char separator) const
456  { return UT_StringWrap(c_str()).multiMatch(pattern, caseSensitive, separator); }
457  unsigned multiMatch(const char *pattern, int caseSensitive = 1,
458  const char *separators = ", ",
459  bool *explicitlyExcluded = 0,
460  int *matchIndex = 0,
461  ut_PatternRecord *pattern_record=NULL) const
462  { return UT_StringWrap(c_str()).multiMatch(pattern, caseSensitive, separators, explicitlyExcluded, matchIndex, pattern_record); }
464  bool *explicitlyExcluded = 0,
465  int *matchIndex = 0,
466  ut_PatternRecord *pattern_record=NULL) const
467  { return UT_StringWrap(c_str()).multiMatch(pattern, explicitlyExcluded, matchIndex, pattern_record); }
468 
469  /// Returns true if the entire string matches the provided regular
470  /// expression, false otherwise. See UT_Regex.
471  bool matchRegex(const char *expr) const;
472 
473  int toInt() const
474  { return UT_StringWrap(c_str()).toInt(); }
475  fpreal toFloat() const
476  { return UT_StringWrap(c_str()).toFloat(); }
477 
478  /// Determine if string can be seen as a single floating point number
479  unsigned isFloat(int skip_spaces = 0, int loose = 0) const
480  { return UT_StringWrap(c_str()).isFloat(skip_spaces, loose); }
481  /// Determine if string can be seen as a single integer number
482  unsigned isInteger(int skip_spaces = 0) const
483  { return UT_StringWrap(c_str()).isInteger(skip_spaces); }
484 
486  operator const char *() const
487  { return c_str(); }
488 
490  const char *buffer() const
491  { return c_str(); }
492  // We are always non-null by definition!
494  const char *nonNullBuffer() const
495  { return c_str(); }
496 
497  /// Iterators
498  typedef const char * const_iterator;
499 
502  { return c_str(); }
505  { return begin() + length(); }
506 
507 
508  /// Converts the contents of this UT_String to a std::string. Since
509  /// we are never null this is easy
511  { return std::string(c_str(), length()); }
512 
514  void swap( UT_StringRef &other )
515  {
516  UTswap(myData, other.myData);
517  UTswap(myLength, other.myLength);
518  UTswap(myHash, other.myHash);
519  }
520 
521  /// Friend specialization of std::swap() to use UT_StringRef::swap()
522  friend void swap(UT_StringRef& a, UT_StringRef& b) { a.swap(b); }
523 
525  bool isstring() const
526  {
527  // This test works for both references and inline.
528  return !isSentinelOrNullPtr(myData);
529  }
530 
532  bool
533  hasNonSpace() const
534  {
535  const char *ptr = c_str();
536  while (*ptr && SYSisspace(*ptr))
537  ptr++;
538  return (*ptr) ? true : false;
539  }
540 
542  int
543  findCharIndex(char c) const
544  {
545  const char *ptr = c_str();
546  while (*ptr && *ptr != c)
547  ptr++;
548  return (*ptr) ? (ptr - c_str()) : -1;
549  }
550 
552  int
553  findCharIndex(const char *str) const
554  {
555  const char *ptr = c_str();
556  const char *found_char = nullptr;
557 
558  if (UTisstring(ptr) && UTisstring(str))
559  {
560  found_char = strpbrk(ptr, str);
561 
562  if (found_char)
563  return (intptr_t)(found_char - ptr);
564  }
565 
566  return -1;
567  }
568 
570  int
571  findCharIndex(char c, exint start_offset) const
572  {
573  const char *ptr = c_str() + start_offset;
574  while (*ptr && *ptr != c)
575  ptr++;
576  return (*ptr) ? (ptr - c_str()) : -1;
577  }
578 
580  int
581  findCharIndex(const char *str, exint start_offset) const
582  {
583  const char *ptr = c_str() + start_offset;
584  const char *found_char = nullptr;
585 
586  if (UTisstring(ptr) && UTisstring(str))
587  {
588  found_char = strpbrk(ptr, str);
589 
590  if (found_char)
591  return (intptr_t)(found_char - c_str());
592  }
593 
594  return -1;
595  }
596 
598  int
599  lastCharIndex(char c, int occurance_number = 1) const
600  {
601  const char *ptr = c_str();
602  for (int i = length(); i --> 0;)
603  {
604  if(c == ptr[i])
605  {
606  occurance_number--;
607  if(occurance_number <= 0)
608  return i;
609  }
610  }
611 
612  return -1;
613  }
614 
616  int
617  countChar(char c) const
618  {
619  const char *ptr = c_str();
620  int count = 0;
621  while (*ptr)
622  {
623  if (*ptr == c)
624  count++;
625  ptr++;
626  }
627  return count;
628  }
629 
631  void clear()
632  {
633  if (myData)
634  {
635  Holder *h = getHolder();
636  if (!isSentinelOrNullPtr(h))
637  h->decref();
638  init();
639  }
640  }
641 
643  const char *c_str() const
644  {
645  UT_ASSERT_P(!isSentinel());
646  Holder *holder = getHolder();
647  if (!isSentinelOrNullPtr(holder))
648  return holder->c_str();
649  // Harden empty strings.
650  if (isSentinelOrNullPtr(myDataIfChars))
651  {
652 #if SYS_IS_GCC_GE(6, 0) && !SYS_IS_GCC_GE(7, 0)
653  // We need to do this to fix bad GCC 6 warning:
654  // offset outside bounds of constant string
655  const char *volatile empty = "";
656  return empty;
657 #else
658  return "";
659 #endif
660  }
661  return myDataIfChars;
662  }
663 
664  exint length() const
665  {
666  Holder *holder = getHolder();
667 
668  if (!isSentinelOrNullPtr(holder))
669  return holder->length();
670 
671  if (myLength >= 0)
672  return myLength;
673 
674  exint result = -myLength;
675  result <<= 31;
676  result += myHash;
677 
678  return result;
679  }
680 
681  bool isEmpty() const
682  {
683  return length() == 0;
684  }
685 
686  unsigned hash() const
687  {
688  Holder *holder = getHolder();
689  if (!isSentinelOrNullPtr(holder))
690  return holder->hash();
691  if (myLength >= 0)
692  {
693  if (!myLength)
694  return 0;
695  if (!myHash)
696  {
697  myHash = hash_string(c_str(), length());
698  }
699  return myHash;
700  }
701  return hash_string(c_str(), length());
702  }
703 
704  /// Make a light weight reference to the source.
705  /// Caller must make sure src lives for the duration of this object,
706  /// and any objects value copied from this!
707  void reference(const char *src)
708  {
709  Holder *h = getHolder();
710  if (!isSentinelOrNullPtr(h))
711  h->decref();
712 
713  if (!src || !*src)
714  {
715  init();
716  }
717  else
718  {
719  myDataIfChars = src;
720 
721  exint len = ::strlen(src);
722  if (len >= (((exint)1) << 31))
723  {
724  myLength = -(len >> 31);
725  myHash = len & (0x7fffffff);
726  }
727  else
728  {
729  myLength = len;
730  myHash = 0;
731  }
732  }
733  }
734  /// Fast reference that takes the length of the string.
735  /// This is NOT a string view, the string must actually null terminate
736  /// at the given length or later functions will be confused.
738  {
739  Holder *h = getHolder();
740  if (!isSentinelOrNullPtr(h))
741  h->decref();
742 
743  if (!src || length <= 0)
744  {
745  UT_ASSERT(length == 0);
746  init();
747  }
748  else
749  {
750  UT_ASSERT_P(!src[length]);
751  myDataIfChars = src;
752 
753  if (length >= (((exint)1) << 31))
754  {
755  myLength = -(length >> 31);
756  myHash = length & (0x7fffffff);
757  }
758  else
759  {
760  myLength = length;
761  myHash = 0;
762  }
763  }
764  }
765 
766  int64 getMemoryUsage(bool inclusive) const
767  {
768  int64 mem = inclusive ? sizeof(*this) : 0;
769 
770  const Holder *holder = getHolder();
771  if (!isSentinelOrNullPtr(holder))
772  mem += holder->getMemoryUsage(true);
773  return mem;
774  }
775 
776  // This hash function does not look for null termination, but
777  // instead goes directly for the length.
779  static unsigned hash_string(const char *str, exint len)
780  {
781  return SYSstring_hash(str, len);
782  }
783 
785 
786  /// A version of trimSpace() that only removes leading and following spaces
787  /// from a string, leaving any between words intact.
788  bool trimBoundingSpace();
789 
790  /// trimSpace() will remove all space characters (leading and following)
791  /// from a string. If the string consists of multiple words, the words
792  /// will be collapsed. To keep a single space between words, pass in true.
793  /// The function returns true if space was trimmed.
794  bool trimSpace(bool leave_single_space_between_words = false);
795 
796  /// Convert to lower case. If the string is already lower case, the string
797  /// itself is returned.
798  UT_StringRef toLower() const;
799 
800  /// Often people reflexively use this from UT_String days to
801  /// this increases code compataibility.
802  void harden(const char *src);
803 
804  // Steals the given string, gaining ownership of it.
805  // Will be freed by this when the reference count hits zero.
806  void adoptFromMalloc(const char *str, exint length=-1)
807  {
808  clear();
809 
810  if (length == 0 || !UTisstring(str))
811  return;
812  else
813  {
814  if (length < 0)
815  length = ::strlen(str);
816  Holder *h = Holder::buildFromData(str, length, STORE_MALLOC);
817  h->incref();
818  myLength = 0;
819  myData = h;
820  }
821  }
822  void adoptFromNew(const char *str, exint length=-1)
823  {
824  clear();
825 
826  if (length == 0 || !UTisstring(str))
827  return;
828  else
829  {
830  if (length < 0)
831  length = ::strlen(str);
832  Holder *h = Holder::buildFromData(str, length, STORE_NEW);
833  h->incref();
834  myLength = 0;
835  myData = h;
836  }
837  }
839  {
840  if (!str.isstring())
841  {
842  clear();
843  return;
844  }
845  // We want to steal from always deep strings as well.
846  // We will erase the data in the source string!
847  str.harden();
848 
849  // Clear after harden in case str refers to us!
850  clear();
851 
852  Holder *h = Holder::build(str.myData, STORE_MALLOC);
853  h->incref();
854  myLength = 0;
855  myData = h;
856 
857  str.myData = 0;
858  str.myIsReference = true;
859  // Leave always deep as it was.
860  }
861 
862  // Extracts a string from ourself of the given allocation mode.
863  // The result can be freed with that allocation mode.
864  // Will always clear myself afterwards. This will return our
865  // own string without copying if reference count is 1.
866  // Will return 0 for empty strings.
867  char *stealAsMalloc();
868 
869  // Tests to see if UT_StringLit's memory layout is the same
870  static bool verifyStringLit();
871 
872  /// Does a "smart" string compare which will sort based on numbered names.
873  /// That is "text20" is bigger than "text3". In a strictly alphanumeric
874  /// comparison, this would not be the case.
876  {
877  bool operator()(const UT_StringRef &s1, const UT_StringRef &s2) const
878  {
879  return UT_String::compareNumberedString(s1.c_str(), s2.c_str()) < 0;
880  }
881  };
882 
883  /// Save string to binary stream.
884  void saveBinary(std::ostream &os) const
885  { UT_StringWrap(c_str()).saveBinary(os); }
886 
887  /// Save string to ASCII stream. This will add double quotes and escape to
888  /// the stream if necessary (empty string or contains spaces).
889  void saveAscii(std::ostream &os) const
890  { UT_StringWrap(c_str()).saveAscii(os); }
891 
892 private:
893  void init()
894  {
895  myData = nullptr;
896  myLength = 0;
897  myHash = 0;
898  }
899 
900  void copy(const UT_StringRef &s)
901  {
902  myData = s.myData;
903  myLength = s.myLength;
904  myHash = s.myHash;
905  }
906 
908  Holder *getHolder() const
909  {
910  if (!myLength)
911  return myDataIfHolder;
912  return NULL;
913  }
914 
915  // This union makes viewing in a debugger much easier.
916  union {
917  const void *myData;
918  const char *myDataIfChars;
920  };
921  int myLength;
922  mutable int myHash;
923 
924  /// This operator saves the string to the stream via the string's
925  /// saveAscii() method, protecting any whitespace (by adding quotes),
926  /// backslashes or quotes in the string.
927  friend UT_API std::ostream &operator<<(std::ostream &os, const UT_StringRef &d);
928  friend UT_API UT_OStream &operator<<(UT_OStream &os, const UT_StringRef &d);
929 
930  // UT_StringHolder needs to be a friend class so that the
931  // UT_StringHolder(const UT_StringRef &) constructor can access myHash and
932  // getHolder() for the UT_StringRef that is passed in.
933  friend class UT_StringHolder;
934 
935  static constexpr uintptr_t SENTINEL_DATA = 1;
936  static constexpr uint32 SENTINEL_HASH = 0xdeadbeef;
937 
938  template<typename T>
939  static SYS_FORCE_INLINE bool isSentinelOrNullPtr(const T *p)
940  {
941  return uintptr_t(p) <= SENTINEL_DATA;
942  }
943 };
944 
946 {
947  return str.hash();
948 }
949 
950 /// A holder for a string, which stores the length and caches the hash value.
951 /// The lifetime of the string is >= the lifetime of the UT_StringHolder.
953 {
954 public:
955  /// UT_StringHolder can be constructed with UT_StringHolder::REFERENCE to
956  /// create a shallow reference to the const char *.
957  enum UT_StringReferenceType { REFERENCE };
958 
961  : UT_StringRef()
962  {
963  }
964 
965  /// Will make a copy of the provided string.
967  UT_StringHolder(const char *str)
968  {
969  if (UTisstring(str))
970  {
971  Holder *h = Holder::build(str, STORE_INLINE);
972  h->incref();
973  myLength = 0;
974  myDataIfHolder = h;
975  }
976  }
977 
978  /// Will make a shallow reference.
981  : UT_StringRef(str)
982  {
983  }
984 
985  /// Will make a copy of the provided string.
988  {
989  if (data && length > 0)
990  {
991  Holder *h = Holder::buildFromData(data, length, STORE_INLINE);
992  h->incref();
993  myLength = 0;
994  myDataIfHolder = h;
995  }
996  }
997 
998  // Prohibit accidents when converting from UT_String like:
999  // myStringHolder(buffer, /*deep*/true)
1000  UT_StringHolder(const char *data, bool bad) = delete;
1001 
1002  // Add back explicit conversions for the length parameter
1005  : UT_StringHolder(data, exint(length)) { }
1008  : UT_StringHolder(data, exint(length)) { }
1011  : UT_StringHolder(data, exint(length)) { }
1012 #if defined(MBSD)
1014  UT_StringHolder(const char *data, size_t length)
1015  : UT_StringHolder(data, exint(length)) { }
1016 #endif
1017 
1018  /// Will make a copy of the provided string.
1021  {
1022  const char *s = str.c_str();
1023  if (UTisstring(s))
1024  {
1025  Holder *h = Holder::buildFromData(s, str.length(), STORE_INLINE);
1026  h->incref();
1027  myLength = 0;
1028  myDataIfHolder = h;
1029  }
1030  }
1031 
1032  /// This will make a shallow reference to the contents of the string.
1035  : UT_StringRef(str)
1036  {
1037  }
1038 
1039  /// Will make a copy of the provided string.
1040  UT_StringHolder(const UT_WorkBuffer &str);
1041 
1042  /// This will make a shallow reference to the contents of the string.
1045  : UT_StringRef(str)
1046  {
1047  }
1048 
1049  /// Will make a copy of the provided string.
1052  {
1053  *this = UT_StringHolder(str.buffer());
1054  }
1055 
1056  /// This will make a shallow reference to the contents of the string.
1059  : UT_StringRef(str)
1060  {
1061  }
1062 
1063  /// Will make a copy of the provided string.
1064  UT_StringHolder(const UT_StringView &sv);
1065 
1066  /// Makes a shallow reference to the contents of the UT_StringRef.
1069  : UT_StringRef(ref)
1070  {
1071  }
1072 
1073  /// Makes a deep copy of the provided UT_StringRef.
1074  /// This constructor is not marked explicit since we often want this
1075  /// conversion (e.g. when inserting a UT_StringRef into a UT_StringMap, as
1076  /// with the const char* constructor).
1078 
1079  /// Construct as a sentinel value
1080  SYS_FORCE_INLINE explicit
1082  : UT_StringRef(sentinel)
1083  {
1084  }
1085 
1086  /// Makes a copy of the provided string.
1089  : UT_StringRef(str)
1090  {
1091  }
1092 
1093  /// Move constructor. Steals the working data from the original.
1096  : UT_StringRef(std::move(a))
1097  {
1098  }
1099 
1100  /// Makes a bit-wise copy of the string and adjust the reference count.
1103  {
1105  return *this;
1106  }
1107 
1108  /// Move the contents of about-to-be-destructed string
1109  /// s to this string.
1112  {
1113  UT_StringRef::operator=(std::move(s));
1114  return *this;
1115  }
1116 
1118  void swap(UT_StringHolder &other)
1119  {
1120  UT_StringRef::swap(other);
1121  }
1122 
1124  void swap(UT_StringRef &other)
1125  {
1126  UT_StringRef::swap(other);
1127  // harden ourselves like UT_StringHolder::operator=(UT_StringRef&)
1128  Holder *h = getHolder();
1129  if (!isSentinelOrNullPtr(h))
1130  return; // already a holder
1131  if (!isSentinelOrNullPtr(myDataIfChars))
1132  {
1133  exint len = (myLength >= 0) ? myLength
1134  : (exint(-myLength) << 31) + myHash;
1135  h = Holder::buildFromData(myDataIfChars, len, STORE_INLINE, myHash);
1136  h->incref();
1137  myLength = 0;
1138  myData = h;
1139  }
1140  }
1141 
1142  /// Friend specialization of std::swap() to use UT_StringHolder::swap()
1143  /// @{
1144  friend void swap(UT_StringHolder& a, UT_StringRef& b) { a.swap(b); }
1145  friend void swap(UT_StringHolder& a, UT_StringHolder& b) { a.swap(b); }
1146  /// @}
1147 
1148  /// In some functions it's nice to be able to return a const-reference to a
1149  /// UT_StringHolder. However, in error cases, you likely want to return an
1150  /// empty string. This would mean that you'd have to return a real
1151  /// UT_StringHolder (not a const reference). This static lets you return a
1152  /// reference to an empty string.
1154 
1156 
1157  /// Format a string using the same formatting codes as @c UTformat.
1158  template<typename... Args>
1159  size_t format(const char *fmt, const Args &...args)
1160  {
1161  clear();
1162 
1163  using namespace UT::Format;
1164  Writer w;
1166  size_t nb_needed = f.format(w, fmt, {args...});
1167 
1168  auto h = Holder::buildBuffer(nb_needed, STORE_MALLOC);
1169  h->incref();
1170  myLength = 0;
1171  myData = h;
1172 
1173  w.setBuffer(h->bufferNC(), nb_needed);
1174  f.format(w, fmt, {args...});
1175  h->bufferNC()[nb_needed] = '\0';
1176 
1177  return nb_needed;
1178  }
1179 
1180  /// Format a string using the same formatting codes as @c UTprintf.
1181  template<typename... Args>
1182  size_t sprintf(const char *fmt, const Args &...args)
1183  {
1184  clear();
1185 
1186  using namespace UT::Format;
1187  Writer w;
1189  size_t nb_needed = f.printf(w, fmt, {args...});
1190 
1191  auto h = Holder::buildBuffer(nb_needed, STORE_MALLOC);
1192  h->incref();
1193  myLength = 0;
1194  myData = h;
1195 
1196  w.setBuffer(h->bufferNC(), nb_needed);
1197  f.printf(w, fmt, {args...});
1198  h->bufferNC()[nb_needed] = '\0';
1199 
1200  return nb_needed;
1201  }
1202 
1203  /// Replace all occurances of 'find' with 'replacement'.
1204  /// Returns number of replacements.
1205  int substitute(const char *find, const char *replacement, bool all = true)
1206  {
1207  UT_String s(buffer());
1208  int n = s.substitute(find, replacement, all);
1209  if (n > 0)
1210  adoptFromString(s);
1211  return n;
1212  }
1213 
1214  /// Load string from stream. Use is.eof() to check eof status
1215  bool load(UT_IStream &is)
1216  {
1217  UT_String s;
1218  if (s.load(is))
1219  {
1220  adoptFromString(s);
1221  return true;
1222  }
1223  return false;
1224  }
1225 
1226 protected:
1227  friend UT_StringHolder UT::Literal::operator"" _sh(
1228  const char *s, std::size_t const length);
1229  friend UT_StringHolder operator"" _UTsh(
1230  const char *s, std::size_t const length);
1231 
1232  /// A marker enum to use this constructor.
1233  enum UT_StringLiteralType { LITERAL };
1234 
1235  /// Only accepts string literals. Since there's no way to guarantee that
1236  /// a const char * argument is a string literal, we do this through the
1237  /// use of user-defined literal and *only* provide this constructor to our
1238  /// user-defined literal operator.
1240  {
1241  if (str && length)
1242  {
1243  myDataIfChars = str;
1244  myLength = length;
1245  // As of C++14, user defined literals don't support constexpr so
1246  // this hash computation here is actually done at run-time except
1247  // for in some cases where the compiler (clang?) is able to
1248  // optimize this. Therefore, disable this to avoid extraneous hash
1249  // computation in cases where we just want to use "foo"_sh to avoid
1250  // heap allocation but never use its hash.
1251  // Use UT_StringLit if you want to get compile time hashes
1252 #if 0
1253  myHash = SYSstring_hash_literal(str);
1254 #else
1255  myHash = 0;
1256 #endif
1257  }
1258  }
1259 };
1260 
1261 UT_EXTERN_TEMPLATE(UT_Array<UT_StringHolder>); // requires #include "UT_Array.h"
1262 
1263 /// Convert a UT_StringRef into a UT_StringHolder that is a shallow reference.
1265 {
1266  SYS_STATIC_ASSERT(sizeof(UT_StringRef) == sizeof(UT_StringHolder));
1267  return reinterpret_cast<const UT_StringHolder &>(ref);
1268 }
1269 
1270 /// Convert a UT_StringRef into a UT_StringHolder that is a shallow reference,
1271 /// and also precompute the hash. Use this for string literals
1272 /// that will be used repeatedly in hash tables.
1274 {
1275  SYS_STATIC_ASSERT(sizeof(UT_StringRef) == sizeof(UT_StringHolder));
1276  ref.hash();
1277  return reinterpret_cast<const UT_StringHolder &>(ref);
1278 }
1279 
1282 {
1283  SYS_STATIC_ASSERT(sizeof(UT_StringHolder) == sizeof(*this));
1284  return reinterpret_cast<const UT_StringHolder &>(*this);
1285 }
1286 
1289 {
1290  SYS_STATIC_ASSERT(sizeof(UT_StringRef) == sizeof(*this));
1291  return reinterpret_cast<const UT_StringRef &>(*this);
1292 }
1293 
1294 SYS_FORCE_INLINE size_t tbb_hasher(const UT_StringRef &s) { return s.hash(); }
1295 SYS_FORCE_INLINE size_t tbb_hasher(const UT_StringHolder &s) { return s.hash(); }
1296 
1297 /// A user-defined string literal to construct UT_StringHolder objects.
1298 /// E.g:
1299 /// @code
1300 /// auto lit = "This is my UT_StringHolder literal"_sh;
1301 /// @endcode
1302 namespace UT { inline namespace Literal {
1303 SYS_FORCE_INLINE UT_StringHolder operator"" _sh(const char *s, std::size_t const length)
1304 {
1305  return UT_StringHolder(UT_StringHolder::LITERAL, s, length);
1306 }
1307 } }
1308 
1309 /// A user-defined literal in the global namespace. Uglier, but allows the use
1310 /// of UT_StringHolder UDLs in headers.
1311 SYS_FORCE_INLINE UT_StringHolder operator"" _UTsh(const char *s, std::size_t const length)
1312 {
1313  return UT_StringHolder(UT_StringHolder::LITERAL, s, length);
1314 }
1315 
1316 
1317 namespace std
1318 {
1319  template<>
1320  struct hash<UT_StringRef>
1321  {
1322  size_t operator()(const UT_StringRef &s) const
1323  {
1324  return s.hash();
1325  }
1326  };
1327  template<>
1328  struct hash<UT_StringHolder>
1329  {
1330  size_t operator()(const UT_StringHolder &s) const
1331  {
1332  return s.hash();
1333  }
1334  };
1335 }
1336 
1337 // For UT::ArraySet.
1338 namespace UT
1339 {
1340 template <typename T>
1341 struct DefaultClearer;
1342 
1343 template <>
1345 {
1346  static void clear(UT_StringHolder &v) { v.makeSentinel(); }
1347  static bool isClear(const UT_StringHolder &v) { return v.isSentinel(); }
1349  {
1350  new ((void *)p) UT_StringHolder(UT_StringRef::SENTINEL);
1351  }
1352  static const bool clearNeedsDestruction = false;
1353 };
1354 } // namespace UT
1355 
1356 #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.
GLdouble s
Definition: glew.h:1390
std::string toStdString() const
static Holder * build(const char *str, StorageMode storage)
void adoptFromString(UT_String &str)
SYS_FORCE_INLINE UT_StringHolder(const UT_StringHolder &str)
Makes a copy of the provided string.
SYS_FORCE_INLINE const_iterator begin() const
unsigned hash() const
SYS_FORCE_INLINE const char * nonNullBuffer() const
#define SYS_STATIC_ASSERT(expr)
unsigned match(const char *pattern, int caseSensitive=1) const
GLenum src
Definition: glew.h:2410
unsigned multiMatch(const char *pattern, int caseSensitive, char separator) const
GLenum GLint ref
Definition: glew.h:1845
bool endsWith(const char *suffix, bool case_sensitive=true, exint len=-1) const
#define SYS_PRAGMA_PUSH_WARN()
Definition: SYS_Pragma.h:34
size_t operator()(const UT_StringRef &s) const
friend void swap(UT_StringRef &a, UT_StringRef &b)
Friend specialization of std::swap() to use UT_StringRef::swap()
SYS_FORCE_INLINE constexpr exint length() const
void UTswap(T &a, T &b)
Definition: UT_Swap.h:35
SYS_FORCE_INLINE UT_StringHolder(UT_StringLiteralType, const char *str, size_t length)
unsigned match(const char *pattern, int caseSensitive=1) const
FMT_CONSTEXPR auto begin(const C &c) -> decltype(c.begin())
Definition: format.h:251
const Args & args
Definition: printf.h:628
SYS_FORCE_INLINE UT_StringHolder(const char *data, exint length)
Will make a copy of the provided string.
SYS_FORCE_INLINE UT_StringHolder()
UT_StringLiteralType
A marker enum to use this constructor.
SYS_FORCE_INLINE void clear()
bool contains(const char *pattern, bool case_sensitive=true) const
fpreal toFloat() const
int toInt() const
GLboolean GLboolean GLboolean GLboolean a
Definition: glew.h:9477
SYS_FORCE_INLINE T * SYSconst_cast(const T *foo)
Definition: SYS_Types.h:131
bool isEmpty() const
static void clear(UT_StringHolder &v)
SYS_FORCE_INLINE UT_StringRef(const UT_StringRef &s)
Shares a reference with the source.
SYS_FORCE_INLINE void swap(UT_StringHolder &other)
bool startsWith(const char *prefix, bool case_sense=true, exint len=-1) const
Imported from UT_String.
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)
void adoptFromMalloc(const char *str, exint length=-1)
#define UT_API
Definition: UT_API.h:13
bool equal(const UT_StringRef &str, bool ignore_case=false) const
SYS_FORCE_INLINE UT_StringHolder(const char *data, uint64 length)
bool operator!=(const char *s) const
SYS_FORCE_INLINE bool hasNonSpace() const
const GLdouble * v
Definition: glew.h:1391
#define UT_ASSERT_MSG_P(ZZ,...)
Definition: UT_Assert.h:137
unsigned multiMatch(const char *pattern, int caseSensitive=1, const char *separators=", ", bool *explicitlyExcluded=0, int *matchIndex=0, ut_PatternRecord *pattern_record=NULL) const
SYS_FORCE_INLINE int findCharIndex(const char *str, exint start_offset) const
unsigned isInteger(int skip_spaces=0) const
Determine if string can be seen as a single integer number.
UT_EXTERN_TEMPLATE(UT_Array< UT_StringHolder >)
SYS_FORCE_INLINE int lastCharIndex(char c, int occurance_number=1) const
SYS_FORCE_INLINE size_t tbb_hasher(const UT_StringRef &s)
int substitute(const char *find, const char *replacement, bool all=true)
constexpr SYS_FORCE_INLINE UT_StringLit()
SYS_FORCE_INLINE constexpr uint32 hash() const
SYS_FORCE_INLINE UT_StringRef(const UT_StringLit &lit)
Construct from string literal.
PUGI__FN unsigned int hash_string(const char_t *str)
Definition: pugixml.cpp:8490
SYS_FORCE_INLINE const UT_StringHolder & UTmakeUnsafeRefHash(const UT_StringRef &ref)
bool load(UT_IStream &is)
Load string from stream. Use is.eof() to check eof status.
fpreal toFloat() const
const void * myData
bool contains(const char *pattern, bool case_sensitive=true) const
constexpr SYS_FORCE_INLINE UT_StringLit(const char(&str)[N])
std::ostream & operator<<(std::ostream &ostr, const DataType &a)
Definition: DataType.h:133
SYS_FORCE_INLINE const_iterator end() const
void saveAscii(std::ostream &os) const
bool operator==(const BaseDimensions< T > &a, const BaseDimensions< Y > &b)
Definition: Dimensions.h:137
UT_StringRef & operator=(const UT_StringRef &s)
Shares a reference with the source.
SYS_FORCE_INLINE UT_StringHolder(const UT_String &str)
Will make a copy of the provided string.
long long int64
Definition: SYS_Types.h:111
const char * buffer() const
Definition: UT_String.h:503
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)
unsigned multiMatch(const char *pattern, int caseSensitive, char separator) const
A utility class to do read-only operations on a subset of an existing string.
Definition: UT_StringView.h:32
size_t sprintf(const char *fmt, const Args &...args)
Format a string using the same formatting codes as UTprintf.
SYS_FORCE_INLINE size_t hash_value(const UT_StringRef &str)
SYS_FORCE_INLINE UT_StringRef(UT_StringRef &&s) SYS_NOEXCEPT
Move constructor. Steals the working data from the original.
unsigned long long uint64
Definition: SYS_Types.h:112
SYS_FORCE_INLINE UT_StringHolder(const std::string &str)
Will make a copy of the provided string.
bool operator==(const UT_StringRef &s) const
SYS_FORCE_INLINE int findCharIndex(char c) const
GLclampf f
Definition: glew.h:3499
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:4246
int64 getMemoryUsage(bool inclusive) const
#define SYS_SAFE_BOOL
Definition: SYS_Compiler.h:62
exint length() const
SYS_FORCE_INLINE const char * buffer() const
int64 exint
Definition: SYS_Types.h:120
friend void swap(UT_StringHolder &a, UT_StringHolder &b)
GLint GLenum GLsizei GLint GLsizei const void * data
Definition: glew.h:1379
#define UT_ASSERT_P(ZZ)
Definition: UT_Assert.h:134
SYS_FORCE_INLINE UT_StringHolder(const char *data, uint32 length)
static const UT_StringHolder theEmptyString
bool operator>=(const UT_StringRef &k) 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
GLubyte GLubyte GLubyte GLubyte w
Definition: glew.h:1890
void
Definition: png.h:1083
SYS_FORCE_INLINE UT_StringRef()
GLsizei n
Definition: glew.h:4040
const GLfloat * c
Definition: glew.h:16296
GLuint GLsizei GLsizei * length
Definition: glew.h:1825
SYS_FORCE_INLINE UT_StringHolder & operator=(UT_StringHolder &&s)
void harden()
Take shallow copy and make it deep.
Definition: UT_String.h:213
SYS_FORCE_INLINE void makeSentinel()
void saveAscii(std::ostream &os) const
Definition: UT_String.h:298
#define SYS_PRAGMA_DISABLE_FREE_NONHEAP_OBJECT()
Definition: SYS_Pragma.h:114
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
GLfloat GLfloat GLfloat GLfloat h
Definition: glew.h:8011
#define SYS_PRAGMA_POP_WARN()
Definition: SYS_Pragma.h:35
size_t format(const char *fmt, const Args &...args)
Format a string using the same formatting codes as UTformat.
SYS_FORCE_INLINE UT_StringHolder & operator=(const UT_StringHolder &s)
Makes a bit-wise copy of the string and adjust the reference count.
int int32
Definition: SYS_Types.h:39
SYS_FORCE_INLINE constexpr const char * c_str() const
bool operator<=(const UT_StringRef &k) const
bool operator<(const UT_StringRef &k) const
bool operator!=(const UT_StringRef &s) const
void fastReferenceWithStrlen(const char *src, exint length)
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:294
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
GLdouble GLdouble GLdouble b
Definition: glew.h:9122
static int compareNumberedString(const char *s1, const char *s2, bool case_sensitive=true, bool allow_negatives=false)
GLfloat GLfloat p
Definition: glew.h:16321
static Holder * buildFromData(const char *str, exint len, StorageMode storage, int hash=0)
GLsizei const GLchar *const * string
Definition: glew.h:1844
double fpreal
Definition: SYS_Types.h:276
SYS_FORCE_INLINE UT_StringRef(const UT_String &str)
This will make a shallow reference to the contents of the string.
void adoptFromNew(const char *str, exint length=-1)
bool operator>(const UT_StringRef &k) const
static bool isClear(const UT_StringHolder &v)
unsigned multiMatch(const UT_StringMMPattern &pattern, bool *explicitlyExcluded=0, int *matchIndex=0, ut_PatternRecord *pattern_record=NULL) const
SYS_FORCE_INLINE ~UT_StringRef()
size_t operator()(const UT_StringHolder &s) const
SYS_FORCE_INLINE bool UTisstring(const char *s)
Definition: UT_String.h:57
bool operator==(const UT_String &s) const
const void * ptr(const T *p)
Definition: format.h:3292
int substitute(const char *find, const char *replacement, bool all=true)
bool load(UT_IStream &is)
Load string from stream. Use is.eof() to check eof status.
#define SYS_NOEXCEPT
Definition: SYS_Compiler.h:55
bool endsWith(const char *prefix, bool case_sense=true, exint len=-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:227
SYS_FORCE_INLINE int countChar(char c) const
friend class UT_StringHolder
int64 getMemoryUsage(bool inclusive) const
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat s1
Definition: glew.h:12681
SYS_FORCE_INLINE UT_StringHolder(UT_StringReferenceType, const char *str)
Will make a shallow reference.
FMT_CONSTEXPR bool find(Ptr first, Ptr last, T value, Ptr &out)
Definition: format.h:2104
OIIO_API bool copy(string_view from, string_view to, std::string &err)
SYS_FORCE_INLINE const UT_StringHolder & asHolder() const
GLuint GLuint GLsizei count
Definition: glew.h:1253
Type-safe formatting, modeled on the Python str.format function.
GA_API const UT_StringHolder N
const char * const_iterator
Iterators.
SYS_FORCE_INLINE UT_StringRef(const char *str)
Will make a shallow reference.
void reference(const char *src)
GLenum const void GLuint GLint reference
Definition: glew.h:13644
GLuint64EXT * result
Definition: glew.h:14007
bool isstring() const
Definition: UT_String.h:705
getOption("OpenEXR.storage") storage
Definition: HDK_Image.dox:276
unsigned isInteger(int skip_spaces=0) const
Determine if string can be seen as a single integer number.
#define UT_ASSERT(ZZ)
Definition: UT_Assert.h:135
SYS_FORCE_INLINE constexpr const char * buffer() const
SYS_FORCE_INLINE void swap(UT_StringRef &other)
int toInt() const
bool operator!=(const BaseDimensions< T > &a, const BaseDimensions< Y > &b)
Definition: Dimensions.h:165
#define const
Definition: zconf.h:214
GLubyte * pattern
Definition: glew.h:5711
unsigned hash() const
unsigned isFloat(int skip_spaces=0, int loose=0, bool allow_underscore=false) const
Determine if string can be seen as a single floating point number.
SYS_FORCE_INLINE int findCharIndex(const char *str) const
SYS_FORCE_INLINE UT_StringHolder(UT_StringHolder &&a) SYS_NOEXCEPT
Move constructor. Steals the working data from the original.
SYS_FORCE_INLINE UT_StringHolder(const char *str)
Will make a copy of the provided string.
bool all(const vbool4 &v)
Definition: simd.h:3371
const char * c_str() const
const char * myDataIfChars
SYS_FORCE_INLINE UT_StringRef(const std::string &str)
This will make a shallow reference to the contents of the string.
unsigned isFloat(int skip_spaces=0, int loose=0) const
Determine if string can be seen as a single floating point number.
bool operator!=(const UT_String &s) const
SYS_FORCE_INLINE bool isstring() const
Holder * myDataIfHolder
SYS_FORCE_INLINE T relaxedLoad() const
Definition: SYS_AtomicInt.h:57
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.
bool startsWith(const char *prefix, bool case_sensitive=true, exint len=-1) const
static const UT_StringHolder theSentinel
SYS_FORCE_INLINE int findCharIndex(char c, exint start_offset) const
GLenum GLsizei len
Definition: glew.h:7752
unsigned int uint32
Definition: SYS_Types.h:40
SYS_FORCE_INLINE void swap(UT_StringRef &other)