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 /*
2  Copyright 2014 Larry Gritz and the other authors and contributors.
3  All Rights Reserved.
4 
5  Redistribution and use in source and binary forms, with or without
6  modification, are permitted provided that the following conditions are
7  met:
8  * Redistributions of source code must retain the above copyright
9  notice, this list of conditions and the following disclaimer.
10  * Redistributions in binary form must reproduce the above copyright
11  notice, this list of conditions and the following disclaimer in the
12  documentation and/or other materials provided with the distribution.
13  * Neither the name of the software's owners nor the names of its
14  contributors may be used to endorse or promote products derived from
15  this software without specific prior written permission.
16  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28  (This is the Modified BSD License)
29 */
30 
31 // clang-format off
32 
33 #pragma once
34 
35 #include <algorithm>
36 #include <cstddef>
37 #include <cstring>
38 #include <ostream>
39 #include <stdexcept>
40 #include <string>
41 
42 #include <OpenImageIO/export.h>
44 
45 
47 
48 
49 /// string_view : a non-owning, non-copying, non-allocating reference to a
50 /// sequence of characters. It encapsulates both a character pointer and a
51 /// length.
52 ///
53 /// A function that takes a string input (but does not need to alter the
54 /// string in place) may use a string_view parameter and accept input that
55 /// is any of char* (C string), string literal (constant char array), a
56 /// std::string (C++ string), or OIIO ustring. For all of these cases, no
57 /// extra allocations are performed, and no extra copies of the string
58 /// contents are performed (as they would be, for example, if the function
59 /// took a const std::string& argument but was passed a char* or string
60 /// literal).
61 ///
62 /// Furthermore, a function that returns a copy or a substring of one of its
63 /// inputs (for example, a substr()-like function) may return a string_view
64 /// rather than a std::string, and thus generate its return value without
65 /// any allocation or copying. Upon assignment to a std::string or ustring,
66 /// it will properly auto-convert.
67 ///
68 /// There are two important caveats to using this class:
69 /// 1. The string_view merely refers to characters owned by another string,
70 /// so the string_view may not be used outside the lifetime of the string
71 /// it refers to. Thus, string_view is great for parameter passing, but
72 /// it's not a good idea to use a string_view to store strings in a data
73 /// structure (unless you are really sure you know what you're doing).
74 /// 2. Because the run of characters that the string_view refers to may not
75 /// be 0-terminated, it is important to distinguish between the data()
76 /// method, which returns the pointer to the characters, and the c_str()
77 /// method, which is guaranteed to return a valid C string that is
78 /// 0-terminated. Thus, if you want to pass the contents of a string_view
79 /// to a function that expects a 0-terminated string (say, fopen), you
80 /// must call fopen(my_string_view.c_str()). Note that the usual case
81 /// is that the string_view does refer to a 0-terminated string, and in
82 /// that case c_str() returns the same thing as data() without any extra
83 /// expense; but in the rare case that it is not 0-terminated, c_str()
84 /// will incur extra expense to internally allocate a valid C string.
85 ///
86 
87 
89 public:
90  typedef char charT;
91  typedef charT value_type;
92  typedef const charT* pointer;
93  typedef const charT* const_pointer;
94  typedef const charT& reference;
95  typedef const charT& const_reference;
98  typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
100  typedef size_t size_type;
101  typedef ptrdiff_t difference_type;
102  typedef std::char_traits<charT> traits;
103  static const size_type npos = ~size_type(0);
104 
105  /// Default ctr
106  string_view() { init(NULL, 0); }
107  /// Copy ctr
108  string_view(const string_view& copy) { init(copy.m_chars, copy.m_len); }
109  /// Construct from char* and length.
110  string_view(const charT* chars, size_t len) { init(chars, len); }
111  /// Construct from char*, use strlen to determine length.
112  string_view(const charT* chars) { init(chars, chars ? strlen(chars) : 0); }
113  /// Construct from std::string.
114  string_view(const std::string& str) { init(str.data(), str.size()); }
115 
116  std::string str() const
117  {
118  return (m_chars ? std::string(m_chars, m_len) : std::string());
119  }
120 
121  /// Explicitly request a 0-terminated string. USUALLY, this turns out to
122  /// be just data(), with no significant added expense (because most uses
123  /// of string_view are simple wrappers of C strings, C++ std::string, or
124  /// ustring -- all of which are 0-terminated). But in the more rare case
125  /// that the string_view represetns a non-0-terminated substring, it
126  /// will force an allocation and copy underneath.
127  ///
128  /// Caveats:
129  /// 1. This is NOT going to be part of the C++17 std::string_view, so
130  /// it's probably best to avoid this method if you want to have 100%
131  /// drop-in compatibility with std::string_view.
132  /// 2. It is NOT SAFE to use c_str() on a string_view whose last char
133  /// is the end of an allocation -- because that next char may only
134  /// *coincidentally* be a '\0', which will cause c_str() to return
135  /// the string start (thinking it's a valid C string, so why not just
136  /// return its address?), if there's any chance that the subsequent
137  /// char could change from 0 to non-zero during the use of the result
138  /// of c_str(), and thus break the assumption that it's a valid C str.
139  const char* c_str() const;
140 
141  // assignments
143  {
144  init(copy.data(), copy.length());
145  return *this;
146  }
147 
148  operator std::string() const { return str(); }
149 
150  // iterators
151  const_iterator begin() const { return m_chars; }
152  const_iterator end() const { return m_chars + m_len; }
153  const_iterator cbegin() const { return m_chars; }
154  const_iterator cend() const { return m_chars + m_len; }
159 
160  // capacity
161  size_type size() const { return m_len; }
162  size_type length() const { return m_len; }
163  size_type max_size() const { return m_len; }
164  bool empty() const { return m_len == 0; }
165 
166  // element access
167  const charT& operator[](size_type pos) const { return m_chars[pos]; }
168  const charT& at(size_t pos) const
169  {
170  if (pos >= m_len)
171  throw(std::out_of_range("OpenImageIO::string_view::at"));
172  return m_chars[pos];
173  }
174  const charT& front() const { return m_chars[0]; }
175  const charT& back() const { return m_chars[m_len - 1]; }
176  const charT* data() const { return m_chars; }
177 
178  // modifiers
179  void clear() { init(NULL, 0); }
181  {
182  if (n > m_len)
183  n = m_len;
184  m_chars += n;
185  m_len -= n;
186  }
188  {
189  if (n > m_len)
190  n = m_len;
191  m_len -= n;
192  }
193 
195  {
196  if (pos > size())
197  return string_view(); // start past end -> return empty
198  if (n == npos || pos + n > size())
199  n = size() - pos;
200  return string_view(data() + pos, n);
201  }
202 
203  int compare (string_view x) const {
204  const int cmp = std::char_traits<char>::compare (m_chars, x.m_chars, (std::min)(m_len, x.m_len));
205  return cmp != 0 ? cmp : int(m_len - x.m_len);
206  // Equivalent to:
207  // cmp != 0 ? cmp : (m_len == x.m_len ? 0 : (m_len < x.m_len ? -1 : 1));
208  }
209 
210 #if 0
211  // Do these later if anybody needs them
212  bool starts_with(string_view x) const;
213  bool ends_with(string_view x) const;
214 #endif
215 
216  /// Find the first occurrence of substring s in *this, starting at
217  /// position pos.
218  size_type find(string_view s, size_t pos = 0) const
219  {
220  if (pos > size())
221  pos = size();
222  const_iterator i = std::search(this->cbegin() + pos, this->cend(),
223  s.cbegin(), s.cend(), traits::eq);
224  return i == this->cend() ? npos : std::distance(this->cbegin(), i);
225  }
226 
227  /// Find the first occurrence of character c in *this, starting at
228  /// position pos.
229  size_type find (charT c, size_t pos=0) const {
230  if (pos > size())
231  pos = size();
232  const_iterator i = std::find_if (this->cbegin()+pos, this->cend(),
233  traits_eq(c));
234  return i == this->cend() ? npos : std::distance (this->cbegin(), i);
235  }
236 
237  /// Find the last occurrence of substring s *this, but only those
238  /// occurrences earlier than position pos.
239  size_type rfind (string_view s, size_t pos=npos) const {
240  if (pos > size())
241  pos = size();
242  const_reverse_iterator b = this->crbegin()+(size()-pos);
243  const_reverse_iterator e = this->crend();
244  const_reverse_iterator i = std::search (b, e, s.crbegin(), s.crend(), traits::eq);
245  return i == e ? npos : (reverse_distance(this->crbegin(),i) - s.size() + 1);
246  }
247 
248  /// Find the last occurrence of character c in *this, but only those
249  /// occurrences earlier than position pos.
250  size_type rfind (charT c, size_t pos=npos) const {
251  if (pos > size())
252  pos = size();
253  const_reverse_iterator b = this->crbegin()+(size()-pos);
254  const_reverse_iterator e = this->crend();
255  const_reverse_iterator i = std::find_if (b, e, traits_eq(c));
256  return i == e ? npos : reverse_distance (this->crbegin(),i);
257  }
258 
259  size_type find_first_of (charT c, size_t pos=0) const { return find (c, pos); }
260 
261  size_type find_last_of (charT c, size_t pos=npos) const { return rfind (c, pos); }
262 
263  size_type find_first_of (string_view s, size_t pos=0) const {
264  if (pos >= size())
265  return npos;
266  const_iterator i = std::find_first_of (this->cbegin()+pos, this->cend(),
267  s.cbegin(), s.cend(), traits::eq);
268  return i == this->cend() ? npos : std::distance (this->cbegin(), i);
269  }
270 
271  size_type find_last_of (string_view s, size_t pos=npos) const {
272  if (pos > size())
273  pos = size();
274  size_t off = size()-pos;
275  const_reverse_iterator i = std::find_first_of (this->crbegin()+off, this->crend(),
276  s.cbegin(), s.cend(), traits::eq);
277  return i == this->crend() ? npos : reverse_distance (this->crbegin(), i);
278  }
279 
280  size_type find_first_not_of (string_view s, size_t pos=0) const {
281  if (pos >= size())
282  return npos;
283  const_iterator i = find_not_of (this->cbegin()+pos, this->cend(), s);
284  return i == this->cend() ? npos : std::distance (this->cbegin(), i);
285  }
286 
287  size_type find_first_not_of (charT c, size_t pos=0) const {
288  if (pos >= size())
289  return npos;
290  for (const_iterator i = this->cbegin()+pos; i != this->cend(); ++i)
291  if (! traits::eq (c, *i))
292  return std::distance (this->cbegin(), i);
293  return npos;
294  }
295 
296  size_type find_last_not_of (string_view s, size_t pos=npos) const {
297  if (pos > size())
298  pos = size();
299  size_t off = size()-pos;
300  const_reverse_iterator i = find_not_of (this->crbegin()+off, this->crend(), s);
301  return i == this->crend() ? npos : reverse_distance (this->crbegin(), i);
302  }
303 
304  size_type find_last_not_of (charT c, size_t pos=npos) const {
305  if (pos > size())
306  pos = size();
307  size_t off = size()-pos;
308  for (const_reverse_iterator i = this->crbegin()+off; i != this->crend(); ++i)
309  if (! traits::eq (c, *i))
310  return reverse_distance (this->crbegin(), i);
311  return npos;
312  }
313 
314 private:
315  const charT* m_chars;
316  size_t m_len;
317 
318  void init(const charT* chars, size_t len)
319  {
320  m_chars = chars;
321  m_len = len;
322  }
323 
324  template<typename r_iter>
325  size_type reverse_distance(r_iter first, r_iter last) const
326  {
327  return m_len - 1 - std::distance(first, last);
328  }
329 
330  template<typename iter>
331  iter find_not_of(iter first, iter last, string_view s) const
332  {
333  for (; first != last; ++first)
334  if (!traits::find(s.data(), s.length(), *first))
335  return first;
336  return last;
337  }
338 
339  class traits_eq {
340  public:
341  traits_eq (charT ch) : ch(ch) {}
342  bool operator () (charT val) const { return traits::eq (ch, val); }
343  charT ch;
344  };
345 };
346 
347 
348 
349 inline bool
351 {
352  return x.size() == y.size() ? (x.compare(y) == 0) : false;
353 }
354 
355 inline bool
357 {
358  return x.size() == y.size() ? (x.compare(y) != 0) : true;
359 }
360 
361 inline bool
363 {
364  return x.compare(y) < 0;
365 }
366 
367 inline bool
369 {
370  return x.compare(y) > 0;
371 }
372 
373 inline bool
375 {
376  return x.compare(y) <= 0;
377 }
378 
379 inline bool
381 {
382  return x.compare(y) >= 0;
383 }
384 
385 
386 
387 // Inserter
388 inline std::ostream&
389 operator<<(std::ostream& out, const string_view& str)
390 {
391  if (out.good())
392  out.write(str.data(), str.size());
393  return out;
394 }
395 
396 
397 
398 // Temporary name equivalence
400 
401 
GLdouble s
Definition: glew.h:1390
GLsizeiptr size
Definition: glew.h:1681
std::char_traits< charT > traits
Definition: string_view.h:102
charT value_type
Definition: string_view.h:91
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition: string_view.h:98
string_view string_ref
Definition: string_view.h:399
size_type rfind(charT c, size_t pos=npos) const
Definition: string_view.h:250
const charT * const_pointer
Definition: string_view.h:93
FMT_CONSTEXPR auto begin(const C &c) -> decltype(c.begin())
Definition: format.h:251
const_iterator cend() const
Definition: string_view.h:154
ptrdiff_t difference_type
Definition: string_view.h:101
GLuint const GLfloat * val
Definition: glew.h:2794
const charT & back() const
Definition: string_view.h:175
size_type find(string_view s, size_t pos=0) const
Definition: string_view.h:218
string_view()
Default ctr.
Definition: string_view.h:106
bool OIIO_API ends_with(string_view a, string_view b)
Does 'a' end with the string 'b', with a case-sensitive comparison?
const GLint * first
Definition: glew.h:1528
const_reverse_iterator rbegin() const
Definition: string_view.h:155
size_t size_type
Definition: string_view.h:100
const_iterator cbegin() const
Definition: string_view.h:153
bool operator>=(string_view x, string_view y)
Definition: string_view.h:380
size_type find_first_of(string_view s, size_t pos=0) const
Definition: string_view.h:263
const_iterator iterator
Definition: string_view.h:97
const charT & reference
Definition: string_view.h:94
size_type find_first_not_of(charT c, size_t pos=0) const
Definition: string_view.h:287
const charT * data() const
Definition: string_view.h:176
size_type find_first_not_of(string_view s, size_t pos=0) const
Definition: string_view.h:280
const charT & const_reference
Definition: string_view.h:95
size_type find(charT c, size_t pos=0) const
Definition: string_view.h:229
CompareResults OIIO_API compare(const ImageBuf &A, const ImageBuf &B, float failthresh, float warnthresh, ROI roi={}, int nthreads=0)
const_iterator end() const
Definition: string_view.h:152
const_pointer const_iterator
Definition: string_view.h:96
GLint GLint GLint GLint GLint x
Definition: glew.h:1252
size_type size() const
Definition: string_view.h:161
void clear()
Definition: string_view.h:179
GLint GLint GLint GLint GLint GLint y
Definition: glew.h:1252
GLint GLenum GLsizei GLint GLsizei const void * data
Definition: glew.h:1379
size_type find_first_of(charT c, size_t pos=0) const
Definition: string_view.h:259
void remove_prefix(size_type n)
Definition: string_view.h:180
GLuint GLuint end
Definition: glew.h:1253
basic_string_view< char > string_view
Definition: core.h:426
std::ostream & operator<<(std::ostream &out, const string_view &str)
Definition: string_view.h:389
bool operator<=(string_view x, string_view y)
Definition: string_view.h:374
GLsizei n
Definition: glew.h:4040
const GLfloat * c
Definition: glew.h:16296
GLsizei GLsizei GLfloat distance
Definition: glew.h:13640
const_iterator begin() const
Definition: string_view.h:151
bool operator!=(const Mat3< T0 > &m0, const Mat3< T1 > &m1)
Inequality operator, does exact floating point comparisons.
Definition: Mat3.h:604
typedef int(WINAPI *PFNWGLRELEASEPBUFFERDCARBPROC)(HPBUFFERARB hPbuffer
string_view(const std::string &str)
Construct from std::string.
Definition: string_view.h:114
PUGI__NS_END PUGI__NS_BEGIN PUGI__FN bool starts_with(const char_t *string, const char_t *pattern)
Definition: pugixml.cpp:7721
const_reverse_iterator reverse_iterator
Definition: string_view.h:99
int cmp(T a, T b)
Definition: ImathFun.h:119
GLdouble GLdouble GLdouble b
Definition: glew.h:9122
const charT & front() const
Definition: string_view.h:174
std::string str() const
Definition: string_view.h:116
GLsizei const GLchar *const * string
Definition: glew.h:1844
const_reverse_iterator rend() const
Definition: string_view.h:156
string_view(const charT *chars, size_t len)
Construct from char* and length.
Definition: string_view.h:110
size_type find_last_of(string_view s, size_t pos=npos) const
Definition: string_view.h:271
string_view(const string_view &copy)
Copy ctr.
Definition: string_view.h:108
const_reverse_iterator crbegin() const
Definition: string_view.h:157
bool operator>(string_view x, string_view y)
Definition: string_view.h:368
size_type length() const
Definition: string_view.h:162
bool empty() const
Definition: string_view.h:164
FMT_CONSTEXPR bool find(Ptr first, Ptr last, T value, Ptr &out)
Definition: format.h:2104
int compare(string_view x) const
Definition: string_view.h:203
OIIO_API bool copy(string_view from, string_view to, std::string &err)
string_view substr(size_type pos, size_type n=npos) const
Definition: string_view.h:194
size_type find_last_of(charT c, size_t pos=npos) const
Definition: string_view.h:261
const charT * pointer
Definition: string_view.h:92
size_type rfind(string_view s, size_t pos=npos) const
Definition: string_view.h:239
size_type find_last_not_of(charT c, size_t pos=npos) const
Definition: string_view.h:304
string_view(const charT *chars)
Construct from char*, use strlen to determine length.
Definition: string_view.h:112
#define OIIO_NAMESPACE_END
Definition: oiioversion.h:66
vint4 min(const vint4 &a, const vint4 &b)
Definition: simd.h:4694
string_view & operator=(const string_view &copy)
Definition: string_view.h:142
const_reverse_iterator crend() const
Definition: string_view.h:158
bool operator==(const Mat3< T0 > &m0, const Mat3< T1 > &m1)
Equality operator, does exact floating point comparisons.
Definition: Mat3.h:590
const charT & at(size_t pos) const
Definition: string_view.h:168
size_type max_size() const
Definition: string_view.h:163
const charT & operator[](size_type pos) const
Definition: string_view.h:167
size_type find_last_not_of(string_view s, size_t pos=npos) const
Definition: string_view.h:296
bool operator<(string_view x, string_view y)
Definition: string_view.h:362
GLenum GLsizei len
Definition: glew.h:7752
#define OIIO_NAMESPACE_BEGIN
Definition: oiioversion.h:65
#define OIIO_API
Definition: export.h:91
void remove_suffix(size_type n)
Definition: string_view.h:187