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