MySQL 8.2.0
Source Code Documentation
span.h
Go to the documentation of this file.
1/*
2 Copyright (c) 2023, Oracle and/or its affiliates.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License, version 2.0,
6 as published by the Free Software Foundation.
7
8 This program is also distributed with certain software (including
9 but not limited to OpenSSL) that is licensed under separate terms,
10 as designated in a particular file or component or in included license
11 documentation. The authors of MySQL hereby grant you an additional
12 permission to link the program and your derivative works with the
13 separately licensed software that they have included with MySQL.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23*/
24
25#ifndef MYSQL_HARNESS_STDX_SPAN_INCLUDED
26#define MYSQL_HARNESS_STDX_SPAN_INCLUDED
27
28#include <array>
29#include <cassert>
30#include <cstddef>
31#include <iterator>
32#include <limits>
33#include <type_traits>
34
36
37namespace stdx {
38
39// C++20's std::span.
40//
41// - uses slightly different constructor for std::vector<> as there are no
42// <ranges> in C++17.
43
44inline constexpr std::size_t dynamic_extent =
45 std::numeric_limits<std::size_t>::max();
46
47template <class T, std::size_t Extent = dynamic_extent>
48class span;
49
50namespace detail {
51template <class C, class = void>
52struct has_data : std::false_type {};
53
54template <class C>
55struct has_data<C, std::void_t<decltype(std::data(std::declval<C>()))>>
56 : std::true_type {};
57
58template <class C, class = void>
59struct has_size : std::false_type {};
60
61template <class C>
62struct has_size<C, std::void_t<decltype(std::size(std::declval<C>()))>>
63 : std::true_type {};
64
65// is-std-array
66
67template <class T, class = void>
68struct is_std_array_impl : std::false_type {};
69
70template <class T, size_t Extend>
71struct is_std_array_impl<std::array<T, Extend>> : std::true_type {};
72
73template <class T>
74struct is_std_array : is_std_array_impl<stdx::remove_cvref_t<T>> {};
75
76// is-span
77
78template <class T, class = void>
79struct is_span_impl : std::false_type {};
80
81template <class T, std::size_t Extend>
82struct is_span_impl<span<T, Extend>> : std::true_type {};
83
84template <class T>
85struct is_span : is_span_impl<stdx::remove_cvref_t<T>> {};
86
87// minimalistic "concept std::ranged::contiguous_range"
88template <class C>
89struct is_contiguous_range : std::bool_constant<has_data<C>::value> {};
90
91// minimalistic "concept std::ranged::sized_range"
92template <class C>
93struct is_sized_range : std::bool_constant<has_size<C>::value> {};
94
95template <class C, class E, class = void>
96struct is_compatible_element : std::false_type {};
97
98template <class C, class E>
100 C, E, std::void_t<decltype(std::data(std::declval<C>()))>>
101 : std::is_convertible<
102 std::remove_pointer_t<decltype(std::data(std::declval<C &>()))> (*)[],
103 E (*)[]> {};
104
105/*
106 * - R satisfies contiguous_range or sized_range
107 * - (either R satisfies borrowed_range or is_const_v<element_type> is true)
108 * - std::remove_cvref_t<R> is not a specialization of std::span
109 * - std::remove_cvref_t<R> is not a specialization of std::array
110 * - std::is_array_v<std::remove_cvref_t<R>> is false, and
111 * - the conversion from range_ref_t<R> to element_type is at most a
112 * qualification conversion.
113 */
114template <class R, class E>
116 : std::bool_constant<is_contiguous_range<R>::value && //
117 is_sized_range<R>::value && //
118 !is_span<R>::value && //
119 !is_std_array<R>::value && //
120 !std::is_array_v<stdx::remove_cvref_t<R>> && //
121 is_compatible_element<R, E>::value> {};
122
123template <class From, class To>
124struct is_array_convertible : std::is_convertible<From (*)[], To (*)[]> {};
125
126// iterator over a continous memory range.
127//
128// random-access.
129template <class T>
130class iterator {
131 public:
132 using iterator_category = std::random_access_iterator_tag;
133 using reference = typename T::reference;
134 using pointer = typename T::pointer;
135 using value_type = typename T::value_type;
136 using difference_type = typename T::difference_type;
137
138 constexpr iterator(pointer data) : data_(data) {}
139
140 // +=
142 data_ += n;
143
144 return *this;
145 }
146
147 // binary plus.
149 auto tmp = *this;
150
151 tmp.data_ += n;
152
153 return tmp;
154 }
155
156 // -=
158 data_ -= n;
159
160 return *this;
161 }
162
163 // binary minus.
165 auto tmp = *this;
166
167 tmp.data_ -= n;
168
169 return tmp;
170 }
171
172 // pre-decrement
173 constexpr iterator &operator++() {
174 ++data_;
175
176 return *this;
177 }
178
179 // pre-decrement
180 constexpr iterator &operator--() {
181 --data_;
182
183 return *this;
184 }
185
186 // post-decrement
187 constexpr iterator operator--(int) {
188 auto tmp = *this;
189
190 --tmp.data_;
191
192 return *this;
193 }
194
195 // a - b
196 constexpr difference_type operator-(const iterator &other) {
197 return data_ - other.data_;
198 }
199
200 // *it;
201 constexpr reference operator*() { return *data_; }
202
203 // it[n]
204 constexpr reference operator[](difference_type n) { return *(data_ + n); }
205
206 // a == b
207 constexpr bool operator==(const iterator &other) const {
208 return data_ == other.data_;
209 }
210
211 // a != b
212 constexpr bool operator!=(const iterator &other) const {
213 return !(*this == other);
214 }
215
216 // a < b
217 constexpr bool operator<(const iterator &other) const {
218 return data_ < other.data_;
219 }
220
221 // a > b
222 constexpr bool operator>(const iterator &other) const {
223 return (other < *this);
224 }
225
226 // a >= b
227 constexpr bool operator>=(const iterator &other) const {
228 return !(*this < other);
229 }
230
231 // a <= b
232 constexpr bool operator<=(const iterator &other) const {
233 return !(*other < *this);
234 }
235
236 private:
238};
239
240template <class T, size_t Extent>
241struct span_size {
242 static constexpr size_t size = sizeof(T) * Extent;
243};
244
245template <class T>
247 static constexpr size_t size = dynamic_extent;
248};
249
250template <size_t Extent, size_t Offset, size_t Count>
252 static constexpr size_t size = Count;
253};
254
255template <size_t Extent, size_t Offset>
256struct extent_size<Extent, Offset, dynamic_extent> {
257 static constexpr size_t size =
258 Extent == dynamic_extent ? dynamic_extent : Extent - Offset;
259};
260
261} // namespace detail
262
263template <class T, std::size_t Extent>
264class span {
265 public:
266 using element_type = T;
267 using value_type = std::remove_cv_t<T>;
268
269 using size_type = std::size_t;
270 using difference_type = std::ptrdiff_t;
271
272 using pointer = T *;
273 using const_pointer = const T *;
274
275 using reference = T &;
276 using const_reference = const T &;
277
279 using reverse_iterator = std::reverse_iterator<iterator>;
280
281 static constexpr const size_t extent = Extent;
282
283 /**
284 * default construct.
285 *
286 * only enabled if Extent is 0 or dynamic.
287 */
288 template <bool B = (Extent == 0) || (Extent == dynamic_extent),
289 typename std::enable_if<B, int>::type = 0>
290 constexpr span() noexcept : span(nullptr, 0) {}
291
292 /**
293 * construct a span from pointer and size
294 */
295 constexpr span(pointer ptr, size_type count) : data_(ptr), size_(count) {}
296
297 /**
298 * construct a span from a continous range like a vector.
299 */
300 template <
301 class Range,
302 std::enable_if_t<detail::is_compatible_range<Range, element_type>::value,
303 int> = 0>
304 constexpr span(Range &cont) noexcept
305 : data_(std::data(cont)), size_(std::size(cont)) {}
306
307 /**
308 * construct a span from a const continous range like a vector.
309 */
310 template <class Range, std::enable_if_t<std::is_const_v<element_type> &&
311 detail::is_compatible_range<
312 Range, element_type>::value,
313 int> = 0>
314 constexpr span(const Range &range) noexcept
315 : data_(std::data(range)), size_(std::size(range)) {}
316
317 /**
318 * construct a span from C-array.
319 */
320 template <std::size_t N,
321 std::enable_if_t<extent == dynamic_extent || extent == N, int> = 0>
322 constexpr span(stdx::type_identity_t<element_type> (&arr)[N]) noexcept
323 : data_(std::data(arr)), size_(N) {}
324
325 /**
326 * construct a span from a std::array.
327 */
328 template <class U, std::size_t N,
329 std::enable_if_t<(Extent == dynamic_extent || Extent == N) &&
331 int> = 0>
332 constexpr span(std::array<U, N> &arr) noexcept
333 : data_(std::data(arr)), size_(std::size(arr)) {}
334
335 template <class U, std::size_t N,
336 std::enable_if_t<(Extent == dynamic_extent || Extent == N) &&
338 int> = 0>
339 constexpr span(const std::array<U, N> &arr) noexcept
340 : data_(std::data(arr)), size_(std::size(arr)) {}
341
342 // copy constructor
343 constexpr span(const span &other) noexcept = default;
344 constexpr span &operator=(const span &other) noexcept = default;
345
346 ~span() noexcept = default;
347
348 // span.sub
349
350 /**
351 * create a span of the first Count elements.
352 *
353 * The behaviour is undefined if Count > size()
354 */
355 template <std::size_t Count>
356 constexpr span<element_type, Count> first() const {
357 static_assert(Count <= Extent);
358
359 assert(Count <= size());
360
361 return {data(), Count};
362 }
363
364 /**
365 * create a span of the first Count elements.
366 *
367 * The behaviour is undefined if count > size().
368 */
370 assert(count <= size());
371
372 return {data(), count};
373 }
374
375 /**
376 * create a span of the last Count elements.
377 *
378 * The behaviour is undefined if Count > size().
379 */
380 template <std::size_t Count>
381 constexpr span<element_type, Count> last() const {
382 if constexpr (Extent != dynamic_extent) {
383 static_assert(Count <= Extent);
384 }
385
386 assert(Count <= size());
387
388 return {data() + (size() - Count), Count};
389 }
390
391 /**
392 * create a span of the last Count elements.
393 *
394 * The behaviour is undefined if count > size().
395 */
397 assert(count <= size());
398
399 return {data() + (size() - count), count};
400 }
401
402 /**
403 * create a span of the Count elements, starting at offset.
404 *
405 * if 'Count' is 'dynamic_extent', then up to the end of the span.
406 *
407 * The behaviour is undefined if Offset or Count are out of range.
408 */
409 template <std::size_t Offset, std::size_t Count = dynamic_extent>
411 subspan() const {
412 if constexpr (Extent != dynamic_extent) {
413 static_assert(Offset <= Extent);
414 }
415
416 assert(Offset <= size());
417
418 if constexpr (Count == dynamic_extent) {
419 return {data() + Offset, size() - Offset};
420 } else {
421 assert(Count <= size() - Offset);
422
423 if constexpr (Extent != dynamic_extent) {
424 static_assert(Count <= Extent);
425 static_assert(Count <= Extent - Offset);
426 }
427 }
428
429 return {data() + Offset, Count};
430 }
431
432 /**
433 * create a span of the Count elements, starting at offset.
434 *
435 * if 'count' is 'dynamic_extent', then up to the end of the span.
436 *
437 * The behaviour is undefined if `Count > size()`, and if `Offset > size()`.
438 */
440 size_type offset, size_type count = dynamic_extent) const {
441 assert(offset <= size());
442
443 if (count == dynamic_extent) {
444 return {data() + offset, size() - offset};
445 }
446
447 assert(count <= size());
448
449 return {data() + offset, count};
450 }
451
452 /**
453 * returns a ref to the idx-tn element in the sequence.
454 *
455 * The behaviour is undefined if idx >= size()
456 */
457 constexpr reference operator[](size_type idx) const {
458 assert(idx < size());
459
460 return *(data() + idx);
461 }
462
463 /**
464 * check if this span is empty.
465 *
466 * @retval true if span is empty.
467 * @retval false if span is not empty.
468 */
469 [[nodiscard]] constexpr bool empty() const noexcept { return size() == 0; }
470
471 /**
472 * get the pointer the first element.
473 */
474 constexpr pointer data() const noexcept { return data_; }
475
476 /**
477 * get size in elements.
478 */
479 constexpr size_type size() const noexcept { return size_; }
480
481 /**
482 * get size in bytes.
483 */
484 constexpr size_type size_bytes() const noexcept {
485 return size_ * sizeof(element_type);
486 }
487
488 /**
489 * return a reference to the first element.
490 *
491 * The behaviour is undefined if the span is empty.
492 */
493 constexpr reference front() const {
494 assert(!empty());
495
496 return *begin();
497 }
498
499 /**
500 * return a reference to the last element.
501 *
502 * The behaviour is undefined if the span is empty.
503 */
504 constexpr reference back() const {
505 assert(!empty());
506
507 return *(end() - 1);
508 }
509
510 /**
511 * iterator to the first element.
512 */
513 constexpr iterator begin() const noexcept { return data_; }
514
515 /**
516 * iterator past the last element.
517 */
518 constexpr iterator end() const noexcept { return data_ + size_; }
519
520 constexpr reverse_iterator rbegin() const noexcept {
521 return reverse_iterator(this->end());
522 }
523
524 constexpr reverse_iterator rend() const noexcept {
525 return reverse_iterator(this->begin());
526 }
527
528 private:
531};
532
533// deduction guides
534
535template <class Container>
537
538template <class Container>
540
541// as_bytes
542
543/**
544 * get a view to underlying bytes of a span 'spn'.
545 */
546template <class T, std::size_t N>
548 span<T, N> spn) noexcept {
549 return {reinterpret_cast<const std::byte *>(spn.data()), spn.size_bytes()};
550}
551
552/**
553 * get a writable view to underlying bytes of a span 'spn'.
554 */
555template <class T, std::size_t N,
556 std::enable_if_t<!std::is_const_v<T>, int> = 0>
558 span<T, N> spn) noexcept {
559 return {reinterpret_cast<std::byte *>(spn.data()), spn.size_bytes()};
560}
561
562} // namespace stdx
563
564#endif
Definition: span.h:130
constexpr bool operator>(const iterator &other) const
Definition: span.h:222
constexpr bool operator==(const iterator &other) const
Definition: span.h:207
constexpr iterator & operator+=(difference_type n)
Definition: span.h:141
constexpr bool operator<=(const iterator &other) const
Definition: span.h:232
typename T::pointer pointer
Definition: span.h:134
typename T::reference reference
Definition: span.h:133
std::random_access_iterator_tag iterator_category
Definition: span.h:132
typename T::difference_type difference_type
Definition: span.h:136
constexpr iterator & operator--()
Definition: span.h:180
constexpr reference operator*()
Definition: span.h:201
constexpr bool operator<(const iterator &other) const
Definition: span.h:217
pointer data_
Definition: span.h:237
constexpr reference operator[](difference_type n)
Definition: span.h:204
constexpr bool operator!=(const iterator &other) const
Definition: span.h:212
constexpr bool operator>=(const iterator &other) const
Definition: span.h:227
constexpr iterator operator--(int)
Definition: span.h:187
constexpr iterator operator+(difference_type n)
Definition: span.h:148
constexpr iterator(pointer data)
Definition: span.h:138
constexpr iterator & operator-=(difference_type n)
Definition: span.h:157
constexpr iterator & operator++()
Definition: span.h:173
typename T::value_type value_type
Definition: span.h:135
constexpr difference_type operator-(const iterator &other)
Definition: span.h:196
constexpr iterator operator-(difference_type n)
Definition: span.h:164
Definition: span.h:264
constexpr size_type size() const noexcept
get size in elements.
Definition: span.h:479
constexpr iterator end() const noexcept
iterator past the last element.
Definition: span.h:518
constexpr span< element_type, Count > last() const
create a span of the last Count elements.
Definition: span.h:381
std::ptrdiff_t difference_type
Definition: span.h:270
constexpr span(const std::array< U, N > &arr) noexcept
Definition: span.h:339
const T * const_pointer
Definition: span.h:273
constexpr span(const span &other) noexcept=default
std::reverse_iterator< iterator > reverse_iterator
Definition: span.h:279
std::size_t size_type
Definition: span.h:269
constexpr span(pointer ptr, size_type count)
construct a span from pointer and size
Definition: span.h:295
constexpr reverse_iterator rend() const noexcept
Definition: span.h:524
constexpr iterator begin() const noexcept
iterator to the first element.
Definition: span.h:513
constexpr span< element_type, dynamic_extent > first(size_type count) const
create a span of the first Count elements.
Definition: span.h:369
T element_type
Definition: span.h:266
constexpr span & operator=(const span &other) noexcept=default
const T & const_reference
Definition: span.h:276
size_type size_
Definition: span.h:530
constexpr span< element_type, detail::extent_size< Extent, Offset, Count >::size > subspan() const
create a span of the Count elements, starting at offset.
Definition: span.h:411
static constexpr const size_t extent
Definition: span.h:281
constexpr span(stdx::type_identity_t< element_type >(&arr)[N]) noexcept
construct a span from C-array.
Definition: span.h:322
constexpr reference operator[](size_type idx) const
returns a ref to the idx-tn element in the sequence.
Definition: span.h:457
constexpr span< element_type, Count > first() const
create a span of the first Count elements.
Definition: span.h:356
constexpr pointer data() const noexcept
get the pointer the first element.
Definition: span.h:474
std::remove_cv_t< T > value_type
Definition: span.h:267
pointer data_
Definition: span.h:529
constexpr reference back() const
return a reference to the last element.
Definition: span.h:504
constexpr span< element_type, dynamic_extent > last(size_type count) const
create a span of the last Count elements.
Definition: span.h:396
constexpr span< element_type, dynamic_extent > subspan(size_type offset, size_type count=dynamic_extent) const
create a span of the Count elements, starting at offset.
Definition: span.h:439
T * pointer
Definition: span.h:272
constexpr reference front() const
return a reference to the first element.
Definition: span.h:493
constexpr bool empty() const noexcept
check if this span is empty.
Definition: span.h:469
constexpr span() noexcept
default construct.
Definition: span.h:290
T & reference
Definition: span.h:275
constexpr span(const Range &range) noexcept
construct a span from a const continous range like a vector.
Definition: span.h:314
~span() noexcept=default
constexpr size_type size_bytes() const noexcept
get size in bytes.
Definition: span.h:484
constexpr span(std::array< U, N > &arr) noexcept
construct a span from a std::array.
Definition: span.h:332
constexpr reverse_iterator rbegin() const noexcept
Definition: span.h:520
constexpr span(Range &cont) noexcept
construct a span from a continous range like a vector.
Definition: span.h:304
#define U
Definition: ctype-tis620.cc:73
unsigned char byte
Blob class.
Definition: common.h:150
static int count
Definition: myisam_ftdump.cc:44
std::atomic< Type > N
Definition: ut0counter.h:224
uint16_t value_type
Definition: vt100.h:183
Definition: ut0tuple.h:56
Definition: varlen_sort.h:183
Definition: bit.h:33
span< std::byte, detail::span_size< T, N >::size > as_writable_bytes(span< T, N > spn) noexcept
get a writable view to underlying bytes of a span 'spn'.
Definition: span.h:557
typename type_identity< T >::type type_identity_t
Definition: type_traits.h:80
span< const std::byte, detail::span_size< T, N >::size > as_bytes(span< T, N > spn) noexcept
get a view to underlying bytes of a span 'spn'.
Definition: span.h:547
span(Container &) -> span< typename Container::value_type >
constexpr std::size_t dynamic_extent
Definition: span.h:44
required string type
Definition: replication_group_member_actions.proto:33
Definition: gen_lex_token.cc:148
Definition: span.h:251
static constexpr size_t size
Definition: span.h:252
Definition: span.h:52
Definition: span.h:59
Definition: span.h:121
Definition: span.h:93
Definition: span.h:79
Definition: span.h:85
Definition: span.h:68
Definition: span.h:74
Definition: span.h:241
static constexpr size_t size
Definition: span.h:242
int n
Definition: xcom_base.cc:508