utils.hpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. #ifndef UTILS_HPP
  2. #define UTILS_HPP
  3. #include <cstddef>
  4. #include <limits>
  5. #include <type_traits>
  6. #include <iterator>
  7. #include "simple/support/algorithm.hpp"
  8. #include "simple.hpp"
  9. // this was really hard :/
  10. template <typename Range>
  11. class loop
  12. {
  13. public:
  14. using iterator = decltype(std::begin(std::declval<Range>()));
  15. using difference_type = typename std::iterator_traits<iterator>::difference_type;
  16. using value_type = typename std::iterator_traits<iterator>::value_type;
  17. using pointer = typename std::iterator_traits<iterator>::pointer;
  18. using reference = typename std::iterator_traits<iterator>::reference;
  19. using iterator_category = typename std::iterator_traits<iterator>::iterator_category;
  20. constexpr loop(Range range, iterator current) :
  21. range(range), current(current)
  22. { }
  23. constexpr loop(Range range) :
  24. range(range), current(std::begin(range))
  25. { }
  26. constexpr decltype(auto) operator*() const
  27. { return *current; }
  28. constexpr auto operator->() const
  29. { return current.operator->(); }
  30. constexpr decltype(auto) operator*()
  31. { return *current; }
  32. constexpr auto operator->()
  33. { return current.operator->(); }
  34. constexpr loop& operator++()
  35. {
  36. ++current;
  37. if(current == std::end(range))
  38. current = std::begin(range);
  39. return *this;
  40. }
  41. constexpr loop operator++(int)
  42. {
  43. loop ret = loop(range, current++);
  44. if(current == std::end(range))
  45. current = std::begin(range);
  46. return ret;
  47. }
  48. constexpr loop& operator+=(difference_type d)
  49. {
  50. const iterator begin = std::begin(range);
  51. const iterator end = std::end(range);
  52. const difference_type size = std::distance(begin, end);
  53. const difference_type current_index = std::distance(begin, current);
  54. current = begin + simple::support::wrap((current_index + d) % size, size);
  55. return *this;
  56. }
  57. constexpr loop& operator-=(difference_type d)
  58. {
  59. return *this += -d;
  60. }
  61. constexpr friend loop operator+(const loop& one, difference_type d)
  62. {
  63. return loop(one) += d;
  64. }
  65. constexpr friend loop operator+(difference_type d, const loop& one)
  66. {
  67. return loop(one) += d;
  68. }
  69. constexpr friend loop operator-(const loop& one, difference_type d)
  70. {
  71. return loop(one) -= d;
  72. }
  73. constexpr friend loop operator-(difference_type d, const loop& one)
  74. {
  75. return loop(one) -= d;
  76. }
  77. // TODO: clever cleverdom huh? well now I know difference_type must be a signed interger type so this won't fly in general, but even in particular no use cases so far
  78. // struct two_way_difference : public std::array<difference_type, 2>
  79. // {
  80. // using std::array<difference_type,2>::array;
  81. // operator difference_type() const noexcept { return *(this->begin()); }
  82. // };
  83. // this is all extra work that can be done outside of this function if needed, so maybe just provide a helper function instead for getting the second difference,
  84. // clockwise/forward or anti-clockwise/backward version might also be useful
  85. // related to way and wayback functions in simple support algorithm, except there the modulo arithmetic is implicit (the numeric properties of the type)
  86. // constexpr friend auto operator-(const loop& one, const loop& other)
  87. // {
  88. // assert(one.range == other.range);
  89. // auto expanse = end(one.range) - begin(other.range);
  90. // auto difference = one.current - other.current;
  91. // return two_way_difference{difference, difference - expanse};
  92. // }
  93. constexpr friend bool operator==(const loop& one, const loop& other)
  94. {
  95. return one.range == other.range && one.current == other.current;
  96. }
  97. constexpr friend bool operator!=(const loop& one, const loop& other)
  98. {
  99. return !(one == other);
  100. }
  101. constexpr operator iterator()
  102. {
  103. return current;
  104. }
  105. constexpr void reset()
  106. {
  107. current = std::begin(range);
  108. }
  109. private:
  110. Range range;
  111. iterator current;
  112. };
  113. class random_access_istream_iterator // more or less
  114. {
  115. // TODO:
  116. };
  117. template <typename Range>
  118. constexpr auto center(const Range& area)
  119. {
  120. return (area.upper() - area.lower())/2;
  121. }
  122. template <typename Object, typename Area>
  123. constexpr auto center(const Object& object, const Area& area)
  124. {
  125. return center(area) - center(object);
  126. }
  127. void outline(const graphical::surface&, graphical::color, range2D);
  128. void lowlight(const graphical::surface&, graphical::color, range2D, int2 dim = int2(2,1));
  129. void outline_lowlight(const graphical::surface&, graphical::color, range2D, int2 dim = int2(2,2));
  130. template <typename ExtractedDuration, typename Duration>
  131. ExtractedDuration extract_duration(Duration& duration)
  132. {
  133. auto extracted = std::chrono::duration_cast<ExtractedDuration>(duration);
  134. duration -= extracted;
  135. return extracted;
  136. }
  137. template <typename... SplitDuration, typename Duration>
  138. std::tuple<SplitDuration...> split_duration(Duration duration)
  139. {
  140. return { extract_duration<SplitDuration>(duration)... };
  141. };
  142. #endif /* end of include guard */