summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/collections.h60
-rw-r--r--test/test-lib.cpp20
2 files changed, 80 insertions, 0 deletions
diff --git a/lib/collections.h b/lib/collections.h
index 943b986..6cee10c 100644
--- a/lib/collections.h
+++ b/lib/collections.h
@@ -2,6 +2,7 @@
#include <algorithm>
#include <array>
+#include <cstdint>
#include <span>
#include <utility>
#include <vector>
@@ -160,3 +161,62 @@ template<typename T> struct pair_range {
};
template<typename T> pair_range(std::pair<T, T>) -> pair_range<T>;
+
+template<typename iter> struct stripiter {
+ [[nodiscard]] constexpr bool
+ operator!=(const stripiter & other) const
+ {
+ return current != other.current;
+ }
+
+ [[nodiscard]] constexpr bool
+ operator==(const stripiter & other) const
+ {
+ return current == other.current;
+ }
+
+ constexpr stripiter &
+ operator++()
+ {
+ ++current;
+ off = 1 - off;
+ return *this;
+ }
+
+ constexpr stripiter &
+ operator--()
+ {
+ --current;
+ off = 1 - off;
+ return *this;
+ }
+
+ constexpr auto
+ operator-(const stripiter & other) const
+ {
+ return current - other.current;
+ }
+
+ constexpr auto
+ operator*() const
+ {
+ return std::tie(*(current - (2 - off)), *(current - off - 1), *current);
+ }
+
+ iter current;
+ uint8_t off {};
+};
+
+template<typename T> struct std::iterator_traits<stripiter<T>> : std::iterator_traits<T> { };
+
+constexpr auto
+strip_begin(IterableCollection auto & cont)
+{
+ return stripiter {cont.begin() + 2};
+}
+
+constexpr auto
+strip_end(IterableCollection auto & cont)
+{
+ return stripiter {cont.end()};
+}
diff --git a/test/test-lib.cpp b/test/test-lib.cpp
index 58b769a..5f0b5e5 100644
--- a/test/test-lib.cpp
+++ b/test/test-lib.cpp
@@ -4,6 +4,7 @@
#include <boost/test/data/test_case.hpp>
#include <boost/test/unit_test.hpp>
+#include <collections.h>
#include <glArrays.h>
#include <glad/gl.h>
#include <set>
@@ -49,3 +50,22 @@ BOOST_AUTO_TEST_CASE(generate_move_and_delete)
}
BOOST_CHECK(active.empty());
}
+
+constexpr std::array TRIANGLE_STRIP_IN {0, 1, 2, 3, 4, 5};
+static_assert(std::distance(strip_begin(TRIANGLE_STRIP_IN), strip_end(TRIANGLE_STRIP_IN)) == 4);
+
+BOOST_AUTO_TEST_CASE(triangle_strip_iter)
+{
+ constexpr std::array TRIANGLE_STRIP_EXPECTED {0, 1, 2, 2, 1, 3, 2, 3, 4, 4, 3, 5};
+
+ std::vector<int> out;
+ std::for_each(strip_begin(TRIANGLE_STRIP_IN), strip_end(TRIANGLE_STRIP_IN), [&out](const auto & t) {
+ const auto [a, b, c] = t;
+ out.push_back(a);
+ out.push_back(b);
+ out.push_back(c);
+ });
+ BOOST_REQUIRE_EQUAL(out.size(), (TRIANGLE_STRIP_IN.size() - 2) * 3);
+ BOOST_CHECK_EQUAL_COLLECTIONS(
+ out.begin(), out.end(), TRIANGLE_STRIP_EXPECTED.begin(), TRIANGLE_STRIP_EXPECTED.end());
+}