HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros 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_Format.h"
24 #include "UT_String.h"
25 #include "UT_StringView.h"
26 #include "UT_Swap.h"
27 
28 #include <SYS/SYS_AtomicInt.h>
29 #include <SYS/SYS_Inline.h>
30 #include <SYS/SYS_StaticAssert.h>
31 #include <SYS/SYS_Types.h>
32 
33 #include <stdlib.h>
34 
35 #include <functional>
36 
37 class UT_StringHolder;
38 class UT_WorkBuffer;
39 
40 // Forward declare the UDSL so that we can friend it inside of UT_StringHolder.
41 namespace UT { inline namespace Literal {
42 UT_StringHolder operator"" _sh(const char *s, std::size_t const length);
43 } }
44 
45 /// A holder for a string, which stores the length and caches the hash value.
46 /// A UT_StringRef does not necessarily own the string, and it is therefore not
47 /// safe to e.g. store a UT_StringRef in a container or member variable.
48 /// @see UT_StringHolder
49 /// @see UTmakeUnsafeRef
51 {
52 public:
53  typedef char value_type;
54 
56  {
60  STORE_INLINE
61  };
62 
63  class UT_API Holder
64  {
65  public:
67  : myRefCount(0), myStorageMode(STORE_INLINE),
68  myHash(0), myLength(0), myData(0)
69  {
70  }
71 
72  static Holder *build(const char *str,
74  static Holder *buildFromData(const char *str,
75  exint len,
77  int hash = 0);
78  static Holder *buildBuffer(
79  exint length,
81 
82  const char *c_str() const
83  {
84  if (myStorageMode == STORE_INLINE)
85  return myDataIfInline;
86 
87  return myData;
88  }
89 
90  void incref()
91  {
92  myRefCount.add(1);
93  }
94  void decref()
95  {
96  if (myRefCount.add(-1) == 0)
97  {
98  // We can't invoke delete as we were malloced.
99  // Further, we have custom behaviour on ownership!
100  switch (myStorageMode)
101  {
102  case STORE_EXTERNAL:
103  case STORE_INLINE:
104  // Do nothing.
105  break;
106  case STORE_NEW:
107  delete [] myData;
108  break;
109  case STORE_MALLOC:
110  if (myData)
111  free( (void*)SYSconst_cast(myData));
112  break;
113  }
114  free(this);
115  }
116  }
117 
118  exint length() const
119  {
120  return myLength;
121  }
122 
123  unsigned hash() const
124  {
125  if (!myHash)
126  {
127  myHash = hash_string(c_str(), length());
128  }
129  return myHash;
130  }
131 
132  int64 getMemoryUsage(bool inclusive) const
133  {
134  int64 mem = inclusive ? sizeof(*this) : 0;
135 
136  switch (myStorageMode)
137  {
138  case STORE_EXTERNAL:
139  // Nothing extra.
140  break;
141  case STORE_INLINE:
142  UT_ASSERT_MSG_P(inclusive,
143  "If a Holder is STORE_INLINE, it *really* can't be a "
144  "member variable, because the size isn't determined "
145  "at runtime.");
146  mem += myLength + 1 - sizeof(const char *);
147  break;
148  case STORE_NEW:
149  case STORE_MALLOC:
150  // External reference we own.
151  mem += myLength + 1;
152  break;
153  }
154  return mem;
155  }
156 
157  private:
158  char *bufferNC() const
159  {
160  if (myStorageMode == STORE_INLINE)
161  return SYSconst_cast(myDataIfInline);
162 
163  return SYSconst_cast(myData);
164  }
165 
166  friend class UT_StringHolder;
167  friend class UT_StringRef;
168 
169  private:
170  SYS_AtomicInt32 myRefCount;
171  StorageMode myStorageMode;
172  mutable int myHash;
173  exint myLength;
174 
175  // This union makes viewing in a debugger much easier.
176  union {
177  const char *myData;
178  char myDataIfInline[sizeof(const char *)];
179  };
180  };
181 
184  {
185  // Ensure that the union doesn't lead the compiler to do any
186  // funny business.
187  UT_ASSERT_COMPILETIME(sizeof(UT_StringRef) == sizeof(const void *) + 2*sizeof(int));
188 
189  ::memset(this, 0, sizeof(UT_StringRef));
190  }
191 
192  /// Will make a shallow reference.
194  UT_StringRef(const char *str)
195  {
196  // Empty, trivial!
197  ::memset(this, 0, sizeof(UT_StringRef));
198  if (UTisstring(str))
199  {
200  reference(str);
201  }
202  }
203 
204  /// This will make a shallow reference to the contents of the string.
207  {
208  const char *s = str.c_str();
209  ::memset(this, 0, sizeof(UT_StringRef));
210  if (UTisstring(s))
211  {
212  fastReferenceWithStrlen(s, str.length());
213  }
214  }
215 
216  /// This will make a shallow reference to the contents of the string.
217  UT_StringRef(const UT_WorkBuffer &str);
218 
219  /// This will make a shallow reference to the contents of the string.
222  {
223  ::memset(this, 0, sizeof(UT_StringRef));
224  if (str.isstring())
225  reference(str);
226  }
227 
228  /// Shares a reference with the source.
231  {
232  Holder *sh = s.getHolder();
233  if (sh)
234  sh->incref();
235  // Can now blindly copy.
236  ::memcpy(this, &s, sizeof(UT_StringRef));
237  }
238 
239  /// Move constructor. Steals the working data from the original.
242  {
243  ::memcpy(this, &s, sizeof(UT_StringRef));
244  ::memset(&s, 0, sizeof(UT_StringRef));
245  }
246 
249  {
250  Holder *h = getHolder();
251  if (h)
252  h->decref();
253  }
254 
255  /// Shares a reference with the source.
257  {
258  Holder *sh = s.getHolder();
259  Holder *th = getHolder();
260 
261  if (sh)
262  sh->incref();
263  if (th)
264  th->decref();
265  // Can now blindly copy.
266  ::memcpy(this, &s, sizeof(UT_StringRef));
267  return *this;
268  }
269 
270  /// Move the contents of about-to-be-destructed string
271  /// s to this string.
274  {
275  // Can just swap, since s is about to be destructed.
276  swap(s);
277  return *this;
278  }
279 
280  bool operator==(const UT_StringRef &s) const
281  {
282  // It is sensible to fast-path this based on myData!
283  // If our two pointers are equal, we either are pointing to
284  // the same Holder or to the same const char *, so are good
285  // to call it equal.
286  if (myData == s.myData)
287  return true;
288  exint tl = length();
289  exint sl = s.length();
290  if (tl != sl)
291  return false;
292  return ::memcmp(c_str(), s.c_str(), tl) == 0;
293  }
294  bool operator==(const char *s) const
295  {
296  // It is sensible to fast-path this based on myData!
297  // If our two pointers are equal, we either are pointing to
298  // the same Holder or to the same const char *, so are good
299  // to call it equal.
300  // We don't test for myData being a Holder because it should
301  // never alias a const char *.
302  if (myDataIfChars == s)
303  return true;
304  // Avoid comparison with null.
305  if (!s)
306  return !isstring();
307  return ::strcmp(c_str(), s) == 0;
308  }
309  bool operator==(const UT_String &s) const
310  { return operator==(s.buffer()); }
311 
312  bool operator!=(const UT_StringRef &s) const
313  { return !operator==(s); }
314  bool operator!=(const char *s) const
315  { return !operator==(s); }
316  bool operator!=(const UT_String &s) const
317  { return operator!=(s.buffer()); }
318 
319  bool operator<(const UT_StringRef &k) const
320  { return ::strcmp(c_str(), k.c_str()) < 0; }
321  bool operator<=(const UT_StringRef &k) const
322  { return ::strcmp(c_str(), k.c_str()) <= 0; }
323  bool operator>(const UT_StringRef &k) const
324  { return ::strcmp(c_str(), k.c_str()) > 0; }
325  bool operator>=(const UT_StringRef &k) const
326  { return ::strcmp(c_str(), k.c_str()) >= 0; }
327  int compare(const UT_StringRef &str,
328  bool ignore_case=false) const
329  { return ignore_case ?
330  SYSstrcasecmp(c_str(), str.c_str()) :
331  ::strcmp(c_str(), str.c_str()); }
332  bool equal(const UT_StringRef &str,
333  bool ignore_case=false) const
334  { return compare(str, ignore_case) == 0; }
335 
336  /// Test whether the string is defined or not
338  SYS_SAFE_BOOL operator bool() const { return isstring(); }
339 
340  /// Imported from UT_String.
341  bool startsWith(const char *prefix, bool case_sense = true,
342  exint len=-1) const
343  {
344  return UT_StringWrap(c_str()).startsWith(prefix, case_sense, len);
345  }
346  bool endsWith(const char *prefix, bool case_sense = true,
347  exint len=-1) const
348  {
349  return UT_StringWrap(c_str()).endsWith(prefix, case_sense, len);
350  }
351  unsigned multiMatch(const char *pattern,
352  int caseSensitive, char separator) const
353  { return UT_StringWrap(c_str()).multiMatch(pattern, caseSensitive, separator); }
354  unsigned multiMatch(const char *pattern, int caseSensitive = 1,
355  const char *separators = ", ",
356  bool *explicitlyExcluded = 0,
357  int *matchIndex = 0,
358  ut_PatternRecord *pattern_record=NULL) const
359  { return UT_StringWrap(c_str()).multiMatch(pattern, caseSensitive, separators, explicitlyExcluded, matchIndex, pattern_record); }
360  unsigned multiMatch(const UT_StringMMPattern &pattern,
361  bool *explicitlyExcluded = 0,
362  int *matchIndex = 0,
363  ut_PatternRecord *pattern_record=NULL) const
364  { return UT_StringWrap(c_str()).multiMatch(pattern, explicitlyExcluded, matchIndex, pattern_record); }
365 
366  int toInt() const
367  { return UT_StringWrap(c_str()).toInt(); }
368  fpreal toFloat() const
369  { return UT_StringWrap(c_str()).toFloat(); }
370 
371  /// Determine if string can be seen as a single floating point number
372  unsigned isFloat(int skip_spaces = 0, int loose = 0) const
373  { return UT_StringWrap(c_str()).isFloat(skip_spaces, loose); }
374  /// Determine if string can be seen as a single integer number
375  unsigned isInteger(int skip_spaces = 0) const
376  { return UT_StringWrap(c_str()).isInteger(skip_spaces); }
377 
379  operator const char *() const
380  { return c_str(); }
381 
383  const char *buffer() const
384  { return c_str(); }
385  // We are always non-null by definition!
387  const char *nonNullBuffer() const
388  { return c_str(); }
389 
390  /// Iterators
391  typedef const char * const_iterator;
392 
395  { return c_str(); }
398  { return begin() + length(); }
399 
400 
401  /// Converts the contents of this UT_String to a std::string. Since
402  /// we are never null this is easy
404  { return std::string(c_str(), length()); }
405 
407  void swap( UT_StringRef &other )
408  {
409  UTswap(myData, other.myData);
410  UTswap(myLength, other.myLength);
411  UTswap(myHash, other.myHash);
412  }
413 
415  bool isstring() const
416  {
417  // This test works for both references and inline.
418  return (myData != 0);
419  }
420 
422  bool
423  hasNonSpace() const
424  {
425  const char *ptr = c_str();
426  while (*ptr && SYSisspace(*ptr))
427  ptr++;
428  return (*ptr) ? true : false;
429  }
430 
432  int
433  findChar(char c) const
434  {
435  const char *ptr = c_str();
436  while (*ptr && *ptr != c)
437  ptr++;
438  return (*ptr) ? (ptr - c_str()) : -1;
439  }
440 
442  int
443  lastChar(char c, int occurance_number = 1) const
444  {
445  const char *ptr = c_str();
446  for (int i = myLength - 1; i > 0; --i)
447  {
448  if(c == ptr[i])
449  {
450  occurance_number--;
451  if(occurance_number <= 0)
452  return i;
453  }
454  }
455 
456  return -1;
457  }
458 
460  void clear()
461  {
462  if (myData)
463  {
464  Holder *h = getHolder();
465  if (h)
466  h->decref();
467  memset(this, 0, sizeof(UT_StringRef));
468  }
469  }
470 
472  const char *c_str() const
473  {
474  Holder *holder = getHolder();
475  if (holder)
476  return holder->c_str();
477  // Harden empty strings.
478  if (!myDataIfChars)
479  return "";
480  return myDataIfChars;
481  }
482 
483  exint length() const
484  {
485  Holder *holder = getHolder();
486 
487  if (holder)
488  return holder->length();
489 
490  if (myLength >= 0)
491  return myLength;
492 
493  exint result = -myLength;
494  result <<= 31;
495  result += myHash;
496 
497  return result;
498  }
499 
500  bool isEmpty() const
501  {
502  return length() == 0;
503  }
504 
505  unsigned hash() const
506  {
507  Holder *holder = getHolder();
508  if (holder)
509  return holder->hash();
510  if (myLength >= 0)
511  {
512  if (!myLength)
513  return 0;
514  if (!myHash)
515  {
516  myHash = hash_string(c_str(), length());
517  }
518  return myHash;
519  }
520  return hash_string(c_str(), length());
521  }
522 
523  /// Make a light weight reference to the source.
524  /// Caller must make sure src lives for the duration of this object,
525  /// and any objects value copied from this!
526  void reference(const char *src)
527  {
528  Holder *h = getHolder();
529  if (h)
530  h->decref();
531 
532  if (!src || !*src)
533  {
534  memset(this, 0, sizeof(UT_StringRef));
535  }
536  else
537  {
538  myDataIfChars = src;
539 
540  exint len = ::strlen(src);
541  if (len >= (((exint)1) << 31))
542  {
543  myLength = -(len >> 31);
544  myHash = len & (0x7fffffff);
545  }
546  else
547  {
548  myLength = len;
549  myHash = 0;
550  }
551  }
552  }
553  /// Fast reference that takes the length of the string.
554  /// This is NOT a string view, the string must actually null terminate
555  /// at the given length or later functions will be confused.
557  {
558  Holder *h = getHolder();
559  if (h)
560  h->decref();
561 
562  if (!src || length <= 0)
563  {
564  UT_ASSERT(length == 0);
565  memset(this, 0, sizeof(UT_StringRef));
566  }
567  else
568  {
569  UT_ASSERT_P(!src[length]);
570  myDataIfChars = src;
571 
572  if (length >= (((exint)1) << 31))
573  {
574  myLength = -(length >> 31);
575  myHash = length & (0x7fffffff);
576  }
577  else
578  {
579  myLength = length;
580  myHash = 0;
581  }
582  }
583  }
584 
585  int64 getMemoryUsage(bool inclusive) const
586  {
587  int64 mem = inclusive ? sizeof(*this) : 0;
588 
589  const Holder *holder = getHolder();
590  if (holder)
591  mem += holder->getMemoryUsage(true);
592  return mem;
593  }
594 
595  // This hash function does not look for null termination, but
596  // instead goes directly for the length.
598  static unsigned hash_string(const char *str, exint len)
599  {
600  return SYSstring_hash(str, len);
601  }
602 
603  UT_StringRef &operator+=(const UT_StringRef &src);
604 
605  /// A version of trimSpace() that only removes leading and following spaces
606  /// from a string, leaving any between words intact.
607  bool trimBoundingSpace();
608 
609  /// Convert to lower case. If the string is already lower case, the string
610  /// itself is returned.
611  UT_StringRef toLower() const;
612 
613  /// Often people reflexively use this from UT_String days to
614  /// this increases code compataibility.
615  void harden(const char *src);
616 
617  // Steals the given string, gaining ownership of it.
618  // Will be freed by this when the reference count hits zero.
619  void adoptFromMalloc(const char *str, exint length=-1)
620  {
621  clear();
622 
623  if (length == 0 || !UTisstring(str))
624  return;
625  else
626  {
627  if (length < 0)
628  length = ::strlen(str);
629  Holder *h = Holder::buildFromData(str, length, STORE_MALLOC);
630  h->incref();
631  myLength = 0;
632  myData = h;
633  }
634  }
635  void adoptFromNew(const char *str, exint length=-1)
636  {
637  clear();
638 
639  if (length == 0 || !UTisstring(str))
640  return;
641  else
642  {
643  if (length < 0)
644  length = ::strlen(str);
645  Holder *h = Holder::buildFromData(str, length, STORE_NEW);
646  h->incref();
647  myLength = 0;
648  myData = h;
649  }
650  }
652  {
653  if (!str.isstring())
654  {
655  clear();
656  return;
657  }
658  // We want to steal from always deep strings as well.
659  // We will erase the data in the source string!
660  str.harden();
661 
662  // Clear after harden in case str refers to us!
663  clear();
664 
665  Holder *h = Holder::build(str.myData, STORE_MALLOC);
666  h->incref();
667  myLength = 0;
668  myData = h;
669 
670  str.myData = 0;
671  str.myIsReference = true;
672  // Leave always deep as it was.
673  }
674 
675  // Extracts a string from ourself of the given allocation mode.
676  // The result can be freed with that allocation mode.
677  // Will always clear myself afterwards. This will return our
678  // own string without copying if reference count is 1.
679  // Will return 0 for empty strings.
680  char *stealAsMalloc();
681 
682  /// Does a "smart" string compare which will sort based on numbered names.
683  /// That is "text20" is bigger than "text3". In a strictly alphanumeric
684  /// comparison, this would not be the case.
686  {
687  bool operator()(const UT_StringRef &s1, const UT_StringRef &s2) const
688  {
689  return UT_String::compareNumberedString(s1.c_str(), s2.c_str()) < 0;
690  }
691  };
692 
693 private:
694 
696  Holder *getHolder() const
697  {
698  if (!myLength)
699  return myDataIfHolder;
700  return NULL;
701  }
702 
703  // This union makes viewing in a debugger much easier.
704  union {
705  const void *myData;
706  const char *myDataIfChars;
708  };
709  int myLength;
710  mutable int myHash;
711 
712  /// This operator saves the string to the stream via the string's
713  /// saveAscii() method, protecting any whitespace (by adding quotes),
714  /// backslashes or quotes in the string.
715  friend UT_API std::ostream &operator<<(std::ostream &os, const UT_StringRef &d);
716  friend UT_API UT_OStream &operator<<(UT_OStream &os, const UT_StringRef &d);
717 
718  // UT_StringHolder needs to be a friend class so that the
719  // UT_StringHolder(const UT_StringRef &) constructor can access myHash and
720  // getHolder() for the UT_StringRef that is passed in.
721  friend class UT_StringHolder;
722 };
723 
725 {
726  return str.hash();
727 }
728 
729 /// A holder for a string, which stores the length and caches the hash value.
730 /// The lifetime of the string is >= the lifetime of the UT_StringHolder.
732 {
733 public:
734  /// UT_StringHolder can be constructed with UT_StringHolder::REFERENCE to
735  /// create a shallow reference to the const char *.
736  enum UT_StringReferenceType { REFERENCE };
737 
740  : UT_StringRef()
741  {
742  }
743 
744  /// Will make a copy of the provided string.
746  UT_StringHolder(const char *str)
747  {
748  if (!UTisstring(str))
749  {
750  // Empty, trivial!
751  ::memset(this, 0, sizeof(UT_StringHolder));
752  }
753  else
754  {
755  Holder *h = Holder::build(str, STORE_INLINE);
756  h->incref();
757  myLength = 0;
758  myDataIfHolder = h;
759  }
760  }
761 
762  /// Will make a shallow reference.
765  : UT_StringRef(str)
766  {
767  }
768 
769  /// Will make a copy of the provided string.
772  {
773  if (!data || length <= 0)
774  {
775  UT_ASSERT(length == 0);
776  // Empty, trivial!
777  ::memset(this, 0, sizeof(UT_StringHolder));
778  }
779  else
780  {
781  Holder *h = Holder::buildFromData(data, length, STORE_INLINE);
782  h->incref();
783  myLength = 0;
784  myDataIfHolder = h;
785  }
786  }
787 
788  /// Will make a copy of the provided string.
791  {
792  const char *s = str.c_str();
793  if (!UTisstring(s))
794  {
795  ::memset(this, 0, sizeof(UT_StringHolder));
796  }
797  else
798  {
799  Holder *h = Holder::buildFromData(s, str.length(), STORE_INLINE);
800  h->incref();
801  myLength = 0;
802  myDataIfHolder = h;
803  }
804  }
805 
806  /// This will make a shallow reference to the contents of the string.
809  : UT_StringRef(str)
810  {
811  }
812 
813  /// Will make a copy of the provided string.
814  UT_StringHolder(const UT_WorkBuffer &str);
815 
816  /// This will make a shallow reference to the contents of the string.
819  : UT_StringRef(str)
820  {
821  }
822 
823  /// Will make a copy of the provided string.
826  {
827  *this = UT_StringHolder(str.buffer());
828  }
829 
830  /// This will make a shallow reference to the contents of the string.
833  : UT_StringRef(str)
834  {
835  }
836 
837  /// Will make a copy of the provided string.
840  {
841  if (sv.isEmpty())
842  ::memset(this, 0, sizeof(UT_StringHolder));
843  else
844  {
845  Holder *h = Holder::buildFromData(sv.begin(), sv.length(),
846  STORE_INLINE);
847  h->incref();
848  myLength = 0;
849  myDataIfHolder = h;
850  }
851  }
852 
853  /// Makes a shallow reference to the contents of the UT_StringRef.
856  : UT_StringRef(ref)
857  {
858  }
859 
860  /// Makes a deep copy of the provided UT_StringRef.
861  /// This constructor is not marked explicit since we often want this
862  /// conversion (e.g. when inserting a UT_StringRef into a UT_StringMap, as
863  /// with the const char* constructor).
865 
866  /// Makes a copy of the provided string.
869  : UT_StringRef(str)
870  {
871  }
872 
873  /// Move constructor. Steals the working data from the original.
876  : UT_StringRef(std::move(a))
877  {
878  }
879 
880  /// Makes a bit-wise copy of the string and adjust the reference count.
883  {
885  return *this;
886  }
887 
888  /// Move the contents of about-to-be-destructed string
889  /// s to this string.
892  {
893  UT_StringRef::operator=(std::move(s));
894  return *this;
895  }
896 
897  /// In some functions it's nice to be able to return a const-reference to a
898  /// UT_StringHolder. However, in error cases, you likely want to return an
899  /// empty string. This would mean that you'd have to return a real
900  /// UT_StringHolder (not a const reference). This static lets you return a
901  /// reference to an empty string.
903 
904  /// Format a string using the same formatting codes as @c UTformat.
905  template<typename... Args>
906  size_t format(const char *fmt, const Args &...args)
907  {
908  clear();
909 
910  using namespace UT::Format;
911  Writer w;
913  size_t nb_needed = f.format(w, fmt, {args...});
914 
915  auto h = Holder::buildBuffer(nb_needed, STORE_MALLOC);
916  h->incref();
917  myLength = 0;
918  myData = h;
919 
920  w.setBuffer(h->bufferNC(), nb_needed);
921  f.format(w, fmt, {args...});
922  h->bufferNC()[nb_needed] = '\0';
923 
924  return nb_needed;
925  }
926 
927  /// Format a string using the same formatting codes as @c UTprintf.
928  template<typename... Args>
929  size_t sprintf(const char *fmt, const Args &...args)
930  {
931  clear();
932 
933  using namespace UT::Format;
934  Writer w;
936  size_t nb_needed = f.printf(w, fmt, {args...});
937 
938  auto h = Holder::buildBuffer(nb_needed, STORE_MALLOC);
939  h->incref();
940  myLength = 0;
941  myData = h;
942 
943  w.setBuffer(h->bufferNC(), nb_needed);
944  f.printf(w, fmt, {args...});
945  h->bufferNC()[nb_needed] = '\0';
946 
947  return nb_needed;
948  }
949 
950 protected:
951  friend UT_StringHolder UT::Literal::operator"" _sh(
952  const char *s, std::size_t const length);
953  friend UT_StringHolder operator"" _UTsh(
954  const char *s, std::size_t const length);
955 
956  /// A marker enum to use this constructor.
957  enum UT_StringLiteralType { LITERAL };
958 
959  /// Only accepts string literals. Since there's no way to guarantee that
960  /// a const char * argument is a string literal, we do this through the
961  /// use of user-defined literal and *only* provide this constructor to our
962  /// user-defined literal operator.
964  {
965  if (str && length)
966  {
967  myDataIfChars = str;
968  myLength = length;
969  myHash = SYSstring_hash_literal(str);
970  }
971  else
972  {
973  ::memset(this, 0, sizeof(UT_StringHolder));
974  }
975  }
976 };
977 
978 /// Convert a UT_StringRef into a UT_StringHolder that is a shallow reference.
980 {
981  SYS_STATIC_ASSERT(sizeof(UT_StringRef) == sizeof(UT_StringHolder));
982  return reinterpret_cast<const UT_StringHolder &>(ref);
983 }
984 
985 /// Convert a UT_StringRef into a UT_StringHolder that is a shallow reference,
986 /// and also precompute the hash. Use this for string literals
987 /// that will be used repeatedly in hash tables.
989 {
990  SYS_STATIC_ASSERT(sizeof(UT_StringRef) == sizeof(UT_StringHolder));
991  ref.hash();
992  return reinterpret_cast<const UT_StringHolder &>(ref);
993 }
994 
995 SYS_FORCE_INLINE size_t tbb_hasher(const UT_StringRef &s) { return s.hash(); }
996 SYS_FORCE_INLINE size_t tbb_hasher(const UT_StringHolder &s) { return s.hash(); }
997 
998 /// A user-defined string literal to construct UT_StringHolder objects.
999 /// E.g:
1000 /// @code
1001 /// auto lit = "This is my UT_StringHolder literal"_sh;
1002 /// @endcode
1003 namespace UT { inline namespace Literal {
1004 SYS_FORCE_INLINE UT_StringHolder operator"" _sh(const char *s, std::size_t const length)
1005 {
1006  return UT_StringHolder(UT_StringHolder::LITERAL, s, length);
1007 }
1008 } }
1009 
1010 /// A user-defined literal in the global namespace. Uglier, but allows the use
1011 /// of UT_StringHolder UDLs in headers.
1012 SYS_FORCE_INLINE UT_StringHolder operator"" _UTsh(const char *s, std::size_t const length)
1013 {
1014  return UT_StringHolder(UT_StringHolder::LITERAL, s, length);
1015 }
1016 
1017 
1018 namespace std
1019 {
1020  template<>
1021  struct hash<UT_StringRef>
1022  {
1023  size_t operator()(const UT_StringRef &s) const
1024  {
1025  return s.hash();
1026  }
1027  };
1028  template<>
1029  struct hash<UT_StringHolder>
1030  {
1031  size_t operator()(const UT_StringHolder &s) const
1032  {
1033  return s.hash();
1034  }
1035  };
1036 }
1037 
1038 #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.
std::string toStdString() const
#define UT_ASSERT_COMPILETIME(expr)
Definition: UT_Assert.h:109
static Holder * build(const char *str, StorageMode storage)
void adoptFromString(UT_String &str)
SYS_FORCE_INLINE UT_StringHolder(const UT_StringHolder &str)
Makes a copy of the provided string.
SYS_FORCE_INLINE const_iterator begin() const
unsigned hash() const
SYS_FORCE_INLINE const char * nonNullBuffer() const
#define SYS_STATIC_ASSERT(expr)
unsigned multiMatch(const char *pattern, int caseSensitive, char separator) const
bool endsWith(const char *suffix, bool case_sensitive=true, exint len=-1) const
size_t operator()(const UT_StringRef &s) const
png_voidp s1
Definition: png.h:2193
void UTswap(T &a, T &b)
Definition: UT_Swap.h:35
SYS_FORCE_INLINE UT_StringHolder(UT_StringLiteralType, const char *str, size_t length)
SYS_FORCE_INLINE int findChar(char c) const
void swap(UT::ArraySet< Key, MULTI, MAX_LOAD_FACTOR_256, Clearer, Hash, KeyEqual > &a, UT::ArraySet< Key, MULTI, MAX_LOAD_FACTOR_256, Clearer, Hash, KeyEqual > &b)
Definition: UT_ArraySet.h:1561
SYS_FORCE_INLINE UT_StringHolder(const char *data, exint length)
Will make a copy of the provided string.
SYS_FORCE_INLINE UT_StringHolder()
UT_StringLiteralType
A marker enum to use this constructor.
SYS_FORCE_INLINE void clear()
GLsizei const GLchar *const * string
Definition: glcorearb.h:813
png_voidp ptr
Definition: png.h:2145
fpreal toFloat() const
int toInt() const
SYS_FORCE_INLINE T * SYSconst_cast(const T *foo)
Definition: SYS_Types.h:120
bool isEmpty() const
SYS_FORCE_INLINE UT_StringRef(const UT_StringRef &s)
Shares a reference with the source.
const_iterator begin() const
Returns a constant iterator pointing to the beginning of the string.
GLboolean GLboolean GLboolean GLboolean a
Definition: glcorearb.h:1221
bool startsWith(const char *prefix, bool case_sense=true, exint len=-1) const
Imported from UT_String.
SYS_FORCE_INLINE UT_StringRef & operator=(UT_StringRef &&s)
void adoptFromMalloc(const char *str, exint length=-1)
#define UT_API
Definition: UT_API.h:12
bool equal(const UT_StringRef &str, bool ignore_case=false) const
bool operator!=(const char *s) const
SYS_FORCE_INLINE bool hasNonSpace() const
unsigned multiMatch(const char *pattern, int caseSensitive=1, const char *separators=", ", bool *explicitlyExcluded=0, int *matchIndex=0, ut_PatternRecord *pattern_record=NULL) const
unsigned isInteger(int skip_spaces=0) const
Determine if string can be seen as a single integer number.
png_uint_32 i
Definition: png.h:2877
SYS_FORCE_INLINE size_t tbb_hasher(const UT_StringRef &s)
#define UT_ASSERT_P(ZZ)
Definition: UT_Assert.h:101
SYS_FORCE_INLINE const UT_StringHolder & UTmakeUnsafeRefHash(const UT_StringRef &ref)
fpreal toFloat() const
const void * myData
std::ostream & operator<<(std::ostream &ostr, const DataType &a)
Definition: DataType.h:133
SYS_FORCE_INLINE const_iterator end() const
bool operator==(const BaseDimensions< T > &a, const BaseDimensions< Y > &b)
Definition: Dimensions.h:137
UT_StringRef & operator=(const UT_StringRef &s)
Shares a reference with the source.
SYS_FORCE_INLINE UT_StringHolder(const UT_String &str)
Will make a copy of the provided string.
long long int64
Definition: SYS_Types.h:100
const char * buffer() const
Definition: UT_String.h:503
unsigned multiMatch(const char *pattern, int caseSensitive, char separator) const
A utility class to do read-only operations on a subset of an existing string.
Definition: UT_StringView.h:30
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)
GLfloat f
Definition: glcorearb.h:1925
SYS_FORCE_INLINE UT_StringRef(UT_StringRef &&s) SYS_NOEXCEPT
Move constructor. Steals the working data from the original.
SYS_FORCE_INLINE UT_StringHolder(const std::string &str)
Will make a copy of the provided string.
bool operator==(const UT_StringRef &s) const
int compare(const UT_StringRef &str, bool ignore_case=false) const
exint length() const
GLint ref
Definition: glcorearb.h:123
#define UT_ASSERT(ZZ)
Definition: UT_Assert.h:102
int64 getMemoryUsage(bool inclusive) const
#define SYS_SAFE_BOOL
Definition: SYS_Compiler.h:56
exint length() const
SYS_FORCE_INLINE const char * buffer() const
SYS_FORCE_INLINE UT_StringHolder(const UT_StringView &sv)
Will make a copy of the provided string.
int64 exint
Definition: SYS_Types.h:109
static const UT_StringHolder theEmptyString
bool operator>=(const UT_StringRef &k) const
SYS_FORCE_INLINE const UT_StringHolder & UTmakeUnsafeRef(const UT_StringRef &ref)
Convert a UT_StringRef into a UT_StringHolder that is a shallow reference.
#define SYS_FORCE_INLINE
Definition: SYS_Inline.h:45
SYS_FORCE_INLINE UT_StringRef()
SYS_FORCE_INLINE UT_StringHolder & operator=(UT_StringHolder &&s)
void harden()
Take shallow copy and make it deep.
Definition: UT_String.h:213
bool isEmpty() const
Returns true if the string is empty.
Definition: UT_StringView.h:76
static SYS_FORCE_INLINE unsigned hash_string(const char *str, exint len)
SYS_FORCE_INLINE const char * c_str() const
GLboolean * data
Definition: glcorearb.h:130
size_t format(const char *fmt, const Args &...args)
Format a string using the same formatting codes as UTformat.
SYS_FORCE_INLINE UT_StringHolder & operator=(const UT_StringHolder &s)
Makes a bit-wise copy of the string and adjust the reference count.
bool operator<=(const UT_StringRef &k) const
bool operator<(const UT_StringRef &k) const
bool operator!=(const UT_StringRef &s) const
void fastReferenceWithStrlen(const char *src, exint length)
SYS_FORCE_INLINE UT_StringHolder(UT_StringReferenceType, const UT_StringRef &ref)
Makes a shallow reference to the contents of the UT_StringRef.
static int compareNumberedString(const char *s1, const char *s2, bool case_sensitive=true, bool allow_negatives=false)
GLfloat GLfloat GLfloat GLfloat h
Definition: glcorearb.h:2001
static Holder * buildFromData(const char *str, exint len, StorageMode storage, int hash=0)
double fpreal
Definition: SYS_Types.h:263
png_voidp png_voidp s2
Definition: png.h:2193
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
#define UT_ASSERT_MSG_P(ZZ, MM)
Definition: UT_Assert.h:104
unsigned multiMatch(const UT_StringMMPattern &pattern, bool *explicitlyExcluded=0, int *matchIndex=0, ut_PatternRecord *pattern_record=NULL) const
SYS_FORCE_INLINE ~UT_StringRef()
size_t operator()(const UT_StringHolder &s) const
SYS_FORCE_INLINE bool UTisstring(const char *s)
Definition: UT_String.h:58
bool operator==(const UT_String &s) const
#define SYS_NOEXCEPT
Definition: SYS_Compiler.h:49
bool endsWith(const char *prefix, bool case_sense=true, exint len=-1) const
bool operator()(const UT_StringRef &s1, const UT_StringRef &s2) const
int SYSstrcasecmp(const char *a, const char *b)
Definition: SYS_String.h:224
friend class UT_StringHolder
int64 getMemoryUsage(bool inclusive) const
SYS_FORCE_INLINE UT_StringHolder(UT_StringReferenceType, const char *str)
Will make a shallow reference.
Type-safe formatting, modeled on the Python str.format function.
const char * const_iterator
Iterators.
SYS_FORCE_INLINE UT_StringRef(const char *str)
Will make a shallow reference.
void reference(const char *src)
exint length() const
Returns the length of the string in bytes.
Definition: UT_StringView.h:73
bool isstring() const
Definition: UT_String.h:689
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.
GLubyte GLubyte GLubyte GLubyte w
Definition: glcorearb.h:856
int toInt() const
bool operator!=(const BaseDimensions< T > &a, const BaseDimensions< Y > &b)
Definition: Dimensions.h:165
unsigned isFloat(int skip_spaces=0, int loose=0) const
Determine if string can be seen as a single floating point number.
unsigned hash() const
SYS_FORCE_INLINE int lastChar(char c, int occurance_number=1) const
SYS_FORCE_INLINE UT_StringHolder(UT_StringHolder &&a) SYS_NOEXCEPT
Move constructor. Steals the working data from the original.
SYS_FORCE_INLINE UT_StringHolder(const char *str)
Will make a copy of the provided string.
const char * c_str() const
const char * myDataIfChars
SYS_FORCE_INLINE UT_StringRef(const std::string &str)
This will make a shallow reference to the contents of the string.
unsigned isFloat(int skip_spaces=0, int loose=0) const
Determine if string can be seen as a single floating point number.
bool operator!=(const UT_String &s) const
SYS_FORCE_INLINE bool isstring() const
Holder * myDataIfHolder
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 startsWith(const char *prefix, bool case_sensitive=true, exint len=-1) const
GLuint GLsizei GLsizei * length
Definition: glcorearb.h:794
GLenum src
Definition: glcorearb.h:1792
SYS_FORCE_INLINE void swap(UT_StringRef &other)