Gamedev Framework (gf) 0.22.0
A C++17 framework for 2D games
Span.h
1/*
2 * Gamedev Framework (gf)
3 * Copyright (C) 2016-2022 Julien Bernard
4 *
5 * This software is provided 'as-is', without any express or implied
6 * warranty. In no event will the authors be held liable for any damages
7 * arising from the use of this software.
8 *
9 * Permission is granted to anyone to use this software for any purpose,
10 * including commercial applications, and to alter it and redistribute it
11 * freely, subject to the following restrictions:
12 *
13 * 1. The origin of this software must not be misrepresented; you must not
14 * claim that you wrote the original software. If you use this software
15 * in a product, an acknowledgment in the product documentation would be
16 * appreciated but is not required.
17 * 2. Altered source versions must be plainly marked as such, and must not be
18 * misrepresented as being the original software.
19 * 3. This notice may not be removed or altered from any source distribution.
20 */
21#ifndef GF_SPAN_H
22#define GF_SPAN_H
23
24#include <cassert>
25#include <array>
26#include <vector>
27
28#include "Unused.h"
29
30namespace gf {
31#ifndef DOXYGEN_SHOULD_SKIP_THIS
32inline namespace v1 {
33#endif
34
35 template<typename T>
36 class Span;
37
50 template<typename T, std::size_t N>
51 class StaticSpan {
52 public:
56 static constexpr std::size_t Size = N;
57
58
64 constexpr
65 StaticSpan() noexcept
66 : m_data(nullptr)
67 {
68 }
69
75 constexpr
76 StaticSpan(std::nullptr_t) noexcept
77 : m_data(nullptr)
78 {
79 }
80
89 constexpr
90 StaticSpan(T *data, std::size_t size) noexcept
91 : m_data(data)
92 {
93 assert(size == Size);
94 gf::unused(size);
95 }
96
104 template<typename U, typename = std::enable_if_t<std::is_convertible<U(*)[], T(*)[]>::value>>
105 constexpr
106 StaticSpan(U (&data)[N]) noexcept
107 : m_data(data)
108 {
109 }
110
118 template<typename U, typename = std::enable_if_t<std::is_convertible<U(*)[], T(*)[]>::value>>
119 constexpr
120 StaticSpan(std::array<U, N>& array) noexcept
121 : m_data(array.data())
122 {
123 }
124
130 template<typename U, typename = std::enable_if_t<std::is_convertible<U(*)[], T(*)[]>::value>>
131 constexpr
133 : m_data(other.getData())
134 {
135 }
136
142 constexpr
143 T *getData() noexcept {
144 return m_data;
145 }
146
152 constexpr
153 const T *getData() const noexcept {
154 return m_data;
155 }
156
162 constexpr
163 std::size_t getSize() const noexcept {
164 return Size;
165 }
166
172 constexpr
173 bool isEmpty() const noexcept {
174 return m_data == nullptr || Size == 0;
175 }
176
184 constexpr
185 T *begin() noexcept {
186 return m_data;
187 }
188
196 constexpr
197 T *end() noexcept {
198 return m_data == nullptr ? nullptr : m_data + Size;
199 }
200
208 constexpr
209 const T *begin() const noexcept {
210 return m_data;
211 }
212
220 constexpr
221 const T *end() const noexcept {
222 return m_data == nullptr ? nullptr : m_data + Size;
223 }
224
231 constexpr
232 T& operator[](std::size_t index) noexcept {
233 assert(m_data != nullptr && index < Size);
234 return m_data[index];
235 }
236
243 constexpr
244 const T& operator[](std::size_t index) const noexcept {
245 assert(m_data != nullptr && index < Size);
246 return m_data[index];
247 }
248
254 template<std::size_t I>
255 constexpr
256 T& get() noexcept {
257 static_assert(I < N, "Out of bounds.");
258 assert(m_data != nullptr);
259 return m_data[I];
260 }
261
267 template<std::size_t I>
268 constexpr
269 const T& get() const noexcept {
270 static_assert(I < N, "Out of bounds.");
271 assert(m_data != nullptr);
272 return m_data[I];
273 }
274
282 constexpr
283 Span<T> slice(std::size_t b, std::size_t e) const noexcept {
284 assert(b <= e && e <= Size);
285 return Span<T>(m_data + b, e - b);
286 }
287
295 template<std::size_t B, std::size_t E>
296 constexpr
297 StaticSpan<T, E - B> slice() const noexcept {
298 static_assert(B <= E && E <= Size, "Out of bounds.");
299 return StaticSpan<T, E - B>(m_data + B);
300 }
301
308 constexpr
309 Span<T> first(std::size_t count) const noexcept {
310 return slice(0, count);
311 }
312
319 template<std::size_t C>
320 constexpr
321 StaticSpan<T, C> first() const noexcept {
322 static_assert(C <= Size, "Out of bounds.");
323 return slice<0, C>();
324 }
325
332 constexpr
333 Span<T> last(std::size_t count) const noexcept {
334 assert(count <= Size);
335 return slice(Size - count, Size);
336 }
337
344 template<std::size_t C>
345 constexpr
346 StaticSpan<T, C> last() const noexcept {
347 static_assert(C <= Size, "Out of bounds.");
348 return slice<Size - C, Size>();
349 }
350
357 constexpr
358 Span<T> firstExcept(std::size_t count) const noexcept {
359 assert(count <= Size);
360 return slice(0, Size - count);
361 }
362
369 template<std::size_t C>
370 constexpr
371 StaticSpan<T, Size - C> firstExcept() const noexcept {
372 static_assert(C <= Size, "Out of bounds.");
373 return slice<0, Size - C>();
374 }
375
382 constexpr
383 Span<T> lastExcept(std::size_t count) const noexcept {
384 return slice(count, Size);
385 }
386
393 template<std::size_t C>
394 constexpr
395 StaticSpan<T, Size - C> lastExcept() const noexcept {
396 static_assert(C <= Size, "Out of bounds.");
397 return slice<C, Size>();
398 }
399
400 private:
401 T *m_data;
402 };
403
404
416 template<typename T>
417 class Span {
418 public:
419
420
426 constexpr
428 : m_data(nullptr)
429 , m_size(0)
430 {
431 }
432
438 constexpr
439 Span(std::nullptr_t)
440 : m_data(nullptr)
441 , m_size(0)
442 {
443 }
444
451 constexpr
452 Span(T *data, std::size_t size)
453 : m_data(data)
454 , m_size(size)
455 {
456 }
457
463 template<typename U, typename = std::enable_if_t<std::is_convertible<U(*)[], T(*)[]>::value>>
464 Span(std::vector<U>& values)
465 : m_data(values.data())
466 , m_size(values.size())
467 {
468 }
469
475 template<typename U, typename = std::enable_if_t<std::is_convertible<U(*)[], T(*)[]>::value && std::is_const<T>::value>>
476 Span(const std::vector<U>& values)
477 : m_data(values.data())
478 , m_size(values.size())
479 {
480 }
481
487 template<typename U, std::size_t N, typename = std::enable_if_t<std::is_convertible<U(*)[], T(*)[]>::value>>
488 Span(std::array<U,N>& values)
489 : m_data(values.data())
490 , m_size(values.size())
491 {
492 }
493
501 template<typename U, std::size_t N, typename = std::enable_if_t<std::is_convertible<U(*)[], T(*)[]>::value>>
502 constexpr Span(U (&data)[N])
503 : m_data(data)
504 , m_size(N)
505 {
506 }
507
513 template<typename U, typename = std::enable_if_t<std::is_convertible<U(*)[], T(*)[]>::value>>
514 constexpr Span(Span<U> other)
515 : m_data(other.getData())
516 , m_size(other.getSize())
517 {
518 }
519
525 template<typename U, std::size_t N, typename = std::enable_if_t<std::is_convertible<U(*)[], T(*)[]>::value>>
526 constexpr Span(StaticSpan<U, N> other)
527 : m_data(other.getData())
528 , m_size(other.getSize())
529 {
530 }
531
537 constexpr T *getData() noexcept {
538 return m_data;
539 }
540
546 constexpr const T *getData() const noexcept {
547 return m_data;
548 }
549
555 constexpr std::size_t getSize() const noexcept {
556 return m_size;
557 }
558
564 constexpr bool isEmpty() const noexcept {
565 return m_size == 0;
566 }
567
575 constexpr T *begin() noexcept {
576 return m_data;
577 }
578
586 constexpr T *end() noexcept {
587 return m_data + m_size;
588 }
589
597 constexpr const T *begin() const noexcept {
598 return m_data;
599 }
600
608 constexpr const T *end() const noexcept {
609 return m_data + m_size;
610 }
611
620 constexpr T& operator[](std::size_t index) {
621 return m_data[index];
622 }
623
632 constexpr const T& operator[](std::size_t index) const {
633 return m_data[index];
634 }
635
643 constexpr
644 Span<T> slice(std::size_t b, std::size_t e) const noexcept {
645 assert(b <= e && e <= m_size);
646 return Span<T>(m_data + b, e - b);
647 }
648
656 template<std::size_t B, std::size_t E>
657 constexpr
658 StaticSpan<T, E - B> slice() const noexcept {
659 static_assert(B <= E, "Out of bounds.");
660 assert(E <= m_size);
661 return StaticSpan<T, E - B>(m_data + B);
662 }
663
670 constexpr
671 Span<T> first(std::size_t count) const noexcept {
672 return slice(0, count);
673 }
674
681 template<std::size_t C>
682 constexpr
683 StaticSpan<T, C> first() const noexcept {
684 assert(C <= m_size);
685 return StaticSpan<T, C>(m_data, C);
686 }
687
694 constexpr
695 Span<T> last(std::size_t count) const noexcept {
696 assert(count <= m_size);
697 return slice(m_size - count, m_size);
698 }
699
706 template<std::size_t C>
707 constexpr
708 StaticSpan<T, C> last() const noexcept {
709 assert(C <= m_size);
710 return StaticSpan<T, C>(m_data + m_size - C, C);
711 }
712
719 constexpr
720 Span<T> firstExcept(std::size_t count) const noexcept {
721 assert(count <= m_size);
722 return slice(0, m_size - count);
723 }
724
731 template<std::size_t C>
732 constexpr
733 Span<T> firstExcept() const noexcept {
734 assert(C <= m_size);
735 return slice(0, m_size - C);
736 }
737
744 constexpr
745 Span<T> lastExcept(std::size_t count) const noexcept {
746 return slice(count, m_size);
747 }
748
755 template<std::size_t C>
756 constexpr
757 Span<T> lastExcept() const noexcept {
758 assert(C <= m_size);
759 return slice(C, m_size);
760 }
761
762 private:
763 T *m_data;
764 std::size_t m_size;
765 };
766
767
768 template<typename T>
769 constexpr
770 Span<T> span(T *data, std::size_t size) {
771 return Span<T>(data, size);
772 }
773
774 template<typename T, std::size_t N>
775 constexpr
776 StaticSpan<T, N> span(T (&data)[N]) {
777 return StaticSpan<T, N>(data);
778 }
779
780#ifndef DOXYGEN_SHOULD_SKIP_THIS
781}
782#endif
783}
784
785#endif // GF_SPAN_H
A span.
Definition: Span.h:417
constexpr T & operator[](std::size_t index)
Get an element at a given index.
Definition: Span.h:620
constexpr Span< T > firstExcept() const noexcept
Take a span on the first objects.
Definition: Span.h:733
constexpr const T * getData() const noexcept
Get a pointer to the elements.
Definition: Span.h:546
constexpr const T * end() const noexcept
Get an iterator past the last element.
Definition: Span.h:608
constexpr Span(StaticSpan< U, N > other)
Constructor from another static span.
Definition: Span.h:526
constexpr Span< T > slice(std::size_t b, std::size_t e) const noexcept
Take a sub-span.
Definition: Span.h:644
constexpr const T & operator[](std::size_t index) const
Get an element at a given index.
Definition: Span.h:632
constexpr T * end() noexcept
Get an iterator past the last element.
Definition: Span.h:586
constexpr Span(Span< U > other)
Constructor from another span.
Definition: Span.h:514
constexpr Span(T *data, std::size_t size)
Constructor from a pointer and a size.
Definition: Span.h:452
constexpr T * begin() noexcept
Get an iterator to the first element.
Definition: Span.h:575
constexpr T * getData() noexcept
Get a pointer to the elements.
Definition: Span.h:537
constexpr Span(std::nullptr_t)
Null constructor.
Definition: Span.h:439
Span(std::vector< U > &values)
Constructor from a std::vector
Definition: Span.h:464
Span(const std::vector< U > &values)
Constructor from a std::vector
Definition: Span.h:476
constexpr bool isEmpty() const noexcept
Check if the array is empty.
Definition: Span.h:564
Span(std::array< U, N > &values)
Constructor from a std::array
Definition: Span.h:488
constexpr StaticSpan< T, C > last() const noexcept
Take a constant span on the last objects.
Definition: Span.h:708
constexpr const T * begin() const noexcept
Get an iterator to the first element.
Definition: Span.h:597
constexpr Span< T > lastExcept() const noexcept
Take a span on the last objects.
Definition: Span.h:757
constexpr Span()
Default constructor.
Definition: Span.h:427
constexpr Span< T > last(std::size_t count) const noexcept
Take a span on the last objects.
Definition: Span.h:695
constexpr StaticSpan< T, E - B > slice() const noexcept
Take a constant sub-span.
Definition: Span.h:658
constexpr Span(U(&data)[N])
Constructor from a static array.
Definition: Span.h:502
constexpr StaticSpan< T, C > first() const noexcept
Take a constant span on the first objects.
Definition: Span.h:683
constexpr Span< T > first(std::size_t count) const noexcept
Take a span on the first objects.
Definition: Span.h:671
constexpr Span< T > lastExcept(std::size_t count) const noexcept
Take a span on the last objects.
Definition: Span.h:745
constexpr std::size_t getSize() const noexcept
Get the number of elements.
Definition: Span.h:555
constexpr Span< T > firstExcept(std::size_t count) const noexcept
Take a span on the first objects.
Definition: Span.h:720
A static span.
Definition: Span.h:51
constexpr bool isEmpty() const noexcept
Check if the array is empty.
Definition: Span.h:173
constexpr StaticSpan(std::array< U, N > &array) noexcept
Constructor from a std::array
Definition: Span.h:120
constexpr T & get() noexcept
Get an element at a constant index.
Definition: Span.h:256
constexpr StaticSpan< T, C > first() const noexcept
Take a constant span on the first objects.
Definition: Span.h:321
constexpr Span< T > firstExcept(std::size_t count) const noexcept
Take a span on the first objects.
Definition: Span.h:358
constexpr T * getData() noexcept
Get a pointer to the elements.
Definition: Span.h:143
constexpr const T * end() const noexcept
Get an iterator past the last element.
Definition: Span.h:221
constexpr StaticSpan() noexcept
Default constructor.
Definition: Span.h:65
constexpr Span< T > slice(std::size_t b, std::size_t e) const noexcept
Take a sub-span.
Definition: Span.h:283
constexpr T * begin() noexcept
Get an iterator to the first element.
Definition: Span.h:185
constexpr StaticSpan(U(&data)[N]) noexcept
Constructor from a static array.
Definition: Span.h:106
constexpr StaticSpan< T, Size - C > lastExcept() const noexcept
Take a constant span on the last objects.
Definition: Span.h:395
constexpr T * end() noexcept
Get an iterator past the last element.
Definition: Span.h:197
constexpr StaticSpan(T *data, std::size_t size) noexcept
Constructor from a pointer and a size.
Definition: Span.h:90
constexpr Span< T > first(std::size_t count) const noexcept
Take a span on the first objects.
Definition: Span.h:309
constexpr StaticSpan(StaticSpan< U, N > other) noexcept
Constructor from another span.
Definition: Span.h:132
constexpr const T * begin() const noexcept
Get an iterator to the first element.
Definition: Span.h:209
constexpr StaticSpan< T, Size - C > firstExcept() const noexcept
Take a constant span on the first objects.
Definition: Span.h:371
constexpr const T & operator[](std::size_t index) const noexcept
Get an element at a given index.
Definition: Span.h:244
constexpr const T & get() const noexcept
Get an element at a constant index.
Definition: Span.h:269
constexpr Span< T > last(std::size_t count) const noexcept
Take a span on the last objects.
Definition: Span.h:333
constexpr StaticSpan< T, E - B > slice() const noexcept
Take a constant sub-span.
Definition: Span.h:297
constexpr std::size_t getSize() const noexcept
Get the number of elements.
Definition: Span.h:163
constexpr StaticSpan< T, C > last() const noexcept
Take a constant span on the last objects.
Definition: Span.h:346
constexpr StaticSpan(std::nullptr_t) noexcept
Null constructor.
Definition: Span.h:76
constexpr T & operator[](std::size_t index) noexcept
Get an element at a given index.
Definition: Span.h:232
constexpr const T * getData() const noexcept
Get a pointer to the elements.
Definition: Span.h:153
constexpr Span< T > lastExcept(std::size_t count) const noexcept
Take a span on the last objects.
Definition: Span.h:383
constexpr void unused(Args &&...)
A simple way to avoid warnings about unused variables.
Definition: Unused.h:35
@ B
The B button.
The namespace for gf classes.
constexpr Span< T > span(T *data, std::size_t size)
Definition: Span.h:770