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 #include <string.h>
40 
41 class UT_IStream;
42 class UT_OStream;
43 class UT_StringHolder;
44 class UT_StringRef;
45 class UT_StringView;
46 class UT_WorkBuffer;
47 
48 // Forward declare the UDSL so that we can friend it inside of UT_StringHolder.
49 namespace UT { inline namespace Literal {
50 UT_StringHolder operator"" _sh(const char *s, std::size_t const length);
51 } }
52 
53 /// A string literal with length and compile-time computed hash value.
54 /// @note This will only be compile-time when used in compile time expressions
55 /// like template parameters and constexpr variables.
56 /// @note String literals whose length requires more than 31 bits not supported
57 /// @see UT_StringRef
59 {
60 public:
61  constexpr SYS_FORCE_INLINE
63  : myData(nullptr)
64  , myLength(0)
65  , myHash(0)
66  {
67  }
68 
69  template <size_t N>
70  constexpr SYS_FORCE_INLINE
71  UT_StringLit(const char (&str)[N])
72  : myData(str)
73  , myLength(N-1)
74  , myHash(SYSstring_hash_inner(str, 0))
75  {
76  SYS_STATIC_ASSERT(N-1 < (((exint)1) << 31));
77  }
78 
79  SYS_FORCE_INLINE constexpr const char* buffer() const { return myData; }
80  SYS_FORCE_INLINE constexpr const char* data() const { return myData; }
81  SYS_FORCE_INLINE constexpr const char* c_str() const { return myData; }
82  SYS_FORCE_INLINE constexpr operator const char*() const { return myData; }
83 
84  SYS_FORCE_INLINE constexpr exint length() const { return myLength; }
85 
86  SYS_FORCE_INLINE constexpr uint32 hash() const { return myHash; }
87 
89  SYS_FORCE_INLINE const UT_StringRef& asRef() const;
90 
91 
92 private:
93  const char* myData;
94  int32 myLength;
95  uint32 myHash;
96 
97  friend class UT_StringRef;
98 };
99 
100 /// A holder for a string, which stores the length and caches the hash value.
101 /// A UT_StringRef does not necessarily own the string, and it is therefore not
102 /// safe to e.g. store a UT_StringRef in a container or member variable.
103 /// @see UT_StringHolder
104 /// @see UTmakeUnsafeRef
106 {
107 public:
108  typedef char value_type;
109 
111  {
115  STORE_INLINE
116  };
117 
119  {
120  public:
122  : myRefCount(0), myStorageMode(STORE_INLINE),
123  myHash(0), myLength(0), myData(0)
124  {
125  }
126 
127  static Holder *build(const char *str,
129  static Holder *buildFromData(const char *str,
130  exint len,
132  int hash = 0);
133  static Holder *buildBuffer(
134  exint length,
136 
137  const char *c_str() const
138  {
139  if (myStorageMode == STORE_INLINE)
140  return myDataIfInline;
141 
142  return myData;
143  }
144 
145  void incref()
146  {
147  myRefCount.add(1);
148  }
149  void decref()
150  {
151  if (myRefCount.add(-1) == 0)
152  {
153  // We can't invoke delete as we were malloced.
154  // Further, we have custom behaviour on ownership!
155  switch (myStorageMode)
156  {
157  case STORE_EXTERNAL:
158  case STORE_INLINE:
159  // Do nothing.
160  break;
161  case STORE_NEW:
162  delete [] myData;
163  break;
164  case STORE_MALLOC:
165  if (myData)
166  free( (void*)SYSconst_cast(myData));
167  break;
168  }
171  free(this);
173  }
174  }
175 
176  exint length() const
177  {
178  return myLength;
179  }
180 
181  unsigned hash() const
182  {
183  if (!myHash)
184  {
185  myHash = hash_string(c_str(), length());
186  }
187  return myHash;
188  }
189 
190  int64 getMemoryUsage(bool inclusive) const
191  {
192  int64 mem = inclusive ? sizeof(*this) : 0;
193 
194  switch (myStorageMode)
195  {
196  case STORE_EXTERNAL:
197  // Nothing extra.
198  break;
199  case STORE_INLINE:
200  UT_ASSERT_MSG_P(inclusive,
201  "If a Holder is STORE_INLINE, it *really* can't be a "
202  "member variable, because the size isn't determined "
203  "at runtime.");
204  mem += myLength + 1 - sizeof(const char *);
205  break;
206  case STORE_NEW:
207  case STORE_MALLOC:
208  // External reference we own.
209  mem += myLength + 1;
210  break;
211  }
212  return mem;
213  }
214 
215  private:
216  char *bufferNC() const
217  {
218  if (myStorageMode == STORE_INLINE)
219  return SYSconst_cast(myDataIfInline);
220 
221  return SYSconst_cast(myData);
222  }
223 
224  friend class UT_StringHolder;
225  friend class UT_StringRef;
226 
227  private:
228  SYS_AtomicInt32 myRefCount;
229  StorageMode myStorageMode;
230  mutable int myHash;
231  exint myLength;
232 
233  // This union makes viewing in a debugger much easier.
234  union {
235  const char *myData;
236  char myDataIfInline[sizeof(const char *)];
237  };
238  };
239 
242  {
243  init();
244  }
245 
246  /// Will make a shallow reference.
248  UT_StringRef(const char *str)
249  {
250  init();
251  if (UTisstring(str))
252  {
253  reference(str);
254  }
255  }
256 
257  /// Construct from string literal
258  SYS_FORCE_INLINE explicit
260  : UT_StringRef(lit.asRef())
261  {
262  }
263 
264  /// This will make a shallow reference to the contents of the string.
267  {
268  init();
269  if (str.size())
270  {
271  const char *s = str.c_str();
272  fastReferenceWithStrlen(s, str.length());
273  }
274  }
275 
276  /// This will make a shallow reference to the contents of the string.
277  UT_StringRef(const UT_WorkBuffer &str);
278 
279  /// This will make a shallow reference to the contents of the string.
282  {
283  init();
284  if (str.isstring())
285  reference(str);
286  }
287 
288  /// Shares a reference with the source.
291  {
292  Holder *sh = s.getHolder();
293  if (!isSentinelOrNullPtr(sh))
294  sh->incref();
295  // Can now blindly copy.
296  copy(s);
297  }
298 
299  /// Move constructor. Steals the working data from the original.
302  {
303  copy(s);
304  s.init();
305  }
306 
309  {
310  Holder *h = getHolder();
311  if (!isSentinelOrNullPtr(h))
312  h->decref();
313  }
314 
315  /// Special sentinel value support
316  /// @{
317  enum UT_StringSentinelType { SENTINEL };
318 
319  SYS_FORCE_INLINE explicit
321  : myData((const void*)SENTINEL_DATA)
322  , myLength(0)
323  , myHash(SENTINEL_HASH)
324  {
325  }
326 
328  bool isSentinel() const
329  {
330  return uintptr_t(myData) == SENTINEL_DATA && myHash == SENTINEL_HASH && !myLength;
331  }
332 
335  {
336  Holder *h = getHolder();
337  if (!isSentinelOrNullPtr(h))
338  h->decref();
339  myData = (const void*)SENTINEL_DATA;
340  myLength = 0;
341  myHash = SENTINEL_HASH;
342  }
343  /// @}
344 
345  /// Returns true this object is the sole owner of the underlying string
346  bool isUnique() const
347  {
348  Holder *h = getHolder();
349  if (isSentinelOrNullPtr(h))
350  return false;
351  return (h->myRefCount.relaxedLoad() == 1);
352  }
353 
354  /// Shares a reference with the source.
356  {
357  Holder *sh = s.getHolder();
358  Holder *th = getHolder();
359 
360  if (!isSentinelOrNullPtr(sh))
361  sh->incref();
362  if (!isSentinelOrNullPtr(th))
363  th->decref();
364  // Can now blindly copy.
365  copy(s);
366  return *this;
367  }
368 
369  /// Move the contents of about-to-be-destructed string
370  /// s to this string.
373  {
374  // Can just swap, since s is about to be destructed.
375  swap(s);
376  return *this;
377  }
378 
379  bool operator==(const UT_StringRef &s) const
380  {
381  // It is sensible to fast-path this based on myData!
382  // If our two pointers are equal, we either are pointing to
383  // the same Holder or to the same const char *, so are good
384  // to call it equal.
385  if (myData == s.myData)
386  return true;
387  exint tl = length();
388  exint sl = s.length();
389  if (tl != sl)
390  return false;
391  if (tl == 0)
392  return (uintptr_t(myData) == SENTINEL_DATA) == (uintptr_t(s.myData) == SENTINEL_DATA);
393  return ::memcmp(c_str(), s.c_str(), tl) == 0;
394  }
395  bool operator==(const char *s) const
396  {
397  // It is sensible to fast-path this based on myData!
398  // If our two pointers are equal, we either are pointing to
399  // the same Holder or to the same const char *, so are good
400  // to call it equal.
401  // We don't test for myData being a Holder because it should
402  // never alias a const char *.
403  if (myDataIfChars == s)
404  return true;
405  // Avoid comparison with null.
406  if (!s)
407  return !isstring();
408  return ::strcmp(c_str(), s) == 0;
409  }
410  bool operator==(const UT_String &s) const
411  { return operator==(s.buffer()); }
412 
413  bool operator!=(const UT_StringRef &s) const
414  { return !operator==(s); }
415  bool operator!=(const char *s) const
416  { return !operator==(s); }
417  bool operator!=(const UT_String &s) const
418  { return operator!=(s.buffer()); }
419 
420  /// Spaceship comparison returns:
421  /// - < 0 if *this < k
422  /// - == 0 if *this == k
423  /// - > 0 if *this > k
424  int spaceship(const UT_StringRef &k) const
425  {
426  exint minlen = SYSmin(length(), k.length());
427  int r = memcmp(c_str(), k.c_str(), minlen);
428  if (r != 0)
429  return r;
430  if (k.length() > minlen)
431  return -1;
432  return length() > minlen ? 1 : 0;
433  }
434 
435  bool operator<(const UT_StringRef &k) const
436  { return spaceship(k) < 0; }
437  bool operator<=(const UT_StringRef &k) const
438  { return spaceship(k) <= 0; }
439  bool operator>(const UT_StringRef &k) const
440  { return spaceship(k) > 0; }
441  bool operator>=(const UT_StringRef &k) const
442  { return spaceship(k) >= 0; }
443  int compare(const UT_StringRef &str,
444  bool ignore_case=false) const
445  {
446  return ignore_case
447  ? SYSstrcasecmp(c_str(), str.c_str())
448  : spaceship(str); }
449  bool equal(const UT_StringRef &str,
450  bool ignore_case=false) const
451  { return compare(str, ignore_case) == 0; }
452 
453  /// Test whether the string is defined or not
455  SYS_SAFE_BOOL operator bool() const { return isstring(); }
456 
457  /// Imported from UT_String.
458  bool startsWith(const UT_StringView &pfx, bool case_sense=true) const
459  {
460  return UT_StringWrap(c_str()).startsWith(pfx, case_sense);
461  }
462  bool endsWith(const UT_StringView &suffix, bool case_sense=true) const
463  {
464  return UT_StringWrap(c_str()).endsWith(suffix, case_sense);
465  }
466  unsigned match(const char *pattern, bool case_sensitive=true) const
467  { return UT_StringWrap(c_str()).match(pattern, case_sensitive); }
468 
469  bool contains(const char *pattern, bool case_sensitive=true) const
470  { return UT_StringWrap(c_str()).contains(pattern, case_sensitive); }
471  const char *fcontain(const char *pattern, bool case_sensitive=true) const
472  { return UT_StringWrap(c_str()).fcontain(pattern, case_sensitive); }
473  const char *findWord(const char *word) const
474  { return UT_StringWrap(c_str()).findWord(word); }
475 
476  unsigned multiMatch(const char *pattern, bool case_sensitive,
477  char separator) const
478  {
479  return UT_StringWrap(c_str()).multiMatch(
480  pattern, case_sensitive, separator);
481  }
482  unsigned multiMatch(const char *pattern, bool case_sensitive = true,
483  const char *separators = ", ",
484  bool *explicitly_excluded = 0,
485  int *match_index = 0,
486  ut_PatternRecord *pattern_record=NULL) const
487  {
488  return UT_StringWrap(c_str()).multiMatch(
489  pattern, case_sensitive, separators, explicitly_excluded,
490  match_index, pattern_record);
491  }
493  bool *explicitly_excluded = 0,
494  int *match_index = 0,
495  ut_PatternRecord *pattern_record=NULL) const
496  {
497  return UT_StringWrap(c_str()).multiMatch(
498  pattern, explicitly_excluded, match_index, pattern_record);
499  }
500 
501  /// Returns true if the entire string matches the provided regular
502  /// expression, false otherwise. See UT_Regex.
503  bool matchRegex(const char *expr) const;
504 
505  int toInt() const
506  { return UT_StringWrap(c_str()).toInt(); }
507  fpreal toFloat() const
508  { return UT_StringWrap(c_str()).toFloat(); }
509 
510  /// Determine if string can be seen as a single floating point number
511  unsigned isFloat(int skip_spaces = 0, int loose = 0) const
512  { return UT_StringWrap(c_str()).isFloat(skip_spaces, loose); }
513  /// Determine if string can be seen as a single integer number
514  unsigned isInteger(int skip_spaces = 0) const
515  { return UT_StringWrap(c_str()).isInteger(skip_spaces); }
516 
518  operator const char *() const
519  { return c_str(); }
520 
522  const char *buffer() const
523  { return c_str(); }
524  // We are always non-null by definition!
526  const char *nonNullBuffer() const
527  { return c_str(); }
528 
529  /// Iterators
530  typedef const char * const_iterator;
531 
534  { return c_str(); }
537  { return begin() + length(); }
538 
539 
540  /// Converts the contents of this UT_String to a std::string. Since
541  /// we are never null this is easy
543  { return std::string(c_str(), length()); }
544 
546  void swap( UT_StringRef &other )
547  {
548  UTswap(myData, other.myData);
549  UTswap(myLength, other.myLength);
550  UTswap(myHash, other.myHash);
551  }
552 
553  /// Friend specialization of std::swap() to use UT_StringRef::swap()
554  friend void swap(UT_StringRef& a, UT_StringRef& b) { a.swap(b); }
555 
557  bool isstring() const
558  {
559  // This test works for both references and inline.
560  return !isSentinelOrNullPtr(myData);
561  }
562 
564  bool
565  hasNonSpace() const
566  {
567  const char *ptr = c_str();
568  for (exint i = 0, n = length(); i < n; ++i)
569  if (!SYSisspace(ptr[i]))
570  return true;
571  return false;
572  }
573 
574  /// Find the location of the character @c (or -1 if not found)
576  exint
577  findCharIndex(char c) const
578  {
579  const void *ptr = ::memchr(c_str(), c, length());
580  return ptr ? (const char *)ptr - c_str() : -1;
581  }
582 
583  /// Find the first location of any of the characters in the @c str passed in
585  exint
586  findCharIndex(const char *str) const
587  {
588  if (UTisstring(str))
589  {
590  const char *found_char = strpbrk(c_str(), str);
591  if (found_char)
592  return found_char - c_str();
593  }
594  return -1;
595  }
596 
597  /// Find the location of the character @c (or -1 if not found)
599  exint
600  findCharIndex(char c, exint start_offset) const
601  {
602  if (start_offset < length())
603  {
604  const void *ptr = ::memchr(c_str()+start_offset, c,
605  length()-start_offset);
606  if (ptr)
607  return (const char *)ptr - c_str();
608  }
609  return -1;
610  }
611 
612  /// Find the first location of any of the characters in the @c str passed in
614  exint
615  findCharIndex(const char *str, exint start_offset) const
616  {
617  if (UTisstring(str) && start_offset < length())
618  {
619  const char *found_char = strpbrk(c_str()+start_offset, str);
620  if (found_char)
621  return found_char - c_str();
622  }
623  return -1;
624  }
625 
627  exint
628  lastCharIndex(char c, int occurrence_number = 1) const
629  {
630  exint n = length();
631  const void *start = SYSmemrchr(c_str(), c, n);
632  while (start)
633  {
634  n = (const char *)start - c_str();
635  occurrence_number--;
636  if (occurrence_number <= 0)
637  return n;
638  start = (n == 0) ? nullptr : SYSmemrchr(c_str(), c, n-1);
639  }
640  return -1;
641  }
642 
643  /// Count the number of times the character @c c occurs
645  exint
646  countChar(char c) const
647  {
648  exint start = 0;
649  exint len = length();
650  exint count = 0;
651  while (start < len)
652  {
653  const void *ptr = memchr(c_str() + start, c, len-start);
654  if (!ptr)
655  break;
656  count++;
657  start = (const char *)ptr - c_str() + 1;
658  }
659  return count;
660  }
661 
663  void clear()
664  {
665  if (myData)
666  {
667  Holder *h = getHolder();
668  if (!isSentinelOrNullPtr(h))
669  h->decref();
670  init();
671  }
672  }
673 
675  const char *c_str() const
676  {
677  UT_ASSERT_P(!isSentinel());
678  Holder *holder = getHolder();
679  if (!isSentinelOrNullPtr(holder))
680  return holder->c_str();
681  // Harden empty strings.
682  if (isSentinelOrNullPtr(myDataIfChars))
683  {
684 #if SYS_IS_GCC_GE(6, 0) && !SYS_IS_GCC_GE(8, 0)
685  // We need to do this to fix bad GCC warning:
686  // offset outside bounds of constant string
687  const char *volatile empty = "";
688  return empty;
689 #else
690  return "";
691 #endif
692  }
693  return myDataIfChars;
694  }
696  const char* data() const
697  {
698  return c_str();
699  }
700 
701  exint length() const
702  {
703  Holder *holder = getHolder();
704 
705  if (!isSentinelOrNullPtr(holder))
706  return holder->length();
707 
708  if (myLength >= 0)
709  return myLength;
710 
711  exint result = -myLength;
712  result <<= 31;
713  result += myHash;
714 
715  return result;
716  }
717 
718  bool isEmpty() const
719  {
720  return length() == 0;
721  }
722 
723  unsigned hash() const
724  {
725  Holder *holder = getHolder();
726  if (!isSentinelOrNullPtr(holder))
727  return holder->hash();
728  if (myLength >= 0)
729  {
730  if (!myLength)
731  return 0;
732  if (!myHash)
733  {
734  myHash = hash_string(c_str(), length());
735  }
736  return myHash;
737  }
738  return hash_string(c_str(), length());
739  }
740 
741  /// Make a light weight reference to the source.
742  /// Caller must make sure src lives for the duration of this object,
743  /// and any objects value copied from this!
744  void reference(const char *src)
745  {
746  Holder *h = getHolder();
747  if (!isSentinelOrNullPtr(h))
748  h->decref();
749 
750  if (!src || !*src)
751  {
752  init();
753  }
754  else
755  {
756  myDataIfChars = src;
757 
758  exint len = ::strlen(src);
759  if (len >= (((exint)1) << 31))
760  {
761  myLength = -(len >> 31);
762  myHash = len & (0x7fffffff);
763  }
764  else
765  {
766  myLength = len;
767  myHash = 0;
768  }
769  }
770  }
771  /// Fast reference that takes the length of the string.
772  /// This is NOT a string view, the string must actually null terminate
773  /// at the given length or later functions will be confused.
775  {
776  Holder *h = getHolder();
777  if (!isSentinelOrNullPtr(h))
778  h->decref();
779 
780  if (!src || length <= 0)
781  {
782  UT_ASSERT(length == 0);
783  init();
784  }
785  else
786  {
787  UT_ASSERT_P(!src[length]);
788  myDataIfChars = src;
789 
790  if (length >= (((exint)1) << 31))
791  {
792  myLength = -(length >> 31);
793  myHash = length & (0x7fffffff);
794  }
795  else
796  {
797  myLength = length;
798  myHash = 0;
799  }
800  }
801  }
802 
803  int64 getMemoryUsage(bool inclusive) const
804  {
805  int64 mem = inclusive ? sizeof(*this) : 0;
806 
807  const Holder *holder = getHolder();
808  if (!isSentinelOrNullPtr(holder))
809  mem += holder->getMemoryUsage(true);
810  return mem;
811  }
812 
813  // This hash function does not look for null termination, but
814  // instead goes directly for the length.
816  static unsigned hash_string(const char *str, exint len)
817  {
818  return SYSstring_hash(str, len);
819  }
820 
822 
823  /// A version of trimSpace() that only removes leading and following spaces
824  /// from a string, leaving any between words intact.
825  bool trimBoundingSpace();
826 
827  /// trimSpace() will remove all space characters (leading and following)
828  /// from a string. If the string consists of multiple words, the words
829  /// will be collapsed. To keep a single space between words, pass in true.
830  /// The function returns true if space was trimmed.
831  bool trimSpace(bool leave_single_space_between_words = false);
832 
833  /// Convert the string into a valid C style variable name.
834  /// All non-alpha numerics will be converted to _.
835  /// If the first letter is a digit, it is prefixed with an _.
836  /// If the string is already valid, the string itself is returned.
837  /// Note that this does NOT force the name to be non-zero in length.
838  /// The safechars parameter is a string containing extra characters
839  /// that should be considered safe. These characters are not
840  /// converted to underscores.
842  UT_StringRef forceValidVariableName(const char *safechars = nullptr) const;
843 
844  /// Convert to lower case. If the string is already lower case, the string
845  /// itself is returned.
847  UT_StringRef toLower() const;
848  /// Convert to upper case. If the string is already upper case, the string
849  /// itsef is returned.
851  UT_StringRef toUpper() const;
852 
853  /// Often people reflexively use this from UT_String days to
854  /// this increases code compataibility.
855  void harden(const char *src);
856 
857  // Steals the given string, gaining ownership of it.
858  // Will be freed by this when the reference count hits zero.
859  void adoptFromMalloc(const char *str, exint length=-1)
860  {
861  clear();
862 
863  if (length == 0 || !str)
864  return;
865  else
866  {
867  if (length < 0)
868  {
869  length = ::strlen(str);
870  if (length == 0)
871  return;
872  }
873  Holder *h = Holder::buildFromData(str, length, STORE_MALLOC);
874  h->incref();
875  myLength = 0;
876  myData = h;
877  }
878  }
879  void adoptFromNew(const char *str, exint length=-1)
880  {
881  clear();
882 
883  if (length == 0 || !str)
884  return;
885  else
886  {
887  if (length < 0)
888  {
889  length = ::strlen(str);
890  if (length == 0)
891  return;
892  }
893  Holder *h = Holder::buildFromData(str, length, STORE_NEW);
894  h->incref();
895  myLength = 0;
896  myData = h;
897  }
898  }
900  {
901  if (!str.isstring())
902  {
903  clear();
904  return;
905  }
906  // We want to steal from always deep strings as well.
907  // We will erase the data in the source string!
908  str.harden();
909 
910  // Clear after harden in case str refers to us!
911  clear();
912 
913  Holder *h = Holder::build(str.myData, STORE_MALLOC);
914  h->incref();
915  myLength = 0;
916  myData = h;
917 
918  str.myData = 0;
919  str.myIsReference = true;
920  // Leave always deep as it was.
921  }
922 
923  // Extracts a string from ourself of the given allocation mode.
924  // The result can be freed with that allocation mode.
925  // Will always clear myself afterwards. This will return our
926  // own string without copying if reference count is 1.
927  // Will return 0 for empty strings.
928  char *stealAsMalloc();
929 
930  // Tests to see if UT_StringLit's memory layout is the same
931  static bool verifyStringLit();
932 
933  /// Does a "smart" string compare which will sort based on numbered names.
934  /// That is "text20" is bigger than "text3". In a strictly alphanumeric
935  /// comparison, this would not be the case.
937  {
938  bool operator()(const UT_StringRef &s1, const UT_StringRef &s2) const
939  {
940  return UT_String::compareNumberedString(s1.c_str(), s2.c_str()) < 0;
941  }
942  };
943 
944  /// Save string to binary stream.
945  void saveBinary(std::ostream &os) const
946  { UT_StringWrap(c_str()).saveBinary(os); }
947 
948  /// Save string to ASCII stream. This will add double quotes and escape to
949  /// the stream if necessary (empty string or contains spaces).
950  void saveAscii(std::ostream &os) const
951  { UT_StringWrap(c_str()).saveAscii(os); }
952 
953 private:
954  void init()
955  {
956  myData = nullptr;
957  myLength = 0;
958  myHash = 0;
959  }
960 
961  void copy(const UT_StringRef &s)
962  {
963  myData = s.myData;
964  myLength = s.myLength;
965  myHash = s.myHash;
966  }
967 
969  Holder *getHolder() const
970  {
971  if (!myLength)
972  return myDataIfHolder;
973  return NULL;
974  }
975 
976  // This union makes viewing in a debugger much easier.
977  union {
978  const void *myData;
979  const char *myDataIfChars;
981  };
982  int myLength;
983  mutable int myHash;
984 
985  /// This operator saves the string to the stream via the string's
986  /// saveAscii() method, protecting any whitespace (by adding quotes),
987  /// backslashes or quotes in the string.
988  friend UT_API std::ostream &operator<<(std::ostream &os, const UT_StringRef &d);
989  friend UT_API UT_OStream &operator<<(UT_OStream &os, const UT_StringRef &d);
990 
991  // UT_StringHolder needs to be a friend class so that the
992  // UT_StringHolder(const UT_StringRef &) constructor can access myHash and
993  // getHolder() for the UT_StringRef that is passed in.
994  friend class UT_StringHolder;
995 
996  static constexpr uintptr_t SENTINEL_DATA = 1;
997  static constexpr uint32 SENTINEL_HASH = 0xdeadbeef;
998 
999  template<typename T>
1000  static SYS_FORCE_INLINE bool isSentinelOrNullPtr(const T *p)
1001  {
1002  return uintptr_t(p) <= SENTINEL_DATA;
1003  }
1004 };
1005 
1007 {
1008  return str.hash();
1009 }
1010 
1011 /// A holder for a string, which stores the length and caches the hash value.
1012 /// The lifetime of the string is >= the lifetime of the UT_StringHolder.
1014 {
1015 public:
1016  /// UT_StringHolder can be constructed with UT_StringHolder::REFERENCE to
1017  /// create a shallow reference to the const char *.
1018  enum UT_StringReferenceType { REFERENCE };
1019 
1022  : UT_StringRef()
1023  {
1024  }
1025 
1026  /// Will make a copy of the provided string.
1028  UT_StringHolder(const char *str)
1029  {
1030  if (UTisstring(str))
1031  {
1032  Holder *h = Holder::build(str, STORE_INLINE);
1033  h->incref();
1034  myLength = 0;
1035  myDataIfHolder = h;
1036  }
1037  }
1038 
1039  /// Will make a shallow reference.
1042  : UT_StringRef(str)
1043  {
1044  }
1045 
1046  /// Will make a copy of the provided string.
1049  {
1050  if (data && length > 0)
1051  {
1052  Holder *h = Holder::buildFromData(data, length, STORE_INLINE);
1053  h->incref();
1054  myLength = 0;
1055  myDataIfHolder = h;
1056  }
1057  }
1058 
1059  // Prohibit accidents when converting from UT_String like:
1060  // myStringHolder(buffer, /*deep*/true)
1061  UT_StringHolder(const char *data, bool bad) = delete;
1062 
1063  // Add back explicit conversions for the length parameter
1066  : UT_StringHolder(data, exint(length)) { }
1069  : UT_StringHolder(data, exint(length)) { }
1072  : UT_StringHolder(data, exint(length)) { }
1073 #if defined(MBSD)
1075  UT_StringHolder(const char *data, size_t length)
1076  : UT_StringHolder(data, exint(length)) { }
1078  UT_StringHolder(const char *data, ptrdiff_t length)
1079  : UT_StringHolder(data, exint(length)) { }
1080 #endif
1081 
1082  /// Will make a copy of the provided string.
1085  {
1086  if (str.size())
1087  {
1088  const char *s = str.c_str();
1089  Holder *h = Holder::buildFromData(s, str.length(), STORE_INLINE);
1090  h->incref();
1091  myLength = 0;
1092  myDataIfHolder = h;
1093  }
1094  }
1095 
1096  /// This will make a shallow reference to the contents of the string.
1099  : UT_StringRef(str)
1100  {
1101  }
1102 
1103  /// Will make a copy of the provided string.
1104  UT_StringHolder(const UT_WorkBuffer &str);
1105 
1106  /// This will make a shallow reference to the contents of the string.
1109  : UT_StringRef(str)
1110  {
1111  }
1112 
1113  /// Will make a copy of the provided string.
1116  {
1117  *this = UT_StringHolder(str.buffer());
1118  }
1119 
1120  /// This will make a shallow reference to the contents of the string.
1123  : UT_StringRef(str)
1124  {
1125  }
1126 
1127  /// Will make a copy of the provided string.
1128  UT_StringHolder(const UT_StringView &sv);
1129 
1130  /// Makes a shallow reference to the contents of the UT_StringRef.
1133  : UT_StringRef(ref)
1134  {
1135  }
1136 
1137  /// Makes a deep copy of the provided UT_StringRef.
1138  /// This constructor is not marked explicit since we often want this
1139  /// conversion (e.g. when inserting a UT_StringRef into a UT_StringMap, as
1140  /// with the const char* constructor).
1142 
1143  /// Construct as a sentinel value
1144  SYS_FORCE_INLINE explicit
1146  : UT_StringRef(sentinel)
1147  {
1148  }
1149 
1150  /// Makes a copy of the provided string.
1153  : UT_StringRef(str)
1154  {
1155  }
1156 
1157  /// Move constructor. Steals the working data from the original.
1160  : UT_StringRef(std::move(a))
1161  {
1162  }
1163 
1164  /// Move constructor. Steals the data from the work buffer.
1165  UT_StringHolder(UT_WorkBuffer &&buf) noexcept;
1166 
1167  /// Makes a bit-wise copy of the string and adjust the reference count.
1170  {
1172  return *this;
1173  }
1174 
1175  /// Move the contents of about-to-be-destructed string
1176  /// s to this string.
1179  {
1180  UT_StringRef::operator=(std::move(s));
1181  return *this;
1182  }
1183 
1184  /// Move the contents buffer into this string holder.
1186 
1188  void swap(UT_StringHolder &other)
1189  {
1190  UT_StringRef::swap(other);
1191  }
1192 
1194  void swap(UT_StringRef &other)
1195  {
1196  UT_StringRef::swap(other);
1197  // harden ourselves like UT_StringHolder::operator=(UT_StringRef&)
1198  Holder *h = getHolder();
1199  if (!isSentinelOrNullPtr(h))
1200  return; // already a holder
1201  if (!isSentinelOrNullPtr(myDataIfChars))
1202  {
1203  exint len = (myLength >= 0) ? myLength
1204  : (exint(-myLength) << 31) + myHash;
1205  h = Holder::buildFromData(myDataIfChars, len, STORE_INLINE, myHash);
1206  h->incref();
1207  myLength = 0;
1208  myData = h;
1209  }
1210  }
1211 
1212  /// Friend specialization of std::swap() to use UT_StringHolder::swap()
1213  /// @{
1214  friend void swap(UT_StringHolder& a, UT_StringRef& b) { a.swap(b); }
1215  friend void swap(UT_StringHolder& a, UT_StringHolder& b) { a.swap(b); }
1216  /// @}
1217 
1218  /// In some functions it's nice to be able to return a const-reference to a
1219  /// UT_StringHolder. However, in error cases, you likely want to return an
1220  /// empty string. This would mean that you'd have to return a real
1221  /// UT_StringHolder (not a const reference). This static lets you return a
1222  /// reference to an empty string.
1224 
1226 
1227  /// Format a string using the same formatting codes as @c UTformat.
1228  template<typename... Args>
1229  size_t format(const char *fmt, const Args &...args)
1230  {
1231  clear();
1232 
1233  using namespace UT::Format;
1234  Writer w;
1236  size_t nb_needed = f.format(w, fmt, {args...});
1237 
1238  auto h = Holder::buildBuffer(nb_needed, STORE_MALLOC);
1239  h->incref();
1240  myLength = 0;
1241  myData = h;
1242 
1243  w.setBuffer(h->bufferNC(), nb_needed);
1244  f.format(w, fmt, {args...});
1245  h->bufferNC()[nb_needed] = '\0';
1246 
1247  return nb_needed;
1248  }
1249 
1250  /// Format a string using the same formatting codes as @c UTprintf.
1251  template<typename... Args>
1252  size_t sprintf(const char *fmt, const Args &...args)
1253  {
1254  clear();
1255 
1256  using namespace UT::Format;
1257  Writer w;
1259  size_t nb_needed = f.printf(w, fmt, {args...});
1260 
1261  auto h = Holder::buildBuffer(nb_needed, STORE_MALLOC);
1262  h->incref();
1263  myLength = 0;
1264  myData = h;
1265 
1266  w.setBuffer(h->bufferNC(), nb_needed);
1267  f.printf(w, fmt, {args...});
1268  h->bufferNC()[nb_needed] = '\0';
1269 
1270  return nb_needed;
1271  }
1272 
1273  /// Replace all occurrences of 'find' with 'replacement'.
1274  /// Returns number of replacements.
1275  int substitute(const char *find, const char *replacement, bool all = true)
1276  {
1277  UT_String s(buffer());
1278  int n = s.substitute(find, replacement, all);
1279  if (n > 0)
1280  adoptFromString(s);
1281  return n;
1282  }
1283 
1284  /// Load string from stream. Use is.eof() to check eof status
1285  bool load(UT_IStream &is)
1286  {
1287  UT_String s;
1288  if (s.load(is))
1289  {
1290  adoptFromString(s);
1291  return true;
1292  }
1293  return false;
1294  }
1295 
1296 protected:
1297  friend UT_StringHolder UT::Literal::operator"" _sh(
1298  const char *s, std::size_t const length);
1299  friend UT_StringHolder operator"" _UTsh(
1300  const char *s, std::size_t const length);
1301  friend UT_API std::istream &operator>>(std::istream& is, UT_StringHolder& s);
1302 
1303  /// A marker enum to use this constructor.
1304  enum UT_StringLiteralType { LITERAL };
1305 
1306  /// Only accepts string literals. Since there's no way to guarantee that
1307  /// a const char * argument is a string literal, we do this through the
1308  /// use of user-defined literal and *only* provide this constructor to our
1309  /// user-defined literal operator.
1311  {
1312  if (str && length)
1313  {
1314  myDataIfChars = str;
1315  myLength = length;
1316  // As of C++14, user defined literals don't support constexpr so
1317  // this hash computation here is actually done at run-time except
1318  // for in some cases where the compiler (clang?) is able to
1319  // optimize this. Therefore, disable this to avoid extraneous hash
1320  // computation in cases where we just want to use "foo"_sh to avoid
1321  // heap allocation but never use its hash.
1322  // Use UT_StringLit if you want to get compile time hashes
1323 #if 0
1324  myHash = SYSstring_hash_literal(str);
1325 #else
1326  myHash = 0;
1327 #endif
1328  }
1329  }
1330 };
1331 
1332 UT_EXTERN_TEMPLATE(UT_Array<UT_StringHolder>); // requires #include "UT_Array.h"
1333 
1334 /// Convert a UT_StringRef into a UT_StringHolder that is a shallow reference.
1336 {
1337  SYS_STATIC_ASSERT(sizeof(UT_StringRef) == sizeof(UT_StringHolder));
1338  return reinterpret_cast<const UT_StringHolder &>(ref);
1339 }
1340 
1341 /// Convert a UT_StringRef into a UT_StringHolder that is a shallow reference,
1342 /// and also precompute the hash. Use this for string literals
1343 /// that will be used repeatedly in hash tables.
1345 {
1346  SYS_STATIC_ASSERT(sizeof(UT_StringRef) == sizeof(UT_StringHolder));
1347  ref.hash();
1348  return reinterpret_cast<const UT_StringHolder &>(ref);
1349 }
1350 
1353 {
1354  SYS_STATIC_ASSERT(sizeof(UT_StringHolder) == sizeof(*this));
1355  return reinterpret_cast<const UT_StringHolder &>(*this);
1356 }
1357 
1360 {
1361  SYS_STATIC_ASSERT(sizeof(UT_StringRef) == sizeof(*this));
1362  return reinterpret_cast<const UT_StringRef &>(*this);
1363 }
1364 
1365 SYS_FORCE_INLINE size_t tbb_hasher(const UT_StringRef &s) { return s.hash(); }
1366 SYS_FORCE_INLINE size_t tbb_hasher(const UT_StringHolder &s) { return s.hash(); }
1367 
1368 /// A user-defined string literal to construct UT_StringHolder objects.
1369 /// E.g:
1370 /// @code
1371 /// auto lit = "This is my UT_StringHolder literal"_sh;
1372 /// @endcode
1373 namespace UT { inline namespace Literal {
1374 SYS_FORCE_INLINE UT_StringHolder operator"" _sh(const char *s, std::size_t const length)
1375 {
1376  return UT_StringHolder(UT_StringHolder::LITERAL, s, length);
1377 }
1378 } }
1379 
1380 /// A user-defined literal in the global namespace. Uglier, but allows the use
1381 /// of UT_StringHolder UDLs in headers.
1382 SYS_FORCE_INLINE UT_StringHolder operator"" _UTsh(const char *s, std::size_t const length)
1383 {
1384  return UT_StringHolder(UT_StringHolder::LITERAL, s, length);
1385 }
1386 
1387 
1388 namespace std
1389 {
1390  template<>
1391  struct hash<UT_StringRef>
1392  {
1393  size_t operator()(const UT_StringRef &s) const
1394  {
1395  return s.hash();
1396  }
1397  };
1398  template<>
1399  struct hash<UT_StringHolder>
1400  {
1401  size_t operator()(const UT_StringHolder &s) const
1402  {
1403  return s.hash();
1404  }
1405  };
1406 }
1407 
1408 // For UT::ArraySet.
1409 namespace UT
1410 {
1411 template <typename T>
1412 struct DefaultClearer;
1413 
1414 template <>
1416 {
1417  static void clear(UT_StringHolder &v) { v.makeSentinel(); }
1418  static bool isClear(const UT_StringHolder &v) { return v.isSentinel(); }
1420  {
1421  new ((void *)p) UT_StringHolder(UT_StringRef::SENTINEL);
1422  }
1423  static const bool clearNeedsDestruction = false;
1424 };
1425 } // namespace UT
1426 
1427 #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
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)
const char * fcontain(const char *pattern, bool case_sensitive=true) const
GLenum src
Definition: glew.h:2410
int int32
Definition: SYS_Types.h:39
GLenum GLint ref
Definition: glew.h:1845
SYS_FORCE_INLINE exint findCharIndex(char c, exint start_offset) const
Find the location of the character (or -1 if not found)
#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)
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()
bool isInteger(bool skip_spaces=false) const
Determine if string can be seen as a single integer number.
UT_StringLiteralType
A marker enum to use this constructor.
SYS_FORCE_INLINE void clear()
HALF_EXPORT std::istream & operator>>(std::istream &is, half &h)
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:136
bool isEmpty() const
static void clear(UT_StringHolder &v)
int64 exint
Definition: SYS_Types.h:125
SYS_FORCE_INLINE UT_StringRef(const UT_StringRef &s)
Shares a reference with the source.
unsigned multiMatch(const char *pattern, bool case_sensitive=true, const char *separators=", ", bool *explicitly_excluded=0, int *match_index=0, ut_PatternRecord *pattern_record=NULL) const
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
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)
SYS_FORCE_INLINE UT_StringRef(UT_StringRef &&s) noexcept
Move constructor. Steals the working data from the original.
bool operator!=(const char *s) const
SYS_FORCE_INLINE bool hasNonSpace() const
const GLdouble * v
Definition: glew.h:1391
unsigned multiMatch(const UT_StringMMPattern &pattern, bool *explicitly_excluded=0, int *match_index=0, ut_PatternRecord *pattern_record=NULL) const
#define UT_ASSERT_MSG_P(ZZ,...)
Definition: UT_Assert.h:137
Format
Definition: oidn.hpp:29
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.
UT_EXTERN_TEMPLATE(UT_Array< UT_StringHolder >)
unsigned multiMatch(const char *pattern, bool case_sensitive, char separator) 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 const char * data() const
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.
const char * buffer() const
Definition: UT_String.h:506
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
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_StringHolder(const std::string &str)
Will make a copy of the provided string.
bool operator==(const UT_StringRef &s) 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: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
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
const char * findWord(const char *word) const
SYS_FORCE_INLINE const UT_StringHolder & UTmakeUnsafeRef(const UT_StringRef &ref)
Convert a UT_StringRef into a UT_StringHolder that is a shallow reference.
#define SYS_FORCE_INLINE
Definition: SYS_Inline.h:45
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
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.
#define SYS_PRAGMA_DISABLE_FREE_NONHEAP_OBJECT()
Definition: SYS_Pragma.h:117
SYS_FORCE_INLINE UT_StringHolder(UT_StringHolder &&a) noexcept
Move constructor. Steals the working data from the original.
long long int64
Definition: SYS_Types.h:116
#define SYS_NO_DISCARD_RESULT
Definition: SYS_Compiler.h:93
static SYS_FORCE_INLINE unsigned hash_string(const char *str, exint len)
SYS_FORCE_INLINE const char * c_str() const
SYS_FORCE_INLINE bool isSentinel() const
SYS_FORCE_INLINE constexpr const char * data() const
int spaceship(const UT_StringRef &k) 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 constexpr const char * c_str() const
bool operator<=(const UT_StringRef &k) const
const char * findWord(const char *word) const
bool operator<(const UT_StringRef &k) const
bool operator!=(const UT_StringRef &s) const
GLuint start
Definition: glew.h:1253
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
bool isFloat(bool skip_spaces=false, bool loose=false, bool allow_underscore=false) const
Determine if string can be seen as a single floating point number.
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
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)
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.
fpreal64 fpreal
Definition: SYS_Types.h:277
bool multiMatch(const char *pattern, bool case_sensitive, char separator) const
SYS_FORCE_INLINE exint lastCharIndex(char c, int occurrence_number=1) const
bool operator()(const UT_StringRef &s1, const UT_StringRef &s2) const
int SYSstrcasecmp(const char *a, const char *b)
Definition: SYS_String.h:227
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
GLdouble GLdouble GLdouble r
Definition: glew.h:1406
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.
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.
unsigned int uint32
Definition: SYS_Types.h:40
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:711
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
unsigned match(const char *pattern, bool case_sensitive=true) 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
bool startsWith(const UT_StringView &prefix, bool case_sensitive=true) const
bool startsWith(const UT_StringView &pfx, bool case_sense=true) const
Imported from UT_String.
GLenum GLuint GLsizei const GLchar * buf
Definition: glew.h:2580
#define SYSmin(a, b)
Definition: SYS_Math.h:1527
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
bool endsWith(const UT_StringView &suffix, bool case_sensitive=true) 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:59
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
GLenum GLsizei len
Definition: glew.h:7752
const char * fcontain(const char *pattern, bool case_sensitive=true) const
Definition: UT_String.h:1008
SYS_FORCE_INLINE void swap(UT_StringRef &other)