ThinSQLite++
A thin, safe and convenient modern C++ wrapper for SQLite API.
Loading...
Searching...
No Matches
span.hpp
1/*
2 Copyright 2019 Eugene Gershnik
3
4 Use of this source code is governed by a BSD-style
5 license that can be found in the LICENSE file or at
6 https://github.com/gershnik/thinsqlitepp/blob/main/LICENSE
7*/
8
9#ifndef HEADER_SQLITEPP_SPAN_INCLUDED
10#define HEADER_SQLITEPP_SPAN_INCLUDED
11
12#include "config.hpp"
13
14#include <iterator>
15#include <cassert>
16
17#if __cplusplus > 201703L
18
19 #include <span>
20
21 namespace thinsqlitepp
22 {
34 template<class T>
36
38 }
39
40#else
41
42 #include <iterator>
43 #include <array>
44
45 namespace thinsqlitepp
46 {
47
48 template <class T> class span;
49
50 namespace span_internal
51 {
52 template <class T>
53 struct is_span_impl : std::false_type {};
54
55 template <class T>
56 struct is_span_impl<span<T>> : std::true_type {};
57
58 template <class T>
59 using is_span = is_span_impl<std::decay_t<T>>;
60
61 template <class T>
62 struct is_std_array_impl : std::false_type {};
63
64 template <class T, size_t N>
65 struct is_std_array_impl<std::array<T, N>> : std::true_type {};
66
67 template <class T>
68 using is_std_array = is_std_array_impl<std::decay_t<T>>;
69
70 template <class T>
72
73 template <class From, class To>
74 using is_legal_data_conversion = std::is_convertible<From (*)[], To (*)[]>;
75
76 template <class Container, class T>
77 using container_has_convertible_data = is_legal_data_conversion<
79 T>;
80
81 template <class Container>
82 using container_has_integral_size =
84
85 // SFINAE check if Container can be converted to a Span<T>.
86 template <class Container, class T>
87 using is_span_compatible_container =
89 !is_std_array<Container>::value &&
90 !is_c_array<Container>::value &&
91 container_has_convertible_data<Container, T>::value &&
92 container_has_integral_size<Container>::value,
95
96
97 }
98
99 template <class T>
100 class span
101 {
102 public:
103 using element_type = T;
104 using value_type = std::remove_cv_t<T>;
105 using index_type = size_t;
106 using difference_type = ptrdiff_t;
107 using pointer = T *;
108 using const_pointer = const T *;
109 using reference = T &;
110 using const_reference = const T &;
111 using iterator = pointer;
112 using const_iterator = const_pointer;
113 using reverse_iterator = std::reverse_iterator<iterator>;
114 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
115
116 public:
117 constexpr span() noexcept : _data{nullptr}, _size{0} {}
118
119 constexpr span (const span&) noexcept = default;
120 constexpr span& operator=(const span&) noexcept = default;
121
122 constexpr span(pointer ptr, index_type count) noexcept : _data{ptr}, _size{count} {}
123 constexpr span(pointer first, pointer last) noexcept : _data{first}, _size{static_cast<size_t>(std::distance(first, last))} {}
124
125 template <size_t N>
126 constexpr span(element_type (&arr)[N]) noexcept : _data{arr}, _size{N} {}
127
128 template <size_t N>
129 constexpr span(std::array<value_type, N>& arr) noexcept : _data{arr.data()}, _size{N} {}
130
131 template <size_t N>
132 constexpr span(const std::array<value_type, N>& arr) noexcept : _data{arr.data()}, _size{N} {}
133
134 template <class Container>
135 constexpr span(Container& cont,
136 std::enable_if_t<span_internal::is_span_compatible_container<Container, T>::value, std::nullptr_t> = nullptr)
137 : _data{std::data(cont)}, _size{(index_type) std::size(cont)} {}
138
139 template <class Container>
140 constexpr span(const Container& cont,
141 std::enable_if_t<span_internal::is_span_compatible_container<const Container, T>::value, std::nullptr_t> = nullptr)
142 : _data{std::data(cont)}, _size{(index_type) std::size(cont)} {}
143
144
145 template <class OtherElementType>
146 constexpr span(const span<OtherElementType>& other,
148 std::is_convertible_v<OtherElementType(*)[], element_type (*)[]>,
149 std::nullptr_t> = nullptr) noexcept
150 : _data{other.data()}, _size{other.size()} {}
151
152
153 constexpr span<element_type> first(index_type count) const noexcept
154 {
155 assert(count <= size());
156 return {data(), count};
157 }
158
159 constexpr span<element_type> last (index_type count) const noexcept
160 {
161 assert(count <= size());
162 return {data() + size() - count, count};
163 }
164
165 constexpr span<element_type>
166 subspan(index_type offset, index_type count = size_t(-1)) const noexcept
167 {
168 assert(offset <= size());
169 assert(count <= size() || count == size_t(-1));
170 if (count == size_t(-1))
171 return {data() + offset, size() - offset};
172 assert(offset <= size() - count);
173 return {data() + offset, count};
174 }
175
176 constexpr index_type size() const noexcept { return _size; }
177 constexpr index_type size_bytes() const noexcept { return _size * sizeof(element_type); }
178 constexpr bool empty() const noexcept { return _size == 0; }
179
180 constexpr reference operator[](index_type idx) const noexcept
181 {
182 assert(idx < size());
183 return _data[idx];
184 }
185
186 constexpr reference front() const noexcept
187 {
188 assert(!empty());
189 return _data[0];
190 }
191
192 constexpr reference back() const noexcept
193 {
194 assert(!empty());
195 return _data[size()-1];
196 }
197
198
199 constexpr pointer data() const noexcept { return _data; }
200
201 constexpr iterator begin() const noexcept { return iterator(data()); }
202 constexpr iterator end() const noexcept { return iterator(data() + size()); }
203 constexpr const_iterator cbegin() const noexcept { return const_iterator(data()); }
204 constexpr const_iterator cend() const noexcept { return const_iterator(data() + size()); }
205 constexpr reverse_iterator rbegin() const noexcept { return reverse_iterator(end()); }
206 constexpr reverse_iterator rend() const noexcept { return reverse_iterator(begin()); }
207 constexpr const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(cend()); }
208 constexpr const_reverse_iterator crend() const noexcept { return const_reverse_iterator(cbegin()); }
209
210 constexpr void swap(span &other) noexcept
211 {
212 pointer p = _data;
213 _data = other._data;
214 other._data = p;
215
216 index_type s = _size;
217 _size = other._size;
218 other._size = s;
219 }
220
221 private:
222 pointer _data;
223 index_type _size;
224 };
225
226 }
227
228#endif
229
230
231namespace thinsqlitepp
232{
240
241
256 {
257 public:
258 using element_type = const std::byte;
259 using value_type = std::byte;
260 using index_type = size_t;
261 using difference_type = ptrdiff_t;
262 using pointer = const std::byte *;
263 using const_pointer = const std::byte *;
264 using reference = const std::byte &;
265 using const_reference = const std::byte &;
266
267 class const_iterator
268 {
269 friend class zero_blob;
270 public:
271 using iterator_category = std::random_access_iterator_tag;
273 using difference_type = zero_blob::difference_type;
276 public:
277 constexpr const_iterator() noexcept = default;
278
279 constexpr const_reference operator*() const noexcept { return s_value; }
280
281 constexpr const_iterator & operator++() noexcept { ++_idx; return *this; }
282 constexpr const_iterator operator++(int) noexcept { return _idx++; }
283 constexpr const_iterator & operator+=(difference_type diff) noexcept { _idx += diff; return *this; }
284
285 constexpr const_iterator & operator--() noexcept { --_idx; return *this; }
286 constexpr const_iterator operator--(int) noexcept { return _idx--; }
287 constexpr const_iterator & operator-=(difference_type diff) noexcept { _idx -= diff; return *this; }
288
289 friend constexpr difference_type operator-(const_iterator lhs, const_iterator rhs) noexcept { return lhs._idx - rhs._idx; }
290
291 friend constexpr bool operator==(const_iterator lhs, const_iterator rhs) noexcept { return lhs._idx == rhs._idx; };
292 friend constexpr bool operator!=(const_iterator lhs, const_iterator rhs) noexcept { return lhs._idx != rhs._idx; };
293 friend constexpr bool operator<(const_iterator lhs, const_iterator rhs) noexcept { return lhs._idx < rhs._idx; };
294 friend constexpr bool operator<=(const_iterator lhs, const_iterator rhs) noexcept { return lhs._idx <= rhs._idx; };
295 friend constexpr bool operator>(const_iterator lhs, const_iterator rhs) noexcept { return lhs._idx > rhs._idx; };
296 friend constexpr bool operator>=(const_iterator lhs, const_iterator rhs) noexcept { return lhs._idx >= rhs._idx; };
297 private:
298 constexpr const_iterator(size_t idx) noexcept : _idx(idx) {};
299 private:
300 size_t _idx = size_t(-1);
301 };
302
303 using iterator = const_iterator;
306
307 public:
308 constexpr zero_blob(size_t size = 0) noexcept : _size{size} {}
309
310 constexpr zero_blob (const zero_blob&) noexcept = default;
311 constexpr zero_blob& operator=(const zero_blob&) noexcept = default;
312
313 constexpr zero_blob first(index_type count) const noexcept
314 {
315 assert(count <= size());
316 return {count};
317 }
318
319 constexpr zero_blob last (index_type count) const noexcept
320 {
321 assert(count <= size());
322 return {count};
323 }
324
325 constexpr zero_blob
326 subspan(index_type offset, index_type count = size_t(-1)) const noexcept
327 {
328 assert(offset <= size());
329 assert(count <= size() || count == size_t(-1));
330 if (count == size_t(-1))
331 return {size() - offset};
332 assert(offset <= size() - count);
333 return {count};
334 }
335
336 constexpr index_type size() const noexcept { return _size; }
337 constexpr index_type size_bytes() const noexcept { return _size * sizeof(element_type); }
338 constexpr bool empty() const noexcept { return _size == 0; }
339
340 constexpr reference operator[](index_type idx) const noexcept
341 {
342 assert(idx < size());
343 (void)idx;
344 return s_value;
345 }
346
347 constexpr reference front() const noexcept
348 {
349 assert(!empty());
350 return s_value;
351 }
352
353 constexpr reference back() const noexcept
354 {
355 assert(!empty());
356 return s_value;
357 }
358
359 constexpr iterator begin() const noexcept { return iterator(0); }
360 constexpr iterator end() const noexcept { return iterator(size()); }
361 constexpr const_iterator cbegin() const noexcept { return const_iterator(0); }
362 constexpr const_iterator cend() const noexcept { return const_iterator(size()); }
363 constexpr reverse_iterator rbegin() const noexcept { return reverse_iterator(end()); }
364 constexpr reverse_iterator rend() const noexcept { return reverse_iterator(begin()); }
365 constexpr const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(cend()); }
366 constexpr const_reverse_iterator crend() const noexcept { return const_reverse_iterator(cbegin()); }
367 private:
368 size_t _size;
369
370 static inline const std::byte s_value{0};
371 };
372
374}
375
376#endif
377
T begin(T... args)
An efficient blob of zeroes of a given size.
Definition span.hpp:256
T count(T... args)
T data(T... args)
T distance(T... args)
T empty(T... args)
T end(T... args)
std::span< T > span
Alias or reimplementation of std::span.
Definition span.hpp:35
ThinSQLite++ namespace.
Definition backup_iface.hpp:17
T rbegin(T... args)
T rend(T... args)
T size(T... args)
T swap(T... args)