HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ustring.h
Go to the documentation of this file.
1 // Copyright 2008-present Contributors to the OpenImageIO project.
2 // SPDX-License-Identifier: BSD-3-Clause
3 // https://github.com/OpenImageIO/oiio
4 
5 
6 #pragma once
7 #define OPENIMAGEIO_USTRING_H
8 
9 #if defined(_MSC_VER)
10 // Ignore warnings about DLL exported classes with member variables that are template classes.
11 // This happens with the std::string empty_std_string static member variable of ustring below.
12 // Also remove a warning about the strncpy function not being safe and deprecated in MSVC.
13 // There is no equivalent safe and portable function and trying to fix this is more trouble than
14 // its worth. (see http://stackoverflow.com/questions/858252/alternatives-to-ms-strncpy-s)
15 # pragma warning(disable : 4251 4996)
16 #endif
17 
18 #include <OpenImageIO/dassert.h>
19 #include <OpenImageIO/export.h>
22 #include <OpenImageIO/strutil.h>
23 #include <cstring>
24 #include <iostream>
25 #include <string>
26 
27 
29 
30 /// A ustring is an alternative to char* or std::string for storing
31 /// strings, in which the character sequence is unique (allowing many
32 /// speed advantages for assignment, equality testing, and inequality
33 /// testing).
34 ///
35 /// The implementation is that behind the scenes there is a hash set of
36 /// allocated strings, so the characters of each string are unique. A
37 /// ustring itself is a pointer to the characters of one of these canonical
38 /// strings. Therefore, assignment and equality testing is just a single
39 /// 32- or 64-bit int operation, the only mutex is when a ustring is
40 /// created from raw characters, and the only malloc is the first time
41 /// each canonical ustring is created.
42 ///
43 /// The internal table also contains a std::string version and the length
44 /// of the string, so converting a ustring to a std::string (via
45 /// ustring::string()) or querying the number of characters (via
46 /// ustring::size() or ustring::length()) is extremely inexpensive, and does
47 /// not involve creation/allocation of a new std::string or a call to
48 /// strlen.
49 ///
50 /// We try very hard to completely mimic the API of std::string,
51 /// including all the constructors, comparisons, iterations, etc. Of
52 /// course, the charaters of a ustring are non-modifiable, so we do not
53 /// replicate any of the non-const methods of std::string. But in most
54 /// other ways it looks and acts like a std::string and so most templated
55 /// algorthms that would work on a "const std::string &" will also work
56 /// on a ustring.
57 ///
58 /// Usage guidelines:
59 ///
60 /// Compared to standard strings, ustrings have several advantages:
61 ///
62 /// - Each individual ustring is very small -- in fact, we guarantee that
63 /// a ustring is the same size and memory layout as an ordinary char*.
64 /// - Storage is frugal, since there is only one allocated copy of each
65 /// unique character sequence, throughout the lifetime of the program.
66 /// - Assignment from one ustring to another is just copy of the pointer;
67 /// no allocation, no character copying, no reference counting.
68 /// - Equality testing (do the strings contain the same characters) is
69 /// a single operation, the comparison of the pointer.
70 /// - Memory allocation only occurs when a new ustring is constructed from
71 /// raw characters the FIRST time -- subsequent constructions of the
72 /// same string just finds it in the canonical string set, but doesn't
73 /// need to allocate new storage. Destruction of a ustring is trivial,
74 /// there is no de-allocation because the canonical version stays in
75 /// the set. Also, therefore, no user code mistake can lead to
76 /// memory leaks.
77 ///
78 /// But there are some problems, too. Canonical strings are never freed
79 /// from the table. So in some sense all the strings "leak", but they
80 /// only leak one copy for each unique string that the program ever comes
81 /// across. Also, creation of unique strings from raw characters is more
82 /// expensive than for standard strings, due to hashing, table queries,
83 /// and other overhead.
84 ///
85 /// On the whole, ustrings are a really great string representation
86 /// - if you tend to have (relatively) few unique strings, but many
87 /// copies of those strings;
88 /// - if the creation of strings from raw characters is relatively
89 /// rare compared to copying or comparing to existing strings;
90 /// - if you tend to make the same strings over and over again, and
91 /// if it's relatively rare that a single unique character sequence
92 /// is used only once in the entire lifetime of the program;
93 /// - if your most common string operations are assignment and equality
94 /// testing and you want them to be as fast as possible;
95 /// - if you are doing relatively little character-by-character assembly
96 /// of strings, string concatenation, or other "string manipulation"
97 /// (other than equality testing).
98 ///
99 /// ustrings are not so hot
100 /// - if your program tends to have very few copies of each character
101 /// sequence over the entire lifetime of the program;
102 /// - if your program tends to generate a huge variety of unique
103 /// strings over its lifetime, each of which is used only a short
104 /// time and then discarded, never to be needed again;
105 /// - if you don't need to do a lot of string assignment or equality
106 /// testing, but lots of more complex string manipulation.
107 ///
109 public:
110  typedef char value_type;
111  typedef value_type* pointer;
113  typedef const value_type& const_reference;
114  typedef size_t size_type;
115  static const size_type npos = static_cast<size_type>(-1);
116  typedef std::string::const_iterator const_iterator;
117  typedef std::string::const_reverse_iterator const_reverse_iterator;
118 
119  /// Default ctr for ustring -- make an empty string.
120  ustring(void) noexcept
121  : m_chars(nullptr)
122  {
123  }
124 
125  /// Construct a ustring from a null-terminated C string (char *).
126  explicit ustring(const char* str)
127  {
128  m_chars = str ? make_unique(str) : nullptr;
129  }
130 
131  /// Construct a ustring from a string_view, which can be auto-converted
132  /// from either a null-terminated C string (char *) or a C++
133  /// std::string.
134  explicit ustring(string_view str)
135  {
136  m_chars = str.data() ? make_unique(str) : nullptr;
137  }
138 
139  /// Construct a ustring from at most n characters of str, starting at
140  /// position pos.
141  ustring(const char* str, size_type pos, size_type n)
142  : m_chars(make_unique(std::string(str, pos, n).c_str()))
143  {
144  }
145 
146  /// Construct a ustring from the first n characters of str.
147  ustring(const char* str, size_type n)
148  : m_chars(make_unique(string_view(str, n)))
149  {
150  }
151 
152  /// Construct a ustring from n copies of character c.
153  ustring(size_type n, char c)
154  : m_chars(make_unique(std::string(n, c).c_str()))
155  {
156  }
157 
158  /// Construct a ustring from an indexed substring of a std::string.
159  ustring(const std::string& str, size_type pos, size_type n = npos)
160  {
161  string_view sref(str);
162  sref = sref.substr(pos, n);
163  m_chars = make_unique(sref);
164  }
165 
166  /// Copy construct a ustring from another ustring.
167  ustring(const ustring& str) noexcept
168  : m_chars(str.m_chars)
169  {
170  }
171 
172  /// Construct a ustring from an indexed substring of a ustring.
173  ustring(const ustring& str, size_type pos, size_type n = npos)
174  {
175  string_view sref(str);
176  sref = sref.substr(pos, n);
177  m_chars = make_unique(sref);
178  }
179 
180  /// ustring destructor.
181  ~ustring() noexcept {}
182 
183  /// Conversion to string_view
184  operator string_view() const noexcept
185  {
186  return string_view(c_str(), length());
187  }
188 
189  /// Conversion to std::string (explicit only!).
190  explicit operator std::string() const noexcept { return string(); }
191 
192  /// Assign a ustring to *this.
193  const ustring& assign(const ustring& str)
194  {
195  m_chars = str.m_chars;
196  return *this;
197  }
198 
199  /// Assign a substring of a ustring to *this.
200  const ustring& assign(const ustring& str, size_type pos, size_type n = npos)
201  {
202  *this = ustring(str, pos, n);
203  return *this;
204  }
205 
206  /// Assign a std::string to *this.
207  const ustring& assign(const std::string& str)
208  {
209  assign(str.c_str());
210  return *this;
211  }
212 
213  /// Assign a substring of a std::string to *this.
214  const ustring& assign(const std::string& str, size_type pos,
215  size_type n = npos)
216  {
217  *this = ustring(str, pos, n);
218  return *this;
219  }
220 
221  /// Assign a null-terminated C string (char*) to *this.
222  const ustring& assign(const char* str)
223  {
224  m_chars = str ? make_unique(str) : nullptr;
225  return *this;
226  }
227 
228  /// Assign the first n characters of str to *this.
229  const ustring& assign(const char* str, size_type n)
230  {
231  *this = ustring(str, n);
232  return *this;
233  }
234 
235  /// Assign n copies of c to *this.
236  const ustring& assign(size_type n, char c)
237  {
238  *this = ustring(n, c);
239  return *this;
240  }
241 
242  /// Assign a string_view to *this.
244  {
245  m_chars = str.length() ? make_unique(str) : nullptr;
246  return *this;
247  }
248 
249  /// Assign a ustring to another ustring.
250  const ustring& operator=(const ustring& str) { return assign(str); }
251 
252  /// Assign a null-terminated C string (char *) to a ustring.
253  const ustring& operator=(const char* str) { return assign(str); }
254 
255  /// Assign a C++ std::string to a ustring.
256  const ustring& operator=(const std::string& str) { return assign(str); }
257 
258  /// Assign a string_view to a ustring.
259  const ustring& operator=(string_view str) { return assign(str); }
260 
261  /// Assign a single char to a ustring.
262  const ustring& operator=(char c)
263  {
264  char s[2];
265  s[0] = c;
266  s[1] = 0;
267  *this = ustring(s);
268  return *this;
269  }
270 
271  /// Return a C string representation of a ustring.
272  const char* c_str() const noexcept { return m_chars; }
273 
274  /// Return a C string representation of a ustring.
275  const char* data() const noexcept { return c_str(); }
276 
277  /// Return a C++ std::string representation of a ustring.
278  const std::string& string() const noexcept
279  {
280  if (m_chars) {
281  const TableRep* rep = (const TableRep*)m_chars - 1;
282  return rep->str;
283  } else
284  return empty_std_string;
285  }
286 
287  /// Reset to an empty string.
288  void clear(void) noexcept { m_chars = nullptr; }
289 
290  /// Return the number of characters in the string.
291  size_t length(void) const noexcept
292  {
293  if (!m_chars)
294  return 0;
295  const TableRep* rep = ((const TableRep*)m_chars) - 1;
296  return rep->length;
297  }
298 
299  /// Return a hashed version of the string
300  size_t hash(void) const noexcept
301  {
302  if (!m_chars)
303  return 0;
304  const TableRep* rep = ((const TableRep*)m_chars) - 1;
305  return rep->hashed;
306  }
307 
308  /// Return the number of characters in the string.
309  size_t size(void) const noexcept { return length(); }
310 
311  /// Is the string empty -- i.e., is it nullptr or does it point to an
312  /// empty string?
313  bool empty(void) const noexcept { return (size() == 0); }
314 
315  /// Return a const_iterator that references the first character of
316  /// the string.
317  const_iterator begin() const noexcept { return string().begin(); }
318 
319  /// Return a const_iterator that references the end of a traversal
320  /// of the characters of the string.
321  const_iterator end() const noexcept { return string().end(); }
322 
323  /// Return a const_reverse_iterator that references the last
324  /// character of the string.
325  const_reverse_iterator rbegin() const noexcept { return string().rbegin(); }
326 
327  /// Return a const_reverse_iterator that references the end of
328  /// a reverse traversal of the characters of the string.
329  const_reverse_iterator rend() const noexcept { return string().rend(); }
330 
331  /// Return a reference to the character at the given position.
332  /// Note that it's up to the caller to be sure pos is within the
333  /// size of the string.
335  {
336  return c_str()[pos];
337  }
338 
339  /// Dump into character array s the characters of this ustring,
340  /// beginning with position pos and copying at most n characters.
341  size_type copy(char* s, size_type n, size_type pos = 0) const
342  {
343  if (m_chars == nullptr) {
344  s[0] = 0;
345  return 0;
346  }
347  char* c = strncpy(s, c_str() + pos, n);
348  return (size_type)(c - s);
349  }
350 
351  /// Returns a substring of the ustring object consisting of n
352  /// characters starting at position pos.
353  ustring substr(size_type pos = 0, size_type n = npos) const
354  {
355  return ustring(*this, pos, n);
356  }
357 
358  // FIXME: implement compare.
359 
360  size_type find(const ustring& str, size_type pos = 0) const noexcept
361  {
362  return string().find(str.string(), pos);
363  }
364 
365  size_type find(const std::string& str, size_type pos = 0) const noexcept
366  {
367  return string().find(str, pos);
368  }
369 
370  size_type find(const char* s, size_type pos, size_type n) const
371  {
372  return string().find(s, pos, n);
373  }
374 
375  size_type find(const char* s, size_type pos = 0) const
376  {
377  return string().find(s, pos);
378  }
379 
380  size_type find(char c, size_type pos = 0) const noexcept
381  {
382  return string().find(c, pos);
383  }
384 
385  size_type rfind(const ustring& str, size_type pos = npos) const noexcept
386  {
387  return string().rfind(str.string(), pos);
388  }
389 
390  size_type rfind(const std::string& str, size_type pos = npos) const noexcept
391  {
392  return string().rfind(str, pos);
393  }
394 
395  size_type rfind(const char* s, size_type pos, size_type n) const
396  {
397  return string().rfind(s, pos, n);
398  }
399 
400  size_type rfind(const char* s, size_type pos = npos) const
401  {
402  return string().rfind(s, pos);
403  }
404 
405  size_type rfind(char c, size_type pos = npos) const noexcept
406  {
407  return string().rfind(c, pos);
408  }
409 
411  size_type pos = 0) const noexcept
412  {
413  return string().find_first_of(str.string(), pos);
414  }
415 
417  size_type pos = 0) const noexcept
418  {
419  return string().find_first_of(str, pos);
420  }
421 
422  size_type find_first_of(const char* s, size_type pos, size_type n) const
423  {
424  return string().find_first_of(s, pos, n);
425  }
426 
427  size_type find_first_of(const char* s, size_type pos = 0) const
428  {
429  return string().find_first_of(s, pos);
430  }
431 
432  size_type find_first_of(char c, size_type pos = 0) const noexcept
433  {
434  return string().find_first_of(c, pos);
435  }
436 
438  size_type pos = npos) const noexcept
439  {
440  return string().find_last_of(str.string(), pos);
441  }
442 
444  size_type pos = npos) const noexcept
445  {
446  return string().find_last_of(str, pos);
447  }
448 
449  size_type find_last_of(const char* s, size_type pos, size_type n) const
450  {
451  return string().find_last_of(s, pos, n);
452  }
453 
454  size_type find_last_of(const char* s, size_type pos = npos) const
455  {
456  return string().find_last_of(s, pos);
457  }
458 
459  size_type find_last_of(char c, size_type pos = npos) const noexcept
460  {
461  return string().find_last_of(c, pos);
462  }
463 
465  size_type pos = 0) const noexcept
466  {
467  return string().find_first_not_of(str.string(), pos);
468  }
469 
471  size_type pos = 0) const noexcept
472  {
473  return string().find_first_not_of(str, pos);
474  }
475 
477  {
478  return string().find_first_not_of(s, pos, n);
479  }
480 
481  size_type find_first_not_of(const char* s, size_type pos = 0) const
482  {
483  return string().find_first_not_of(s, pos);
484  }
485 
486  size_type find_first_not_of(char c, size_type pos = 0) const noexcept
487  {
488  return string().find_first_not_of(c, pos);
489  }
490 
492  size_type pos = npos) const noexcept
493  {
494  return string().find_last_not_of(str.string(), pos);
495  }
496 
498  size_type pos = npos) const noexcept
499  {
500  return string().find_last_not_of(str, pos);
501  }
502 
503  size_type find_last_not_of(const char* s, size_type pos, size_type n) const
504  {
505  return string().find_last_not_of(s, pos, n);
506  }
507 
508  size_type find_last_not_of(const char* s, size_type pos = npos) const
509  {
510  return string().find_last_not_of(s, pos);
511  }
512 
513  size_type find_last_not_of(char c, size_type pos = npos) const noexcept
514  {
515  return string().find_last_not_of(c, pos);
516  }
517 
518  /// Return 0 if *this is lexicographically equal to str, -1 if
519  /// *this is lexicographically earlier than str, 1 if *this is
520  /// lexicographically after str.
521  int compare(string_view str) const noexcept
522  {
523  return string_view(*this).compare(str);
524  }
525 
526  /// Return 0 if *this is lexicographically equal to str, -1 if
527  /// *this is lexicographically earlier than str, 1 if *this is
528  /// lexicographically after str.
529  int compare(const char* str) const noexcept
530  {
531  return strcmp(c_str() ? c_str() : "", str ? str : "");
532  }
533 
534  /// Return 0 if a is lexicographically equal to b, -1 if a is
535  /// lexicographically earlier than b, 1 if a is lexicographically
536  /// after b.
537  friend int compare(const std::string& a, const ustring& b) noexcept
538  {
539  return string_view(a).compare(b);
540  }
541 
542  /// Test two ustrings for equality -- are they comprised of the same
543  /// sequence of characters. Note that because ustrings are unique,
544  /// this is a trivial pointer comparison, not a char-by-char loop as
545  /// would be the case with a char* or a std::string.
546  bool operator==(const ustring& str) const noexcept
547  {
548  return c_str() == str.c_str();
549  }
550 
551  /// Test two ustrings for inequality -- are they comprised of different
552  /// sequences of characters. Note that because ustrings are unique,
553  /// this is a trivial pointer comparison, not a char-by-char loop as
554  /// would be the case with a char* or a std::string.
555  bool operator!=(const ustring& str) const noexcept
556  {
557  return c_str() != str.c_str();
558  }
559 
560  /// Test a ustring (*this) for lexicographic equality with std::string
561  /// x.
562  bool operator==(const std::string& x) const noexcept
563  {
564  return compare(x) == 0;
565  }
566 
567  /// Test a ustring (*this) for lexicographic equality with string_view
568  /// x.
569  bool operator==(string_view x) const noexcept { return compare(x) == 0; }
570 
571  /// Test a ustring (*this) for lexicographic equality with char* x.
572  bool operator==(const char* x) const noexcept { return compare(x) == 0; }
573 
574  /// Test for lexicographic equality between std::string a and ustring
575  /// b.
576  friend bool operator==(const std::string& a, const ustring& b) noexcept
577  {
578  return b.compare(a) == 0;
579  }
580 
581  /// Test for lexicographic equality between string_view a and ustring
582  /// b.
583  friend bool operator==(string_view a, const ustring& b) noexcept
584  {
585  return b.compare(a) == 0;
586  }
587 
588  /// Test for lexicographic equality between char* a and ustring
589  /// b.
590  friend bool operator==(const char* a, const ustring& b) noexcept
591  {
592  return b.compare(a) == 0;
593  }
594 
595  /// Test a ustring (*this) for lexicographic inequality with
596  /// std::string x.
597  bool operator!=(const std::string& x) const noexcept
598  {
599  return compare(x) != 0;
600  }
601 
602  /// Test a ustring (*this) for lexicographic inequality with
603  /// string_view x.
604  bool operator!=(string_view x) const noexcept { return compare(x) != 0; }
605 
606  /// Test a ustring (*this) for lexicographic inequality with
607  /// char* x.
608  bool operator!=(const char* x) const noexcept { return compare(x) != 0; }
609 
610  /// Test for lexicographic inequality between std::string a and
611  /// ustring b.
612  friend bool operator!=(const std::string& a, const ustring& b) noexcept
613  {
614  return b.compare(a) != 0;
615  }
616 
617  /// Test for lexicographic inequality between string_view a and
618  /// ustring b.
619  friend bool operator!=(string_view a, const ustring& b) noexcept
620  {
621  return b.compare(a) != 0;
622  }
623 
624  /// Test for lexicographic inequality between char* a and
625  /// ustring b.
626  friend bool operator!=(const char* a, const ustring& b) noexcept
627  {
628  return b.compare(a) != 0;
629  }
630 
631  /// Test for lexicographic 'less', comes in handy for lots of STL
632  /// containers and algorithms.
633  bool operator<(const ustring& x) const noexcept { return compare(x) < 0; }
634 
635  /// Construct a ustring in a printf-like fashion. In other words,
636  /// something like:
637  /// ustring s = ustring::sprintf("blah %d %g", (int)foo, (float)bar);
638  /// The argument list is fully typesafe.
639  /// The formatting of the string will always use the classic "C" locale
640  /// conventions (in particular, '.' as decimal separator for float values).
641  template<typename... Args>
642  static ustring sprintf(const char* fmt, const Args&... args)
643  {
644  return ustring(Strutil::sprintf(fmt, args...));
645  }
646 
647  /// Construct a ustring in a fmt::format-like fashion. In other words,
648  /// something like:
649  /// ustring s = ustring::fmtformat("blah {} {}", (int)foo, (float)bar);
650  /// The argument list is fully typesafe.
651  /// The formatting of the string will always use the classic "C" locale
652  /// conventions (in particular, '.' as decimal separator for float values).
653  template<typename... Args>
654  static ustring fmtformat(const char* fmt, const Args&... args)
655  {
656  return ustring(Strutil::fmt::format(fmt, args...));
657  }
658 
659  /// NOTE: Semi-DEPRECATED! This will someday switch to behave like
660  /// fmt::format (or future std::format) but for now, it is back
661  /// compatible and equivalent to sprintf.
662  template<typename... Args>
663  OIIO_FORMAT_DEPRECATED static ustring format(const char* fmt,
664  const Args&... args)
665  {
666  return ustring(Strutil::format(fmt, args...));
667  }
668 
669  /// Concatenate two strings, returning a ustring, implemented carefully
670  /// to not perform any redundant copies or allocations. This is
671  /// semantically equivalent to `ustring::sprintf("%s%s", s, t)`, but is
672  /// more efficient.
674 
675  /// Generic stream output of a ustring.
676  friend std::ostream& operator<<(std::ostream& out, const ustring& str)
677  {
678  if (str.c_str() && out.good())
679  out.write(str.c_str(), str.size());
680  return out;
681  }
682 
683  /// Return the statistics output as a string.
684  static std::string getstats(bool verbose = true);
685 
686  /// Return the amount of memory consumed by the ustring table.
687  static size_t memory();
688 
689  /// Return the total number of ustrings in the internal table.
690  static size_t total_ustrings();
691 
692  /// Return the total number ustrings that have the exact hash as another
693  /// ustring. If `collisions` is passed, store all the colliding ustrings
694  /// in the vector.
695  static size_t hash_collisions(std::vector<ustring>* collisions = nullptr);
696 
697  /// Given a string_view, return a pointer to the unique
698  /// version kept in the internal table (creating a new table entry
699  /// if we haven't seen this sequence of characters before).
700  /// N.B.: this is equivalent to ustring(str).c_str(). It's also the
701  /// routine that is used directly by ustring's internals to generate
702  /// the canonical unique copy of the characters.
703  static const char* make_unique(string_view str);
704 
705  /// Is this character pointer a unique ustring representation of
706  /// those characters? Useful for diagnostics and debugging.
707  static bool is_unique(const char* str)
708  {
709  return str == nullptr || make_unique(str) == str;
710  }
711 
712  /// Create a ustring from characters guaranteed to already be
713  /// ustring-clean, without having to run through the hash yet
714  /// again. Use with extreme caution!!!
715  static ustring from_unique(const char* unique)
716  {
717  OIIO_DASSERT(is_unique(unique)); // DEBUG builds -- check it!
718  ustring u;
719  u.m_chars = unique;
720  return u;
721  }
722 
723 private:
724  // Individual ustring internal representation -- the unique characters.
725  //
726  const char* m_chars;
727 
728 public:
729  // Representation within the hidden string table -- DON'T EVER CREATE
730  // ONE OF THESE YOURSELF!
731  // The characters are found directly after the rep. So that means that
732  // if you know the rep, the chars are at (char *)(rep+1), and if you
733  // know the chars, the rep is at ((TableRep *)chars - 1).
734  struct TableRep {
735  size_t hashed; // precomputed Hash value
736  std::string str; // String representation
737  size_t length; // Length of the string; must be right before cap
738  size_t dummy_capacity; // Dummy field! must be right before refcount
739  int dummy_refcount; // Dummy field! must be right before chars
740  TableRep(string_view strref, size_t hash);
741  ~TableRep();
742  const char* c_str() const noexcept { return (const char*)(this + 1); }
743  };
744 
745 private:
746  static std::string empty_std_string;
747 };
748 
749 
750 
751 /// Functor class to use as a hasher when you want to make a hash_map or
752 /// hash_set using ustring as a key.
753 class ustringHash {
754 public:
755  size_t operator()(const ustring& s) const noexcept { return s.hash(); }
756 };
757 
758 
759 
760 /// Functor class to use for comparisons when sorting ustrings, if you
761 /// want the strings sorted lexicographically.
762 class ustringLess {
763 public:
764  size_t operator()(ustring a, ustring b) const noexcept { return a < b; }
765 };
766 
767 
768 /// Functor class to use for comparisons when sorting ustrings, if you
769 /// don't care if the sort order is lexicographic. This sorts based on
770 /// the pointers themselves, which is safe because once allocated, a
771 /// ustring's characters will never be moved. But beware, the resulting
772 /// sorting order may vary from run to run!
774 public:
775  size_t operator()(ustring a, ustring b) const noexcept
776  {
777  return size_t(a.data()) < size_t(b.data());
778  }
779 };
780 
781 
782 
783 /// Case-insensitive comparison of ustrings. For speed, this always
784 /// uses a static locale that doesn't require a mutex lock.
785 inline bool
787 {
788  return a == b || Strutil::iequals(a.string(), b.string());
789 }
790 
791 inline bool
793 {
794  return Strutil::iequals(a.string(), b);
795 }
796 
797 inline bool
799 {
800  return Strutil::iequals(a, b.string());
801 }
802 
803 
804 
805 // ustring variant stof from OpenImageIO/strutil.h
806 namespace Strutil {
807 
808 inline float
810 {
811  return Strutil::stof(s.string());
812 }
813 
814 template<>
815 inline std::string
817 {
818  return value.string();
819 }
820 
821 } // end namespace Strutil
822 
GLsizei GLenum GLsizei GLsizei GLuint memory
Definition: RE_OGL.h:202
const ustring & assign(const char *str)
Assign a null-terminated C string (char*) to *this.
Definition: ustring.h:222
std::string::const_iterator const_iterator
Definition: ustring.h:116
bool operator==(const ustring &str) const noexcept
Definition: ustring.h:546
static OIIO_FORMAT_DEPRECATED ustring format(const char *fmt, const Args &...args)
Definition: ustring.h:663
value_type * pointer
Definition: ustring.h:111
size_type find_last_of(const char *s, size_type pos, size_type n) const
Definition: ustring.h:449
bool OIIO_UTIL_API iequals(string_view a, string_view b)
size_type find_last_of(const std::string &str, size_type pos=npos) const noexcept
Definition: ustring.h:443
bool operator==(const char *x) const noexcept
Test a ustring (this) for lexicographic equality with char x.
Definition: ustring.h:572
char value_type
Definition: ustring.h:110
size_type find(const char *s, size_type pos=0) const
Definition: ustring.h:375
size_type copy(char *s, size_type n, size_type pos=0) const
Definition: ustring.h:341
size_type find_first_not_of(char c, size_type pos=0) const noexcept
Definition: ustring.h:486
void clear(void) noexcept
Reset to an empty string.
Definition: ustring.h:288
friend bool operator!=(string_view a, const ustring &b) noexcept
Definition: ustring.h:619
size_t length(void) const noexcept
Return the number of characters in the string.
Definition: ustring.h:291
const ustring & assign(string_view str)
Assign a string_view to *this.
Definition: ustring.h:243
const value_type & const_reference
Definition: ustring.h:113
size_type find_first_of(const char *s, size_type pos, size_type n) const
Definition: ustring.h:422
OIIO_CONSTEXPR14 string_view substr(size_type pos, size_type n=npos) const noexcept
Definition: string_view.h:188
size_type rfind(char c, size_type pos=npos) const noexcept
Definition: ustring.h:405
size_type find_last_not_of(char c, size_type pos=npos) const noexcept
Definition: ustring.h:513
std::string format(const Str &fmt, Args &&...args)
Definition: strutil.h:121
size_type rfind(const char *s, size_type pos=npos) const
Definition: ustring.h:400
GLsizei const GLchar *const * string
Definition: glcorearb.h:814
static bool is_unique(const char *str)
Definition: ustring.h:707
bool operator!=(const char *x) const noexcept
Definition: ustring.h:608
value_type & reference
Definition: ustring.h:112
const ustring & operator=(const char *str)
Assign a null-terminated C string (char *) to a ustring.
Definition: ustring.h:253
std::string to_string(const T &value)
Definition: strutil.h:610
GLboolean GLboolean GLboolean GLboolean a
Definition: glcorearb.h:1222
GLdouble s
Definition: glad.h:3009
GLuint GLsizei GLsizei * length
Definition: glcorearb.h:795
size_type find_last_of(char c, size_type pos=npos) const noexcept
Definition: ustring.h:459
ustring(size_type n, char c)
Construct a ustring from n copies of character c.
Definition: ustring.h:153
const ustring & operator=(char c)
Assign a single char to a ustring.
Definition: ustring.h:262
bool operator!=(const std::string &x) const noexcept
Definition: ustring.h:597
bool operator!=(string_view x) const noexcept
Definition: ustring.h:604
ustring substr(size_type pos=0, size_type n=npos) const
Definition: ustring.h:353
const ustring & assign(const std::string &str, size_type pos, size_type n=npos)
Assign a substring of a std::string to *this.
Definition: ustring.h:214
String-related utilities, all in namespace Strutil.
#define OIIO_UTIL_API
Definition: export.h:71
bool operator==(const std::string &x) const noexcept
Definition: ustring.h:562
friend bool operator!=(const std::string &a, const ustring &b) noexcept
Definition: ustring.h:612
const ustring & operator=(string_view str)
Assign a string_view to a ustring.
Definition: ustring.h:259
ustring(const std::string &str, size_type pos, size_type n=npos)
Construct a ustring from an indexed substring of a std::string.
Definition: ustring.h:159
constexpr const_pointer data() const noexcept
Definition: string_view.h:170
size_t hash(void) const noexcept
Return a hashed version of the string.
Definition: ustring.h:300
OIIO_UTIL_API float stof(string_view s, size_t *pos=0)
basic_string_view< char > string_view
Definition: core.h:522
bool empty(void) const noexcept
Definition: ustring.h:313
size_t operator()(ustring a, ustring b) const noexcept
Definition: ustring.h:764
const_iterator begin() const noexcept
Definition: ustring.h:317
CompareResults OIIO_API compare(const ImageBuf &A, const ImageBuf &B, float failthresh, float warnthresh, ROI roi={}, int nthreads=0)
size_type find_last_not_of(const char *s, size_type pos, size_type n) const
Definition: ustring.h:503
const_reverse_iterator rend() const noexcept
Definition: ustring.h:329
GLdouble n
Definition: glcorearb.h:2008
size_type find_last_not_of(const ustring &str, size_type pos=npos) const noexcept
Definition: ustring.h:491
size_type find(const ustring &str, size_type pos=0) const noexcept
Definition: ustring.h:360
static ustring fmtformat(const char *fmt, const Args &...args)
Definition: ustring.h:654
FMT_CONSTEXPR_CHAR_TRAITS auto compare(basic_string_view other) const -> int
Definition: core.h:492
const_reverse_iterator rbegin() const noexcept
Definition: ustring.h:325
ustring(const char *str, size_type pos, size_type n)
Definition: ustring.h:141
size_type find_first_of(const char *s, size_type pos=0) const
Definition: ustring.h:427
const_reference operator[](size_type pos) const noexcept
Definition: ustring.h:334
friend std::ostream & operator<<(std::ostream &out, const ustring &str)
Generic stream output of a ustring.
Definition: ustring.h:676
size_type find_first_not_of(const ustring &str, size_type pos=0) const noexcept
Definition: ustring.h:464
size_t operator()(ustring a, ustring b) const noexcept
Definition: ustring.h:775
std::string str
Definition: ustring.h:736
size_type find_first_not_of(const char *s, size_type pos, size_type n) const
Definition: ustring.h:476
#define OIIO_DASSERT
Definition: dassert.h:55
~ustring() noexcept
ustring destructor.
Definition: ustring.h:181
size_type rfind(const char *s, size_type pos, size_type n) const
Definition: ustring.h:395
const ustring & assign(const char *str, size_type n)
Assign the first n characters of str to *this.
Definition: ustring.h:229
size_type find(const char *s, size_type pos, size_type n) const
Definition: ustring.h:370
static ustring sprintf(const char *fmt, const Args &...args)
Definition: ustring.h:642
GLint GLint GLsizei GLint GLenum format
Definition: glcorearb.h:108
const ustring & assign(size_type n, char c)
Assign n copies of c to *this.
Definition: ustring.h:236
int compare(string_view str) const noexcept
Definition: ustring.h:521
ustring(const ustring &str, size_type pos, size_type n=npos)
Construct a ustring from an indexed substring of a ustring.
Definition: ustring.h:173
size_t operator()(const ustring &s) const noexcept
Definition: ustring.h:755
ustring(void) noexcept
Default ctr for ustring – make an empty string.
Definition: ustring.h:120
ustring(const char *str)
Construct a ustring from a null-terminated C string (char *).
Definition: ustring.h:126
GLboolean GLboolean GLboolean b
Definition: glcorearb.h:1222
const ustring & assign(const ustring &str)
Assign a ustring to *this.
Definition: ustring.h:193
GLint GLenum GLint x
Definition: glcorearb.h:409
bool operator<(const ustring &x) const noexcept
Definition: ustring.h:633
size_t size_type
Definition: ustring.h:114
const ustring & assign(const std::string &str)
Assign a std::string to *this.
Definition: ustring.h:207
friend bool operator==(const std::string &a, const ustring &b) noexcept
Definition: ustring.h:576
GLdouble t
Definition: glad.h:2397
const_iterator end() const noexcept
Definition: ustring.h:321
bool operator!=(const ustring &str) const noexcept
Definition: ustring.h:555
size_type rfind(const std::string &str, size_type pos=npos) const noexcept
Definition: ustring.h:390
I unique(I begin, I end)
Definition: pugixml.cpp:7195
size_type find(const std::string &str, size_type pos=0) const noexcept
Definition: ustring.h:365
GLsizeiptr size
Definition: glcorearb.h:664
ustring(const char *str, size_type n)
Construct a ustring from the first n characters of str.
Definition: ustring.h:147
size_type find_first_not_of(const std::string &str, size_type pos=0) const noexcept
Definition: ustring.h:470
const ustring & assign(const ustring &str, size_type pos, size_type n=npos)
Assign a substring of a ustring to *this.
Definition: ustring.h:200
size_type find_last_of(const char *s, size_type pos=npos) const
Definition: ustring.h:454
size_type find_last_not_of(const std::string &str, size_type pos=npos) const noexcept
Definition: ustring.h:497
bool operator==(string_view x) const noexcept
Definition: ustring.h:569
size_type find_first_of(char c, size_type pos=0) const noexcept
Definition: ustring.h:432
size_t dummy_capacity
Definition: ustring.h:738
size_type find_first_of(const ustring &str, size_type pos=0) const noexcept
Definition: ustring.h:410
operator std::string() const noexcept
Conversion to std::string (explicit only!).
Definition: ustring.h:190
size_type rfind(const ustring &str, size_type pos=npos) const noexcept
Definition: ustring.h:385
constexpr size_type length() const noexcept
Definition: string_view.h:151
ustring(const ustring &str) noexcept
Copy construct a ustring from another ustring.
Definition: ustring.h:167
bool iequals(ustring a, ustring b)
Definition: ustring.h:786
**If you just want to fire and args
Definition: thread.h:609
friend bool operator==(const char *a, const ustring &b) noexcept
Definition: ustring.h:590
size_type find_last_of(const ustring &str, size_type pos=npos) const noexcept
Definition: ustring.h:437
size_type find(char c, size_type pos=0) const noexcept
Definition: ustring.h:380
int compare(const char *str) const noexcept
Definition: ustring.h:529
friend bool operator!=(const char *a, const ustring &b) noexcept
Definition: ustring.h:626
#define OIIO_FORMAT_DEPRECATED
Definition: strutil.h:49
Definition: core.h:1131
static ustring from_unique(const char *unique)
Definition: ustring.h:715
#define const
Definition: zconf.h:214
#define OIIO_NAMESPACE_END
Definition: oiioversion.h:94
auto sprintf(const S &fmt, const T &...args) -> std::basic_string< Char >
Definition: printf.h:574
size_t size(void) const noexcept
Return the number of characters in the string.
Definition: ustring.h:309
size_type find_first_not_of(const char *s, size_type pos=0) const
Definition: ustring.h:481
size_type find_last_not_of(const char *s, size_type pos=npos) const
Definition: ustring.h:508
std::string::const_reverse_iterator const_reverse_iterator
Definition: ustring.h:117
const char * data() const noexcept
Return a C string representation of a ustring.
Definition: ustring.h:275
const char * c_str() const noexcept
Definition: ustring.h:742
const std::string & string() const noexcept
Return a C++ std::string representation of a ustring.
Definition: ustring.h:278
std::string OIIO_UTIL_API concat(string_view s, string_view t)
const char * c_str() const noexcept
Return a C string representation of a ustring.
Definition: ustring.h:272
ustring(string_view str)
Definition: ustring.h:134
const ustring & operator=(const ustring &str)
Assign a ustring to another ustring.
Definition: ustring.h:250
friend bool operator==(string_view a, const ustring &b) noexcept
Definition: ustring.h:583
const ustring & operator=(const std::string &str)
Assign a C++ std::string to a ustring.
Definition: ustring.h:256
#define OIIO_NAMESPACE_BEGIN
Definition: oiioversion.h:93
size_type find_first_of(const std::string &str, size_type pos=0) const noexcept
Definition: ustring.h:416
friend int compare(const std::string &a, const ustring &b) noexcept
Definition: ustring.h:537