From ca227411102b615edb40a78d2355d2f6cf5291c5 Mon Sep 17 00:00:00 2001 From: Garret Rieger Date: Tue, 30 Nov 2021 12:53:15 -0800 Subject: [PATCH] [iter] add hb_concat (a, b). Iterates over a, and then over b. --- src/hb-iter.hh | 73 ++++++++++++++++++++++++++++++++++++++++++++++++ src/test-iter.cc | 33 ++++++++++++++++++++++ 2 files changed, 106 insertions(+) diff --git a/src/hb-iter.hh b/src/hb-iter.hh index 87b8ed880..db2a50f26 100644 --- a/src/hb-iter.hh +++ b/src/hb-iter.hh @@ -581,6 +581,79 @@ struct } HB_FUNCOBJ (hb_zip); +/* hb_concat() */ + +template +struct hb_concat_iter_t : + hb_iter_t, typename A::item_t> +{ + hb_concat_iter_t () {} + hb_concat_iter_t (A& a, B& b) : a (a), b (b) {} + hb_concat_iter_t (const A& a, const B& b) : a (a), b (b) {} + + + typedef typename A::item_t __item_t__; + static constexpr bool is_random_access_iterator = + A::is_random_access_iterator && + B::is_random_access_iterator; + static constexpr bool is_sorted_iterator = false; + + __item_t__ __item__ () const + { + if (!a) + return *b; + return *a; + } + + __item_t__ __item_at__ (unsigned i) const + { + if (i < a.len()) + return a[i]; + return b[i - a.len()]; + } + + bool __more__ () const { return bool (a) || bool (b); } + + unsigned __len__ () const { return a.len () + b.len (); } + + void __next__ () + { + if (a) + ++a; + else + ++b; + } + + void __forward__ (unsigned n) + { + if (n > a.len ()) { + a.__forward__ (a.len ()); + n -= a.len (); + } + b.__forward (n); + } + + hb_concat_iter_t __end__ () const { return hb_concat_iter_t (a.end (), b.end ()); } + bool operator != (const hb_concat_iter_t& o) const + { + return a != o.a + || b != o.b; + } + + private: + A a; + B b; +}; +struct +{ HB_PARTIALIZE(2); + template + hb_concat_iter_t, hb_iter_type> + operator () (A&& a, B&& b) const + { return hb_concat_iter_t, hb_iter_type> (hb_iter (a), hb_iter (b)); } +} +HB_FUNCOBJ (hb_concat); + /* hb_apply() */ template diff --git a/src/test-iter.cc b/src/test-iter.cc index fd201c85e..ccc911891 100644 --- a/src/test-iter.cc +++ b/src/test-iter.cc @@ -114,6 +114,37 @@ test_iterable (const Iterable &lst = Null (Iterable)) test_iterator (lst.iter ()); } +template +static void check_sequential (It it) +{ + int i = 1; + for (int v : +it) { + assert (v == i++); + } +} + +static void test_concat () +{ + hb_vector_t a = {1, 2, 3}; + hb_vector_t b = {4, 5}; + + hb_vector_t c = {}; + hb_vector_t d = {1, 2, 3, 4, 5}; + + auto it1 = hb_concat (a, b); + auto it2 = hb_concat (c, d); + auto it3 = hb_concat (d, c); + for (int i = 0; i < 5; i++) { + assert(it1[i] == i + 1); + assert(it2[i] == i + 1); + assert(it3[i] == i + 1); + } + + check_sequential (it1); + check_sequential (it2); + check_sequential (it3); +} + int main (int argc, char **argv) { @@ -282,5 +313,7 @@ main (int argc, char **argv) assert (hb_range (-2, -8, -3).len () == 2); assert (hb_range (-2, -7, -3).len () == 2); + test_concat (); + return 0; }