HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
span.h
Go to the documentation of this file.
1 //
2 // Copyright 2019 Pixar
3 //
4 // Licensed under the Apache License, Version 2.0 (the "Apache License")
5 // with the following modification; you may not use this file except in
6 // compliance with the Apache License and the following modification to it:
7 // Section 6. Trademarks. is deleted and replaced with:
8 //
9 // 6. Trademarks. This License does not grant permission to use the trade
10 // names, trademarks, service marks, or product names of the Licensor
11 // and its affiliates, except as required to comply with Section 4(c) of
12 // the License and to reproduce the content of the NOTICE file.
13 //
14 // You may obtain a copy of the Apache License at
15 //
16 // http://www.apache.org/licenses/LICENSE-2.0
17 //
18 // Unless required by applicable law or agreed to in writing, software
19 // distributed under the Apache License with the above modification is
20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21 // KIND, either express or implied. See the Apache License for the specific
22 // language governing permissions and limitations under the Apache License.
23 //
24 #ifndef PXR_BASE_TF_SPAN_H
25 #define PXR_BASE_TF_SPAN_H
26 
27 /// \file tf/span.h
28 
29 #include "pxr/pxr.h"
30 #include "pxr/base/tf/api.h"
31 #include "pxr/base/tf/diagnostic.h"
32 
33 #include <cstddef>
34 #include <iterator>
35 #include <type_traits>
36 
37 
39 
40 
41 /// \class TfSpan
42 /// Represents a range of contiguous elements.
43 ///
44 /// This simply pairs a pointer with a size, while adding a common
45 /// array interface.
46 ///
47 /// A span allows ranges of elements to be referenced in a container-neutral
48 /// manner. While it is possible to achieve that effect by simply passing around
49 /// raw pointers, a span has the advantage of carrying around additional size
50 /// information, both enabling use of common array patterns, as well as
51 /// providing sufficient information to perform boundary tests.
52 ///
53 /// A TfSpan is implicitly convertible from common array types,
54 /// as well as from other spans, but preserves const-ness:
55 ///
56 /// \code
57 /// std::vector<int> data;
58 /// TfSpan<int> span(data); // Okay
59 ///
60 /// VtIntArray data;
61 /// TfSpan<int> span = data; // Okay
62 /// TfSpan<const int> cspan = span; // Okay
63 ///
64 /// const std::vector<int> data;
65 /// TfSpan<const int> span = data; // Okay
66 ///
67 /// const std::vector<int> data;
68 /// TfSpan<int> span = data; // Error! Discards cv-qualifier.
69 /// \endcode
70 ///
71 /// Helper methods TfMakeSpan and TfMakeConstSpan are also provided to enable
72 /// auto-typing when constructing spans:
73 /// \code
74 /// VtIntArray data;
75 /// auto readOnlySpan = TfMakeConstSpan(data); // TfSpan<const int>
76 /// auto readWriteSpan = TfMakeSpan(data); // TfSpan<int>
77 /// \endcode
78 ///
79 /// Spans do not own the data they reference. It is up to the user of the span
80 /// to ensure that the underlying data is not destructed while the span is in
81 /// use.
82 ///
83 /// This is modelled after std::span (C++20), but does not currently include
84 /// any specialization for static extents.
85 ///
86 template <typename T>
87 class TfSpan
88 {
89 public:
90  using element_type = T;
92  using pointer = T*;
93  using reference = T&;
94  using index_type = std::size_t;
95  using difference_type = std::ptrdiff_t;
96 
97  using iterator = T*;
98  using const_iterator = const T*;
99  using reverse_iterator = std::reverse_iterator<iterator>;
100  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
101 
102  TfSpan() noexcept = default;
103 
104  /// Construct a span over the range of [ptr, ptr+count).
105  /// In debug builds, a runtime assertion will fail if \p count > 0 and
106  /// \p ptr is null. The behavior is otherwise undefined for invalid ranges.
108  : _data(ptr), _size(count)
109  {
110  TF_DEV_AXIOM(count == 0 || ptr);
111  }
112 
113  /// Construct a span over the range [first, last).
115  : TfSpan(first, index_type(last-first))
116  {
117  TF_DEV_AXIOM(last >= first);
118  }
119 
120  /// Construct a span from a container.
121  /// The resulting span has a range of
122  /// [cont.data(), cont.data()+cont.size())
123  template <class Container>
124  TfSpan(Container& cont,
125  typename std::enable_if<
127  std::is_same<typename Container::value_type, value_type
128  >::value, Container
129  >::type* = 0)
130  : _data(cont.data()), _size(cont.size())
131  {
132  TF_DEV_AXIOM(_size == 0 || _data);
133  }
134 
135  /// Construct a span from a container.
136  /// The resulting span has a range of
137  /// [cont.data(), cont.data()+cont.size())
138  template <class Container>
139  TfSpan(const Container& cont,
140  typename std::enable_if<
141  std::is_same<typename Container::value_type, value_type
142  >::value, Container
143  >::type* = 0)
144  : _data(cont.data()), _size(cont.size())
145  {
146  TF_DEV_AXIOM(_size == 0 || _data);
147  }
148 
149  /// Return a pointer to the first element of the span.
150  pointer data() const noexcept { return _data; }
151 
152  /// Return the total number of elements in the span.
153  index_type size() const noexcept { return _size; }
154 
155  /// Returns true if this span contains no elements, false otherwise.
156  bool empty() const noexcept { return _size == 0; }
157 
158  /// Returns a reference to the \p idx'th element of the span.
159  /// In debug builds, a runtime assertion will fail if \p idx is out of
160  /// range. The behavior is otherwise undefined if \p idx is out of range.
162  TF_DEV_AXIOM(idx < _size);
163  return _data[idx];
164  }
165 
166  /// Return a reference to the first element in the span.
167  reference front() const {
168  TF_DEV_AXIOM(!empty());
169  return *begin();
170  }
171 
172  /// Return a reference to the last element in the span.
173  reference back() const {
174  TF_DEV_AXIOM(!empty());
175  return *(end() - 1);
176  }
177 
178  /// Returns a non-const iterator the start of the span.
179  iterator begin() const noexcept { return _data; }
180 
181  /// Returns a cons iterator to the start of the span.
182  const_iterator cbegin() const noexcept { return _data; }
183 
184  /// Returns a non-const iterator to the end of the span.
185  iterator end() const noexcept { return _data + _size; }
186 
187  /// Returns a const iterator to the end of the span.
188  const_iterator cend() const noexcept { return _data + _size; }
189 
190  /// Returns a non-const reverse iterator the start of the span.
191  reverse_iterator rbegin() const noexcept
192  { return reverse_iterator(end()); }
193 
194  /// Returns a cons reverse iterator to the start of the span.
195  const_reverse_iterator crbegin() const noexcept
196  { return const_reverse_iterator(cend()); }
197 
198  /// Returns a non-const reverse iterator to the end of the span.
199  reverse_iterator rend() const noexcept
200  { return reverse_iterator(begin()); }
201 
202  /// Returns a const reverse iterator to the end of the span.
203  const_reverse_iterator crend() const noexcept
204  { return const_reverse_iterator(cbegin()); }
205 
206  /// Returns a new span referencing a sub-range of this span.
207  /// If \p count == -1 (or std::dynamic_extent in C++20), the new span
208  /// has a range of [data()+offset, data()+size()). Otherwise, the new
209  /// span has range [data()+offset, data()+offset+count).
211  TF_DEV_AXIOM(offset >= 0 && (index_type)offset < _size);
212  if (count == -1) {
213  return TfSpan<T>(_data + offset, _size - offset);
214  } else {
215  TF_DEV_AXIOM(count >= 0);
216  TF_DEV_AXIOM(((index_type)offset+(index_type)count) <= _size);
217  return TfSpan<T>(_data + offset, count);
218  }
219  }
220 
221  /// Return a subspan consisting of the first \p count elements of this span.
222  TfSpan<T> first(size_t count) const {
223  return subspan(0, count);
224  }
225 
226  /// Return a subspan consisting of the last \p count elements of this span.
227  TfSpan<T> last(size_t count) const {
228  TF_DEV_AXIOM(_size >= count);
229  return TfSpan<T>(end() - count, count);
230  }
231 
232 private:
233  pointer _data = nullptr;
234  index_type _size = 0;
235 };
236 
237 
238 /// Helper for constructing a non-const TfSpan from a container.
239 template <typename Container>
241 TfMakeSpan(Container& cont)
242 {
244 }
245 
246 
247 /// Helper for constructing a const TfSpan from a container.
248 template <typename Container>
250 TfMakeConstSpan(const Container& cont)
251 {
253 }
254 
256 
257 #endif // PXR_BASE_TF_SPAN_H
const_reverse_iterator crend() const noexcept
Returns a const reverse iterator to the end of the span.
Definition: span.h:203
TfSpan() noexcept=default
GLint first
Definition: glcorearb.h:405
const_iterator cend() const noexcept
Returns a const iterator to the end of the span.
Definition: span.h:188
TfSpan(Container &cont, typename std::enable_if< !std::is_const< element_type >::value &&std::is_same< typename Container::value_type, value_type >::value, Container >::type *=0)
Definition: span.h:124
index_type size() const noexcept
Return the total number of elements in the span.
Definition: span.h:153
bool empty() const noexcept
Returns true if this span contains no elements, false otherwise.
Definition: span.h:156
std::ptrdiff_t difference_type
Definition: span.h:95
GLsizei const GLfloat * value
Definition: glcorearb.h:824
reference operator[](index_type idx) const
Definition: span.h:161
const_iterator cbegin() const noexcept
Returns a cons iterator to the start of the span.
Definition: span.h:182
TfSpan(pointer first, pointer last)
Construct a span over the range [first, last).
Definition: span.h:114
uint64 value_type
Definition: GA_PrimCompat.h:29
#define TF_DEV_AXIOM(cond)
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition: span.h:100
GLintptr offset
Definition: glcorearb.h:665
const T * const_iterator
Definition: span.h:98
TfSpan(const Container &cont, typename std::enable_if< std::is_same< typename Container::value_type, value_type >::value, Container >::type *=0)
Definition: span.h:139
TfSpan< T > last(size_t count) const
Return a subspan consisting of the last count elements of this span.
Definition: span.h:227
Definition: span.h:87
T & reference
Definition: span.h:93
TfSpan< T > first(size_t count) const
Return a subspan consisting of the first count elements of this span.
Definition: span.h:222
TfSpan< T > subspan(difference_type offset, difference_type count=-1) const
Definition: span.h:210
T * pointer
Definition: span.h:92
typename std::remove_cv< T >::type value_type
Definition: span.h:91
T * iterator
Definition: span.h:97
std::size_t index_type
Definition: span.h:94
std::reverse_iterator< iterator > reverse_iterator
Definition: span.h:99
iterator end() const noexcept
Returns a non-const iterator to the end of the span.
Definition: span.h:185
reverse_iterator rbegin() const noexcept
Returns a non-const reverse iterator the start of the span.
Definition: span.h:191
GLsizeiptr size
Definition: glcorearb.h:664
GLenum void ** pointer
Definition: glcorearb.h:810
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1432
TfSpan< typename Container::value_type > TfMakeSpan(Container &cont)
Helper for constructing a non-const TfSpan from a container.
Definition: span.h:241
TfSpan< const typename Container::value_type > TfMakeConstSpan(const Container &cont)
Helper for constructing a const TfSpan from a container.
Definition: span.h:250
auto ptr(T p) -> const void *
Definition: format.h:2448
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:91
T element_type
Definition: span.h:90
pointer data() const noexcept
Return a pointer to the first element of the span.
Definition: span.h:150
Definition: core.h:1131
iterator begin() const noexcept
Returns a non-const iterator the start of the span.
Definition: span.h:179
reference back() const
Return a reference to the last element in the span.
Definition: span.h:173
type
Definition: core.h:1059
reverse_iterator rend() const noexcept
Returns a non-const reverse iterator to the end of the span.
Definition: span.h:199
reference front() const
Return a reference to the first element in the span.
Definition: span.h:167
GLint GLsizei count
Definition: glcorearb.h:405
Definition: format.h:895
const_reverse_iterator crbegin() const noexcept
Returns a cons reverse iterator to the start of the span.
Definition: span.h:195