diff --git a/src/nostalgia/geo/vec.hpp b/src/nostalgia/geo/vec.hpp index 37960557..9a01ab86 100644 --- a/src/nostalgia/geo/vec.hpp +++ b/src/nostalgia/geo/vec.hpp @@ -8,11 +8,123 @@ #include #endif +#include +#include +#include #include namespace nostalgia::geo { struct Vec2 { + using value_type = float; + using size_type = std::size_t; + + template + struct iterator: public std::iterator { + private: + PtrType m_t = nullptr; + size_type m_offset = 0; + size_type m_max = 0; + + public: + constexpr iterator() noexcept = default; + + constexpr iterator(PtrType t, size_type offset, size_type max) noexcept { + m_t = t; + m_offset = offset; + m_max = max; + } + + [[nodiscard]] + constexpr auto offset() const noexcept { + return m_offset; + } + + constexpr iterator operator+(size_type s) const noexcept { + if constexpr(reverse) { + return iterator(m_t, ox::max(m_offset - s, 0), m_max); + } else { + return iterator(m_t, ox::min(m_offset + s, m_max), m_max); + } + } + + constexpr typename std::iterator::difference_type + operator-(const iterator &other) const noexcept { + if constexpr(reverse) { + return m_offset + other.m_offset; + } else { + return m_offset - other.m_offset; + } + } + + constexpr iterator operator-(size_type s) const noexcept { + if constexpr(reverse) { + return iterator(m_t, ox::min(m_offset + s, m_max), m_max); + } else { + return iterator(m_t, ox::max(m_offset - s, 0), m_max); + } + } + + constexpr iterator &operator+=(size_type s) noexcept { + if constexpr(reverse) { + m_offset = ox::max(m_offset - s, 0); + } else { + m_offset = ox::min(m_offset + s, m_max); + } + return *this; + } + + constexpr iterator &operator-=(size_type s) noexcept { + if constexpr(reverse) { + m_offset = ox::min(m_offset + s, m_max); + } else { + m_offset = ox::max(m_offset - s, 0); + } + return *this; + } + + constexpr iterator &operator++() noexcept { + return operator+=(1); + } + + constexpr iterator &operator--() noexcept { + return operator-=(1); + } + + constexpr RefType operator*() const noexcept { + return m_t[m_offset]; + } + + constexpr RefType operator[](size_type s) const noexcept { + return m_t[s]; + } + + constexpr bool operator<(const iterator &other) const noexcept { + return m_offset < other.m_offset; + } + + constexpr bool operator>(const iterator &other) const noexcept { + return m_offset > other.m_offset; + } + + constexpr bool operator<=(const iterator &other) const noexcept { + return m_offset <= other.m_offset; + } + + constexpr bool operator>=(const iterator &other) const noexcept { + return m_offset >= other.m_offset; + } + + constexpr bool operator==(const iterator &other) const noexcept { + return m_t == other.m_t && m_offset == other.m_offset && m_max == other.m_max; + } + + constexpr bool operator!=(const iterator &other) const noexcept { + return m_t != other.m_t || m_offset != other.m_offset || m_max != other.m_max; + } + + }; + float x = 0; float y = 0; @@ -26,6 +138,46 @@ struct Vec2 { } #endif + [[nodiscard]] + constexpr iterator<> begin() noexcept { + return {&x, 0, size()}; + } + + [[nodiscard]] + constexpr iterator<> end() noexcept { + return {&x, size(), size()}; + } + + [[nodiscard]] + constexpr iterator begin() const noexcept { + return {&x, 0, size()}; + } + + [[nodiscard]] + constexpr iterator end() const noexcept { + return {&x, size(), size()}; + } + + [[nodiscard]] + constexpr iterator rbegin() noexcept { + return {&x, size() - 1, size()}; + } + + [[nodiscard]] + constexpr iterator rend() noexcept { + return {&x, ox::MaxValue, size()}; + } + + [[nodiscard]] + constexpr iterator rbegin() const noexcept { + return {&x, size() - 1, size()}; + } + + [[nodiscard]] + constexpr iterator rend() const noexcept { + return {&x, ox::MaxValue, size()}; + } + constexpr auto &operator[](std::size_t i) noexcept { return (&x)[i]; } @@ -34,6 +186,11 @@ struct Vec2 { return (&x)[i]; } + [[nodiscard]] + constexpr std::size_t size() const noexcept { + return 2; + } + #if __has_include() explicit operator ImVec2() const noexcept { return {x, y};