Gamedev Framework (gf)  0.19.0
A C++17 framework for 2D games
Range.h
1 /*
2  * Gamedev Framework (gf)
3  * Copyright (C) 2016-2021 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_RANGE_H
22 #define GF_RANGE_H
23 
24 #include <cstddef>
25 #include <iterator>
26 
27 #include "CoreApi.h"
28 #include "Math.h"
29 #include "Vector.h"
30 
31 namespace gf {
32 #ifndef DOXYGEN_SHOULD_SKIP_THIS
33 inline namespace v1 {
34 #endif
35 
43  template<typename T>
44  struct Range {
45  T lo;
46  T hi;
47 
52  struct Iterator {
53  using difference_type = std::ptrdiff_t;
54  using value_type = T;
57  using iterator_category = std::bidirectional_iterator_tag;
58 
59  T index;
60 
66  constexpr Iterator(T iteratorIndex) noexcept
67  : index(iteratorIndex)
68  {
69  }
70 
74  void swap(Iterator& other) noexcept {
75  using std::swap;
76  swap(index, other.index);
77  }
78 
84  reference operator*() noexcept {
85  return index;
86  }
87 
93  pointer operator->() noexcept {
94  return index;
95  }
96 
102  Iterator& operator++() noexcept {
103  ++index;
104  return *this;
105  }
106 
112  Iterator operator++(int) noexcept {
113  Iterator copy = *this;
114  ++index;
115  return copy;
116  }
117 
123  Iterator& operator--() noexcept {
124  --index;
125  return *this;
126  }
127 
133  Iterator operator--(int) noexcept {
134  Iterator copy = *this;
135  --index;
136  return copy;
137  }
138 
145  constexpr bool operator!=(const Iterator& other) const noexcept {
146  return index != other.index;
147  }
148 
155  constexpr bool operator==(const Iterator& other) const noexcept {
156  return index == other.index;
157  }
158  };
159 
166  constexpr bool contains(T value) const noexcept {
167  return lo <= value && value < hi;
168  }
169 
176  constexpr Iterator begin() const noexcept {
177  return Iterator(lo);
178  }
179 
186  constexpr Iterator end() const noexcept {
187  return Iterator(hi);
188  }
189 
195  constexpr T length() const noexcept {
196  return hi - lo;
197  }
198 
205  constexpr bool isEmpty() const noexcept {
206  return lo >= hi;
207  }
208 
215  constexpr bool isValid() const noexcept {
216  return lo <= hi;
217  }
218  };
219 
224  template<typename T>
225  inline
226  void swap(typename Range<T>::Iterator& lhs, typename Range<T>::Iterator& rhs) noexcept {
227  lhs.swap(rhs);
228  }
229 
237 
245 
253 
261 
262 // MSVC does not like extern template
263 #ifndef _MSC_VER
264  extern template struct GF_CORE_API Range<float>;
265  extern template struct GF_CORE_API Range<int>;
266  extern template struct GF_CORE_API Range<unsigned>;
267 #endif
268 
269 
270 
277  template<typename T>
278  struct PositionRange {
281 
286  struct Iterator {
287  using difference_type = std::ptrdiff_t;
291  using iterator_category = std::forward_iterator_tag;
292 
295 
302  constexpr Iterator(Range<T> iteratorRange, Vector<T, 2> iteratorPosition) noexcept
303  : range(iteratorRange)
304  , position(iteratorPosition)
305  {
306  }
307 
311  void swap(Iterator& other) noexcept {
312  using std::swap;
313  swap(range, other.range);
314  swap(position, other.position);
315  }
316 
322  reference operator*() noexcept {
323  return position;
324  }
325 
331  pointer operator->() noexcept {
332  return position;
333  }
334 
340  Iterator& operator++() noexcept {
341  step();
342  return *this;
343  }
344 
350  Iterator operator++(int) noexcept {
351  Iterator copy = *this;
352  step();
353  return copy;
354  }
355 
362  constexpr bool operator!=(const Iterator& other) const noexcept {
363  return position.x != other.position.x || position.y != other.position.y;
364  }
365 
372  constexpr bool operator==(const Iterator& other) const noexcept {
373  return position.x == other.position.x && position.y == other.position.y;
374  }
375 
376  private:
377  void step() noexcept {
378  ++position.x;
379 
380  if (position.x >= range.hi) {
381  position.x = range.lo;
382  ++position.y;
383  }
384  }
385  };
386 
393  constexpr Iterator begin() const noexcept {
394  return Iterator(first, { first.lo, second.lo });
395  }
396 
403  constexpr Iterator end() const noexcept {
404  return Iterator(first, { first.lo, second.hi });
405  }
406  };
407 
412  template<typename T>
413  inline
414  void swap(typename PositionRange<T>::Iterator& lhs, typename PositionRange<T>::Iterator& rhs) noexcept {
415  lhs.swap(rhs);
416  }
417 
418 
425  template<typename T>
430 
435  struct Iterator {
436  using difference_type = std::ptrdiff_t;
440  using iterator_category = std::forward_iterator_tag;
441 
444 
451  constexpr Iterator(Vector<T, 2> iteratorPosition, const NeighborSquareRange<T> *iteratorParent) noexcept
452  : position(iteratorPosition)
453  , parent(iteratorParent)
454  {
455  if (isNotNeighbor(position)) {
456  step();
457  }
458  }
459 
465  constexpr Iterator(Vector<T, 2> iteratorPosition) noexcept
466  : position(iteratorPosition)
467  , parent(nullptr)
468  {
469  }
470 
474  void swap(Iterator& other) noexcept {
475  using std::swap;
476  swap(position, other.position);
477  swap(parent, other.parent);
478  }
479 
485  reference operator*() noexcept {
486  return position;
487  }
488 
494  pointer operator->() noexcept {
495  return position;
496  }
497 
503  Iterator& operator++() noexcept {
504  step();
505  return *this;
506  }
507 
513  Iterator operator++(int) noexcept {
514  Iterator copy = *this;
515  step();
516  return copy;
517  }
518 
525  constexpr bool operator!=(const Iterator& other) const noexcept {
526  return position.x != other.position.x || position.y != other.position.y;
527  }
528 
535  constexpr bool operator==(const Iterator& other) const noexcept {
536  return position.x == other.position.x && position.y == other.position.y;
537  }
538 
539  private:
540  void step() noexcept {
541  do {
542  ++position.x;
543 
544  if (position.x >= parent->first.hi) {
545  position.x = parent->first.lo;
546  ++position.y;
547  }
548  } while (isNotNeighbor(position));
549  }
550 
551  bool isNotNeighbor(Vector<T, 2> other) const noexcept {
552  return other.x == parent->origin.x && other.y == parent->origin.y;
553  }
554  };
555 
562  constexpr Iterator begin() const noexcept {
563  return Iterator({ first.lo, second.lo }, this);
564  }
565 
572  constexpr Iterator end() const noexcept {
573  return Iterator({ first.lo, second.hi });
574  }
575  };
576 
581  template<typename T>
582  inline
583  void swap(typename NeighborSquareRange<T>::Iterator& lhs, typename NeighborSquareRange<T>::Iterator& rhs) noexcept {
584  lhs.swap(rhs);
585  }
586 
587 
594  template<typename T>
600 
605  struct Iterator {
606  using difference_type = std::ptrdiff_t;
610  using iterator_category = std::forward_iterator_tag;
611 
614 
621  constexpr Iterator(Vector<T, 2> iteratorPosition, const NeighborDiamondRange<T> *iteratorParent) noexcept
622  : position(iteratorPosition)
623  , parent(iteratorParent)
624  {
625  if (isNotNeighbor(position)) {
626  step();
627  }
628  }
629 
635  constexpr Iterator(Vector<T, 2> iteratorPosition) noexcept
636  : position(iteratorPosition)
637  , parent(nullptr)
638  {
639  }
640 
644  void swap(Iterator& other) noexcept {
645  using std::swap;
646  swap(position, other.position);
647  swap(parent, other.parent);
648  }
649 
655  reference operator*() noexcept {
656  return position;
657  }
658 
664  pointer operator->() noexcept {
665  return position;
666  }
667 
673  Iterator& operator++() noexcept {
674  step();
675  return *this;
676  }
677 
683  Iterator operator++(int) noexcept {
684  Iterator copy = *this;
685  step();
686  return copy;
687  }
688 
695  constexpr bool operator!=(const Iterator& other) const noexcept {
696  return position.x != other.position.x || position.y != other.position.y;
697  }
698 
705  constexpr bool operator==(const Iterator& other) const noexcept {
706  return position.x == other.position.x && position.y == other.position.y;
707  }
708 
709  private:
710  void step() noexcept {
711  do {
712  ++position.x;
713 
714  if (position.x >= parent->first.hi) {
715  position.x = parent->first.lo;
716  ++position.y;
717 
718  if (position.y >= parent->second.hi) {
719  break;
720  }
721  }
722  } while (isNotNeighbor(position));
723  }
724 
725  bool isNotNeighbor(Vector<T, 2> other) const noexcept {
726  return isOrigin(other) || isOutOfDiamond(position);
727  }
728 
729  bool isOrigin(Vector<T, 2> other) const noexcept {
730  return other.x == parent->origin.x && other.y == parent->origin.y;
731  }
732 
733  bool isOutOfDiamond(Vector<T, 2> other) const noexcept {
734  return gf::absdiff(other.x, parent->origin.x) + gf::absdiff(other.y, parent->origin.y) > parent->radius;
735  }
736  };
737 
744  constexpr Iterator begin() const noexcept {
745  return Iterator({ first.lo, second.lo }, this);
746  }
747 
754  constexpr Iterator end() const noexcept {
755  return Iterator({ first.lo, second.hi });
756  }
757  };
758 
763  template<typename T>
764  inline
765  void swap(typename NeighborDiamondRange<T>::Iterator& lhs, typename NeighborDiamondRange<T>::Iterator& rhs) noexcept {
766  lhs.swap(rhs);
767  }
768 
769 
770 #ifndef DOXYGEN_SHOULD_SKIP_THIS
771 }
772 #endif
773 }
774 
775 #endif // GF_RANGE_H
Range< T > second
The range in the second dimension.
Definition: Range.h:428
Vector< T, 2 > position
Definition: Range.h:612
Range< T > first
The range in the first dimension.
Definition: Range.h:596
An iterator for a 2D range.
Definition: Range.h:605
T x
First coordinate in the (x,y) representation.
Definition: Vector.h:514
A range iterator.
Definition: Range.h:52
std::forward_iterator_tag iterator_category
Definition: Range.h:610
constexpr bool operator==(const Iterator &other) const noexcept
Equality operator.
Definition: Range.h:372
pointer operator->() noexcept
Pointer operator.
Definition: Range.h:664
std::forward_iterator_tag iterator_category
Definition: Range.h:440
std::ptrdiff_t difference_type
Definition: Range.h:287
void swap(Iterator &other) noexcept
Swap the iterator with another iterator.
Definition: Range.h:74
constexpr Iterator(T iteratorIndex) noexcept
Constructor.
Definition: Range.h:66
A half-open range of values.
Definition: Range.h:44
constexpr bool operator!=(const Iterator &other) const noexcept
Inequality operator.
Definition: Range.h:525
Iterator & operator++() noexcept
Increment operator (prefix)
Definition: Range.h:673
Range< T > second
The range in the second dimension.
Definition: Range.h:597
constexpr bool operator!=(const Iterator &other) const noexcept
Inequality operator.
Definition: Range.h:145
pointer operator->() noexcept
Pointer operator.
Definition: Range.h:331
Vector< T, 2 > origin
Definition: Range.h:598
Vector< T, 2 > position
Definition: Range.h:442
const NeighborDiamondRange< T > * parent
Definition: Range.h:613
constexpr Iterator(Vector< T, 2 > iteratorPosition) noexcept
Constructor of a end sentinel.
Definition: Range.h:635
Range< T > first
The range in the first dimension.
Definition: Range.h:279
Iterator & operator++() noexcept
Increment operator (prefix)
Definition: Range.h:340
constexpr bool isEmpty() const noexcept
Check if the range is empty.
Definition: Range.h:205
T lo
The lower endpoint (included)
Definition: Range.h:45
constexpr Iterator end() const noexcept
Get a end iterator.
Definition: Range.h:403
constexpr Iterator begin() const noexcept
Get a begin iterator.
Definition: Range.h:744
Iterator operator++(int) noexcept
Increment operator (postfix)
Definition: Range.h:112
A 2D range.
Definition: Range.h:426
constexpr bool operator==(const Iterator &other) const noexcept
Equality operator.
Definition: Range.h:155
constexpr Iterator end() const noexcept
Get a end iterator.
Definition: Range.h:186
constexpr bool operator!=(const Iterator &other) const noexcept
Inequality operator.
Definition: Range.h:362
void swap(Iterator &other) noexcept
Swap the iterator with another iterator.
Definition: Range.h:311
Iterator operator++(int) noexcept
Increment operator (postfix)
Definition: Range.h:350
T y
Second coordinate in the (x,y) representation.
Definition: Vector.h:525
reference operator*() noexcept
Dereference operator.
Definition: Range.h:84
constexpr Iterator(Vector< T, 2 > iteratorPosition) noexcept
Constructor of a end sentinel.
Definition: Range.h:465
constexpr Iterator(Vector< T, 2 > iteratorPosition, const NeighborSquareRange< T > *iteratorParent) noexcept
Constructor.
Definition: Range.h:451
Range< T > second
The range in the second dimension.
Definition: Range.h:280
Iterator & operator--() noexcept
Decrement operator (prefix)
Definition: Range.h:123
constexpr Iterator begin() const noexcept
Get a begin iterator.
Definition: Range.h:562
reference operator*() noexcept
Dereference operator.
Definition: Range.h:322
value_type reference
Definition: Range.h:56
std::ptrdiff_t difference_type
Definition: Range.h:606
T hi
The higher endpoint (excluded)
Definition: Range.h:46
An iterator for a 2D range.
Definition: Range.h:286
Vector< T, 2 > origin
Definition: Range.h:429
constexpr bool contains(T value) const noexcept
Check if a value is in a range.
Definition: Range.h:166
pointer operator->() noexcept
Pointer operator.
Definition: Range.h:93
void swap(Iterator &other) noexcept
Swap the iterator with another iterator.
Definition: Range.h:474
void swap(typename Range< T >::Iterator &lhs, typename Range< T >::Iterator &rhs) noexcept
Swap two range iterators.
Definition: Range.h:226
constexpr Iterator begin() const noexcept
Get a begin iterator.
Definition: Range.h:176
reference operator*() noexcept
Dereference operator.
Definition: Range.h:655
The namespace for gf classes.
Definition: Action.h:35
T value_type
Definition: Range.h:54
pointer operator->() noexcept
Pointer operator.
Definition: Range.h:494
std::forward_iterator_tag iterator_category
Definition: Range.h:291
constexpr bool operator==(const Iterator &other) const noexcept
Equality operator.
Definition: Range.h:535
void swap(Iterator &other) noexcept
Swap the iterator with another iterator.
Definition: Range.h:644
Range< T > first
The range in the first dimension.
Definition: Range.h:427
An iterator for a 2D range.
Definition: Range.h:435
Range< T > range
Definition: Range.h:293
std::bidirectional_iterator_tag iterator_category
Definition: Range.h:57
void swap(typename NeighborSquareRange< T >::Iterator &lhs, typename NeighborSquareRange< T >::Iterator &rhs) noexcept
Swap two range iterators.
Definition: Range.h:583
A 2D range.
Definition: Range.h:595
void swap(typename PositionRange< T >::Iterator &lhs, typename PositionRange< T >::Iterator &rhs) noexcept
Swap two range iterators.
Definition: Range.h:414
constexpr Iterator end() const noexcept
Get a end iterator.
Definition: Range.h:754
Iterator operator--(int) noexcept
Decrement operator (postfix)
Definition: Range.h:133
T radius
Definition: Range.h:599
A 2D vector.
Definition: Vector.h:316
constexpr Iterator begin() const noexcept
Get a begin iterator.
Definition: Range.h:393
constexpr Iterator(Vector< T, 2 > iteratorPosition, const NeighborDiamondRange< T > *iteratorParent) noexcept
Constructor.
Definition: Range.h:621
A 2D range.
Definition: Range.h:278
constexpr Iterator end() const noexcept
Get a end iterator.
Definition: Range.h:572
constexpr bool operator!=(const Iterator &other) const noexcept
Inequality operator.
Definition: Range.h:695
reference operator*() noexcept
Dereference operator.
Definition: Range.h:485
constexpr Iterator(Range< T > iteratorRange, Vector< T, 2 > iteratorPosition) noexcept
Constructor.
Definition: Range.h:302
Iterator & operator++() noexcept
Increment operator (prefix)
Definition: Range.h:503
Vector< T, 2 > position
Definition: Range.h:294
T index
The index in the range.
Definition: Range.h:59
Iterator operator++(int) noexcept
Increment operator (postfix)
Definition: Range.h:683
constexpr bool operator==(const Iterator &other) const noexcept
Equality operator.
Definition: Range.h:705
Iterator operator++(int) noexcept
Increment operator (postfix)
Definition: Range.h:513
constexpr T length() const noexcept
Get the length of the range.
Definition: Range.h:195
void swap(typename NeighborDiamondRange< T >::Iterator &lhs, typename NeighborDiamondRange< T >::Iterator &rhs) noexcept
Swap two range iterators.
Definition: Range.h:765
std::ptrdiff_t difference_type
Definition: Range.h:436
constexpr T absdiff(T lhs, T rhs)
Absolute difference of two values.
Definition: Math.h:352
value_type pointer
Definition: Range.h:55
std::ptrdiff_t difference_type
Definition: Range.h:53
Iterator & operator++() noexcept
Increment operator (prefix)
Definition: Range.h:102
const NeighborSquareRange< T > * parent
Definition: Range.h:443
constexpr bool isValid() const noexcept
Check is the range is valid.
Definition: Range.h:215