scnlib  0.2.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
span.h
Go to the documentation of this file.
1 // Copyright 2017-2019 Elias Kosunen
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15 // This file is a part of scnlib:
16 // https://github.com/eliaskosunen/scnlib
17 
18 #ifndef SCN_DETAIL_SPAN_H
19 #define SCN_DETAIL_SPAN_H
20 
21 #include "config.h"
22 
23 #include <iterator>
24 
25 namespace scn {
27 
28  template <typename T>
29  class span;
30 
31  namespace detail {
32  namespace ranges {
33  // iterator_category
34  using std::bidirectional_iterator_tag;
35  using std::forward_iterator_tag;
36  using std::input_iterator_tag;
37  using std::output_iterator_tag;
38  using std::random_access_iterator_tag;
39  struct contiguous_iterator_tag : random_access_iterator_tag {
40  };
41  } // namespace ranges
42 #if 0
43  template <typename Element>
44  class span_iterator {
45  public:
46  using element_type = Element;
47  using value_type = typename std::remove_cv<element_type>::type;
48  using pointer = Element*;
49  using const_pointer = const Element*;
50  using reference = Element&;
51  using const_reference = const Element&;
52  using difference_type = std::ptrdiff_t;
53  using iterator_category = ranges::contiguous_iterator_tag;
54 
55  span_iterator() = default;
56 
57  template <typename S>
58  span_iterator(const S& s, pointer p)
59  : m_begin(s.data()), m_end(s.data() + s.size()), m_elem(p)
60  {
61  }
62  template <typename S>
63  span_iterator(const S& s, difference_type n)
64  : m_begin(s.data()),
65  m_end(s.data() + s.size()),
66  m_elem(s.data() + n)
67  {
68  }
69 
70  reference operator*()
71  {
72  SCN_EXPECT(m_begin && m_end);
73  SCN_EXPECT(m_elem >= m_begin && m_elem < m_end);
74  return *m_elem;
75  }
76  const_reference operator*() const
77  {
78  SCN_EXPECT(m_begin && m_end);
79  SCN_EXPECT(m_elem >= m_begin && m_elem < m_end);
80  return *m_elem;
81  }
82 
83  span_iterator& operator++()
84  {
85  SCN_EXPECT(m_begin && m_end);
86  SCN_EXPECT(m_elem != m_end);
87  ++m_elem;
88  return *this;
89  }
90  span_iterator operator++(int)
91  {
92  auto tmp = *this;
93  operator++();
94  return tmp;
95  }
96 
97  span_iterator& operator--()
98  {
99  SCN_EXPECT(m_begin && m_end);
100  SCN_EXPECT(m_elem != m_begin);
101  --m_elem;
102  return *this;
103  }
104  span_iterator operator--(int)
105  {
106  auto tmp = *this;
107  operator--();
108  return tmp;
109  }
110 
111  span_iterator& operator+=(difference_type n)
112  {
113  SCN_EXPECT(m_begin && m_end);
114  SCN_EXPECT(m_end - *this >= n);
115  m_elem += n;
116  return *this;
117  }
118  span_iterator& operator-=(difference_type n)
119  {
120  SCN_EXPECT(m_begin && m_end);
121  SCN_EXPECT(*this - m_begin >= n);
122  m_elem += n;
123  return *this;
124  }
125 
126  reference operator[](difference_type i)
127  {
128  SCN_EXPECT(m_begin && m_end);
129  SCN_EXPECT(m_elem + i >= m_begin && m_elem + i < m_end);
130  return *(m_elem + i);
131  }
132  const_reference operator[](difference_type i) const
133  {
134  SCN_EXPECT(m_begin && m_end);
135  SCN_EXPECT(m_elem + i >= m_begin && m_elem + i < m_end);
136  return *(m_elem + i);
137  }
138 
139  private:
140  const_pointer m_begin{nullptr}, m_end{nullptr};
141  pointer m_elem{nullptr};
142  };
143 
144  template <typename ElemL, typename ElemR>
145  bool operator==(const span_iterator<ElemL>& l,
146  const span_iterator<ElemR>& r)
147  {
148  return l.m_elem == r.m_elem;
149  }
150  template <typename ElemL, typename ElemR>
151  bool operator!=(const span_iterator<ElemL>& l,
152  const span_iterator<ElemR>& r)
153  {
154  return !operator==(l, r);
155  }
156 
157  template <typename ElemL, typename ElemR>
158  bool operator<(const span_iterator<ElemL>& l,
159  const span_iterator<ElemR>& r)
160  {
161  return l.m_elem < r.m_elem;
162  }
163  template <typename ElemL, typename ElemR>
164  bool operator>(const span_iterator<ElemL>& l,
165  const span_iterator<ElemR>& r)
166  {
167  return operator<(r, l);
168  }
169  template <typename ElemL, typename ElemR>
170  bool operator<=(const span_iterator<ElemL>& l,
171  const span_iterator<ElemR>& r)
172  {
173  return !operator>(l, r);
174  }
175  template <typename ElemL, typename ElemR>
176  bool operator>=(const span_iterator<ElemL>& l,
177  const span_iterator<ElemR>& r)
178  {
179  return !operator<(l, r);
180  }
181 
182  template <typename Elem>
183  span_iterator<Elem> operator+(
184  span_iterator<Elem> l,
185  typename span_iterator<Elem>::difference_type r)
186  {
187  l += r;
188  return l;
189  }
190  template <typename Elem>
191  span_iterator<Elem> operator+(
192  typename span_iterator<Elem>::difference_type r,
193  span_iterator<Elem> l)
194  {
195  l += r;
196  return l;
197  }
198 
199  template <typename Elem>
200  span_iterator<Elem> operator-(
201  span_iterator<Elem> l,
202  typename span_iterator<Elem>::difference_type r)
203  {
204  l -= r;
205  return l;
206  }
207 
208  template <typename ElemL, typename ElemR>
209  typename span_iterator<ElemL>::difference_type operator-(
210  const span_iterator<ElemL>& l,
211  const span_iterator<ElemR>& r)
212  {
213  SCN_EXPECT(l.m_span && r.m_span);
214  SCN_EXPECT(l.m_span == r.m_span);
215  return l.m_elem - r.m_elem;
216  }
217 #endif
218  } // namespace detail
219 
224  template <typename T>
225  class span {
226  public:
227  using element_type = T;
229  using index_type = std::size_t;
230  using ssize_type = std::ptrdiff_t;
231  using difference_type = std::ptrdiff_t;
232  using pointer = T*;
233  using const_pointer = const T*;
234  using reference = T&;
235  using const_reference = const T&;
236 
237  // using iterator = detail::span_iterator<element_type>;
238  // using const_iterator = detail::span_iterator<const element_type>;
239  using iterator = pointer;
241  using reverse_iterator = std::reverse_iterator<iterator>;
242  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
243 
244  constexpr span() noexcept = default;
245  constexpr span(pointer ptr, index_type count) noexcept
246  : m_ptr(ptr), m_end(ptr + count)
247  {
248  }
249  constexpr span(pointer first, pointer last) noexcept
250  : m_ptr(first), m_end(last)
251  {
252  }
253 
255  {
256  return _make_begin();
257  }
259  {
260  return _make_end();
261  }
263  {
264  return reverse_iterator{end()};
265  }
267  {
268  return reverse_iterator{begin()};
269  }
270 
271  constexpr const_iterator begin() const noexcept
272  {
273  return _make_begin();
274  }
275  constexpr const_iterator end() const noexcept
276  {
277  return _make_end();
278  }
279  constexpr const_reverse_iterator rbegin() const noexcept
280  {
281  return reverse_iterator{end()};
282  }
283  constexpr const_reverse_iterator rend() const noexcept
284  {
285  return reverse_iterator{begin()};
286  }
287 
288  constexpr const_iterator cbegin() const noexcept
289  {
290  return _make_begin();
291  }
292  constexpr const_iterator cend() const noexcept
293  {
294  return _make_end();
295  }
296  constexpr const_reverse_iterator crbegin() const noexcept
297  {
298  return reverse_iterator{cend()};
299  }
300  constexpr const_reverse_iterator crend() const noexcept
301  {
302  return reverse_iterator{cbegin()};
303  }
304 
305  constexpr reference operator[](index_type i) const noexcept
306  {
307  SCN_EXPECT(size() > i);
308  return *(m_ptr + i);
309  }
310 
311  constexpr pointer data() const noexcept
312  {
313  return m_ptr;
314  }
315  constexpr index_type size() const noexcept
316  {
317  return static_cast<index_type>(m_end - m_ptr);
318  }
319  constexpr ssize_type ssize() const noexcept
320  {
321  return m_end - m_ptr;
322  }
323 
324  constexpr span<T> first(index_type n) const
325  {
326  SCN_EXPECT(size() >= n);
327  return span<T>(data(), data() + n);
328  }
329  constexpr span<T> last(index_type n) const
330  {
331  SCN_EXPECT(size() >= n);
332  return span<T>(data() + size() - n, data() + size());
333  }
334  constexpr span<T> subspan(index_type off) const
335  {
336  SCN_EXPECT(size() >= off);
337  return span<T>(data() + off, size() - off);
338  }
339  constexpr span<T> subspan(index_type off, difference_type count) const
340  {
341  SCN_EXPECT(size() > off + count);
342  SCN_EXPECT(count > 0);
343  return span<T>(data() + off, count);
344  }
345 
347  {
348  return {m_ptr, m_end};
349  }
350 
351  private:
352  SCN_CONSTEXPR14 iterator _make_begin()
353  {
354  SCN_EXPECT(m_ptr);
355  // return {*this, m_ptr};
356  return m_ptr;
357  }
358  constexpr const_iterator _make_begin() const
359  {
360  SCN_EXPECT(m_ptr);
361  // return {*this, m_ptr};
362  return m_ptr;
363  }
364 
365  SCN_CONSTEXPR14 iterator _make_end()
366  {
367  SCN_EXPECT(m_ptr);
368  // return {*this, m_ptr + m_size};
369  return m_end;
370  }
371  constexpr const_iterator _make_end() const
372  {
373  SCN_EXPECT(m_ptr);
374  // return {*this, m_ptr + m_size};
375  return m_end;
376  }
377 
378  pointer m_ptr{nullptr};
379  pointer m_end{nullptr};
380  };
381 
382  template <typename T>
383  constexpr span<T> make_span(T* ptr, std::size_t count) noexcept
384  {
385  return span<T>(ptr, count);
386  }
387  template <typename T>
388  constexpr span<T> make_span(T* first, T* last) noexcept
389  {
390  return span<T>(first, last);
391  }
392  template <typename T>
393  constexpr span<typename T::value_type> make_span(T& container) noexcept
394  {
395  using std::begin;
396  using std::end;
398  std::addressof(*begin(container)),
399  std::addressof(*(end(container) - 1)) + 1);
400  }
401 
403 } // namespace scn
404 
405 #endif // SCN_DETAIL_SPAN_H
std::size_t index_type
Definition: span.h:229
constexpr const_iterator cbegin() const noexcept
Definition: span.h:288
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition: span.h:242
std::ptrdiff_t ssize_type
Definition: span.h:230
constexpr span(pointer first, pointer last) noexcept
Definition: span.h:249
SCN_CONSTEXPR14 iterator end() noexcept
Definition: span.h:258
const value_type * pointer
Definition: span.h:232
#define SCN_END_NAMESPACE
Definition: config.h:406
void size(T &&)=delete
constexpr const_reverse_iterator crbegin() const noexcept
Definition: span.h:296
constexpr ssize_type ssize() const noexcept
Definition: span.h:319
const value_type & reference
Definition: span.h:234
const value_type element_type
Definition: span.h:227
std::reverse_iterator< iterator > reverse_iterator
Definition: span.h:241
constexpr span< T > last(index_type n) const
Definition: span.h:329
constexpr const_iterator cend() const noexcept
Definition: span.h:292
constexpr const_reverse_iterator crend() const noexcept
Definition: span.h:300
constexpr const_iterator begin() const noexcept
Definition: span.h:271
constexpr span< T > subspan(index_type off) const
Definition: span.h:334
constexpr bool operator!=(error a, error b) noexcept
Definition: result.h:117
const const value_type * const_pointer
Definition: span.h:233
constexpr bool operator==(error a, error b) noexcept
Definition: result.h:113
constexpr span< T > subspan(index_type off, difference_type count) const
Definition: span.h:339
std::ptrdiff_t difference_type
Definition: span.h:231
constexpr span< T > first(index_type n) const
Definition: span.h:324
const_pointer const_iterator
Definition: span.h:240
constexpr reference operator[](index_type i) const noexcept
Definition: span.h:305
constexpr const_reverse_iterator rend() const noexcept
Definition: span.h:283
#define SCN_BEGIN_NAMESPACE
Definition: config.h:405
constexpr const_reverse_iterator rbegin() const noexcept
Definition: span.h:279
constexpr span< typename std::add_const< T >::type > as_const() const
Definition: span.h:346
constexpr pointer data() const noexcept
Definition: span.h:311
SCN_CONSTEXPR14 reverse_iterator rbegin() noexcept
Definition: span.h:262
void end(T &&)=delete
const const value_type & const_reference
Definition: span.h:235
SCN_CONSTEXPR14 iterator begin() noexcept
Definition: span.h:254
constexpr span< T > make_span(T *ptr, std::size_t count) noexcept
Definition: span.h:383
SCN_CONSTEXPR14 reverse_iterator rend() noexcept
Definition: span.h:266
void begin(T &&)=delete
constexpr index_type size() const noexcept
Definition: span.h:315
constexpr const_iterator end() const noexcept
Definition: span.h:275
typename std::remove_cv< T >::type value_type
Definition: span.h:228
#define SCN_EXPECT(cond)
Definition: config.h:401
A view over a contiguous range.
Definition: span.h:29
#define SCN_CONSTEXPR14
Definition: config.h:246
constexpr span() noexcept=default