HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
UT_StringUtils.h
Go to the documentation of this file.
1 /*
2  * POPRIETARY 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_StringUtils.h
7  *
8  * COMMENTS:
9  *
10  */
11 
12 #ifndef __UT_STRINGUTILS_H__
13 #define __UT_STRINGUTILS_H__
14 
15 #include "UT_API.h"
16 
17 #include "UT_Array.h"
18 #include "UT_StringView.h"
19 
20 #include <SYS/SYS_Compiler.h>
21 #include <SYS/SYS_String.h>
22 #include <SYS/SYS_Inline.h>
23 
24 #include <type_traits>
25 
26 SYS_FORCE_INLINE bool UTisstring(const char *s) { return s && *s; }
27 
28 template <typename T>
31  const T& str,
32  const char* prefix,
33  bool case_sensitive = true,
34  exint len = -1)
35 {
36  if (!UTisstring(str.data()) || !(prefix && *prefix))
37  return false;
38 
39  if (len < 0)
40  len = strlen(prefix);
41 
42  if (len > str.length())
43  return false;
44 
45  const char* start = str.data();
46  if (case_sensitive)
47  return strncmp(start, prefix, len) == 0;
48  return SYSstrncasecmp(start, prefix, len) == 0;
49 }
50 
51 template <typename T>
54  const T& str,
55  const char* suffix,
56  bool case_sensitive = true,
57  exint len = -1)
58 {
59  if (!UTisstring(str.data()) || !(suffix && *suffix))
60  return false;
61 
62  if (len < 0)
63  len = strlen(suffix);
64 
65  if (len > str.length())
66  return false;
67 
68  const char* start = (str.data() + str.length()) - len;
69  if (case_sensitive)
70  return strncmp(start, suffix, len) == 0;
71  return SYSstrncasecmp(start, suffix, len) == 0;
72 }
73 
74 template <typename T>
75 SYS_NO_DISCARD_RESULT const char *
77  const T& str)
78 {
79  int i = str.length();
80  if (i <= 0)
81  return nullptr;
82 
83  const char* data = str.data();
84  while (i--)
85  {
86  if (!SYSisdigit(data[i]))
87  break;
88  }
89  return &data[i + 1];
90 }
91 
92 template <typename StringT>
94 UTstringFileName(const StringT& str)
95 {
96  // Convert the unknown string type to a string view.
97  UT_StringView view(str.data(), str.length());
98  return UTstringFileName(view);
99 }
100 
101 template <>
104 {
105  if (str.isEmpty())
106  return str;
107 
108  exint pos = str.findLastOf('/');
109  if (pos == UT_StringView::npos)
110  {
111  return str;
112  }
113 
114  // Make sure to move the pos past the '/'
115  return UT_StringView(str.begin() + pos + 1, str.end());
116 }
117 
118 template <typename StringT>
120 UTstringFileExtension(const StringT& str)
121 {
122  // Convert the unknown string type to a string view.
123  UT_StringView view(str.data(), str.length());
124  return UTstringFileExtension(view);
125 }
126 
127 template <>
130 {
131  if (str.isEmpty())
132  return str;
133 
134  exint dot = str.findLastOf('.');
135  if (dot == UT_StringView::npos)
136  {
137  return UT_StringView{};
138  }
139 
140  // Make sure the last dot that is found is after the last '/'.
141  exint slash = str.findLastOf('/');
142  if (slash != UT_StringView::npos && slash > dot)
143  return UT_StringView{};
144 
145  return UT_StringView(str.begin() + dot, str.end());
146 }
147 
148 template <typename StringT>
150 UTstringMatchFileExtension(const StringT& str, const char* extension)
151 {
152  UT_StringView str_extension = UTstringFileExtension(str);
153  return str_extension.equal(extension, false);
154 }
155 
156 template <typename StringT>
158 UTstringCountChar(const StringT& str, int c)
159 {
160  UT_StringView view(str.data(), str.length());
161  return UTstringCountChar(view, c);
162 }
163 
164 template <>
165 SYS_NO_DISCARD_RESULT inline int
167 {
168  if (str.isEmpty())
169  return 0;
170 
171  int count = 0;
172  exint pos = 0;
173  while (pos < str.length())
174  {
175  pos = str.findFirstOf(static_cast<char>(c), pos);
176  if (pos == UT_StringView::npos)
177  break;
178 
179  count++;
180  // Skip past the item that was just found.
181  pos++;
182  }
183 
184  return count;
185 }
186 
187 template <typename StringT>
190  const StringT& str,
191  bool skip_spaces = false,
192  bool loose = false,
193  bool allow_underscore = false)
194 {
195  const char* data = str.data();
196  if (!UTisstring(data))
197  return false;
198 
199  int i = 0;
200  // Skip leading spaces
201  if (skip_spaces)
202  for (; SYSisspace(data[i]); i++)
203  continue;
204 
205  for (; data[i] == '-' || data[i] == '+'; i++)
206  continue;
207 
208  int digit = 0;
209  int ecount = 0;
210  int dotcount = 0;
211  int epos = -10;
212 
213  for (; data[i]; i++)
214  {
215  if (SYSisdigit(data[i]))
216  {
217  digit = 1;
218  continue;
219  }
220  switch (data[i])
221  {
222  case 'e':
223  case 'E':
224  if (ecount)
225  return false;
226  epos = i + 1;
227  ecount = 1;
228  break;
229  case '-':
230  case '+':
231  if (epos != i)
232  return false;
233  epos++;
234  break;
235  case '.':
236  if (ecount || dotcount)
237  return false;
238  dotcount = 1;
239  break;
240  case '_':
241  if (allow_underscore)
242  {
243  // If we have not seen a digit, it is an error.
244  if (!digit)
245  return false;
246  // The actual requirements are tighter than this as
247  // I believe trailing underscores are prohibited.
248  }
249  else
250  {
251  return false;
252  }
253  break;
254  case ' ':
255  case '\t':
256  case '\n':
257  case '\r':
258  case '\f':
259  case '\v':
260  if (!skip_spaces)
261  {
262  return false;
263  }
264  else
265  {
266  // ignore trailing spaces
267  for (; data[i]; i++)
268  if (!SYSisspace(data[i]))
269  return false;
270 
271  if (digit || loose)
272  return true;
273  else
274  return false;
275  }
276 
277  default:
278  return false;
279  }
280  }
281 
282  return (digit || loose);
283 }
284 
285 template <>
286 SYS_NO_DISCARD_RESULT inline bool
288  const UT_StringView& str,
289  bool skip_spaces,
290  bool loose,
291  bool allow_underscore)
292 {
293  // Since UT_StringView may not be null terminated we need to use a
294  // specialized method.
295  return str.isFloat(skip_spaces, loose, allow_underscore);
296 }
297 
298 template <typename StringT>
300 UTstringIsInteger(const StringT& str, bool skip_spaces = false)
301 {
302  const char* cur = str.data();
303 
304  if (!UTisstring(cur))
305  return false;
306 
307  // Skip leading spaces
308  if (skip_spaces)
309  {
310  for (; SYSisspace(*cur); ++cur)
311  ;
312  }
313 
314  // Skip all +'s and -'s
315  for (; *cur == '-' || *cur == '+'; ++cur)
316  ;
317 
318  // Skip all digits
319  for (; SYSisdigit(*cur); ++cur)
320  ;
321 
322  // Skip trailing spaces
323  if (skip_spaces)
324  {
325  for (; SYSisspace(*cur); ++cur)
326  ;
327  }
328 
329  // if we have anything left, this is not an integer
330  if (*cur)
331  return false;
332  return true;
333 }
334 
335 template <>
336 SYS_NO_DISCARD_RESULT inline bool
337 UTstringIsInteger<UT_StringView>(const UT_StringView& str, bool skip_spaces)
338 {
339  // Since UT_StringView may not be null terminated we need to use a
340  // specialized method.
341  return str.isInteger(skip_spaces);
342 }
343 
344 #endif // __UT_STRINGUTILS_H__
345 
SYS_NO_DISCARD_RESULT bool UTstringEndsWith(const T &str, const char *suffix, bool case_sensitive=true, exint len=-1)
GLuint start
Definition: glcorearb.h:474
const GLfloat * c
Definition: glew.h:16631
OIIO_API std::string extension(const std::string &filepath, bool include_dot=true) noexcept
int64 exint
Definition: SYS_Types.h:125
SYS_NO_DISCARD_RESULT SYS_FORCE_INLINE const_iterator end() const
Returns a constant iterator pointing to the end of the string.
A utility class to do read-only operations on a subset of an existing string.
Definition: UT_StringView.h:40
SYS_NO_DISCARD_RESULT SYS_FORCE_INLINE bool isEmpty() const
Returns true if the string is empty.
int SYSstrncasecmp(const char *a, const char *b, size_t n)
Definition: SYS_String.h:273
SYS_NO_DISCARD_RESULT UT_StringView UTstringFileName(const StringT &str)
SYS_NO_DISCARD_RESULT bool UTstringIsFloat(const StringT &str, bool skip_spaces=false, bool loose=false, bool allow_underscore=false)
GLenum GLsizei len
Definition: glew.h:7782
fpreal64 dot(const CE_VectorT< T > &a, const CE_VectorT< T > &b)
Definition: CE_Vector.h:130
#define SYS_FORCE_INLINE
Definition: SYS_Inline.h:45
SYS_NO_DISCARD_RESULT int UTstringCountChar(const StringT &str, int c)
SYS_NO_DISCARD_RESULT bool UTstringStartsWith(const T &str, const char *prefix, bool case_sensitive=true, exint len=-1)
static constexpr exint npos
Definition: UT_StringView.h:97
#define SYS_NO_DISCARD_RESULT
Definition: SYS_Compiler.h:93
GLint GLsizei count
Definition: glcorearb.h:404
SYS_NO_DISCARD_RESULT bool UTstringIsInteger(const StringT &str, bool skip_spaces=false)
SYS_NO_DISCARD_RESULT bool UTstringIsInteger< UT_StringView >(const UT_StringView &str, bool skip_spaces)
GLboolean * data
Definition: glcorearb.h:130
SYS_NO_DISCARD_RESULT UT_StringView UTstringFileExtension(const StringT &str)
SYS_NO_DISCARD_RESULT SYS_FORCE_INLINE bool equal(const char *str, bool case_sensitive=true) const
SYS_NO_DISCARD_RESULT bool UTstringMatchFileExtension(const StringT &str, const char *extension)
SYS_NO_DISCARD_RESULT UT_StringView UTstringFileExtension< UT_StringView >(const UT_StringView &str)
SYS_NO_DISCARD_RESULT const char * UTstringNumericSuffix(const T &str)
SYS_FORCE_INLINE bool UTisstring(const char *s)
SYS_NO_DISCARD_RESULT SYS_FORCE_INLINE const_iterator begin() const
Returns a constant iterator pointing to the beginning of the string.
SYS_NO_DISCARD_RESULT bool UTstringIsFloat< UT_StringView >(const UT_StringView &str, bool skip_spaces, bool loose, bool allow_underscore)
GLdouble s
Definition: glew.h:1395
SYS_NO_DISCARD_RESULT exint findLastOf(UT_StringView view, exint pos=npos) const noexcept
SYS_NO_DISCARD_RESULT int UTstringCountChar< UT_StringView >(const UT_StringView &str, int c)