From 513762849a683914fc266a17ddf38f133cccf072 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 13 May 2019 15:36:14 -0700 Subject: [PATCH] [iter] Track strictly-sorted iterators This make output of hb_enumerate() sorted regardless of input iterator. --- src/hb-array.hh | 2 +- src/hb-iter.hh | 30 +++++++++++++++++++++--------- src/hb-ot-layout-common.hh | 2 +- src/hb-set.hh | 2 +- 4 files changed, 24 insertions(+), 12 deletions(-) diff --git a/src/hb-array.hh b/src/hb-array.hh index 705bc6a46..6f6fd7fb1 100644 --- a/src/hb-array.hh +++ b/src/hb-array.hh @@ -226,7 +226,7 @@ struct hb_sorted_array_t : typedef hb_iter_t, Type&> iter_base_t; HB_ITER_USING (iter_base_t); static constexpr bool is_random_access_iterator = true; - static constexpr bool is_sorted_iterator = true; + static constexpr hb_sortedness_t is_sorted_iterator = hb_sortedness_t::SORTED; hb_sorted_array_t () : hb_array_t () {} hb_sorted_array_t (Type *array_, unsigned int length_) : hb_array_t (array_, length_) {} diff --git a/src/hb-iter.hh b/src/hb-iter.hh index d749d4aac..a1fe90420 100644 --- a/src/hb-iter.hh +++ b/src/hb-iter.hh @@ -55,6 +55,12 @@ * type of .end()? */ +enum hb_sortedness_t +{ + NOT_SORTED = 0, + SORTED, + STRICTLY_SORTED, +}; /* * Base classes for iterators. @@ -68,7 +74,7 @@ struct hb_iter_t static constexpr unsigned item_size = hb_static_size (Item); static constexpr bool is_iterator = true; static constexpr bool is_random_access_iterator = false; - static constexpr bool is_sorted_iterator = false; + static constexpr hb_sortedness_t is_sorted_iterator = hb_sortedness_t::NOT_SORTED; private: /* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */ @@ -361,9 +367,9 @@ struct hb_map_iter_t : typedef decltype (hb_get (hb_declval (Proj), *hb_declval (Iter))) __item_t__; static constexpr bool is_random_access_iterator = Iter::is_random_access_iterator; - static constexpr bool is_sorted_iterator = - Sorted == hb_function_sortedness_t::SORTED ? true - : Sorted == hb_function_sortedness_t::RETAINS_SORTING ? Iter::is_sorted_iterator : false; + static constexpr hb_sortedness_t is_sorted_iterator = + Sorted == hb_function_sortedness_t::SORTED ? hb_sortedness_t::SORTED + : Sorted == hb_function_sortedness_t::RETAINS_SORTING ? Iter::is_sorted_iterator : hb_sortedness_t::NOT_SORTED; __item_t__ __item__ () const { return hb_get (f.get (), *it); } __item_t__ __item_at__ (unsigned i) const { return hb_get (f.get (), it[i]); } bool __more__ () const { return bool (it); } @@ -430,7 +436,7 @@ struct hb_filter_iter_t : { while (it && !hb_has (p.get (), hb_get (f.get (), *it))) ++it; } typedef typename Iter::item_t __item_t__; - static constexpr bool is_sorted_iterator = Iter::is_sorted_iterator; + static constexpr hb_sortedness_t is_sorted_iterator = Iter::is_sorted_iterator; __item_t__ __item__ () const { return *it; } bool __more__ () const { return bool (it); } void __next__ () { do ++it; while (it && !hb_has (p.get (), hb_get (f.get (), *it))); } @@ -514,9 +520,15 @@ struct hb_zip_iter_t : static constexpr bool is_random_access_iterator = A::is_random_access_iterator && B::is_random_access_iterator; - static constexpr bool is_sorted_iterator = - A::is_sorted_iterator && - B::is_sorted_iterator; + static constexpr hb_sortedness_t is_sorted_iterator = + (A::is_sorted_iterator == hb_sortedness_t::NOT_SORTED || + B::is_sorted_iterator == hb_sortedness_t::NOT_SORTED) ? + hb_sortedness_t::NOT_SORTED : + (A::is_sorted_iterator == hb_sortedness_t::STRICTLY_SORTED || + B::is_sorted_iterator == hb_sortedness_t::STRICTLY_SORTED) ? + hb_sortedness_t::STRICTLY_SORTED : + hb_sortedness_t::SORTED; + __item_t__ __item__ () const { return __item_t__ (*a, *b); } __item_t__ __item_at__ (unsigned i) const { return __item_t__ (a[i], b[i]); } bool __more__ () const { return bool (a) && bool (b); } @@ -583,7 +595,7 @@ struct hb_counter_iter_t : typedef T __item_t__; static constexpr bool is_random_access_iterator = true; - static constexpr bool is_sorted_iterator = true; + static constexpr hb_sortedness_t is_sorted_iterator = hb_sortedness_t::STRICTLY_SORTED; __item_t__ __item__ () const { return +v; } __item_t__ __item_at__ (unsigned j) const { return v + j * step; } bool __more__ () const { return v != end_; } diff --git a/src/hb-ot-layout-common.hh b/src/hb-ot-layout-common.hh index 71c0ca4a9..67f2617fe 100644 --- a/src/hb-ot-layout-common.hh +++ b/src/hb-ot-layout-common.hh @@ -1115,7 +1115,7 @@ struct Coverage struct iter_t : hb_iter_with_fallback_t { - static constexpr bool is_sorted_iterator = true; + static constexpr hb_sortedness_t is_sorted_iterator = hb_sortedness_t::STRICTLY_SORTED; iter_t (const Coverage &c_ = Null(Coverage)) { memset (this, 0, sizeof (*this)); diff --git a/src/hb-set.hh b/src/hb-set.hh index 332e07bd0..d9ffded57 100644 --- a/src/hb-set.hh +++ b/src/hb-set.hh @@ -691,7 +691,7 @@ struct hb_set_t */ struct iter_t : hb_iter_with_fallback_t { - static constexpr bool is_sorted_iterator = true; + static constexpr hb_sortedness_t is_sorted_iterator = hb_sortedness_t::STRICTLY_SORTED; iter_t (const hb_set_t &s_ = Null(hb_set_t)) : s (&s_), v (INVALID), l (s->get_population () + 1) { __next__ (); }