ThinSQLite++
A thin, safe and convenient modern C++ wrapper for the 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/master/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 {
27
34 SQLITEPP_EXPORTED
35 template<class T>
37
39 }
40
41#else
42
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,
147 std::enable_if_t<
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{
237
239 SQLITEPP_EXPORTED using blob_view = span<const std::byte>;
240
241
255 SQLITEPP_EXPORTED
256 class zero_blob
257 {
258 public:
259 using element_type = const std::byte;
260 using value_type = std::byte;
261 using index_type = size_t;
262 using difference_type = ptrdiff_t;
263 using pointer = const std::byte *;
264 using const_pointer = const std::byte *;
265 using reference = const std::byte &;
266 using const_reference = const std::byte &;
267
268 class const_iterator
269 {
270 friend class zero_blob;
271 public:
272 using iterator_category = std::random_access_iterator_tag;
273 using value_type = zero_blob::value_type;
274 using difference_type = zero_blob::difference_type;
275 using pointer = zero_blob::pointer;
276 using reference = zero_blob::reference;
277 public:
278 constexpr const_iterator() noexcept = default;
279
280 constexpr const_reference operator*() const noexcept { return s_value; }
281
282 constexpr const_iterator & operator++() noexcept { ++_idx; return *this; }
283 constexpr const_iterator operator++(int) noexcept { return _idx++; }
284 constexpr const_iterator & operator+=(difference_type diff) noexcept { _idx += size_t(diff); return *this; }
285
286 constexpr const_iterator & operator--() noexcept { --_idx; return *this; }
287 constexpr const_iterator operator--(int) noexcept { return _idx--; }
288 constexpr const_iterator & operator-=(difference_type diff) noexcept { _idx -= size_t(diff); return *this; }
289
290 friend constexpr difference_type operator-(const_iterator lhs, const_iterator rhs) noexcept { return difference_type(lhs._idx - rhs._idx); }
291
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 friend constexpr bool operator>=(const_iterator lhs, const_iterator rhs) noexcept { return lhs._idx >= rhs._idx; };
298 private:
299 constexpr const_iterator(size_t idx) noexcept : _idx(idx) {};
300 private:
301 size_t _idx = size_t(-1);
302 };
303
304 using iterator = const_iterator;
305 using reverse_iterator = std::reverse_iterator<iterator>;
306 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
307
308 public:
309 constexpr zero_blob(size_t size = 0) noexcept : _size{size} {}
310
311 constexpr zero_blob (const zero_blob&) noexcept = default;
312 constexpr zero_blob& operator=(const zero_blob&) noexcept = default;
313
314 constexpr zero_blob first(index_type count) const noexcept
315 {
316 assert(count <= size());
317 return {count};
318 }
319
320 constexpr zero_blob last (index_type count) const noexcept
321 {
322 assert(count <= size());
323 return {count};
324 }
325
326 constexpr zero_blob
327 subspan(index_type offset, index_type count = size_t(-1)) const noexcept
328 {
329 assert(offset <= size());
330 assert(count <= size() || count == size_t(-1));
331 if (count == size_t(-1))
332 return {size() - offset};
333 assert(offset <= size() - count);
334 return {count};
335 }
336
337 constexpr index_type size() const noexcept { return _size; }
338 constexpr index_type size_bytes() const noexcept { return _size * sizeof(element_type); }
339 constexpr bool empty() const noexcept { return _size == 0; }
340
341 constexpr reference operator[](index_type idx) const noexcept
342 {
343 assert(idx < size());
344 (void)idx;
345 return s_value;
346 }
347
348 constexpr reference front() const noexcept
349 {
350 assert(!empty());
351 return s_value;
352 }
353
354 constexpr reference back() const noexcept
355 {
356 assert(!empty());
357 return s_value;
358 }
359
360 constexpr iterator begin() const noexcept { return iterator(0); }
361 constexpr iterator end() const noexcept { return iterator(size()); }
362 constexpr const_iterator cbegin() const noexcept { return const_iterator(0); }
363 constexpr const_iterator cend() const noexcept { return const_iterator(size()); }
364 constexpr reverse_iterator rbegin() const noexcept { return reverse_iterator(end()); }
365 constexpr reverse_iterator rend() const noexcept { return reverse_iterator(begin()); }
366 constexpr const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(cend()); }
367 constexpr const_reverse_iterator crend() const noexcept { return const_reverse_iterator(cbegin()); }
368 private:
369 size_t _size;
370
371 static inline const std::byte s_value{0};
372 };
373
375}
376
377#endif
378
T back(T... args)
T begin(T... args)
T count(T... args)
T data(T... args)
T distance(T... args)
T empty(T... args)
T end(T... args)
T first(T... args)
T front(T... args)
std::span< T > span
Alias or reimplementation of std::span.
Definition span.hpp:36
span< const std::byte > blob_view
A blob_view is a span of bytes.
Definition span.hpp:239
T last(T... args)
ThinSQLite++ namespace.
Definition backup_iface.hpp:17
T operator=(T... args)
T operator[](T... args)
T rbegin(T... args)
T rend(T... args)
T size_bytes(T... args)
T size(T... args)
T subspan(T... args)
T swap(T... args)