/* * 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 struct array_iter_t : hb_iter_with_fallback_t, T&> { array_iter_t (hb_array_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 arr; }; template struct some_array_t { some_array_t (hb_array_t arr_) : arr (arr_) {} typedef array_iter_t iter_t; array_iter_t iter () { return array_iter_t (arr); } operator array_iter_t () { return iter (); } operator hb_iter_t> () { return iter (); } private: hb_array_t arr; }; template 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 static void test_iterator (Iter it) { Iter default_constructed; assert (!default_constructed); test_iterator_non_default_constructable (it); } template static void test_iterable (const Iterable &lst = Null(Iterable)) { for (auto _ : lst) (void) _; // Test that can take iterator from. test_iterator (lst.iter ()); } int main (int argc, char **argv) { const int src[10] = {}; int dst[20]; hb_vector_t v; array_iter_t s (src); /* Implicit conversion from static array. */ array_iter_t s2 (v); /* Implicit conversion from vector. */ array_iter_t t (dst); static_assert (hb_is_random_access_iterator (array_iter_t), ""); some_array_t 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 sa; (void) static_cast, hb_sorted_array_t::item_t>&> (sa); (void) static_cast, hb_sorted_array_t::__item_t__>&> (sa); (void) static_cast, int&>&>(sa); (void) static_cast>&>(sa); (void) static_cast, int&>&> (sa); test_iterable (sa); test_iterable> (); test_iterable> (); test_iterable> (); test_iterable (); test_iterable (); test_iterator (hb_zip (st, v)); test_iterator_non_default_constructable (hb_enumerate (st)); 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_identity)); 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> pa; pa->as_array (); + hb_iter (src) | hb_map (hb_identity) | hb_filter () | 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) -> int { return 1; }) | hb_reduce ([&] (int acc, int value) -> int { return acc; }, 2) ; 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); unsigned int temp3 = 0; + hb_iter(src) | hb_map([&] (int i) -> int { return ++temp3; }) | hb_reduce([&] (float acc, int value) -> float { return acc + value; }, 0) ; hb_map_destroy (result); + hb_iter (src) | hb_drain ; t << 1; long vl; s >> vl; hb_iota (); assert (hb_iota (9).len () == 9); assert (hb_iota (2, 9).len () == 7); assert (hb_iota (2, 9, 3).len () == 3); assert (hb_iota (2, 8, 3).len () == 2); assert (hb_iota (2, 7, 3).len () == 2); assert (hb_iota (-2, -9, -3).len () == 3); assert (hb_iota (-2, -8, -3).len () == 2); assert (hb_iota (-2, -7, -3).len () == 2); return 0; }