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  }
695 
696  exint length() const
697  {
698  Holder *holder = getHolder();
699 
700  if (!isSentinelOrNullPtr(holder))
701  return holder->length();
702 
703  if (myLength >= 0)
704  return myLength;
705 
706  exint result = -myLength;
707  result <<= 31;
708  result += myHash;
709 
710  return result;
711  }
712 
713  bool isEmpty() const
714  {
715  return length() == 0;
716  }
717 
718  unsigned hash() const
719  {
720  Holder *holder = getHolder();
721  if (!isSentinelOrNullPtr(holder))
722  return holder->hash();
723  if (myLength >= 0)
724  {
725  if (!myLength)
726  return 0;
727  if (!myHash)
728  {
729  myHash = hash_string(c_str(), length());
730  }
731  return myHash;
732  }
733  return hash_string(c_str(), length());
734  }
735 
736  /// Make a light weight reference to the source.
737  /// Caller must make sure src lives for the duration of this object,
738  /// and any objects value copied from this!
739  void reference(const char *src)
740  {
741  Holder *h = getHolder();
742  if (!isSentinelOrNullPtr(h))
743  h->decref();
744 
745  if (!src || !*src)
746  {
747  init();
748  }
749  else
750  {
751  myDataIfChars = src;
752 
753  exint len = ::strlen(src);
754  if (len >= (((exint)1) << 31))
755  {
756  myLength = -(len >> 31);
757  myHash = len & (0x7fffffff);
758  }
759  else
760  {
761  myLength = len;
762  myHash = 0;
763  }
764  }
765  }
766  /// Fast reference that takes the length of the string.
767  /// This is NOT a string view, the string must actually null terminate
768  /// at the given length or later functions will be confused.
770  {
771  Holder *h = getHolder();
772  if (!isSentinelOrNullPtr(h))
773  h->decref();
774 
775  if (!src || length <= 0)
776  {
777  UT_ASSERT(length == 0);
778  init();
779  }
780  else
781  {
782  UT_ASSERT_P(!src[length]);
783  myDataIfChars = src;
784 
785  if (length >= (((exint)1) << 31))
786  {
787  myLength = -(length >> 31);
788  myHash = length & (0x7fffffff);
789  }
790  else
791  {
792  myLength = length;
793  myHash = 0;
794  }
795  }
796  }
797 
798  int64 getMemoryUsage(bool inclusive) const
799  {
800  int64 mem = inclusive ? sizeof(*this) : 0;
801 
802  const Holder *holder = getHolder();
803  if (!isSentinelOrNullPtr(holder))
804  mem += holder->getMemoryUsage(true);
805  return mem;
806  }
807 
808  // This hash function does not look for null termination, but
809  // instead goes directly for the length.
811  static unsigned hash_string(const char *str, exint len)
812  {
813  return SYSstring_hash(str, len);
814  }
815 
817 
818  /// A version of trimSpace() that only removes leading and following spaces
819  /// from a string, leaving any between words intact.
820  bool trimBoundingSpace();
821 
822  /// trimSpace() will remove all space characters (leading and following)
823  /// from a string. If the string consists of multiple words, the words
824  /// will be collapsed. To keep a single space between words, pass in true.
825  /// The function returns true if space was trimmed.
826  bool trimSpace(bool leave_single_space_between_words = false);
827 
828  /// Convert the string into a valid C style variable name.
829  /// All non-alpha numerics will be converted to _.
830  /// If the first letter is a digit, it is prefixed with an _.
831  /// If the string is already valid, the string itself is returned.
832  /// Note that this does NOT force the name to be non-zero in length.
833  /// The safechars parameter is a string containing extra characters
834  /// that should be considered safe. These characters are not
835  /// converted to underscores.
837  UT_StringRef forceValidVariableName(const char *safechars = nullptr) const;
838 
839  /// Convert to lower case. If the string is already lower case, the string
840  /// itself is returned.
842  UT_StringRef toLower() const;
843  /// Convert to upper case. If the string is already upper case, the string
844  /// itsef is returned.
846  UT_StringRef toUpper() const;
847 
848  /// Often people reflexively use this from UT_String days to
849  /// this increases code compataibility.
850  void harden(const char *src);
851 
852  // Steals the given string, gaining ownership of it.
853  // Will be freed by this when the reference count hits zero.
854  void adoptFromMalloc(const char *str, exint length=-1)
855  {
856  clear();
857 
858  if (length == 0 || !str)
859  return;
860  else
861  {
862  if (length < 0)
863  {
864  length = ::strlen(str);
865  if (length == 0)
866  return;
867  }
868  Holder *h = Holder::buildFromData(str, length, STORE_MALLOC);
869  h->incref();
870  myLength = 0;
871  myData = h;
872  }
873  }
874  void adoptFromNew(const char *str, exint length=-1)
875  {
876  clear();
877 
878  if (length == 0 || !str)
879  return;
880  else
881  {
882  if (length < 0)
883  {
884  length = ::strlen(str);
885  if (length == 0)
886  return;
887  }
888  Holder *h = Holder::buildFromData(str, length, STORE_NEW);
889  h->incref();
890  myLength = 0;
891  myData = h;
892  }
893  }
895  {
896  if (!str.isstring())
897  {
898  clear();
899  return;
900  }
901  // We want to steal from always deep strings as well.
902  // We will erase the data in the source string!
903  str.harden();
904 
905  // Clear after harden in case str refers to us!
906  clear();
907 
908  Holder *h = Holder::build(str.myData, STORE_MALLOC);
909  h->incref();
910  myLength = 0;
911  myData = h;
912 
913  str.myData = 0;
914  str.myIsReference = true;
915  // Leave always deep as it was.
916  }
917 
918  // Extracts a string from ourself of the given allocation mode.
919  // The result can be freed with that allocation mode.
920  // Will always clear myself afterwards. This will return our
921  // own string without copying if reference count is 1.
922  // Will return 0 for empty strings.
923  char *stealAsMalloc();
924 
925  // Tests to see if UT_StringLit's memory layout is the same
926  static bool verifyStringLit();
927 
928  /// Does a "smart" string compare which will sort based on numbered names.
929  /// That is "text20" is bigger than "text3". In a strictly alphanumeric
930  /// comparison, this would not be the case.
932  {
933  bool operator()(const UT_StringRef &s1, const UT_StringRef &s2) const
934  {
935  return UT_String::compareNumberedString(s1.c_str(), s2.c_str()) < 0;
936  }
937  };
938 
939  /// Save string to binary stream.
940  void saveBinary(std::ostream &os) const
941  { UT_StringWrap(c_str()).saveBinary(os); }
942 
943  /// Save string to ASCII stream. This will add double quotes and escape to
944  /// the stream if necessary (empty string or contains spaces).
945  void saveAscii(std::ostream &os) const
946  { UT_StringWrap(c_str()).saveAscii(os); }
947 
948 private:
949  void init()
950  {
951  myData = nullptr;
952  myLength = 0;
953  myHash = 0;
954  }
955 
956  void copy(const UT_StringRef &s)
957  {
958  myData = s.myData;
959  myLength = s.myLength;
960  myHash = s.myHash;
961  }
962 
964  Holder *getHolder() const
965  {
966  if (!myLength)
967  return myDataIfHolder;
968  return NULL;
969  }
970 
971  // This union makes viewing in a debugger much easier.
972  union {
973  const void *myData;
974  const char *myDataIfChars;
976  };
977  int myLength;
978  mutable int myHash;
979 
980  /// This operator saves the string to the stream via the string's
981  /// saveAscii() method, protecting any whitespace (by adding quotes),
982  /// backslashes or quotes in the string.
983  friend UT_API std::ostream &operator<<(std::ostream &os, const UT_StringRef &d);
984  friend UT_API UT_OStream &operator<<(UT_OStream &os, const UT_StringRef &d);
985 
986  // UT_StringHolder needs to be a friend class so that the
987  // UT_StringHolder(const UT_StringRef &) constructor can access myHash and
988  // getHolder() for the UT_StringRef that is passed in.
989  friend class UT_StringHolder;
990 
991  static constexpr uintptr_t SENTINEL_DATA = 1;
992  static constexpr uint32 SENTINEL_HASH = 0xdeadbeef;
993 
994  template<typename T>
995  static SYS_FORCE_INLINE bool isSentinelOrNullPtr(const T *p)
996  {
997  return uintptr_t(p) <= SENTINEL_DATA;
998  }
999 };
1000 
1002 {
1003  return str.hash();
1004 }
1005 
1006 /// A holder for a string, which stores the length and caches the hash value.
1007 /// The lifetime of the string is >= the lifetime of the UT_StringHolder.
1009 {
1010 public:
1011  /// UT_StringHolder can be constructed with UT_StringHolder::REFERENCE to
1012  /// create a shallow reference to the const char *.
1013  enum UT_StringReferenceType { REFERENCE };
1014 
1017  : UT_StringRef()
1018  {
1019  }
1020 
1021  /// Will make a copy of the provided string.
1023  UT_StringHolder(const char *str)
1024  {
1025  if (UTisstring(str))
1026  {
1027  Holder *h = Holder::build(str, STORE_INLINE);
1028  h->incref();
1029  myLength = 0;
1030  myDataIfHolder = h;
1031  }
1032  }
1033 
1034  /// Will make a shallow reference.
1037  : UT_StringRef(str)
1038  {
1039  }
1040 
1041  /// Will make a copy of the provided string.
1044  {
1045  if (data && length > 0)
1046  {
1047  Holder *h = Holder::buildFromData(data, length, STORE_INLINE);
1048  h->incref();
1049  myLength = 0;
1050  myDataIfHolder = h;
1051  }
1052  }
1053 
1054  // Prohibit accidents when converting from UT_String like:
1055  // myStringHolder(buffer, /*deep*/true)
1056  UT_StringHolder(const char *data, bool bad) = delete;
1057 
1058  // Add back explicit conversions for the length parameter
1061  : UT_StringHolder(data, exint(length)) { }
1064  : UT_StringHolder(data, exint(length)) { }
1067  : UT_StringHolder(data, exint(length)) { }
1068 #if defined(MBSD)
1070  UT_StringHolder(const char *data, size_t length)
1071  : UT_StringHolder(data, exint(length)) { }
1073  UT_StringHolder(const char *data, ptrdiff_t length)
1074  : UT_StringHolder(data, exint(length)) { }
1075 #endif
1076 
1077  /// Will make a copy of the provided string.
1080  {
1081  if (str.size())
1082  {
1083  const char *s = str.c_str();
1084  Holder *h = Holder::buildFromData(s, str.length(), STORE_INLINE);
1085  h->incref();
1086  myLength = 0;
1087  myDataIfHolder = h;
1088  }
1089  }
1090 
1091  /// This will make a shallow reference to the contents of the string.
1094  : UT_StringRef(str)
1095  {
1096  }
1097 
1098  /// Will make a copy of the provided string.
1099  UT_StringHolder(const UT_WorkBuffer &str);
1100 
1101  /// This will make a shallow reference to the contents of the string.
1104  : UT_StringRef(str)
1105  {
1106  }
1107 
1108  /// Will make a copy of the provided string.
1111  {
1112  *this = UT_StringHolder(str.buffer());
1113  }
1114 
1115  /// This will make a shallow reference to the contents of the string.
1118  : UT_StringRef(str)
1119  {
1120  }
1121 
1122  /// Will make a copy of the provided string.
1123  UT_StringHolder(const UT_StringView &sv);
1124 
1125  /// Makes a shallow reference to the contents of the UT_StringRef.
1128  : UT_StringRef(ref)
1129  {
1130  }
1131 
1132  /// Makes a deep copy of the provided UT_StringRef.
1133  /// This constructor is not marked explicit since we often want this
1134  /// conversion (e.g. when inserting a UT_StringRef into a UT_StringMap, as
1135  /// with the const char* constructor).
1137 
1138  /// Construct as a sentinel value
1139  SYS_FORCE_INLINE explicit
1141  : UT_StringRef(sentinel)
1142  {
1143  }
1144 
1145  /// Makes a copy of the provided string.
1148  : UT_StringRef(str)
1149  {
1150  }
1151 
1152  /// Move constructor. Steals the working data from the original.
1155  : UT_StringRef(std::move(a))
1156  {
1157  }
1158 
1159  /// Move constructor. Steals the data from the work buffer.
1160  UT_StringHolder(UT_WorkBuffer &&buf) noexcept;
1161 
1162  /// Makes a bit-wise copy of the string and adjust the reference count.
1165  {
1167  return *this;
1168  }
1169 
1170  /// Move the contents of about-to-be-destructed string
1171  /// s to this string.
1174  {
1175  UT_StringRef::operator=(std::move(s));
1176  return *this;
1177  }
1178 
1179  /// Move the contents buffer into this string holder.
1181 
1183  void swap(UT_StringHolder &other)
1184  {
1185  UT_StringRef::swap(other);
1186  }
1187 
1189  void swap(UT_StringRef &other)
1190  {
1191  UT_StringRef::swap(other);
1192  // harden ourselves like UT_StringHolder::operator=(UT_StringRef&)
1193  Holder *h = getHolder();
1194  if (!isSentinelOrNullPtr(h))
1195  return; // already a holder
1196  if (!isSentinelOrNullPtr(myDataIfChars))
1197  {
1198  exint len = (myLength >= 0) ? myLength
1199  : (exint(-myLength) << 31) + myHash;
1200  h = Holder::buildFromData(myDataIfChars, len, STORE_INLINE, myHash);
1201  h->incref();
1202  myLength = 0;
1203  myData = h;
1204  }
1205  }
1206 
1207  /// Friend specialization of std::swap() to use UT_StringHolder::swap()
1208  /// @{
1209  friend void swap(UT_StringHolder& a, UT_StringRef& b) { a.swap(b); }
1210  friend void swap(UT_StringHolder& a, UT_StringHolder& b) { a.swap(b); }
1211  /// @}
1212 
1213  /// In some functions it's nice to be able to return a const-reference to a
1214  /// UT_StringHolder. However, in error cases, you likely want to return an
1215  /// empty string. This would mean that you'd have to return a real
1216  /// UT_StringHolder (not a const reference). This static lets you return a
1217  /// reference to an empty string.
1219 
1221 
1222  /// Format a string using the same formatting codes as @c UTformat.
1223  template<typename... Args>
1224  size_t format(const char *fmt, const Args &...args)
1225  {
1226  clear();
1227 
1228  using namespace UT::Format;
1229  Writer w;
1231  size_t nb_needed = f.format(w, fmt, {args...});
1232 
1233  auto h = Holder::buildBuffer(nb_needed, STORE_MALLOC);
1234  h->incref();
1235  myLength = 0;
1236  myData = h;
1237 
1238  w.setBuffer(h->bufferNC(), nb_needed);
1239  f.format(w, fmt, {args...});
1240  h->bufferNC()[nb_needed] = '\0';
1241 
1242  return nb_needed;
1243  }
1244 
1245  /// Format a string using the same formatting codes as @c UTprintf.
1246  template<typename... Args>
1247  size_t sprintf(const char *fmt, const Args &...args)
1248  {
1249  clear();
1250 
1251  using namespace UT::Format;
1252  Writer w;
1254  size_t nb_needed = f.printf(w, fmt, {args...});
1255 
1256  auto h = Holder::buildBuffer(nb_needed, STORE_MALLOC);
1257  h->incref();
1258  myLength = 0;
1259  myData = h;
1260 
1261  w.setBuffer(h->bufferNC(), nb_needed);
1262  f.printf(w, fmt, {args...});
1263  h->bufferNC()[nb_needed] = '\0';
1264 
1265  return nb_needed;
1266  }
1267 
1268  /// Replace all occurrences of 'find' with 'replacement'.
1269  /// Returns number of replacements.
1270  int substitute(const char *find, const char *replacement, bool all = true)
1271  {
1272  UT_String s(buffer());
1273  int n = s.substitute(find, replacement, all);
1274  if (n > 0)
1275  adoptFromString(s);
1276  return n;
1277  }
1278 
1279  /// Load string from stream. Use is.eof() to check eof status
1280  bool load(UT_IStream &is)
1281  {
1282  UT_String s;
1283  if (s.load(is))
1284  {
1285  adoptFromString(s);
1286  return true;
1287  }
1288  return false;
1289  }
1290 
1291 protected:
1292  friend UT_StringHolder UT::Literal::operator"" _sh(
1293  const char *s, std::size_t const length);
1294  friend UT_StringHolder operator"" _UTsh(
1295  const char *s, std::size_t const length);
1296  friend UT_API std::istream &operator>>(std::istream& is, UT_StringHolder& s);
1297 
1298  /// A marker enum to use this constructor.
1299  enum UT_StringLiteralType { LITERAL };
1300 
1301  /// Only accepts string literals. Since there's no way to guarantee that
1302  /// a const char * argument is a string literal, we do this through the
1303  /// use of user-defined literal and *only* provide this constructor to our
1304  /// user-defined literal operator.
1306  {
1307  if (str && length)
1308  {
1309  myDataIfChars = str;
1310  myLength = length;
1311  // As of C++14, user defined literals don't support constexpr so
1312  // this hash computation here is actually done at run-time except
1313  // for in some cases where the compiler (clang?) is able to
1314  // optimize this. Therefore, disable this to avoid extraneous hash
1315  // computation in cases where we just want to use "foo"_sh to avoid
1316  // heap allocation but never use its hash.
1317  // Use UT_StringLit if you want to get compile time hashes
1318 #if 0
1319  myHash = SYSstring_hash_literal(str);
1320 #else
1321  myHash = 0;
1322 #endif
1323  }
1324  }
1325 };
1326 
1327 UT_EXTERN_TEMPLATE(UT_Array<UT_StringHolder>); // requires #include "UT_Array.h"
1328 
1329 /// Convert a UT_StringRef into a UT_StringHolder that is a shallow reference.
1331 {
1332  SYS_STATIC_ASSERT(sizeof(UT_StringRef) == sizeof(UT_StringHolder));
1333  return reinterpret_cast<const UT_StringHolder &>(ref);
1334 }
1335 
1336 /// Convert a UT_StringRef into a UT_StringHolder that is a shallow reference,
1337 /// and also precompute the hash. Use this for string literals
1338 /// that will be used repeatedly in hash tables.
1340 {
1341  SYS_STATIC_ASSERT(sizeof(UT_StringRef) == sizeof(UT_StringHolder));
1342  ref.hash();
1343  return reinterpret_cast<const UT_StringHolder &>(ref);
1344 }
1345 
1348 {
1349  SYS_STATIC_ASSERT(sizeof(UT_StringHolder) == sizeof(*this));
1350  return reinterpret_cast<const UT_StringHolder &>(*this);
1351 }
1352 
1355 {
1356  SYS_STATIC_ASSERT(sizeof(UT_StringRef) == sizeof(*this));
1357  return reinterpret_cast<const UT_StringRef &>(*this);
1358 }
1359 
1360 SYS_FORCE_INLINE size_t tbb_hasher(const UT_StringRef &s) { return s.hash(); }
1361 SYS_FORCE_INLINE size_t tbb_hasher(const UT_StringHolder &s) { return s.hash(); }
1362 
1363 /// A user-defined string literal to construct UT_StringHolder objects.
1364 /// E.g:
1365 /// @code
1366 /// auto lit = "This is my UT_StringHolder literal"_sh;
1367 /// @endcode
1368 namespace UT { inline namespace Literal {
1369 SYS_FORCE_INLINE UT_StringHolder operator"" _sh(const char *s, std::size_t const length)
1370 {
1371  return UT_StringHolder(UT_StringHolder::LITERAL, s, length);
1372 }
1373 } }
1374 
1375 /// A user-defined literal in the global namespace. Uglier, but allows the use
1376 /// of UT_StringHolder UDLs in headers.
1377 SYS_FORCE_INLINE UT_StringHolder operator"" _UTsh(const char *s, std::size_t const length)
1378 {
1379  return UT_StringHolder(UT_StringHolder::LITERAL, s, length);
1380 }
1381 
1382 
1383 namespace std
1384 {
1385  template<>
1386  struct hash<UT_StringRef>
1387  {
1388  size_t operator()(const UT_StringRef &s) const
1389  {
1390  return s.hash();
1391  }
1392  };
1393  template<>
1394  struct hash<UT_StringHolder>
1395  {
1396  size_t operator()(const UT_StringHolder &s) const
1397  {
1398  return s.hash();
1399  }
1400  };
1401 }
1402 
1403 // For UT::ArraySet.
1404 namespace UT
1405 {
1406 template <typename T>
1407 struct DefaultClearer;
1408 
1409 template <>
1411 {
1412  static void clear(UT_StringHolder &v) { v.makeSentinel(); }
1413  static bool isClear(const UT_StringHolder &v) { return v.isSentinel(); }
1415  {
1416  new ((void *)p) UT_StringHolder(UT_StringRef::SENTINEL);
1417  }
1418  static const bool clearNeedsDestruction = false;
1419 };
1420 } // namespace UT
1421 
1422 #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 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:710
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:1515
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:999
SYS_FORCE_INLINE void swap(UT_StringRef &other)