HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
span.h
Go to the documentation of this file.
1 // Copyright 2008-present Contributors to the OpenImageIO project.
2 // https://github.com/OpenImageIO/oiio
3 // BSD 3-clause license:
4 // https://github.com/OpenImageIO/oiio/blob/master/LICENSE
5 
6 // clang-format off
7 
8 #pragma once
9 
10 #include <array>
11 #include <cstddef>
12 #include <initializer_list>
13 #include <iostream>
14 #include <stdexcept>
15 #include <type_traits>
16 #include <vector>
17 
18 #include <OpenImageIO/dassert.h>
20 #include <OpenImageIO/platform.h>
21 
23 
24 // By default, our span::size() is a signed value, because we wrote this at
25 // a time that the draft of std::span said it should be signed. The final
26 // C++20 std::span ended up with an unsigned size, like all the other STL
27 // classes. We will eventually conform by switching, but not until we are at
28 // OIIO 3.0, allowing source code API-breaking incompatibilities. In the
29 // mean time, we allow a back door to experiment with standard conformance
30 // by pre-defining OIIO_SPAN_SIZE_IS_UNSIGNED=1.
31 #if OIIO_VERSION_GREATER_EQUAL(3,0,0)
32 # define OIIO_SPAN_SIZE_IS_UNSIGNED
33 #endif
34 
35 #ifdef OIIO_SPAN_SIZE_IS_UNSIGNED
36 using oiio_span_size_type = size_t;
37 #else
38 using oiio_span_size_type = ptrdiff_t;
39 #endif
40 
41 OIIO_INLINE_CONSTEXPR oiio_span_size_type dynamic_extent = -1;
42 
43 
44 
45 /// span<T> is a non-owning, non-copying, non-allocating reference to a
46 /// contiguous array of T objects known length. A 'span` encapsulates both a
47 /// pointer and a length, and thus is a safer way of passing pointers around
48 /// (because the function called knows how long the array is). A function
49 /// that might ordinarily take a `T*` and a length could instead just take a
50 /// `span<T>`.
51 ///
52 /// `A span<T>` is mutable (the values in the array may be modified). A
53 /// non-mutable (i.e., read-only) reference would be `span<const T>`. Thus,
54 /// a function that might ordinarily take a `const T*` and a length could
55 /// instead take a `span<const T>`.
56 ///
57 /// For convenience, we also define `cspan<T>` as equivalent to
58 /// `span<const T>`.
59 ///
60 /// A `span` may be initialized explicitly from a pointer and length, by
61 /// initializing with a `std::vector<T>`, or by initalizing with a constant
62 /// (treated as an array of length 1). For all of these cases, no extra
63 /// allocations are performed, and no extra copies of the array contents are
64 /// made.
65 ///
66 /// Important caveat: The `span` merely refers to items owned by another
67 /// array, so the `span` should not be used beyond the lifetime of the
68 /// array it refers to. Thus, `span` is great for parameter passing, but
69 /// it's not a good idea to use a `span` to store values in a data
70 /// structure (unless you are really sure you know what you're doing).
71 ///
72 
73 template <typename T, oiio_span_size_type Extent = dynamic_extent>
74 class span {
75  static_assert (std::is_array<T>::value == false, "can't have span of an array");
76 public:
77  using element_type = T;
80  using difference_type = ptrdiff_t;
81 #if OIIO_VERSION < OIIO_MAKE_VERSION(3,0,0)
82  using index_type = size_type; // DEPRECATED(3.0)
83 #endif
87  using const_iterator = const element_type*;
88  using reverse_iterator = std::reverse_iterator<iterator>;
89  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
90  static constexpr size_type extent = Extent;
91 
92  /// Default constructor -- the span points to nothing.
93  constexpr span () noexcept { }
94 
95  /// Copy constructor (copies the span pointer and length, NOT the data).
96  template<class U, oiio_span_size_type N>
97  constexpr span (const span<U,N> &copy) noexcept
98  : m_data(copy.data()), m_size(copy.size()) { }
99  /// Copy constructor (copies the span pointer and length, NOT the data).
100  constexpr span (const span &copy) noexcept = default;
101 
102  /// Construct from T* and length.
103  constexpr span (pointer data, size_type size) noexcept
104  : m_data(data), m_size(size) { }
105 
106  /// Construct from begin and end pointers.
107  constexpr span (pointer b, pointer e) noexcept
108  : m_data(b), m_size(e-b) { }
109 
110  /// Construct from a single T&.
111  constexpr span (T &data) : m_data(&data), m_size(1) { }
112 
113  /// Construct from a fixed-length C array. Template magic automatically
114  /// finds the length from the declared type of the array.
115  template<size_t N>
116  constexpr span (T (&data)[N]) : m_data(data), m_size(N) { }
117 
118  /// Construct from std::vector<T>.
119  template<class Allocator>
120  constexpr span (std::vector<T, Allocator> &v)
121  : m_data(v.size() ? &v[0] : nullptr), m_size(v.size()) {
122  }
123 
124  /// Construct from `const std::vector<T>.` This turns
125  /// `const std::vector<T>` into a `span<const T>` (the span isn't const,
126  /// but the data it points to will be).
127  template<class Allocator>
128  span (const std::vector<value_type, Allocator> &v)
129  : m_data(v.size() ? &v[0] : nullptr), m_size(v.size()) { }
130 
131  /// Construct from mutable element std::array
132  template <size_t N>
133  constexpr span (std::array<value_type, N> &arr)
134  : m_data(arr.data()), m_size(N) {}
135 
136  /// Construct from read-only element std::array
137  template <size_t N>
138  constexpr span (const std::array<value_type, N>& arr)
139  : m_data(arr.data()), m_size(N) {}
140 
141  /// Construct an span from an initializer_list.
142  constexpr span (std::initializer_list<T> il)
143  : span (il.begin(), il.size()) { }
144 
145  /// Assignment copies the pointer and length, not the data.
147  m_data = copy.data();
148  m_size = copy.size();
149  return *this;
150  }
151 
152  /// Subview containing the first Count elements of the span.
153  template<size_type Count>
154  constexpr span<element_type, Count> first () const {
155  return { m_data, Count };
156  }
157  /// Subview containing the last Count elements of the span.
158  template<size_type Count>
159  constexpr span<element_type, Count> last () const {
160  return { m_data + m_size - Count, Count };
161  }
162 
163  template<size_type Offset, size_type Count = dynamic_extent>
164  constexpr span<element_type, Count> subspan () const {
165  return { m_data + Offset, Count != dynamic_extent ? Count : (Extent != dynamic_extent ? Extent - Offset : m_size - Offset) };
166  }
167 
169  return { m_data, count };
170  }
171 
173  return { m_data + ( m_size - count ), count };
174  }
175 
178  return { m_data + offset, count == dynamic_extent ? m_size - offset : count };
179  }
180 
181  // Note: size() currently returns a signed value. But eventually, we
182  // will conform to std::span<>::size() which returns size_t. In the mean
183  // time, apps may choose to avoid the size() method and instead use
184  // std::size(myspan) and std::ssize(myspan), which already conform to
185  // std's practice of returning size_t and ptrdiff_t, respectively.
186  constexpr size_type size() const noexcept { return m_size; }
187  constexpr size_type size_bytes() const noexcept { return size()*sizeof(T); }
188  constexpr bool empty() const noexcept { return m_size == 0; }
189 
190  constexpr pointer data() const noexcept { return m_data; }
191 
192  constexpr reference operator[] (size_type idx) const { return m_data[idx]; }
193  constexpr reference operator() (size_type idx) const { return m_data[idx]; }
194  reference at (size_type idx) const {
195  if (idx >= size())
196  throw (std::out_of_range ("OpenImageIO::span::at"));
197  return m_data[idx];
198  }
199 
200  constexpr reference front() const noexcept { return m_data[0]; }
201  constexpr reference back() const noexcept { return m_data[size()-1]; }
202 
203  constexpr iterator begin() const noexcept { return m_data; }
204  constexpr iterator end() const noexcept { return m_data + m_size; }
205 
206  constexpr const_iterator cbegin() const noexcept { return m_data; }
207  constexpr const_iterator cend() const noexcept { return m_data + m_size; }
208 
209  constexpr reverse_iterator rbegin() const noexcept { return m_data + m_size - 1; }
210  constexpr reverse_iterator rend() const noexcept { return m_data - 1; }
211 
212  constexpr const_reverse_iterator crbegin() const noexcept { return m_data + m_size - 1; }
213  constexpr const_reverse_iterator crend() const noexcept { return m_data - 1; }
214 
215 private:
216  pointer m_data = nullptr;
217  size_type m_size = 0;
218 };
219 
220 
221 
222 /// cspan<T> is a synonym for a non-mutable span<const T>.
223 template <typename T>
225 
226 
227 
228 /// Compare all elements of two spans for equality
229 template <class T, oiio_span_size_type X, class U, oiio_span_size_type Y>
230 OIIO_CONSTEXPR14 bool operator== (span<T,X> l, span<U,Y> r) {
231 #if OIIO_CPLUSPLUS_VERSION >= 20
232  return std::equal (l.begin(), l.end(), r.begin(), r.end());
233 #else
234  auto lsize = l.size();
235  bool same = (lsize == r.size());
236  for (ptrdiff_t i = 0; same && i < lsize; ++i)
237  same &= (l[i] == r[i]);
238  return same;
239 #endif
240 }
241 
242 /// Compare all elements of two spans for inequality
243 template <class T, oiio_span_size_type X, class U, oiio_span_size_type Y>
244 OIIO_CONSTEXPR14 bool operator!= (span<T,X> l, span<U,Y> r) {
245  return !(l == r);
246 }
247 
248 
249 
250 /// span_strided<T> : a non-owning, mutable reference to a contiguous
251 /// array with known length and optionally non-default strides through the
252 /// data. An span_strided<T> is mutable (the values in the array may
253 /// be modified), whereas an span_strided<const T> is not mutable.
254 template <typename T, oiio_span_size_type Extent = dynamic_extent>
256  static_assert (std::is_array<T>::value == false,
257  "can't have span_strided of an array");
258 public:
259  using element_type = T;
262  using difference_type = ptrdiff_t;
263 #if OIIO_VERSION < OIIO_MAKE_VERSION(3,0,0)
264  using index_type = size_type; // DEPRECATED(3.0)
265 #endif
266  using stride_type = ptrdiff_t;
270  using const_iterator = const element_type*;
271  using reverse_iterator = std::reverse_iterator<iterator>;
272  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
273  static constexpr size_type extent = Extent;
274 
275  /// Default ctr -- points to nothing
276  constexpr span_strided () noexcept {}
277 
278  /// Copy constructor
279  constexpr span_strided (const span_strided &copy)
280  : m_data(copy.data()), m_size(copy.size()), m_stride(copy.stride()) {}
281 
282  /// Construct from T* and size, and optionally stride.
284  : m_data(data), m_size(size), m_stride(stride) { }
285 
286  /// Construct from a single T&.
287  constexpr span_strided (T &data) : span_strided(&data,1,1) { }
288 
289  /// Construct from a fixed-length C array. Template magic automatically
290  /// finds the length from the declared type of the array.
291  template<size_t N>
292  constexpr span_strided (T (&data)[N]) : span_strided(data,N,1) {}
293 
294  /// Construct from std::vector<T>.
295  template<class Allocator>
296  OIIO_CONSTEXPR14 span_strided (std::vector<T, Allocator> &v)
297  : span_strided(v.size() ? &v[0] : nullptr, v.size(), 1) {}
298 
299  /// Construct from const std::vector<T>. This turns const std::vector<T>
300  /// into an span_strided<const T> (the span_strided isn't
301  /// const, but the data it points to will be).
302  template<class Allocator>
303  constexpr span_strided (const std::vector<value_type, Allocator> &v)
304  : span_strided(v.size() ? &v[0] : nullptr, v.size(), 1) {}
305 
306  /// Construct an span from an initializer_list.
307  constexpr span_strided (std::initializer_list<T> il)
308  : span_strided (il.begin(), il.size()) { }
309 
310  /// Initialize from an span (stride will be 1).
311  constexpr span_strided (span<T> av)
312  : span_strided(av.data(), av.size(), 1) { }
313 
314  // assignments
316  m_data = copy.data();
317  m_size = copy.size();
318  m_stride = copy.stride();
319  return *this;
320  }
321 
322  constexpr size_type size() const noexcept { return m_size; }
323  constexpr stride_type stride() const noexcept { return m_stride; }
324 
325  constexpr reference operator[] (size_type idx) const {
326  return m_data[m_stride*idx];
327  }
328  constexpr reference operator() (size_type idx) const {
329  return m_data[m_stride*idx];
330  }
331  reference at (size_type idx) const {
332  if (idx >= size())
333  throw (std::out_of_range ("OpenImageIO::span_strided::at"));
334  return m_data[m_stride*idx];
335  }
336  constexpr reference front() const noexcept { return m_data[0]; }
337  constexpr reference back() const noexcept { return (*this)[size()-1]; }
338  constexpr pointer data() const noexcept { return m_data; }
339 
340 private:
341  pointer m_data = nullptr;
342  size_type m_size = 0;
343  stride_type m_stride = 1;
344 };
345 
346 
347 
348 /// cspan_strided<T> is a synonym for a non-mutable span_strided<const T>.
349 template <typename T>
351 
352 
353 
354 /// Compare all elements of two spans for equality
355 template <class T, oiio_span_size_type X, class U, oiio_span_size_type Y>
357  auto lsize = l.size();
358  if (lsize != r.size())
359  return false;
360  for (ptrdiff_t i = 0; i < lsize; ++i)
361  if (l[i] != r[i])
362  return false;
363  return true;
364 }
365 
366 /// Compare all elements of two spans for inequality
367 template <class T, oiio_span_size_type X, class U, oiio_span_size_type Y>
369  return !(l == r);
370 }
371 
372 
374 
375 
376 
377 // Declare std::size and std::ssize for our span.
378 namespace std {
379 
380 template<class T, OIIO::oiio_span_size_type E = OIIO::dynamic_extent>
381 constexpr size_t size(const OIIO::span<T, E>& c) {
382  return static_cast<size_t>(c.size());
383 }
384 
385 template<class T, OIIO::oiio_span_size_type E = OIIO::dynamic_extent>
386 constexpr size_t size(const OIIO::span_strided<T, E>& c) {
387  return static_cast<size_t>(c.size());
388 }
389 
390 
391 #if OIIO_CPLUSPLUS_VERSION < 20
392 // C++20 and beyond already have these declared.
393 template<class T, OIIO::oiio_span_size_type E = OIIO::dynamic_extent>
394 constexpr ptrdiff_t ssize(const OIIO::span<T, E>& c) {
395  return static_cast<ptrdiff_t>(c.size());
396 }
397 
398 template<class T, OIIO::oiio_span_size_type E = OIIO::dynamic_extent>
399 constexpr ptrdiff_t ssize(const OIIO::span_strided<T, E>& 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 span templates.
406 #define OIIO_SPAN_HAS_STD_SIZE 1
407 
408 } // namespace std
type
Definition: core.h:977
GLint GLenum GLsizei GLsizei GLsizei GLsizei extent
Definition: glew.h:15877
GLboolean GLboolean GLboolean b
Definition: glcorearb.h:1221
constexpr span(std::array< value_type, N > &arr)
Construct from mutable element std::array.
Definition: span.h:133
constexpr const_iterator cend() const noexcept
Definition: span.h:207
typename std::remove_cv< T >::type value_type
Definition: span.h:260
constexpr iterator end() const noexcept
Definition: span.h:204
constexpr span(std::vector< T, Allocator > &v)
Construct from std::vector<T>.
Definition: span.h:120
constexpr span_strided(const span_strided &copy)
Copy constructor.
Definition: span.h:279
constexpr span< element_type, dynamic_extent > subspan(size_type offset, size_type count=dynamic_extent) const
Definition: span.h:177
ptrdiff_t difference_type
Definition: span.h:262
constexpr span< element_type, Count > first() const
Subview containing the first Count elements of the span.
Definition: span.h:154
span & operator=(const span &copy)
Assignment copies the pointer and length, not the data.
Definition: span.h:146
element_type * iterator
Definition: span.h:269
constexpr span_strided(T(&data)[N])
Definition: span.h:292
constexpr span_strided(pointer data, size_type size, stride_type stride=1)
Construct from T* and size, and optionally stride.
Definition: span.h:283
const GLfloat * c
Definition: glew.h:16631
constexpr span< element_type, Count > subspan() const
Definition: span.h:164
typename std::remove_cv< unsigned char >::type value_type
Definition: span.h:78
Definition: span.h:74
T element_type
Definition: span.h:259
constexpr span_strided() noexcept
Default ctr – points to nothing.
Definition: span.h:276
constexpr size_type size() const noexcept
Definition: span.h:322
constexpr span_strided(span< T > av)
Initialize from an span (stride will be 1).
Definition: span.h:311
std::reverse_iterator< iterator > reverse_iterator
Definition: span.h:271
GLdouble l
Definition: glew.h:9164
GLsizeiptr size
Definition: glcorearb.h:663
ptrdiff_t oiio_span_size_type
Definition: span.h:38
ptrdiff_t difference_type
Definition: span.h:80
constexpr const_iterator cbegin() const noexcept
Definition: span.h:206
constexpr reference back() const noexcept
Definition: span.h:201
constexpr span(std::initializer_list< T > il)
Construct an span from an initializer_list.
Definition: span.h:142
ptrdiff_t stride_type
Definition: span.h:266
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition: span.h:89
OIIO_CONSTEXPR14 bool operator==(span< T, X > l, span< U, Y > r)
Compare all elements of two spans for equality.
Definition: span.h:230
constexpr reference operator()(size_type idx) const
Definition: span.h:193
OIIO_CONSTEXPR14 bool operator!=(span< T, X > l, span< U, Y > r)
Compare all elements of two spans for inequality.
Definition: span.h:244
OIIO_CONSTEXPR14 span_strided(std::vector< T, Allocator > &v)
Construct from std::vector<T>.
Definition: span.h:296
constexpr iterator begin() const noexcept
Definition: span.h:203
OIIO_INLINE_CONSTEXPR oiio_span_size_type dynamic_extent
Definition: span.h:41
constexpr span< element_type, Count > last() const
Subview containing the last Count elements of the span.
Definition: span.h:159
constexpr pointer data() const noexcept
Definition: span.h:338
element_type * iterator
Definition: span.h:86
const GLdouble * v
Definition: glcorearb.h:836
const element_type * const_iterator
Definition: span.h:270
constexpr const_reverse_iterator crend() const noexcept
Definition: span.h:213
constexpr reference operator[](size_type idx) const
Definition: span.h:192
constexpr span_strided(const std::vector< value_type, Allocator > &v)
Definition: span.h:303
element_type & reference
Definition: span.h:85
const element_type * const_iterator
Definition: span.h:87
constexpr span(T &data)
Construct from a single T&.
Definition: span.h:111
constexpr size_type size() const noexcept
Definition: span.h:186
GLint GLsizei count
Definition: glcorearb.h:404
constexpr reverse_iterator rbegin() const noexcept
Definition: span.h:209
constexpr span< element_type, dynamic_extent > last(size_type count) const
Definition: span.h:172
constexpr span_strided(std::initializer_list< T > il)
Construct an span from an initializer_list.
Definition: span.h:307
constexpr span(const std::array< value_type, N > &arr)
Construct from read-only element std::array.
Definition: span.h:138
unsigned char element_type
Definition: span.h:77
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition: span.h:272
oiio_span_size_type size_type
Definition: span.h:261
GLboolean * data
Definition: glcorearb.h:130
constexpr ptrdiff_t ssize(const OIIO::span_strided< T, E > &c)
Definition: span.h:399
reference at(size_type idx) const
Definition: span.h:331
constexpr span(const span< U, N > &copy) noexcept
Copy constructor (copies the span pointer and length, NOT the data).
Definition: span.h:97
constexpr reference back() const noexcept
Definition: span.h:337
constexpr span(T(&data)[N])
Definition: span.h:116
reference at(size_type idx) const
Definition: span.h:194
constexpr span(pointer data, size_type size) noexcept
Construct from T* and length.
Definition: span.h:103
oiio_span_size_type size_type
Definition: span.h:79
constexpr size_type size_bytes() const noexcept
Definition: span.h:187
constexpr reference front() const noexcept
Definition: span.h:200
OIIO_API bool copy(string_view from, string_view to, std::string &err)
constexpr span_strided(T &data)
Construct from a single T&.
Definition: span.h:287
GA_API const UT_StringHolder N
constexpr span< element_type, dynamic_extent > first(size_type count) const
Definition: span.h:168
span(const std::vector< value_type, Allocator > &v)
Definition: span.h:128
GLsizei const GLfloat * value
Definition: glcorearb.h:823
bool equal(T1 a, T2 b, T3 t)
Definition: ImathFun.h:143
constexpr bool empty() const noexcept
Definition: span.h:188
constexpr span(pointer b, pointer e) noexcept
Construct from begin and end pointers.
Definition: span.h:107
element_type * pointer
Definition: span.h:267
element_type * pointer
Definition: span.h:84
GLintptr offset
Definition: glcorearb.h:664
constexpr reference front() const noexcept
Definition: span.h:336
#define const
Definition: zconf.h:214
GLint GLenum GLboolean GLsizei stride
Definition: glcorearb.h:871
#define OIIO_NAMESPACE_END
Definition: oiioversion.h:94
element_type & reference
Definition: span.h:268
GLboolean r
Definition: glcorearb.h:1221
constexpr span() noexcept
Default constructor – the span points to nothing.
Definition: span.h:93
constexpr reverse_iterator rend() const noexcept
Definition: span.h:210
GLenum void ** pointer
Definition: glcorearb.h:809
constexpr pointer data() const noexcept
Definition: span.h:190
constexpr const_reverse_iterator crbegin() const noexcept
Definition: span.h:212
#define OIIO_NAMESPACE_BEGIN
Definition: oiioversion.h:93
constexpr stride_type stride() const noexcept
Definition: span.h:323
std::reverse_iterator< iterator > reverse_iterator
Definition: span.h:88