19 #ifndef __UT_StringHolder_h__
20 #define __UT_StringHolder_h__
49 namespace UT {
inline namespace Literal {
74 , myHash(SYSstring_hash_inner(str, 0))
122 : myRefCount(0), myStorageMode(STORE_INLINE),
123 myHash(0), myLength(0), myData(0)
127 static Holder *build(
const char *str,
129 static Holder *buildFromData(
const char *str,
133 static Holder *buildBuffer(
139 if (myStorageMode == STORE_INLINE)
140 return myDataIfInline;
151 if (myRefCount.add(-1) == 0)
155 switch (myStorageMode)
192 int64 mem = inclusive ?
sizeof(*this) : 0;
194 switch (myStorageMode)
201 "If a Holder is STORE_INLINE, it *really* can't be a "
202 "member variable, because the size isn't determined "
204 mem += myLength + 1 -
sizeof(
const char *);
216 char *bufferNC()
const
218 if (myStorageMode == STORE_INLINE)
236 char myDataIfInline[
sizeof(
const char *)];
271 const char *
s = str.c_str();
272 fastReferenceWithStrlen(s, str.length());
292 Holder *sh = s.getHolder();
293 if (!isSentinelOrNullPtr(sh))
311 if (!isSentinelOrNullPtr(h))
323 , myHash(SENTINEL_HASH)
330 return uintptr_t(myData) == SENTINEL_DATA && myHash == SENTINEL_HASH && !myLength;
337 if (!isSentinelOrNullPtr(h))
339 myData = (
const void*)SENTINEL_DATA;
341 myHash = SENTINEL_HASH;
349 if (isSentinelOrNullPtr(h))
357 Holder *sh = s.getHolder();
360 if (!isSentinelOrNullPtr(sh))
362 if (!isSentinelOrNullPtr(th))
392 return (uintptr_t(myData) == SENTINEL_DATA) == (uintptr_t(s.
myData) == SENTINEL_DATA);
393 return ::memcmp(c_str(), s.
c_str(), tl) == 0;
403 if (myDataIfChars == s)
408 return ::strcmp(c_str(), s) == 0;
427 int r = memcmp(c_str(), k.
c_str(), minlen);
432 return length() > minlen ? 1 : 0;
436 {
return spaceship(k) < 0; }
438 {
return spaceship(k) <= 0; }
440 {
return spaceship(k) > 0; }
442 {
return spaceship(k) >= 0; }
444 bool ignore_case=
false)
const
450 bool ignore_case=
false)
const
451 {
return compare(str, ignore_case) == 0; }
477 char separator)
const
480 pattern, case_sensitive, separator);
483 const char *separators =
", ",
484 bool *explicitly_excluded = 0,
485 int *match_index = 0,
486 ut_PatternRecord *pattern_record=NULL)
const
489 pattern, case_sensitive, separators, explicitly_excluded,
490 match_index, pattern_record);
493 bool *explicitly_excluded = 0,
494 int *match_index = 0,
495 ut_PatternRecord *pattern_record=NULL)
const
498 pattern, explicitly_excluded, match_index, pattern_record);
503 bool matchRegex(
const char *expr)
const;
511 unsigned isFloat(
int skip_spaces = 0,
int loose = 0)
const
518 operator const char *()
const
549 UTswap(myLength, other.myLength);
550 UTswap(myHash, other.myHash);
560 return !isSentinelOrNullPtr(myData);
567 const char *
ptr = c_str();
569 if (!SYSisspace(ptr[i]))
579 const void *
ptr = ::memchr(c_str(), c,
length());
580 return ptr ? (
const char *)ptr - c_str() : -1;
590 const char *found_char = strpbrk(c_str(), str);
592 return found_char - c_str();
602 if (start_offset <
length())
604 const void *
ptr = ::memchr(c_str()+start_offset, c,
607 return (
const char *)ptr - c_str();
619 const char *found_char = strpbrk(c_str()+start_offset, str);
621 return found_char - c_str();
631 const void *
start = SYSmemrchr(c_str(), c, n);
634 n = (
const char *)start - c_str();
636 if (occurrence_number <= 0)
638 start = (n == 0) ?
nullptr : SYSmemrchr(c_str(),
c, n-1);
653 const void *
ptr = memchr(c_str() + start, c, len-start);
657 start = (
const char *)ptr - c_str() + 1;
668 if (!isSentinelOrNullPtr(h))
678 Holder *holder = getHolder();
679 if (!isSentinelOrNullPtr(holder))
680 return holder->
c_str();
682 if (isSentinelOrNullPtr(myDataIfChars))
684 #if SYS_IS_GCC_GE(6, 0) && !SYS_IS_GCC_GE(8, 0)
687 const char *
volatile empty =
"";
693 return myDataIfChars;
698 Holder *holder = getHolder();
700 if (!isSentinelOrNullPtr(holder))
720 Holder *holder = getHolder();
721 if (!isSentinelOrNullPtr(holder))
722 return holder->
hash();
742 if (!isSentinelOrNullPtr(h))
754 if (len >= (((
exint)1) << 31))
756 myLength = -(len >> 31);
757 myHash = len & (0x7fffffff);
772 if (!isSentinelOrNullPtr(h))
775 if (!src || length <= 0)
785 if (length >= (((
exint)1) << 31))
787 myLength = -(length >> 31);
788 myHash = length & (0x7fffffff);
800 int64 mem = inclusive ?
sizeof(*this) : 0;
802 const Holder *holder = getHolder();
803 if (!isSentinelOrNullPtr(holder))
813 return SYSstring_hash(str, len);
820 bool trimBoundingSpace();
826 bool trimSpace(
bool leave_single_space_between_words =
false);
837 UT_StringRef forceValidVariableName(
const char *safechars =
nullptr)
const;
850 void harden(
const char *
src);
868 Holder *
h = Holder::buildFromData(str,
length, STORE_MALLOC);
908 Holder *
h = Holder::build(str.myData, STORE_MALLOC);
914 str.myIsReference =
true;
923 char *stealAsMalloc();
926 static bool verifyStringLit();
959 myLength = s.myLength;
964 Holder *getHolder()
const
967 return myDataIfHolder;
991 static constexpr uintptr_t SENTINEL_DATA = 1;
992 static constexpr
uint32 SENTINEL_HASH = 0xdeadbeef;
997 return uintptr_t(p) <= SENTINEL_DATA;
1045 if (data && length > 0)
1071 : UT_StringHolder(data,
exint(length)) { }
1074 : UT_StringHolder(data,
exint(length)) { }
1083 const char *
s = str.c_str();
1194 if (!isSentinelOrNullPtr(h))
1196 if (!isSentinelOrNullPtr(myDataIfChars))
1198 exint len = (myLength >= 0) ? myLength
1199 : (
exint(-myLength) << 31) + myHash;
1223 template<
typename... Args>
1231 size_t nb_needed =
f.format(
w, fmt, {args...});
1233 auto h = Holder::buildBuffer(nb_needed, STORE_MALLOC);
1238 w.setBuffer(
h->bufferNC(), nb_needed);
1239 f.format(
w, fmt, {args...});
1240 h->bufferNC()[nb_needed] =
'\0';
1246 template<
typename... Args>
1254 size_t nb_needed =
f.printf(
w, fmt, {args...});
1256 auto h = Holder::buildBuffer(nb_needed, STORE_MALLOC);
1261 w.setBuffer(
h->bufferNC(), nb_needed);
1262 f.printf(
w, fmt, {args...});
1263 h->bufferNC()[nb_needed] =
'\0';
1293 const char *
s, std::size_t
const length);
1295 const char *
s, std::size_t
const length);
1309 myDataIfChars = str;
1319 myHash = SYSstring_hash_literal(str);
1368 namespace UT {
inline namespace Literal {
1406 template <
typename T>
1407 struct DefaultClearer;
1418 static const bool clearNeedsDestruction =
false;
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
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
SYS_FORCE_INLINE const char * nonNullBuffer() const
#define SYS_STATIC_ASSERT(expr)
const char * fcontain(const char *pattern, bool case_sensitive=true) const
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()
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
SYS_FORCE_INLINE UT_StringHolder(UT_StringLiteralType, const char *str, size_t length)
FMT_CONSTEXPR auto begin(const C &c) -> decltype(c.begin())
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
GLboolean GLboolean GLboolean GLboolean a
SYS_FORCE_INLINE T * SYSconst_cast(const T *foo)
static void clear(UT_StringHolder &v)
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)
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)
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
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,...)
unsigned long long uint64
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)
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.
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)
SYS_FORCE_INLINE const_iterator end() const
void saveAscii(std::ostream &os) const
bool operator==(const BaseDimensions< T > &a, const BaseDimensions< Y > &b)
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
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.
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
int compare(const UT_StringRef &str, bool ignore_case=false) const
OIIO_FORCEINLINE const vint4 & operator+=(vint4 &a, const vint4 &b)
int64 getMemoryUsage(bool inclusive) 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
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.
GLubyte GLubyte GLubyte GLubyte w
SYS_FORCE_INLINE UT_StringRef()
GLuint GLsizei GLsizei * length
SYS_FORCE_INLINE UT_StringHolder & operator=(UT_StringHolder &&s)
void harden()
Take shallow copy and make it deep.
SYS_FORCE_INLINE void makeSentinel()
void saveAscii(std::ostream &os) const
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()
SYS_FORCE_INLINE UT_StringHolder(UT_StringHolder &&a) noexcept
Move constructor. Steals the working data from the original.
#define SYS_NO_DISCARD_RESULT
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
#define SYS_PRAGMA_POP_WARN()
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
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.
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
static int compareNumberedString(const char *s1, const char *s2, bool case_sensitive=true, bool allow_negatives=false)
static Holder * buildFromData(const char *str, exint len, StorageMode storage, int hash=0)
GLsizei const GLchar *const * string
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)
bool operator==(const UT_String &s) const
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.
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)
friend class UT_StringHolder
int64 getMemoryUsage(bool inclusive) const
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat s1
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)
GLdouble GLdouble GLdouble r
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
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.
void reference(const char *src)
GLenum const void GLuint GLint reference
getOption("OpenEXR.storage") storage
unsigned isInteger(int skip_spaces=0) const
Determine if string can be seen as a single integer number.
SYS_FORCE_INLINE constexpr const char * buffer() const
SYS_FORCE_INLINE void swap(UT_StringRef &other)
unsigned match(const char *pattern, bool case_sensitive=true) const
bool operator!=(const BaseDimensions< T > &a, const BaseDimensions< Y > &b)
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
SYS_FORCE_INLINE UT_StringHolder(const char *str)
Will make a copy of the provided string.
bool all(const vbool4 &v)
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
SYS_FORCE_INLINE T relaxedLoad() const
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
const char * fcontain(const char *pattern, bool case_sensitive=true) const
SYS_FORCE_INLINE void swap(UT_StringRef &other)