HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
string_view.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 // clang-format off
6 
7 #pragma once
8 
9 #include <algorithm>
10 #include <cstddef>
11 #include <cstring>
12 #include <limits>
13 #include <ostream>
14 #include <stdexcept>
15 #include <string>
16 
17 #include <OpenImageIO/export.h>
19 #include <OpenImageIO/platform.h>
20 
21 
23 
24 
25 /// A `string_view` is a non-owning, non-copying, non-allocating reference
26 /// to a sequence of characters. It encapsulates both a character pointer
27 /// and a length.
28 ///
29 /// A function that takes a string input (but does not need to alter the
30 /// string in place) may use a string_view parameter and accept input that
31 /// is any of char* (C string), string literal (constant char array), a
32 /// std::string (C++ string), or OIIO ustring. For all of these cases, no
33 /// extra allocations are performed, and no extra copies of the string
34 /// contents are performed (as they would be, for example, if the function
35 /// took a const std::string& argument but was passed a char* or string
36 /// literal).
37 ///
38 /// Furthermore, a function that returns a copy or a substring of one of its
39 /// inputs (for example, a substr()-like function) may return a string_view
40 /// rather than a std::string, and thus generate its return value without
41 /// any allocation or copying. Upon assignment to a std::string or ustring,
42 /// it will properly auto-convert.
43 ///
44 /// There are two important caveats to using this class:
45 /// 1. The string_view merely refers to characters owned by another string,
46 /// so the string_view may not be used outside the lifetime of the string
47 /// it refers to. Thus, string_view is great for parameter passing, but
48 /// it's not a good idea to use a string_view to store strings in a data
49 /// structure (unless you are really sure you know what you're doing).
50 /// 2. Because the run of characters that the string_view refers to may not
51 /// be 0-terminated, it is important to distinguish between the data()
52 /// method, which returns the pointer to the characters, and the c_str()
53 /// method, which is guaranteed to return a valid C string that is
54 /// 0-terminated. Thus, if you want to pass the contents of a string_view
55 /// to a function that expects a 0-terminated string (say, fopen), you
56 /// must call fopen(my_string_view.c_str()). Note that the usual case
57 /// is that the string_view does refer to a 0-terminated string, and in
58 /// that case c_str() returns the same thing as data() without any extra
59 /// expense; but in the rare case that it is not 0-terminated, c_str()
60 /// will incur extra expense to internally allocate a valid C string.
61 ///
62 
63 
65 public:
66  using charT = char;
67  using Traits = std::char_traits<charT>; // standard name
69  using value_type = charT;
70  using pointer = const charT*;
71  using const_pointer = const charT*;
72  using reference = const charT&;
73  using const_reference = const charT&;
76  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
78  using size_type = size_t;
79  using difference_type = ptrdiff_t;
80  using traits = std::char_traits<charT>; // obsolete custom name
81  static const size_type npos = ~size_type(0);
82 
83  /// Default ctr
84  constexpr string_view() noexcept : m_chars(nullptr), m_len(0) { }
85 
86  /// Copy ctr
87  constexpr string_view(const string_view& copy)
88  : m_chars(copy.data()), m_len(copy.size()) { }
89 
90  /// Construct from char* and length.
91  constexpr string_view(const charT* chars, size_t len)
92  : m_chars(chars), m_len(len) { }
93 
94  /// Construct from char*, use strlen to determine length.
95  OIIO_CONSTEXPR17 string_view(const charT* chars)
96  : m_chars(chars), m_len(chars ? Traits::length(chars) : 0) { }
97  // N.B. char_traits::length() is constexpr starting with C++17.
98 
99  /// Construct from std::string. Remember that a string_view doesn't have
100  /// its own copy of the characters, so don't use the `string_view` after
101  /// the original string has been destroyed or altered.
102  string_view(const std::string& str) noexcept
103  : m_chars(str.data()), m_len(str.size()) { }
104  // N.B. std::string::size() is constexpr starting with C++20.
105 
106  /// Convert a string_view to a `std::string`.
107  std::string str() const
108  {
109  return (m_chars ? std::string(m_chars, m_len) : std::string());
110  // N.B. std::string ctr from chars+len is constexpr in C++20.
111  }
112 
113  /// Explicitly request a 0-terminated string. USUALLY, this turns out to
114  /// be just data(), with no significant added expense (because most uses
115  /// of string_view are simple wrappers of C strings, C++ std::string, or
116  /// ustring -- all of which are 0-terminated). But in the more rare case
117  /// that the string_view represents a non-0-terminated substring, it
118  /// will force an allocation and copy underneath.
119  ///
120  /// Caveats:
121  /// 1. This is NOT going to be part of the C++17 std::string_view, so
122  /// it's probably best to avoid this method if you want to have 100%
123  /// drop-in compatibility with std::string_view.
124  /// 2. It is NOT SAFE to use c_str() on a string_view whose last char
125  /// is the end of an allocation -- because that next char may only
126  /// *coincidentally* be a '\0', which will cause c_str() to return
127  /// the string start (thinking it's a valid C string, so why not just
128  /// return its address?), if there's any chance that the subsequent
129  /// char could change from 0 to non-zero during the use of the result
130  /// of c_str(), and thus break the assumption that it's a valid C str.
131  const char* c_str() const;
132 
133  // Assignment
134  OIIO_CONSTEXPR14 string_view& operator=(const string_view& copy) noexcept = default;
135 
136  /// Convert a string_view to a `std::string`.
137  operator std::string() const { return str(); }
138 
139  // iterators
140  constexpr iterator begin() const noexcept { return m_chars; }
141  constexpr iterator end() const noexcept { return m_chars + m_len; }
142  constexpr const_iterator cbegin() const noexcept { return m_chars; }
143  constexpr const_iterator cend() const noexcept { return m_chars + m_len; }
144  OIIO_CONSTEXPR17 reverse_iterator rbegin() const noexcept { return reverse_iterator (end()); }
145  OIIO_CONSTEXPR17 reverse_iterator rend() const noexcept { return reverse_iterator (begin()); }
146  OIIO_CONSTEXPR17 const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator (cend()); }
147  OIIO_CONSTEXPR17 const_reverse_iterator crend() const noexcept { return const_reverse_iterator (cbegin()); }
148 
149  // capacity
150  constexpr size_type size() const noexcept { return m_len; }
151  constexpr size_type length() const noexcept { return m_len; }
152  constexpr size_type max_size() const noexcept {
154  }
155  /// Is the string_view empty, containing no characters?
156  constexpr bool empty() const noexcept { return m_len == 0; }
157 
158  /// Element access of an individual character (beware: no bounds
159  /// checking!).
160  constexpr const_reference operator[](size_type pos) const { return m_chars[pos]; }
161  /// Element access with bounds checking and exception if out of bounds.
162  OIIO_CONSTEXPR17 const_reference at(size_t pos) const
163  {
164  if (pos >= m_len)
165  throw(std::out_of_range("OpenImageIO::string_view::at"));
166  return m_chars[pos];
167  }
168  constexpr const_reference front() const { return m_chars[0]; }
169  constexpr const_reference back() const { return m_chars[m_len - 1]; }
170  constexpr const_pointer data() const noexcept { return m_chars; }
171 
172  // modifiers
173  OIIO_CONSTEXPR14 void clear() noexcept { init(nullptr, 0); }
175  {
176  if (n > m_len)
177  n = m_len;
178  m_chars += n;
179  m_len -= n;
180  }
182  {
183  if (n > m_len)
184  n = m_len;
185  m_len -= n;
186  }
187 
189  {
190  if (pos >= size())
191  return string_view(); // start past end -> return empty
192  if (n == npos || pos + n > size())
193  n = size() - pos;
194  return string_view(data() + pos, n);
195  }
196 
197  OIIO_CONSTEXPR17 int compare (string_view x) const noexcept {
198  // N.B. char_traits<char>::compare is constexpr for C++17
199  const int cmp = traits_type::compare (m_chars, x.m_chars, (std::min)(m_len, x.m_len));
200  return cmp != 0 ? cmp : int(m_len - x.m_len);
201  // Equivalent to:
202  // cmp != 0 ? cmp : (m_len == x.m_len ? 0 : (m_len < x.m_len ? -1 : 1));
203  }
204 
205 #if 0
206  // Do these later if anybody needs them
207  bool starts_with(string_view x) const noexcept;
208  bool ends_with(string_view x) const noexcept;
209  size_type copy(CharT* dest, size_type count, size_type pos = 0) const;
210 #endif
211 
212  /// Find the first occurrence of substring s in *this, starting at
213  /// position pos.
214  size_type find(string_view s, size_t pos = 0) const noexcept
215  {
216  if (pos > size())
217  pos = size();
218  const_iterator i = std::search(this->cbegin() + pos, this->cend(),
219  s.cbegin(), s.cend(), traits::eq);
220  return i == this->cend() ? npos : std::distance(this->cbegin(), i);
221  }
222 
223  /// Find the first occurrence of character c in *this, starting at
224  /// position pos.
225  size_type find (charT c, size_t pos=0) const noexcept {
226  if (pos > size())
227  pos = size();
228  const_iterator i = std::find_if (this->cbegin()+pos, this->cend(),
229  traits_eq(c));
230  return i == this->cend() ? npos : std::distance (this->cbegin(), i);
231  }
232 
233  /// Find the last occurrence of substring s *this, but only those
234  /// occurrences earlier than position pos.
235  size_type rfind (string_view s, size_t pos=npos) const noexcept {
236  if (pos > size())
237  pos = size();
238  const_reverse_iterator b = this->crbegin()+(size()-pos);
239  const_reverse_iterator e = this->crend();
240  const_reverse_iterator i = std::search (b, e, s.crbegin(), s.crend(), traits::eq);
241  return i == e ? npos : (reverse_distance(this->crbegin(),i) - s.size() + 1);
242  }
243 
244  /// Find the last occurrence of character c in *this, but only those
245  /// occurrences earlier than position pos.
246  size_type rfind (charT c, size_t pos=npos) const noexcept {
247  if (pos > size())
248  pos = size();
249  const_reverse_iterator b = this->crbegin()+(size()-pos);
250  const_reverse_iterator e = this->crend();
251  const_reverse_iterator i = std::find_if (b, e, traits_eq(c));
252  return i == e ? npos : reverse_distance (this->crbegin(),i);
253  }
254 
255  size_type find_first_of (charT c, size_t pos=0) const noexcept { return find (c, pos); }
256 
257  size_type find_last_of (charT c, size_t pos=npos) const noexcept { return rfind (c, pos); }
258 
259  size_type find_first_of (string_view s, size_t pos=0) const noexcept {
260  if (pos >= size())
261  return npos;
262  const_iterator i = std::find_first_of (this->cbegin()+pos, this->cend(),
263  s.cbegin(), s.cend(), traits::eq);
264  return i == this->cend() ? npos : std::distance (this->cbegin(), i);
265  }
266 
267  size_type find_last_of (string_view s, size_t pos=npos) const noexcept {
268  if (pos > size())
269  pos = size();
270  size_t off = size()-pos;
271  const_reverse_iterator i = std::find_first_of (this->crbegin()+off, this->crend(),
272  s.cbegin(), s.cend(), traits::eq);
273  return i == this->crend() ? npos : reverse_distance (this->crbegin(), i);
274  }
275 
276  size_type find_first_not_of (string_view s, size_t pos=0) const noexcept {
277  if (pos >= size())
278  return npos;
279  const_iterator i = find_not_of (this->cbegin()+pos, this->cend(), s);
280  return i == this->cend() ? npos : std::distance (this->cbegin(), i);
281  }
282 
283  size_type find_first_not_of (charT c, size_t pos=0) const noexcept {
284  if (pos >= size())
285  return npos;
286  for (const_iterator i = this->cbegin()+pos; i != this->cend(); ++i)
287  if (! traits::eq (c, *i))
288  return std::distance (this->cbegin(), i);
289  return npos;
290  }
291 
292  size_type find_last_not_of (string_view s, size_t pos=npos) const noexcept {
293  if (pos > size())
294  pos = size();
295  size_t off = size()-pos;
296  const_reverse_iterator i = find_not_of (this->crbegin()+off, this->crend(), s);
297  return i == this->crend() ? npos : reverse_distance (this->crbegin(), i);
298  }
299 
300  size_type find_last_not_of (charT c, size_t pos=npos) const noexcept {
301  if (pos > size())
302  pos = size();
303  size_t off = size()-pos;
304  for (const_reverse_iterator i = this->crbegin()+off; i != this->crend(); ++i)
305  if (! traits::eq (c, *i))
306  return reverse_distance (this->crbegin(), i);
307  return npos;
308  }
309 
310 private:
311  const charT* m_chars = nullptr;
312  size_t m_len = 0;
313 
314  OIIO_CONSTEXPR14 void init(const charT* chars, size_t len) noexcept
315  {
316  m_chars = chars;
317  m_len = len;
318  }
319 
320  template<typename r_iter>
321  size_type reverse_distance(r_iter first, r_iter last) const noexcept
322  {
323  return m_len - 1 - std::distance(first, last);
324  }
325 
326  template<typename iter>
327  iter find_not_of(iter first, iter last, string_view s) const noexcept
328  {
329  for (; first != last; ++first)
330  if (!traits::find(s.data(), s.length(), *first))
331  return first;
332  return last;
333  }
334 
335  class traits_eq {
336  public:
337  constexpr traits_eq (charT ch) noexcept : ch(ch) {}
338  constexpr bool operator () (charT val) const noexcept { return traits::eq (ch, val); }
339  charT ch;
340  };
341 };
342 
343 
344 
345 inline OIIO_CONSTEXPR17 bool
347 {
348  return x.size() == y.size() ? (x.compare(y) == 0) : false;
349 }
350 
351 inline OIIO_CONSTEXPR17 bool
353 {
354  return x.size() == y.size() ? (x.compare(y) != 0) : true;
355 }
356 
357 inline OIIO_CONSTEXPR17 bool
359 {
360  return x.compare(y) < 0;
361 }
362 
363 inline OIIO_CONSTEXPR17 bool
365 {
366  return x.compare(y) > 0;
367 }
368 
369 inline OIIO_CONSTEXPR17 bool
371 {
372  return x.compare(y) <= 0;
373 }
374 
375 inline OIIO_CONSTEXPR17 bool
377 {
378  return x.compare(y) >= 0;
379 }
380 
381 
382 
383 // Inserter
384 inline std::ostream&
385 operator<<(std::ostream& out, const string_view& str)
386 {
387  if (out.good())
388  out.write(str.data(), str.size());
389  return out;
390 }
391 
392 
393 
394 // Temporary name equivalence
396 
397 
399 
400 
401 
402 // Declare std::size and std::ssize for our string_view.
403 namespace std {
404 
405 #if OIIO_CPLUSPLUS_VERSION < 17
406 constexpr size_t size(const OIIO::string_view& c) { return c.size(); }
407 #endif
408 
409 #if OIIO_CPLUSPLUS_VERSION < 20
410 constexpr ptrdiff_t ssize(const OIIO::string_view& c) {
411  return static_cast<ptrdiff_t>(c.size());
412 }
413 #endif
414 
415 // Allow client software to easily know if the std::size/ssize was added for
416 // our string_view.
417 #define OIIO_STRING_VIEW_HAS_STD_SIZE 1
418 
419 
420 } // namespace std
constexpr const_reference operator[](size_type pos) const
Definition: string_view.h:160
#define OIIO_CONSTEXPR14
Definition: platform.h:101
GLboolean GLboolean GLboolean b
Definition: glcorearb.h:1222
OIIO_CONSTEXPR17 const_reverse_iterator crend() const noexcept
Definition: string_view.h:147
constexpr size_t size(const OIIO::span< T, E > &c)
Definition: span.h:380
OIIO_CONSTEXPR14 void clear() noexcept
Definition: string_view.h:173
size_type find_last_not_of(charT c, size_t pos=npos) const noexcept
Definition: string_view.h:300
constexpr string_view(const string_view &copy)
Copy ctr.
Definition: string_view.h:87
GLint first
Definition: glcorearb.h:405
string_view string_ref
Definition: string_view.h:395
const_reverse_iterator reverse_iterator
Definition: string_view.h:77
const_pointer const_iterator
Definition: string_view.h:74
OIIO_CONSTEXPR14 string_view substr(size_type pos, size_type n=npos) const noexcept
Definition: string_view.h:188
size_type rfind(string_view s, size_t pos=npos) const noexcept
Definition: string_view.h:235
OIIO_UTIL_API bool copy(string_view from, string_view to, std::string &err)
size_type find(string_view s, size_t pos=0) const noexcept
Definition: string_view.h:214
const GLfloat * c
Definition: glew.h:16631
OIIO_CONSTEXPR14 void remove_prefix(size_type n) noexcept
Definition: string_view.h:174
bool OIIO_UTIL_API ends_with(string_view a, string_view b)
Does 'a' end with the string 'b', with a case-sensitive comparison?
ImageBuf OIIO_API min(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
size_type find_first_not_of(charT c, size_t pos=0) const noexcept
Definition: string_view.h:283
constexpr const_pointer data() const noexcept
Definition: string_view.h:170
IMATH_HOSTDEVICE constexpr int cmp(T a, T b) IMATH_NOEXCEPT
Definition: ImathFun.h:84
basic_string_view< char > string_view
Definition: core.h:522
GLint GLenum GLint x
Definition: glcorearb.h:409
GLsizeiptr size
Definition: glcorearb.h:664
constexpr size_type size() const noexcept
Definition: string_view.h:150
size_type find_last_not_of(string_view s, size_t pos=npos) const noexcept
Definition: string_view.h:292
CompareResults OIIO_API compare(const ImageBuf &A, const ImageBuf &B, float failthresh, float warnthresh, ROI roi={}, int nthreads=0)
OIIO_CONSTEXPR17 reverse_iterator rbegin() const noexcept
Definition: string_view.h:144
constexpr const_iterator cbegin() const noexcept
Definition: string_view.h:142
Traits traits_type
Definition: string_view.h:68
const charT * pointer
Definition: string_view.h:70
size_type find(charT c, size_t pos=0) const noexcept
Definition: string_view.h:225
GLsizei GLsizei GLfloat distance
Definition: glew.h:13923
GLenum GLsizei len
Definition: glew.h:7782
size_t OIIO_UTIL_API rfind(string_view a, string_view b)
GLuint GLuint end
Definition: glcorearb.h:475
GLsizei const GLchar *const * string
Definition: glcorearb.h:814
OIIO_CONSTEXPR17 reverse_iterator rend() const noexcept
Definition: string_view.h:145
std::ostream & operator<<(std::ostream &out, const string_view &str)
Definition: string_view.h:385
constexpr const_reference front() const
Definition: string_view.h:168
bool operator!=(const Mat3< T0 > &m0, const Mat3< T1 > &m1)
Inequality operator, does exact floating point comparisons.
Definition: Mat3.h:570
constexpr size_type max_size() const noexcept
Definition: string_view.h:152
typedef int(WINAPI *PFNWGLRELEASEPBUFFERDCARBPROC)(HPBUFFERARB hPbuffer
OIIO_CONSTEXPR17 string_view(const charT *chars)
Construct from char*, use strlen to determine length.
Definition: string_view.h:95
PUGI__NS_END PUGI__NS_BEGIN PUGI__FN bool starts_with(const char_t *string, const char_t *pattern)
Definition: pugixml.cpp:7721
constexpr const_reference back() const
Definition: string_view.h:169
GLint GLsizei count
Definition: glcorearb.h:405
OIIO_CONSTEXPR17 bool operator<=(string_view x, string_view y) noexcept
Definition: string_view.h:370
const charT & const_reference
Definition: string_view.h:73
const charT & reference
Definition: string_view.h:72
size_type rfind(charT c, size_t pos=npos) const noexcept
Definition: string_view.h:246
size_type find_last_of(string_view s, size_t pos=npos) const noexcept
Definition: string_view.h:267
size_t size_type
Definition: string_view.h:78
OIIO_CONSTEXPR14 void remove_suffix(size_type n) noexcept
Definition: string_view.h:181
OIIO_CONSTEXPR17 bool operator<(string_view x, string_view y) noexcept
Definition: string_view.h:358
constexpr size_t size(const OIIO::string_view &c)
Definition: string_view.h:406
size_type find_last_of(charT c, size_t pos=npos) const noexcept
Definition: string_view.h:257
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition: string_view.h:76
OIIO_CONSTEXPR17 bool operator>(string_view x, string_view y) noexcept
Definition: string_view.h:364
OIIO_CONSTEXPR17 const_reverse_iterator crbegin() const noexcept
Definition: string_view.h:146
GLdouble n
Definition: glcorearb.h:2008
charT value_type
Definition: string_view.h:69
GLboolean * data
Definition: glcorearb.h:131
GLuint GLsizei GLsizei * length
Definition: glcorearb.h:795
GLuint GLfloat * val
Definition: glcorearb.h:1608
std::string str() const
Convert a string_view to a std::string.
Definition: string_view.h:107
constexpr string_view() noexcept
Default ctr.
Definition: string_view.h:84
ptrdiff_t difference_type
Definition: string_view.h:79
OIIO_CONSTEXPR17 int compare(string_view x) const noexcept
Definition: string_view.h:197
OIIO_CONSTEXPR17 const_reference at(size_t pos) const
Element access with bounds checking and exception if out of bounds.
Definition: string_view.h:162
constexpr iterator begin() const noexcept
Definition: string_view.h:140
constexpr string_view(const charT *chars, size_t len)
Construct from char* and length.
Definition: string_view.h:91
constexpr const_iterator cend() const noexcept
Definition: string_view.h:143
constexpr size_type length() const noexcept
Definition: string_view.h:151
const charT * const_pointer
Definition: string_view.h:71
constexpr iterator end() const noexcept
Definition: string_view.h:141
OIIO_CONSTEXPR17 bool operator>=(string_view x, string_view y) noexcept
Definition: string_view.h:376
ImageBuf OIIO_API max(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
size_type find_first_not_of(string_view s, size_t pos=0) const noexcept
Definition: string_view.h:276
const_iterator iterator
Definition: string_view.h:75
std::char_traits< charT > Traits
Definition: string_view.h:67
#define const
Definition: zconf.h:214
std::char_traits< charT > traits
Definition: string_view.h:80
constexpr ptrdiff_t ssize(const OIIO::span< T, E > &c)
Definition: span.h:393
#define OIIO_NAMESPACE_END
Definition: oiioversion.h:94
GLdouble s
Definition: glew.h:1395
size_type find_first_of(string_view s, size_t pos=0) const noexcept
Definition: string_view.h:259
GLint y
Definition: glcorearb.h:103
bool operator==(const Mat3< T0 > &m0, const Mat3< T1 > &m1)
Equality operator, does exact floating point comparisons.
Definition: Mat3.h:556
Definition: format.h:895
constexpr bool empty() const noexcept
Is the string_view empty, containing no characters?
Definition: string_view.h:156
FMT_CONSTEXPR auto find(Ptr first, Ptr last, T value, Ptr &out) -> bool
Definition: core.h:2089
string_view(const std::string &str) noexcept
Definition: string_view.h:102
#define OIIO_NAMESPACE_BEGIN
Definition: oiioversion.h:93
#define OIIO_API
Definition: export.h:65
size_type find_first_of(charT c, size_t pos=0) const noexcept
Definition: string_view.h:255
PcpNodeRef_ChildrenIterator begin(const PcpNodeRef::child_const_range &r)
Support for range-based for loops for PcpNodeRef children ranges.
Definition: node.h:450