Gamedev Framework (gf) 1.2.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
28namespace gf {
29#ifndef DOXYGEN_SHOULD_SKIP_THIS
30inline namespace v1 {
31#endif
32
33 template<typename T>
34 class Span;
35
48 template<typename T, std::size_t N>
49 class StaticSpan {
50 public:
54 static constexpr std::size_t Size = N;
55
56
62 constexpr
63 StaticSpan() noexcept
64 : m_data(nullptr)
65 {
66 }
67
73 constexpr
74 StaticSpan(std::nullptr_t) noexcept
75 : m_data(nullptr)
76 {
77 }
78
87 constexpr
88 StaticSpan(T *data, [[maybe_unused]] std::size_t size) noexcept
89 : m_data(data)
90 {
91 assert(size == Size);
92 }
93
101 template<typename U, typename = std::enable_if_t<std::is_convertible<U(*)[], T(*)[]>::value>>
102 constexpr
103 StaticSpan(U (&data)[N]) noexcept
104 : m_data(data)
105 {
106 }
107
115 template<typename U, typename = std::enable_if_t<std::is_convertible<U(*)[], T(*)[]>::value>>
116 constexpr
117 StaticSpan(std::array<U, N>& array) noexcept
118 : m_data(array.data())
119 {
120 }
121
127 template<typename U, typename = std::enable_if_t<std::is_convertible<U(*)[], T(*)[]>::value>>
128 constexpr
130 : m_data(other.getData())
131 {
132 }
133
139 constexpr
140 T *getData() noexcept {
141 return m_data;
142 }
143
149 constexpr
150 const T *getData() const noexcept {
151 return m_data;
152 }
153
159 constexpr
160 std::size_t getSize() const noexcept {
161 return Size;
162 }
163
169 constexpr
170 bool isEmpty() const noexcept {
171 return m_data == nullptr || Size == 0;
172 }
173
181 constexpr
182 T *begin() noexcept {
183 return m_data;
184 }
185
193 constexpr
194 T *end() noexcept {
195 return m_data == nullptr ? nullptr : m_data + Size;
196 }
197
205 constexpr
206 const T *begin() const noexcept {
207 return m_data;
208 }
209
217 constexpr
218 const T *end() const noexcept {
219 return m_data == nullptr ? nullptr : m_data + Size;
220 }
221
228 constexpr
229 T& operator[](std::size_t index) noexcept {
230 assert(m_data != nullptr && index < Size);
231 return m_data[index];
232 }
233
240 constexpr
241 const T& operator[](std::size_t index) const noexcept {
242 assert(m_data != nullptr && index < Size);
243 return m_data[index];
244 }
245
251 template<std::size_t I>
252 constexpr
253 T& get() noexcept {
254 static_assert(I < N, "Out of bounds.");
255 assert(m_data != nullptr);
256 return m_data[I];
257 }
258
264 template<std::size_t I>
265 constexpr
266 const T& get() const noexcept {
267 static_assert(I < N, "Out of bounds.");
268 assert(m_data != nullptr);
269 return m_data[I];
270 }
271
279 constexpr
280 Span<T> slice(std::size_t b, std::size_t e) const noexcept {
281 assert(b <= e && e <= Size);
282 return Span<T>(m_data + b, e - b);
283 }
284
292 template<std::size_t B, std::size_t E>
293 constexpr
294 StaticSpan<T, E - B> slice() const noexcept {
295 static_assert(B <= E && E <= Size, "Out of bounds.");
296 return StaticSpan<T, E - B>(m_data + B);
297 }
298
305 constexpr
306 Span<T> first(std::size_t count) const noexcept {
307 return slice(0, count);
308 }
309
316 template<std::size_t C>
317 constexpr
318 StaticSpan<T, C> first() const noexcept {
319 static_assert(C <= Size, "Out of bounds.");
320 return slice<0, C>();
321 }
322
329 constexpr
330 Span<T> last(std::size_t count) const noexcept {
331 assert(count <= Size);
332 return slice(Size - count, Size);
333 }
334
341 template<std::size_t C>
342 constexpr
343 StaticSpan<T, C> last() const noexcept {
344 static_assert(C <= Size, "Out of bounds.");
345 return slice<Size - C, Size>();
346 }
347
354 constexpr
355 Span<T> firstExcept(std::size_t count) const noexcept {
356 assert(count <= Size);
357 return slice(0, Size - count);
358 }
359
366 template<std::size_t C>
367 constexpr
368 StaticSpan<T, Size - C> firstExcept() const noexcept {
369 static_assert(C <= Size, "Out of bounds.");
370 return slice<0, Size - C>();
371 }
372
379 constexpr
380 Span<T> lastExcept(std::size_t count) const noexcept {
381 return slice(count, Size);
382 }
383
390 template<std::size_t C>
391 constexpr
392 StaticSpan<T, Size - C> lastExcept() const noexcept {
393 static_assert(C <= Size, "Out of bounds.");
394 return slice<C, Size>();
395 }
396
397 private:
398 T *m_data;
399 };
400
401
413 template<typename T>
414 class Span {
415 public:
416
417
423 constexpr
425 : m_data(nullptr)
426 , m_size(0)
427 {
428 }
429
435 constexpr
436 Span(std::nullptr_t)
437 : m_data(nullptr)
438 , m_size(0)
439 {
440 }
441
448 constexpr
449 Span(T *data, std::size_t size)
450 : m_data(data)
451 , m_size(size)
452 {
453 }
454
460 template<typename U, typename = std::enable_if_t<std::is_convertible<U(*)[], T(*)[]>::value>>
461 Span(std::vector<U>& values)
462 : m_data(values.data())
463 , m_size(values.size())
464 {
465 }
466
472 template<typename U, typename = std::enable_if_t<std::is_convertible<U(*)[], T(*)[]>::value && std::is_const<T>::value>>
473 Span(const std::vector<U>& values)
474 : m_data(values.data())
475 , m_size(values.size())
476 {
477 }
478
484 template<typename U, std::size_t N, typename = std::enable_if_t<std::is_convertible<U(*)[], T(*)[]>::value>>
485 Span(std::array<U,N>& values)
486 : m_data(values.data())
487 , m_size(values.size())
488 {
489 }
490
498 template<typename U, std::size_t N, typename = std::enable_if_t<std::is_convertible<U(*)[], T(*)[]>::value>>
499 constexpr Span(U (&data)[N])
500 : m_data(data)
501 , m_size(N)
502 {
503 }
504
510 template<typename U, typename = std::enable_if_t<std::is_convertible<U(*)[], T(*)[]>::value>>
511 constexpr Span(Span<U> other)
512 : m_data(other.getData())
513 , m_size(other.getSize())
514 {
515 }
516
522 template<typename U, std::size_t N, typename = std::enable_if_t<std::is_convertible<U(*)[], T(*)[]>::value>>
523 constexpr Span(StaticSpan<U, N> other)
524 : m_data(other.getData())
525 , m_size(other.getSize())
526 {
527 }
528
534 constexpr T *getData() noexcept {
535 return m_data;
536 }
537
543 constexpr const T *getData() const noexcept {
544 return m_data;
545 }
546
552 constexpr std::size_t getSize() const noexcept {
553 return m_size;
554 }
555
561 constexpr bool isEmpty() const noexcept {
562 return m_size == 0;
563 }
564
572 constexpr T *begin() noexcept {
573 return m_data;
574 }
575
583 constexpr T *end() noexcept {
584 return m_data + m_size;
585 }
586
594 constexpr const T *begin() const noexcept {
595 return m_data;
596 }
597
605 constexpr const T *end() const noexcept {
606 return m_data + m_size;
607 }
608
617 constexpr T& operator[](std::size_t index) {
618 return m_data[index];
619 }
620
629 constexpr const T& operator[](std::size_t index) const {
630 return m_data[index];
631 }
632
640 constexpr
641 Span<T> slice(std::size_t b, std::size_t e) const noexcept {
642 assert(b <= e && e <= m_size);
643 return Span<T>(m_data + b, e - b);
644 }
645
653 template<std::size_t B, std::size_t E>
654 constexpr
655 StaticSpan<T, E - B> slice() const noexcept {
656 static_assert(B <= E, "Out of bounds.");
657 assert(E <= m_size);
658 return StaticSpan<T, E - B>(m_data + B);
659 }
660
667 constexpr
668 Span<T> first(std::size_t count) const noexcept {
669 return slice(0, count);
670 }
671
678 template<std::size_t C>
679 constexpr
680 StaticSpan<T, C> first() const noexcept {
681 assert(C <= m_size);
682 return StaticSpan<T, C>(m_data, C);
683 }
684
691 constexpr
692 Span<T> last(std::size_t count) const noexcept {
693 assert(count <= m_size);
694 return slice(m_size - count, m_size);
695 }
696
703 template<std::size_t C>
704 constexpr
705 StaticSpan<T, C> last() const noexcept {
706 assert(C <= m_size);
707 return StaticSpan<T, C>(m_data + m_size - C, C);
708 }
709
716 constexpr
717 Span<T> firstExcept(std::size_t count) const noexcept {
718 assert(count <= m_size);
719 return slice(0, m_size - count);
720 }
721
728 template<std::size_t C>
729 constexpr
730 Span<T> firstExcept() const noexcept {
731 assert(C <= m_size);
732 return slice(0, m_size - C);
733 }
734
741 constexpr
742 Span<T> lastExcept(std::size_t count) const noexcept {
743 return slice(count, m_size);
744 }
745
752 template<std::size_t C>
753 constexpr
754 Span<T> lastExcept() const noexcept {
755 assert(C <= m_size);
756 return slice(C, m_size);
757 }
758
759 private:
760 T *m_data;
761 std::size_t m_size;
762 };
763
764
765 template<typename T>
766 constexpr
767 Span<T> span(T *data, std::size_t size) {
768 return Span<T>(data, size);
769 }
770
771 template<typename T, std::size_t N>
772 constexpr
773 StaticSpan<T, N> span(T (&data)[N]) {
774 return StaticSpan<T, N>(data);
775 }
776
777#ifndef DOXYGEN_SHOULD_SKIP_THIS
778}
779#endif
780}
781
782#endif // GF_SPAN_H
A span.
Definition: Span.h:414
constexpr T & operator[](std::size_t index)
Get an element at a given index.
Definition: Span.h:617
constexpr Span< T > firstExcept() const noexcept
Take a span on the first objects.
Definition: Span.h:730
constexpr const T * getData() const noexcept
Get a pointer to the elements.
Definition: Span.h:543
constexpr const T * end() const noexcept
Get an iterator past the last element.
Definition: Span.h:605
constexpr Span(StaticSpan< U, N > other)
Constructor from another static span.
Definition: Span.h:523
constexpr Span< T > slice(std::size_t b, std::size_t e) const noexcept
Take a sub-span.
Definition: Span.h:641
constexpr const T & operator[](std::size_t index) const
Get an element at a given index.
Definition: Span.h:629
constexpr T * end() noexcept
Get an iterator past the last element.
Definition: Span.h:583
constexpr Span(Span< U > other)
Constructor from another span.
Definition: Span.h:511
constexpr Span(T *data, std::size_t size)
Constructor from a pointer and a size.
Definition: Span.h:449
constexpr T * begin() noexcept
Get an iterator to the first element.
Definition: Span.h:572
constexpr T * getData() noexcept
Get a pointer to the elements.
Definition: Span.h:534
constexpr Span(std::nullptr_t)
Null constructor.
Definition: Span.h:436
Span(std::vector< U > &values)
Constructor from a std::vector
Definition: Span.h:461
Span(const std::vector< U > &values)
Constructor from a std::vector
Definition: Span.h:473
constexpr bool isEmpty() const noexcept
Check if the array is empty.
Definition: Span.h:561
Span(std::array< U, N > &values)
Constructor from a std::array
Definition: Span.h:485
constexpr StaticSpan< T, C > last() const noexcept
Take a constant span on the last objects.
Definition: Span.h:705
constexpr const T * begin() const noexcept
Get an iterator to the first element.
Definition: Span.h:594
constexpr Span< T > lastExcept() const noexcept
Take a span on the last objects.
Definition: Span.h:754
constexpr Span()
Default constructor.
Definition: Span.h:424
constexpr Span< T > last(std::size_t count) const noexcept
Take a span on the last objects.
Definition: Span.h:692
constexpr StaticSpan< T, E - B > slice() const noexcept
Take a constant sub-span.
Definition: Span.h:655
constexpr Span(U(&data)[N])
Constructor from a static array.
Definition: Span.h:499
constexpr StaticSpan< T, C > first() const noexcept
Take a constant span on the first objects.
Definition: Span.h:680
constexpr Span< T > first(std::size_t count) const noexcept
Take a span on the first objects.
Definition: Span.h:668
constexpr Span< T > lastExcept(std::size_t count) const noexcept
Take a span on the last objects.
Definition: Span.h:742
constexpr std::size_t getSize() const noexcept
Get the number of elements.
Definition: Span.h:552
constexpr Span< T > firstExcept(std::size_t count) const noexcept
Take a span on the first objects.
Definition: Span.h:717
A static span.
Definition: Span.h:49
constexpr bool isEmpty() const noexcept
Check if the array is empty.
Definition: Span.h:170
constexpr StaticSpan(std::array< U, N > &array) noexcept
Constructor from a std::array
Definition: Span.h:117
constexpr T & get() noexcept
Get an element at a constant index.
Definition: Span.h:253
constexpr StaticSpan< T, C > first() const noexcept
Take a constant span on the first objects.
Definition: Span.h:318
constexpr Span< T > firstExcept(std::size_t count) const noexcept
Take a span on the first objects.
Definition: Span.h:355
constexpr T * getData() noexcept
Get a pointer to the elements.
Definition: Span.h:140
constexpr const T * end() const noexcept
Get an iterator past the last element.
Definition: Span.h:218
constexpr StaticSpan() noexcept
Default constructor.
Definition: Span.h:63
constexpr Span< T > slice(std::size_t b, std::size_t e) const noexcept
Take a sub-span.
Definition: Span.h:280
constexpr T * begin() noexcept
Get an iterator to the first element.
Definition: Span.h:182
constexpr StaticSpan(U(&data)[N]) noexcept
Constructor from a static array.
Definition: Span.h:103
constexpr StaticSpan< T, Size - C > lastExcept() const noexcept
Take a constant span on the last objects.
Definition: Span.h:392
constexpr T * end() noexcept
Get an iterator past the last element.
Definition: Span.h:194
constexpr StaticSpan(T *data, std::size_t size) noexcept
Constructor from a pointer and a size.
Definition: Span.h:88
constexpr Span< T > first(std::size_t count) const noexcept
Take a span on the first objects.
Definition: Span.h:306
constexpr StaticSpan(StaticSpan< U, N > other) noexcept
Constructor from another span.
Definition: Span.h:129
constexpr const T * begin() const noexcept
Get an iterator to the first element.
Definition: Span.h:206
constexpr StaticSpan< T, Size - C > firstExcept() const noexcept
Take a constant span on the first objects.
Definition: Span.h:368
constexpr const T & operator[](std::size_t index) const noexcept
Get an element at a given index.
Definition: Span.h:241
constexpr const T & get() const noexcept
Get an element at a constant index.
Definition: Span.h:266
constexpr Span< T > last(std::size_t count) const noexcept
Take a span on the last objects.
Definition: Span.h:330
constexpr StaticSpan< T, E - B > slice() const noexcept
Take a constant sub-span.
Definition: Span.h:294
constexpr std::size_t getSize() const noexcept
Get the number of elements.
Definition: Span.h:160
constexpr StaticSpan< T, C > last() const noexcept
Take a constant span on the last objects.
Definition: Span.h:343
constexpr StaticSpan(std::nullptr_t) noexcept
Null constructor.
Definition: Span.h:74
constexpr T & operator[](std::size_t index) noexcept
Get an element at a given index.
Definition: Span.h:229
constexpr const T * getData() const noexcept
Get a pointer to the elements.
Definition: Span.h:150
constexpr Span< T > lastExcept(std::size_t count) const noexcept
Take a span on the last objects.
Definition: Span.h:380
@ B
The B button.
The namespace for gf classes.
constexpr Span< T > span(T *data, std::size_t size)
Definition: Span.h:767