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