13 #ifndef __UT_String_h__
14 #define __UT_String_h__
29 #if __cplusplus >= 202002L
41 #define strcasecmp stricmp
42 #define strncasecmp strnicmp
50 class ut_PatternRecord;
91 , myIsAlwaysDeep(false)
103 UT_String(
const char *str,
bool deep_copy,
int len = -1);
131 : myIsReference(false),
132 myIsAlwaysDeep(false)
133 { myData = strdup(str.c_str()); }
157 : myIsReference(false),
159 { myData = str ? strdup(str) :
nullptr; }
164 : myIsReference(false),
166 { myData = strdup(str.c_str()); }
181 , myIsReference(str.myIsReference)
182 , myIsAlwaysDeep(str.myIsAlwaysDeep)
184 str.myData =
nullptr;
185 str.myIsReference = !str.myIsAlwaysDeep;
191 myIsReference = str.myIsReference;
192 myIsAlwaysDeep = str.myIsAlwaysDeep;
193 str.myData =
nullptr;
194 str.myIsReference = !str.myIsAlwaysDeep;
202 myIsAlwaysDeep = deep;
203 if (deep && myIsReference)
205 if (myData !=
nullptr)
212 myIsReference =
false;
218 return myIsAlwaysDeep;
227 if (!myIsReference && myData)
229 myData = strdup(myData ? myData :
"");
230 myIsReference =
false;
233 void harden(
const char *
s,
int len = -1);
254 bool isHard()
const {
return !myIsReference; }
270 myData = strdup(myData ? myData :
"");
271 myIsReference =
true;
278 return strdup(myData ? myData :
"");
295 myIsReference =
false;
310 void saveAscii(std::ostream &os)
const { save(os,
false); }
314 void save(std::ostream &os,
bool binary)
const;
322 { *
this = (
const char *)
nullptr; }
326 void prepend(
const char *prefix);
327 void prepend(
char ch);
331 void append(
char ch);
334 void append(
const char *str,
exint len = -1);
339 void truncate(
exint len);
363 bool same = (str == myData);
367 int mylen = (
int)strlen(myData);
368 myData = (
char *)realloc(myData,
369 mylen+strlen(str)+1);
372 strcpy(&myData[mylen], str);
376 memcpy(myData + mylen, myData, mylen);
377 myData[mylen * 2] =
'\0';
386 *
this += (
const char *)str.myData;
392 int compare(
const char *str,
bool case_sensitive=
true)
const
396 if (myData ==
nullptr || str ==
nullptr)
398 if (myData)
return 1;
403 return strcmp(myData, str);
404 return strcasecmp(myData, str);
408 return compare(str.myData,case_sensitive);
412 bool equal(
const char *str,
bool case_sensitive=
true)
const
414 return compare(str,case_sensitive)==0;
418 return compare(str.myData,case_sensitive)==0;
422 return compare(str,case_sensitive)==0;
499 explicit operator bool()
const {
return isstring(); }
507 bool case_sensitive =
true,
508 bool allow_subst =
true)
const;
510 #if __cplusplus >= 202002L
511 template <std::same_as<const
char *> T>
512 operator T() const noexcept
513 {
return (
const char *)myData; }
515 operator const char *()
const
516 {
return (
const char *)myData; }
525 const char *
buffer()
const {
return myData; }
561 std::string toStdString()
const;
569 {
return (myData) ? (unsigned)strlen(myData) : 0; }
574 return (inclusive ?
sizeof(*
this) : 0)
575 + (!myIsReference ? (
length() + 1)*
sizeof(
char) : 0);
581 {
return myData ? strchr(myData, c) :
nullptr; }
589 {
return myData ? strpbrk(myData, str) :
nullptr; }
597 {
return myData ? strrchr(myData, c) :
nullptr; }
603 int countChar(
int c)
const;
606 int count(
const char *str,
bool case_sensitive =
true)
const;
608 char *findNonSpace();
609 const char *findNonSpace()
const;
610 const char *findWord(
const char *word)
const;
611 bool findString(
const char *str,
bool fullword,
612 bool usewildcards)
const;
613 int changeWord(
const char *from,
const char *to,
bool all =
true);
614 int changeString(
const char *from,
const char *to,
bool fullword);
615 int changeQuotedWord(
const char *from,
const char *to,
616 int quote =
'`',
bool all =
true);
618 int findLongestCommonSuffix(
const char *
with )
const;
628 bool isFloat(
bool skip_spaces =
false,
630 bool allow_underscore =
false)
const;
632 bool isInteger(
bool skip_spaces =
false)
const;
638 for (ptr=myData; *
ptr; ptr++)
639 *ptr = (
char)toupper(*ptr);
645 for (ptr=myData; *
ptr; ptr++)
646 *ptr = (
char)tolower(*ptr);
658 return file_name.
begin();
667 return myData + (extension.
begin() - myData);
707 int parseNumberedFilename(
UT_String &prefix,
711 bool fractional =
false)
const;
714 {
return (myData && *myData); }
719 int trimSpace(
bool leave_single_space_between_words =
false);
723 int trimBoundingSpace();
728 int strip(
const char *chars);
734 void protectString(
bool protect_empty=
false);
739 static void protectString(std::ostream& os,
char c);
745 void protectPreQuotePythonStringLiteral(
char delimiter=
'\'');
749 bool isQuotedString(
char delimiter=
'\'')
const;
756 UT_String makeQuotedString(
char delimiter=
'\'',
757 bool escape_nonprinting=
false)
const;
764 UT_String makeSmartQuotedString(
char default_delimiter=
'\'',
765 bool escape_nonprinting=
false)
const;
773 void expandControlSequences(
bool expand_extended =
false);
775 bool hasWhiteSpace()
const;
777 void removeTrailingSpace();
778 void removeTrailingChars(
char chr);
780 void removeTrailingDigits();
798 int cshParse(
char *argv[],
int max_args,
801 int *
error =
nullptr,
806 int *
error =
nullptr,
821 int dosParse(
UT_WorkArgs &argv,
bool preserve_backslashes=
false);
822 int dosParse(
char *argv[],
int max_args,
823 bool preserve_backslashes=
false);
827 bool preserve_backslashes);
835 int parse(
char *argv[],
int max_args,
836 const char *quotes =
"\"'",
bool keep_quotes =
false)
839 return parseInPlace(argv, max_args, quotes, keep_quotes);
842 const char *quotes =
"\"'",
bool keep_quotes =
false)
845 return parseInPlace(argv, start_arg, quotes, keep_quotes);
848 const char *quotes =
"\"'",
bool keep_quotes =
false)
851 return parseInPlace(argv, start_arg, quotes, keep_quotes);
855 int parseInPlace(
char *argv[],
int max_args,
856 const char *quotes =
"\"'",
bool keep_quotes =
false);
857 int parseInPlace(
UT_WorkArgs &argv,
int start_arg = 0,
858 const char *quotes =
"\"'",
bool keep_quotes =
false);
860 const char *quotes =
"\"'",
bool keep_quotes =
false);
864 int tokenize(
char *argv[],
int max_args,
char separator)
867 return tokenizeInPlace(argv, max_args, separator);
869 int tokenizeInPlace(
char *argv[],
int max_args,
char separator);
873 return tokenizeInPlace(argv, separator);
875 int tokenizeInPlace(
UT_WorkArgs &argv,
char separator);
877 const char *separators =
" \t\n")
880 return tokenizeInPlace(argv, max_args, separators);
882 int tokenizeInPlace(
char *argv[],
int max_args,
883 const char *separators =
" \t\n");
887 return tokenizeInPlace(argv, separators);
890 const char *separators =
" \t\n");
896 return tokenizeInPlace(list, separators);
901 const char *separators =
" \t\n")
908 if (!(token =
SYSstrtok(myData, separators, &context)))
913 while ((token =
SYSstrtok(
nullptr, separators, &context))
917 return list.entries();
922 void expandVariables();
935 return SYSstring_hashseed(
944 bool match(
const char *
pattern,
bool case_sensitive =
true)
const;
949 bool matchFile(
const char *
pattern)
const;
954 bool matchPath(
const char *
pattern,
bool case_sensitive =
true,
955 bool *excludes_branch =
nullptr)
const;
961 bool multiMatch(
const char *
pattern,
962 bool case_sensitive,
char separator)
const;
963 bool multiMatch(
const char *
pattern,
bool case_sensitive =
true,
964 const char *separators =
", ",
965 bool *explicitly_excluded =
nullptr,
966 int *match_index =
nullptr,
967 ut_PatternRecord *pattern_record =
nullptr)
const;
969 bool *explicitly_excluded =
nullptr,
970 int *match_index =
nullptr,
971 ut_PatternRecord *pattern_record =
nullptr)
const;
975 bool multiMatchRecord(
const char *
pattern,
int maxpatterns,
976 char *singles,
int &nsingles,
977 char **words,
int &nwords,
978 bool case_sensitive =
true,
979 const char *separators =
", ")
const;
982 char *singles,
int &nsingles,
983 char **words,
int &nwords)
const;
984 bool multiMatchRecord(
const char *
pattern,
987 bool case_sensitive =
true,
988 const char *separators =
", ")
const;
997 bool assume_match=
false)
const;
999 static bool multiMatchCheck(
const char *
pattern);
1000 static bool wildcardMatchCheck(
const char *
pattern);
1007 bool case_sensitive =
true)
const;
1011 bool case_sensitive =
true)
const;
1024 int traversePattern(
int max,
void *
data,
1025 int (*
func)(
int num,
int sec,
void *data),
1026 unsigned int (*secfunc)(
int num,
void *data)
1035 return case_sensitive ? strstr(myData, pattern)
1048 bool patternRename(
const char *match_pattern,
const char *
replace);
1057 const char *suffix()
const;
1064 void incrementNumberedName(
bool preserve_padding =
false);
1077 static std::ostream &setFormat(std::ostream &os,
const char *fmt);
1078 std::ostream &setFormat(std::ostream &os);
1080 int replacePrefix(
const char *oldpref,
1081 const char *newpref);
1082 int replaceSuffix(
const char *oldsuffix,
1083 const char *newsuffix);
1092 int expandArrays(
char *names[],
int max);
1107 int substitute(
const char *
find,
const char *replacement,
1111 int substitute(
char find,
char replacement,
bool all =
true );
1115 int replace(
int pos,
int len,
const char *str );
1119 {
return replace(0, len,
""); }
1135 {
return replace(pos, 0, str); }
1141 static int compareNumberedString(
const char *s1,
1143 bool case_sensitive=
true,
1144 bool allow_negatives=
false);
1145 static int qsortCmpNumberedString(
const char *
const*
v1,
1146 const char *
const*
v2);
1150 static int compareNumberedFilename(
const char *s1,
1152 bool case_sensitive=
false);
1153 static int qsortCmpNumberedFilename(
const char *
const*
v1,
1154 const char *
const*
v2);
1158 static int compareNumberedStringWithExceptions(
const char *s1,
1160 bool case_sensitive=
false,
1161 bool allow_negatives=
false,
1162 const char *sorted_first=
nullptr,
1163 const char *sorted_last=
nullptr);
1168 static int compareVersionString(
const char *s1,
const char *s2);
1182 void extractProgramName(
const char *
path,
1183 bool strip_extension=
true,
1184 bool normalize_path=
true);
1196 static bool matchProgramName(
const char *
path,
const char *expected,
1197 bool normalize_path=
false);
1207 static int itoa(
char *str,
int64 i);
1208 static int utoa(
char *str,
uint64 i);
1221 void timeDeltaToPrettyString(
double time_ms);
1225 void timeDeltaToPrettyStringMS(
double time_ms);
1241 int forceValidVariableName(const
char *safechars =
nullptr);
1245 bool isValidVariableName(const
char *safechars =
nullptr) const;
1249 bool forceAlphaNumeric();
1260 void getRelativePath(const
char *src_fullpath,
1261 const
char *dest_fullpath,
1262 bool file_path = false,
1263 bool allow_relative_path_from_root = true);
1272 static
int findLongestCommonPathPrefix(const
char *fullpath1,
int len1,
1273 const
char *fullpath2,
int len2);
1277 bool isAbsolutePath(
bool file_path=false) const;
1283 bool collapseAbsolutePath(
bool file_path=false);
1289 bool truncateMiddle(
int max_length);
1297 static const
UT_String &getEmptyString();
1305 static
int countCshModifiers(const
char *
src);
1312 bool applyCshModifiers(const
char *modifiers);
1323 void formatByteSize(
exint size,
int digits=2);
1329 int getCodePointCount() const;
1349 template <
typename OSTREAM>
1350 void saveInternal(OSTREAM &os,
bool binary)
const;
1362 bool applyNextModifier(
const char *
mod,
bool all);
1369 void doSmartCopyFrom(
const char* other_string);
1371 static int compareNumberedStringInternal(
const char *s1,
const char *s2,
1372 bool case_sensitive,
1373 bool allow_negatives,
1374 const char *sorted_first,
1375 const char *sorted_last);
1379 #if defined(UT_DEBUG) && !defined(_WIN32)
1381 ::memset((
void *)str, 0xDD, ::strlen(str) + 1);
1383 ::free((
void *)str);
1387 bool myIsReference:1,
1426 using UT_String::operator==;
1427 using UT_String::operator!=;
1473 : myIsReference(false)
1474 , myIsAlwaysDeep(true)
1482 : myIsReference(false)
1483 , myIsAlwaysDeep(true)
1486 *
this = std::move(str);
1493 myIsAlwaysDeep =
true;
1500 if (!myIsReference && myData)
1506 UT_String::freeData()
1520 bool temp = myIsReference;
1521 myIsReference = other.myIsReference;
1522 other.myIsReference = temp;
1524 char *tmp_data = myData;
1525 myData = other.myData;
1526 other.myData = tmp_data;
1531 if (other.myIsAlwaysDeep)
1557 bool operator()(
const std::string &s1,
const std::string &s2)
const
1559 return operator()(s1.c_str(), s2.c_str());
bool match(const char *pattern, bool case_sensitive=true) const
int tokenize(char *argv[], int max_args, const char *separators=" \t\n")
UT_String & operator+=(const char *str)
static SYS_FORCE_INLINE uint32 hash(const char *str, uint32 code=0)
int distance(const char *str, bool case_sensitive=true, bool allow_subst=true) const
typedef int(APIENTRYP RE_PFNGLXSWAPINTERVALSGIPROC)(int)
bool isValidVariableName(const char *safechars=nullptr) const
GLenum GLuint GLenum GLsizei const GLchar * buf
bool operator!=(const char *str) const
UT_String & operator+=(const UT_String &str)
UT_API void normalizePath(UT_String &file_path, bool want_marker=false, bool always_want_expanded_path=false)
bool operator>=(const UT_StringRef &str) const
int count(const char *str, bool case_sensitive=true) const
Count the occurrences of the string.
bool matchFileExtension(const char *match_extension) const
void swap(UT_String &other)
void saveAscii(UT_OStream &os) const
bool operator()(const char *s1, const char *s2) const
T negative(const T &val)
Return the unary negation of the given value.
const char * lastChar(int c) const
bool isInteger(bool skip_spaces=false) const
Determine if string can be seen as a single integer number.
that also have some descendant prim *whose name begins with which in turn has a child named baz where *the predicate and *a name There is also one special expression _ which means *the weaker expression when composing expressions together See with
bool operator<=(const char *str) const
bool operator==(const char *str) const
bool operator<=(const UT_String &str) const
CompareResults OIIO_API compare(const ImageBuf &A, const ImageBuf &B, float failthresh, float warnthresh, float failrelative, float warnrelative, ROI roi={}, int nthreads=0)
const GLuint GLenum const void * binary
bool isHard() const
Returns whether this string is hardened already.
GLsizei const GLchar *const * path
SYS_FORCE_INLINE T * SYSconst_cast(const T *foo)
UT_String makeQuotedString(char delimiter='\'', bool escape_nonprinting=false) const
const char * findChar(const char *str) const
GLboolean GLboolean GLboolean GLboolean a
void swap(T &lhs, T &rhs)
void write(unsigned i, char c)
bool operator==(const UT_String &str) const
GLuint GLsizei GLsizei * length
const char * fileExtension() const
const char * data() const
bool isAbsolutePath(bool file_path=false) const
bool findString(const char *str, bool fullword, bool usewildcards) const
**But if you need a result
FMT_CONSTEXPR auto find(Ptr first, Ptr last, T value, Ptr &out) -> bool
char & operator()(unsigned i)
bool equal(const char *str, bool case_sensitive=true) const
GLfloat GLfloat GLfloat v2
const char * findNonSpace() const
unsigned long long uint64
int compare(const char *str, bool case_sensitive=true) const
void clear()
Reset the string to the default constructor.
bool isAlwaysDeep() const
const char * c_str() const
SYS_FORCE_INLINE UT_String(const char *str=nullptr)
Construct UT_String from a C string, using shallow semantics.
bool matchPath(const char *pattern, bool case_sensitive=true, bool *excludes_branch=nullptr) const
SIM_API const UT_StringHolder all
unsigned length() const
Return length of string.
int compare(const UT_String &str, bool case_sensitive=true) const
const char * suffix() const
bool operator<(const char *str) const
bool operator<(const UT_StringRef &str) const
UT_API void UTexprLookup(const char *name, UT_String &result)
bool contains(const char *pattern, bool case_sensitive=true) const
int tokenize(UT_WorkArgs &argv, const char *separators=" \t\n")
std::ostream & operator<<(std::ostream &ostr, const DataType &a)
UT_String(UT_AlwaysDeepType, const std::string &str)
Construct UT_String from a std::string, using ALWAYS_DEEP semantics.
void hardenIfNeeded(const char *s)
Take shallow copy and make it deep.
const char * buffer() const
A utility class to do read-only operations on a subset of an existing string.
SYS_NO_DISCARD_RESULT SYS_FORCE_INLINE bool isEmpty() const
Returns true if the string is empty.
SYS_FORCE_INLINE uint32 hash() const
bool operator==(const UT_StringRef &str) const
char operator()(unsigned i) const
int tokenize(char *argv[], int max_args, char separator)
bool operator>=(const char *str) const
SYS_NO_DISCARD_RESULT UT_StringView UTstringFileName(const StringT &str)
int tokenizeInPlace(T &list, const char *separators=" \t\n")
bool operator!=(const UT_String &str) const
bool operator>=(const UT_String &str) const
#define SYS_PRINTF_CHECK_ATTRIBUTE(string_index, first_to_check)
std::string OIIO_UTIL_API replace(string_view str, string_view pattern, string_view replacement, bool global=false)
UT_String(UT_AlwaysDeepType, const char *str=nullptr)
Construct UT_String from a C string, using ALWAYS_DEEP semantics.
GLint GLint GLsizei GLint GLenum format
bool matchPattern(const UT_WorkArgs &pattern_args, bool assume_match=false) const
bool operator>(const UT_String &str) const
char * SYSstrtok(char *string, const char *delimit, char **context)
char * findChar(const char *str)
#define UT_ASSERT_SLOW(ZZ)
const char * findChar(int c) const
void harden()
Take shallow copy and make it deep.
void saveAscii(std::ostream &os) const
bool equal(const UT_StringRef &str, bool case_sensitive=true) const
UT_String(UT_String &&str) noexcept
bool equal(const UT_String &str, bool case_sensitive=true) const
void setAlwaysDeep(bool deep)
Make a string always deep.
bool operator>(const UT_StringRef &str) const
const char * findChar(const char *str) const
bool matchFile(const char *pattern) const
bool operator()(const std::string &s1, const std::string &s2) const
GLuint const GLchar * name
void adopt(UT_String &str)
GLboolean GLboolean GLboolean b
SYS_FORCE_INLINE ~UT_StringWrap()
const char * findWord(const char *word) const
bool operator>(const char *str) const
int64 getMemoryUsage(bool inclusive=true) const
Return memory usage in bytes.
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.
static int compareNumberedString(const char *s1, const char *s2, bool case_sensitive=true, bool allow_negatives=false)
UT_String pathUpToExtension() const
const char & operator()(unsigned i) const
__hostdev__ bool isInteger(GridType gridType)
Return true if the GridType maps to a POD integer type.
SYS_NO_DISCARD_RESULT UT_StringView UTstringFileExtension(const StringT &str)
int substr(UT_String &buf, int index, int len=0) const
SYS_NO_DISCARD_RESULT bool UTstringMatchFileExtension(const StringT &str, const char *extension)
void save(std::ostream &os, bool binary) const
Save string to stream. Saves as binary if binary is true.
int parse(UT_StringArray &argv, int start_arg=0, const char *quotes="\"'", bool keep_quotes=false)
bool multiMatch(const char *pattern, bool case_sensitive, char separator) const
LeafData & operator=(const LeafData &)=delete
char * SYSstrcasestr(const char *haystack, const char *needle)
Replacement for strcasestr, since no equivalent exists on Win32.
bool multiMatchRecord(const char *pattern, int maxpatterns, char *singles, int &nsingles, char **words, int &nwords, bool case_sensitive=true, const char *separators=", ") const
int parseNumberedFilename(UT_String &prefix, UT_String &frame, UT_String &suff, bool negative=true, bool fractional=false) const
ImageBuf OIIO_API max(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
**If you just want to fire and args
SYS_NO_DISCARD_RESULT SYS_FORCE_INLINE const_iterator begin() const
Returns a constant iterator pointing to the beginning of the string.
const char * lastChar(int c) const
int findLongestCommonSuffix(const char *with) const
void hardenIfNeeded()
Take shallow copy and make it deep.
const char * findChar(int c) const
int parse(char *argv[], int max_args, const char *quotes="\"'", bool keep_quotes=false)
bool operator<(const UT_String &str) const
int erase(int pos=0, int len=-1)
int tokenize(UT_WorkArgs &argv, char separator)
auto sprintf(const S &fmt, const T &...args) -> std::basic_string< Char >
string_view OIIO_UTIL_API strip(string_view str, string_view chars=string_view())
SIM_API const UT_StringHolder distance
bool operator<=(const UT_StringRef &str) const
bool startsWith(const UT_StringView &prefix, bool case_sensitive=true) const
void splitPath(UT_String &dir_name, UT_String &file_name) const
bool OIIO_UTIL_API contains(string_view a, string_view b)
Does 'a' contain the string 'b' within it?
int parse(UT_WorkArgs &argv, int start_arg=0, const char *quotes="\"'", bool keep_quotes=false)
const char * base(UT_String &buf) const
UT_String & operator=(UT_String &&str) noexcept
void removeLast()
Remove the last character.
UT_API void UTvarLookup(const char *name, UT_String &result)
SYS_FORCE_INLINE UT_StringWrap(const char *str)
bool endsWith(const UT_StringView &suffix, bool case_sensitive=true) const
UT_String(const std::string &str)
Construct UT_String from a std::string, always doing a deep copy. The result will only be a UT_Always...
const char * fileName() const
OIIO_UTIL_API std::string extension(string_view filepath, bool include_dot=true) noexcept
int countChar(int c) const
Return the number of occurrences of the specified character.
UT_API std::ostream & do_setformat(std::ostream &os, const char fmt[])
int tokenize(T &list, const char *separators=" \t\n")
const char * nonNullBuffer() const
int insert(int pos, const char *str)
const char * fcontain(const char *pattern, bool case_sensitive=true) const
bool operator!=(const UT_StringRef &str) const