A 2D tile-based sandbox game.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

util.h 3.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. #pragma once
  2. #include <optional>
  3. #include <functional>
  4. #include <memory>
  5. #include <chrono>
  6. #include <type_traits>
  7. #include <stddef.h>
  8. namespace Swan {
  9. // Inherit from this class to make a class non-copyable
  10. class NonCopyable {
  11. public:
  12. NonCopyable(const NonCopyable &) = delete;
  13. NonCopyable(NonCopyable &&) noexcept = default;
  14. NonCopyable &operator=(const NonCopyable &) = delete;
  15. NonCopyable &operator=(NonCopyable &&) = default;
  16. protected:
  17. NonCopyable() = default;
  18. ~NonCopyable() = default;
  19. };
  20. // Take a deleter function, turn it into a class with an operator() for unique_ptr
  21. template<typename T, void (*Func)(T *)>
  22. class CPtrDeleter {
  23. public:
  24. void operator()(T *ptr) { Func(ptr); }
  25. };
  26. // This is just a bit nicer to use than using unique_ptr directly
  27. template<typename T, void (*Func)(T *)>
  28. using CPtr = std::unique_ptr<T, CPtrDeleter<T, Func>>;
  29. // Take a function, run it when the object goes out of scope
  30. template<void (*Func)()>
  31. class Deferred: NonCopyable {
  32. public:
  33. Deferred() = default;
  34. ~Deferred() { Func(); }
  35. };
  36. // Calling begin/end is stupid...
  37. template<typename T>
  38. auto callBegin(T &v) {
  39. using namespace std;
  40. return begin(v);
  41. }
  42. template<typename T>
  43. auto callEnd(T &v) {
  44. using namespace std;
  45. return end(v);
  46. }
  47. // Ret can't be a reference, because C++ doesn't support optional<T&>.
  48. template<typename Ret, typename Func = std::function<std::optional<Ret>()>>
  49. class Iter {
  50. public:
  51. class It {
  52. public:
  53. It(std::optional<Ret> next, Func &func): next_(std::move(next)), func_(func) {}
  54. bool operator==(const It &other) const {
  55. return next_ == std::nullopt && other.next_ == std::nullopt;
  56. }
  57. bool operator!=(const It &other) const {
  58. return !(*this == other);
  59. }
  60. void operator++() {
  61. auto val(func_());
  62. if (val)
  63. next_.emplace(std::move(*val));
  64. else
  65. next_.reset();
  66. }
  67. Ret operator*() {
  68. return std::move(*next_);
  69. }
  70. private:
  71. std::optional<Ret> next_;
  72. Func &func_;
  73. };
  74. Iter(Func func): func_(func) {}
  75. operator Iter<Ret, std::function<std::optional<Ret>()>>() {
  76. return Iter<Ret, std::function<std::optional<Ret>()>>(func_);
  77. }
  78. It begin() {
  79. return It(func_(), func_);
  80. }
  81. It end() {
  82. return It(std::nullopt, func_);
  83. }
  84. private:
  85. Func func_;
  86. };
  87. template<typename InputIterator, typename Func>
  88. auto map(InputIterator first, InputIterator last, Func func) {
  89. using RetT = decltype(func(*first));
  90. auto l = [=]() mutable -> std::optional<RetT> {
  91. if (first == last)
  92. return std::nullopt;
  93. RetT r = func(*first);
  94. ++first;
  95. return r;
  96. };
  97. return Iter<RetT, decltype(l)>(l);
  98. }
  99. template<typename Range, typename Func>
  100. auto map(Range &rng, Func func) {
  101. return map(callBegin(rng), callEnd(rng), func);
  102. }
  103. template<typename InputIterator, typename Func>
  104. auto filter(InputIterator first, InputIterator last, Func pred) {
  105. using RetT = std::remove_reference_t<decltype(*first)>;
  106. auto l = [=]() mutable -> std::optional<RetT> {
  107. if (first == last)
  108. return std::nullopt;
  109. while (!pred(*first)) {
  110. ++first;
  111. if (first == last)
  112. return std::nullopt;
  113. }
  114. RetT r = *first;
  115. ++first;
  116. return r;
  117. };
  118. return Iter<RetT, decltype(l)>(l);
  119. }
  120. template<typename Range, typename Func>
  121. auto filter(Range &rng, Func func) {
  122. return filter(callBegin(rng), callEnd(rng), func);
  123. }
  124. template<typename InputIterator, typename Func>
  125. auto mapFilter(InputIterator first, InputIterator last, Func func) {
  126. using RetT = std::remove_reference_t<decltype(*func(*first))>;
  127. auto l = [=]() mutable -> std::optional<RetT> {
  128. if (first == last)
  129. return std::nullopt;
  130. std::optional<RetT> r;
  131. while ((r = func(*first)) == std::nullopt) {
  132. ++first;
  133. if (first == last)
  134. return std::nullopt;
  135. }
  136. ++first;
  137. return r;
  138. };
  139. return Iter<RetT, decltype(l)>(l);
  140. }
  141. template<typename Range, typename Func>
  142. auto mapFilter(Range &rng, Func func) {
  143. return mapFilter(callBegin(rng), callEnd(rng), func);
  144. }
  145. }