diff options
Diffstat (limited to 'gfx/harfbuzz/src/test-iter.cc')
-rw-r--r-- | gfx/harfbuzz/src/test-iter.cc | 382 |
1 files changed, 382 insertions, 0 deletions
diff --git a/gfx/harfbuzz/src/test-iter.cc b/gfx/harfbuzz/src/test-iter.cc new file mode 100644 index 0000000000..bb966d4c9c --- /dev/null +++ b/gfx/harfbuzz/src/test-iter.cc @@ -0,0 +1,382 @@ +/* + * Copyright © 2018 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ + +#include "hb.hh" +#include "hb-iter.hh" + +#include "hb-array.hh" +#include "hb-set.hh" +#include "hb-ot-layout-common.hh" + +template <typename T> +struct array_iter_t : hb_iter_with_fallback_t<array_iter_t<T>, T&> +{ + array_iter_t (hb_array_t<T> arr_) : arr (arr_) {} + + typedef T& __item_t__; + static constexpr bool is_random_access_iterator = true; + T& __item_at__ (unsigned i) const { return arr[i]; } + void __forward__ (unsigned n) { arr += n; } + void __rewind__ (unsigned n) { arr -= n; } + unsigned __len__ () const { return arr.length; } + bool operator != (const array_iter_t& o) { return arr != o.arr; } + + private: + hb_array_t<T> arr; +}; + +template <typename T> +struct some_array_t +{ + some_array_t (hb_array_t<T> arr_) : arr (arr_) {} + + typedef array_iter_t<T> iter_t; + array_iter_t<T> iter () { return array_iter_t<T> (arr); } + operator array_iter_t<T> () { return iter (); } + operator hb_iter_t<array_iter_t<T>> () { return iter (); } + + private: + hb_array_t<T> arr; +}; + + +template <typename Iter, + hb_requires (hb_is_iterator (Iter))> +static void +test_iterator_non_default_constructable (Iter it) +{ + /* Iterate over a copy of it. */ + for (auto c = it.iter (); c; c++) + *c; + + /* Same. */ + for (auto c = +it; c; c++) + *c; + + /* Range-based for over a copy. */ + for (auto _ : +it) + (void) _; + + it += it.len (); + it = it + 10; + it = 10 + it; + + assert (*it == it[0]); + + static_assert (true || it.is_random_access_iterator, ""); + static_assert (true || it.is_sorted_iterator, ""); +} + +template <typename Iter, + hb_requires (hb_is_iterator (Iter))> +static void +test_iterator (Iter it) +{ + Iter default_constructed; + assert (!default_constructed); + + test_iterator_non_default_constructable (it); +} + +template <typename Iterable, + hb_requires (hb_is_iterable (Iterable))> +static void +test_iterable (const Iterable &lst = Null (Iterable)) +{ + for (auto _ : lst) + (void) _; + + // Test that can take iterator from. + test_iterator (lst.iter ()); +} + +template <typename It> +static void check_sequential (It it) +{ + int i = 1; + for (int v : +it) { + assert (v == i++); + } +} + +static void test_concat () +{ + hb_vector_t<int> a = {1, 2, 3}; + hb_vector_t<int> b = {4, 5}; + + hb_vector_t<int> c = {}; + hb_vector_t<int> d = {1, 2, 3, 4, 5}; + + auto it1 = hb_concat (a, b); + assert (it1.len () == 5); + assert (it1.is_random_access_iterator); + auto it2 = hb_concat (c, d); + assert (it2.len () == 5); + auto it3 = hb_concat (d, c); + assert (it3.len () == 5); + 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); + + auto it4 = +it1; + it4 += 0; + assert (*it4 == 1); + + it4 += 2; + assert (*it4 == 3); + assert (it4); + assert (it4.len () == 3); + + it4 += 2; + assert (*it4 == 5); + assert (it4); + assert (it4.len () == 1); + + it4++; + assert (!it4); + assert (it4.len () == 0); + + auto it5 = +it1; + it5 += 3; + assert (*it5 == 4); + + hb_set_t s_a = {1, 2, 3}; + hb_set_t s_b = {4, 5}; + auto it6 = hb_concat (s_a, s_b); + assert (!it6.is_random_access_iterator); + check_sequential (it6); + assert (it6.len () == 5); + + it6 += 0; + assert (*it6 == 1); + + it6 += 3; + assert (*it6 == 4); + assert (it6); + assert (it6.len () == 2); +} + +int +main (int argc, char **argv) +{ + const int src[10] = {}; + int dst[20]; + hb_vector_t<int> v; + + array_iter_t<const int> s (src); /* Implicit conversion from static array. */ + array_iter_t<const int> s2 (v); /* Implicit conversion from vector. */ + array_iter_t<int> t (dst); + + static_assert (array_iter_t<int>::is_random_access_iterator, ""); + + some_array_t<const int> a (src); + + s2 = s; + + hb_iter (src); + hb_iter (src, 2); + + hb_fill (t, 42); + hb_copy (s, t); + hb_copy (a.iter (), t); + + test_iterable (v); + hb_set_t st; + st << 1 << 15 << 43; + test_iterable (st); + hb_sorted_array_t<int> sa; + (void) static_cast<hb_iter_t<hb_sorted_array_t<int>, hb_sorted_array_t<int>::item_t>&> (sa); + (void) static_cast<hb_iter_t<hb_sorted_array_t<int>, hb_sorted_array_t<int>::__item_t__>&> (sa); + (void) static_cast<hb_iter_t<hb_sorted_array_t<int>, int&>&>(sa); + (void) static_cast<hb_iter_t<hb_sorted_array_t<int>>&>(sa); + (void) static_cast<hb_iter_t<hb_array_t<int>, int&>&> (sa); + test_iterable (sa); + + test_iterable<hb_array_t<int>> (); + test_iterable<hb_sorted_array_t<const int>> (); + test_iterable<hb_vector_t<float>> (); + test_iterable<hb_set_t> (); + test_iterable<OT::Array16Of<OT::HBUINT16>> (); + + test_iterator (hb_zip (st, v)); + test_iterator_non_default_constructable (hb_enumerate (st)); + test_iterator_non_default_constructable (hb_enumerate (st, -5)); + test_iterator_non_default_constructable (hb_enumerate (hb_iter (st))); + test_iterator_non_default_constructable (hb_enumerate (hb_iter (st) + 1)); + test_iterator_non_default_constructable (hb_iter (st) | hb_filter ()); + test_iterator_non_default_constructable (hb_iter (st) | hb_map (hb_lidentity)); + + assert (true == hb_all (st)); + assert (false == hb_all (st, 42u)); + assert (true == hb_any (st)); + assert (false == hb_any (st, 14u)); + assert (true == hb_any (st, 14u, [] (unsigned _) { return _ - 1u; })); + assert (true == hb_any (st, [] (unsigned _) { return _ == 15u; })); + assert (true == hb_any (st, 15u)); + assert (false == hb_none (st)); + assert (false == hb_none (st, 15u)); + assert (true == hb_none (st, 17u)); + + hb_array_t<hb_vector_t<int>> pa; + pa->as_array (); + + hb_map_t m; + + hb_iter (st); + hb_iter (&st); + + + hb_iter (src) + | hb_map (m) + | hb_map (&m) + | hb_filter () + | hb_filter (st) + | hb_filter (&st) + | hb_filter (hb_bool) + | hb_filter (hb_bool, hb_identity) + | hb_sink (st) + ; + + + hb_iter (src) + | hb_sink (hb_array (dst)) + ; + + + hb_iter (src) + | hb_apply (&st) + ; + + + hb_iter (src) + | hb_map ([] (int i) { return 1; }) + | hb_reduce ([=] (int acc, int value) { return acc; }, 2) + ; + + using map_pair_t = hb_item_type<hb_map_t>; + + hb_iter (m) + | hb_map ([] (map_pair_t p) { return p.first * p.second; }) + ; + + m.keys (); + using map_key_t = decltype (*m.keys()); + + hb_iter (m.keys ()) + | hb_filter ([] (map_key_t k) { return k < 42; }) + | hb_drain + ; + + m.values (); + using map_value_t = decltype (*m.values()); + + hb_iter (m.values ()) + | hb_filter ([] (map_value_t k) { return k < 42; }) + | hb_drain + ; + + unsigned int temp1 = 10; + unsigned int temp2 = 0; + hb_map_t *result = + + hb_iter (src) + | hb_map ([&] (int i) -> hb_set_t * + { + hb_set_t *set = hb_set_create (); + for (unsigned int i = 0; i < temp1; ++i) + hb_set_add (set, i); + temp1++; + return set; + }) + | hb_reduce ([&] (hb_map_t *acc, hb_set_t *value) -> hb_map_t * + { + hb_map_set (acc, temp2++, hb_set_get_population (value)); + /* This is not a memory managed language, take care! */ + hb_set_destroy (value); + return acc; + }, hb_map_create ()) + ; + /* The result should be something like 0->10, 1->11, ..., 9->19 */ + assert (hb_map_get (result, 9) == 19); + hb_map_destroy (result); + + /* Like above, but passing hb_set_t instead of hb_set_t * */ + temp1 = 10; + temp2 = 0; + result = + + hb_iter (src) + | hb_map ([&] (int i) -> hb_set_t + { + hb_set_t set; + for (unsigned int i = 0; i < temp1; ++i) + hb_set_add (&set, i); + temp1++; + return set; + }) + | hb_reduce ([&] (hb_map_t *acc, hb_set_t value) -> hb_map_t * + { + hb_map_set (acc, temp2++, hb_set_get_population (&value)); + return acc; + }, hb_map_create ()) + ; + /* The result should be something like 0->10, 1->11, ..., 9->19 */ + assert (hb_map_get (result, 9) == 19); + hb_map_destroy (result); + + unsigned int temp3 = 0; + + hb_iter(src) + | hb_map([&] (int i) { return ++temp3; }) + | hb_reduce([&] (float acc, int value) { return acc + value; }, 0) + ; + + + hb_iter (src) + | hb_drain + ; + + t << 1; + long vl; + s >> vl; + + hb_iota (); + hb_iota (3); + hb_iota (3, 2); + assert ((&vl) + 1 == *++hb_iota (&vl, hb_inc)); + hb_range (); + hb_repeat (7u); + hb_repeat (nullptr); + hb_repeat (vl) | hb_chop (3); + assert (hb_len (hb_range (10) | hb_take (3)) == 3); + assert (hb_range (9).len () == 9); + assert (hb_range (2, 9).len () == 7); + assert (hb_range (2, 9, 3).len () == 3); + assert (hb_range (2, 8, 3).len () == 2); + assert (hb_range (2, 7, 3).len () == 2); + assert (hb_range (-2, -9, -3).len () == 3); + assert (hb_range (-2, -8, -3).len () == 2); + assert (hb_range (-2, -7, -3).len () == 2); + + test_concat (); + + return 0; +} |