blob: 305d9eaecf85a4d7729ce69a56bff342fb58e57d [file] [log] [blame]
Behdad Esfahbodb80b97b2018-12-21 00:08:05 -05001/*
2 * Copyright © 2018 Google, Inc.
3 *
4 * This is part of HarfBuzz, a text shaping library.
5 *
6 * Permission is hereby granted, without written agreement and without
7 * license or royalty fees, to use, copy, modify, and distribute this
8 * software and its documentation for any purpose, provided that the
9 * above copyright notice and the following two paragraphs appear in
10 * all copies of this software.
11 *
12 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
13 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
14 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
15 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
16 * DAMAGE.
17 *
18 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
19 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
21 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
22 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
23 *
24 * Google Author(s): Behdad Esfahbod
25 */
26
27#ifndef HB_ITER_HH
28#define HB_ITER_HH
29
30#include "hb.hh"
Behdad Esfahbode76a3ca2018-12-27 17:23:12 -050031#include "hb-meta.hh"
Behdad Esfahbodb80b97b2018-12-21 00:08:05 -050032
33
34/* Unified iterator object.
35 *
36 * The goal of this template is to make the same iterator interface
37 * available to all types, and make it very easy and compact to use.
Behdad Esfahbod314d8692018-12-21 00:54:55 -050038 * hb_iter_tator objects are small, light-weight, objects that can be
Behdad Esfahbodb80b97b2018-12-21 00:08:05 -050039 * copied by value. If the collection / object being iterated on
Behdad Esfahbod314d8692018-12-21 00:54:55 -050040 * is writable, then the iterator returns lvalues, otherwise it
Behdad Esfahbodb80b97b2018-12-21 00:08:05 -050041 * returns rvalues.
Behdad Esfahbodb80b97b2018-12-21 00:08:05 -050042 */
43
Behdad Esfahbod8c6cbbd2018-12-28 14:29:09 -050044
45/*
46 * Base classes for iterators.
47 */
48
Behdad Esfahbod314d8692018-12-21 00:54:55 -050049/* Base class for all iterators. */
Behdad Esfahbod6b6783e2019-01-26 22:44:09 +010050template <typename iter_t, typename Item = typename iter_t::__item_t__>
Behdad Esfahbodcb5011d2019-01-04 11:22:32 -050051struct hb_iter_t
Behdad Esfahbodb80b97b2018-12-21 00:08:05 -050052{
Behdad Esfahbodaeb696a2018-12-21 01:57:02 -050053 typedef Item item_t;
Behdad Esfahbod70a52d62019-01-22 12:15:23 +010054 static constexpr unsigned item_size = hb_static_size (Item);
Behdad Esfahbod090fe562019-01-25 15:34:03 +010055 static constexpr bool is_iterator = true;
56 static constexpr bool is_random_access_iterator = false;
57 static constexpr bool is_sorted_iterator = false;
Behdad Esfahbodb80b97b2018-12-21 00:08:05 -050058
Behdad Esfahbod2fc18602018-12-21 18:09:45 -050059 private:
60 /* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */
Behdad Esfahbodaeb696a2018-12-21 01:57:02 -050061 const iter_t* thiz () const { return static_cast<const iter_t *> (this); }
62 iter_t* thiz () { return static_cast< iter_t *> (this); }
Behdad Esfahbod2fc18602018-12-21 18:09:45 -050063 public:
Behdad Esfahbodb80b97b2018-12-21 00:08:05 -050064
Behdad Esfahbod6c548b62019-01-08 13:43:49 -080065 /* TODO:
66 * Port operators below to use hb_enable_if to sniff which method implements
Behdad Esfahbod84a25d72019-01-29 13:39:19 -080067 * an operator and use it, and remove hb_iter_fallback_mixin_t completely. */
Behdad Esfahbod6c548b62019-01-08 13:43:49 -080068
Behdad Esfahbod314d8692018-12-21 00:54:55 -050069 /* Operators. */
Behdad Esfahbod7788ac12018-12-26 20:06:10 -050070 iter_t iter () const { return *thiz(); }
Behdad Esfahbod2f5b1a92019-01-27 00:49:37 +010071 iter_t operator + () const { return *thiz(); }
Behdad Esfahbod7788ac12018-12-26 20:06:10 -050072 explicit_operator bool () const { return thiz()->__more__ (); }
73 unsigned len () const { return thiz()->__len__ (); }
Behdad Esfahbod47333c82019-01-07 21:38:49 -050074 hb_remove_reference (item_t)* operator -> () const { return hb_addressof (**thiz()); }
Behdad Esfahbod5ec11ce2018-12-27 17:17:28 -050075 item_t operator * () const { return thiz()->__item__ (); }
76 item_t operator [] (unsigned i) const { return thiz()->__item_at__ (i); }
Behdad Esfahbod7788ac12018-12-26 20:06:10 -050077 iter_t& operator += (unsigned count) { thiz()->__forward__ (count); return *thiz(); }
78 iter_t& operator ++ () { thiz()->__next__ (); return *thiz(); }
79 iter_t& operator -= (unsigned count) { thiz()->__rewind__ (count); return *thiz(); }
80 iter_t& operator -- () { thiz()->__prev__ (); return *thiz(); }
Behdad Esfahbod8bd96be2019-01-28 16:17:36 -050081 iter_t operator + (unsigned count) const { auto c = thiz()->iter (); c += count; return c; }
Behdad Esfahbod859a8802018-12-30 02:11:03 -050082 friend iter_t operator + (unsigned count, const iter_t &it) { return it + count; }
Behdad Esfahbodaeb696a2018-12-21 01:57:02 -050083 iter_t operator ++ (int) { iter_t c (*thiz()); ++*thiz(); return c; }
Behdad Esfahbod8bd96be2019-01-28 16:17:36 -050084 iter_t operator - (unsigned count) const { auto c = thiz()->iter (); c -= count; return c; }
Behdad Esfahbodaeb696a2018-12-21 01:57:02 -050085 iter_t operator -- (int) { iter_t c (*thiz()); --*thiz(); return c; }
Behdad Esfahbod57795bc2019-01-28 16:23:12 -050086 template <typename T>
87 iter_t& operator >> (T &v) { v = **thiz(); ++*thiz(); return *thiz(); }
88 template <typename T>
89 iter_t& operator << (const T v) { **thiz() = v; ++*thiz(); return *thiz(); }
Behdad Esfahbodb80b97b2018-12-21 00:08:05 -050090
Behdad Esfahbod2fc18602018-12-21 18:09:45 -050091 protected:
92 hb_iter_t () {}
Behdad Esfahbodd25a2f12018-12-23 20:19:52 -050093 hb_iter_t (const hb_iter_t &o HB_UNUSED) {}
94 void operator = (const hb_iter_t &o HB_UNUSED) {}
Behdad Esfahbod2fc18602018-12-21 18:09:45 -050095};
96
Behdad Esfahbod570473a2018-12-27 13:29:51 -050097#define HB_ITER_USING(Name) \
Behdad Esfahbodf78f8372019-01-08 16:38:08 -080098 using item_t = typename Name::item_t; \
Behdad Esfahboddf138da2018-12-28 16:29:48 -050099 using Name::item_size; \
Behdad Esfahbod6cd96ba2018-12-30 20:51:31 -0500100 using Name::is_iterator; \
Behdad Esfahbod570473a2018-12-27 13:29:51 -0500101 using Name::iter; \
102 using Name::operator bool; \
103 using Name::len; \
104 using Name::operator ->; \
105 using Name::operator *; \
106 using Name::operator []; \
107 using Name::operator +=; \
108 using Name::operator ++; \
109 using Name::operator -=; \
110 using Name::operator --; \
Behdad Esfahbod859a8802018-12-30 02:11:03 -0500111 using Name::operator +; \
Behdad Esfahbod570473a2018-12-27 13:29:51 -0500112 using Name::operator -; \
Behdad Esfahbod6521d5b2019-01-29 13:44:39 -0800113 using Name::operator >>; \
114 using Name::operator <<; \
Behdad Esfahbod570473a2018-12-27 13:29:51 -0500115 static_assert (true, "")
116
Behdad Esfahbod778c96b2019-01-27 00:50:54 +0100117/* Returns iterator type of a type. */
118#define hb_iter_t(Iterable) decltype (hb_declval (Iterable).iter ())
119
Behdad Esfahbod0363ce62019-01-27 01:03:56 +0100120
121/* TODO Change to function-object. */
122
Behdad Esfahbod778c96b2019-01-27 00:50:54 +0100123template <typename T>
124inline hb_iter_t (T)
125hb_iter (const T& c) { return c.iter (); }
126
Behdad Esfahbod0363ce62019-01-27 01:03:56 +0100127/* Specialization for C arrays. */
128template <typename> struct hb_array_t;
129template <typename Type> inline hb_array_t<Type>
130hb_iter (Type *array, unsigned int length) { return hb_array_t<Type> (array, length); }
131template <typename Type, unsigned int length> hb_array_t<Type>
132hb_iter (Type (&array)[length]) { return hb_iter (array, length); }
133
134
Behdad Esfahbod2fc18602018-12-21 18:09:45 -0500135/* Mixin to fill in what the subclass doesn't provide. */
Behdad Esfahbod636786e2019-01-08 23:48:35 -0800136template <typename iter_t, typename item_t = typename iter_t::__item_t__>
Behdad Esfahbod84a25d72019-01-29 13:39:19 -0800137struct hb_iter_fallback_mixin_t
Behdad Esfahbod2fc18602018-12-21 18:09:45 -0500138{
139 private:
140 /* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */
141 const iter_t* thiz () const { return static_cast<const iter_t *> (this); }
142 iter_t* thiz () { return static_cast< iter_t *> (this); }
143 public:
Behdad Esfahbodb80b97b2018-12-21 00:08:05 -0500144
Behdad Esfahbod8001e002018-12-21 01:53:27 -0500145 /* Access: Implement __item__(), or __item_at__() if random-access. */
Behdad Esfahbod5ec11ce2018-12-27 17:17:28 -0500146 item_t __item__ () const { return (*thiz())[0]; }
147 item_t __item_at__ (unsigned i) const { return *(*thiz() + i); }
Behdad Esfahbodb80b97b2018-12-21 00:08:05 -0500148
Behdad Esfahbod2a33ab02018-12-21 18:49:27 -0500149 /* Termination: Implement __more__(), or __len__() if random-access. */
Behdad Esfahbod7788ac12018-12-26 20:06:10 -0500150 bool __more__ () const { return thiz()->len (); }
Behdad Esfahbod2a33ab02018-12-21 18:49:27 -0500151 unsigned __len__ () const
152 { iter_t c (*thiz()); unsigned l = 0; while (c) { c++; l++; }; return l; }
Behdad Esfahbodb80b97b2018-12-21 00:08:05 -0500153
Behdad Esfahbod314d8692018-12-21 00:54:55 -0500154 /* Advancing: Implement __next__(), or __forward__() if random-access. */
Behdad Esfahbod7788ac12018-12-26 20:06:10 -0500155 void __next__ () { *thiz() += 1; }
156 void __forward__ (unsigned n) { while (n--) ++*thiz(); }
Behdad Esfahbodb80b97b2018-12-21 00:08:05 -0500157
Behdad Esfahbod19d2b502018-12-21 01:17:35 -0500158 /* Rewinding: Implement __prev__() or __rewind__() if bidirectional. */
Behdad Esfahbod7788ac12018-12-26 20:06:10 -0500159 void __prev__ () { *thiz() -= 1; }
160 void __rewind__ (unsigned n) { while (n--) --*thiz(); }
Behdad Esfahbod19d2b502018-12-21 01:17:35 -0500161
Behdad Esfahbodd3976b72018-12-26 18:54:27 -0500162 protected:
Behdad Esfahbod84a25d72019-01-29 13:39:19 -0800163 hb_iter_fallback_mixin_t () {}
164 hb_iter_fallback_mixin_t (const hb_iter_fallback_mixin_t &o HB_UNUSED) {}
165 void operator = (const hb_iter_fallback_mixin_t &o HB_UNUSED) {}
Behdad Esfahbodb80b97b2018-12-21 00:08:05 -0500166};
167
Behdad Esfahbod849a0f12019-01-29 17:10:19 -0800168template <typename iter_t, typename item_t = typename iter_t::__item_t__>
169struct hb_iter_with_fallback_t :
170 hb_iter_t<iter_t, item_t>,
171 hb_iter_fallback_mixin_t<iter_t, item_t>
172{
173 protected:
174 hb_iter_with_fallback_t () {}
175 hb_iter_with_fallback_t (const hb_iter_with_fallback_t &o HB_UNUSED) {}
176 void operator = (const hb_iter_with_fallback_t &o HB_UNUSED) {}
177};
178
Behdad Esfahbod8c6cbbd2018-12-28 14:29:09 -0500179/*
180 * Meta-programming predicates.
181 */
Behdad Esfahbodb80b97b2018-12-21 00:08:05 -0500182
Behdad Esfahboddf138da2018-12-28 16:29:48 -0500183/* hb_is_iterable() */
184
185template<typename T, typename B>
Behdad Esfahbod8c6cbbd2018-12-28 14:29:09 -0500186struct _hb_is_iterable
187{ enum { value = false }; };
Behdad Esfahboddf138da2018-12-28 16:29:48 -0500188template<typename T>
Behdad Esfahbod50935332019-01-26 22:47:35 +0100189struct _hb_is_iterable<T, hb_bool_tt<true || sizeof (hb_declval (T).iter ())> >
Behdad Esfahbod8c6cbbd2018-12-28 14:29:09 -0500190{ enum { value = true }; };
Behdad Esfahbod8570da12018-12-28 14:40:30 -0500191
Behdad Esfahboddf138da2018-12-28 16:29:48 -0500192template<typename T>
Behdad Esfahbod8c6cbbd2018-12-28 14:29:09 -0500193struct hb_is_iterable { enum { value = _hb_is_iterable<T, hb_true_t>::value }; };
Behdad Esfahbod8c6cbbd2018-12-28 14:29:09 -0500194#define hb_is_iterable(Iterable) hb_is_iterable<Iterable>::value
195
Behdad Esfahboddc0a98c2019-01-08 12:57:01 -0800196/* TODO Add hb_is_iterable_of().
197 * TODO Add random_access / sorted variants. */
198
Behdad Esfahbod8c6cbbd2018-12-28 14:29:09 -0500199
Behdad Esfahbod2658e402019-01-08 12:53:02 -0800200/* hb_is_iterator() / hb_is_random_access_iterator() / hb_is_sorted_iterator() */
Behdad Esfahboddf138da2018-12-28 16:29:48 -0500201
Behdad Esfahboded433662019-01-07 17:24:23 -0500202template <typename Iter>
Behdad Esfahbod445364d2019-01-08 12:42:15 -0800203struct _hb_is_iterator_of
Behdad Esfahboded433662019-01-07 17:24:23 -0500204{
Behdad Esfahbod42bf80e2019-01-08 19:13:17 -0800205 char operator () (...) { return 0; }
Behdad Esfahbod6af9c5f2019-01-08 16:27:37 -0800206 template<typename Item> int operator () (hb_iter_t<Iter, Item> *) { return 0; }
207 template<typename Item> int operator () (hb_iter_t<Iter, const Item> *) { return 0; }
208 template<typename Item> int operator () (hb_iter_t<Iter, Item&> *) { return 0; }
209 template<typename Item> int operator () (hb_iter_t<Iter, const Item&> *) { return 0; }
Behdad Esfahboded433662019-01-07 17:24:23 -0500210 static_assert (sizeof (char) != sizeof (int), "");
211};
Behdad Esfahbod06a44e22018-12-30 18:42:14 -0500212template<typename Iter, typename Item>
Behdad Esfahbod445364d2019-01-08 12:42:15 -0800213struct hb_is_iterator_of { enum {
214 value = sizeof (int) == sizeof (hb_declval (_hb_is_iterator_of<Iter>) (hb_declval (Iter*))) }; };
215#define hb_is_iterator_of(Iter, Item) hb_is_iterator_of<Iter, Item>::value
216#define hb_is_iterator(Iter) hb_is_iterator_of (Iter, typename Iter::item_t)
Behdad Esfahboddf138da2018-12-28 16:29:48 -0500217
Behdad Esfahbod2658e402019-01-08 12:53:02 -0800218#define hb_is_random_access_iterator_of(Iter, Item) \
219 hb_is_iterator_of (Iter, Item) && Iter::is_random_access_iterator
220#define hb_is_random_access_iterator(Iter) \
221 hb_is_random_access_iterator_of (Iter, typename Iter::item_t)
222
Behdad Esfahbod445364d2019-01-08 12:42:15 -0800223#define hb_is_sorted_iterator_of(Iter, Item) \
Behdad Esfahbod2658e402019-01-08 12:53:02 -0800224 hb_is_iterator_of (Iter, Item) && Iter::is_sorted_iterator
Behdad Esfahbod445364d2019-01-08 12:42:15 -0800225#define hb_is_sorted_iterator(Iter) \
226 hb_is_sorted_iterator_of (Iter, typename Iter::item_t)
Behdad Esfahboddf138da2018-12-28 16:29:48 -0500227
Behdad Esfahbod014c5022019-01-09 09:07:01 -0800228
Behdad Esfahbod8c6cbbd2018-12-28 14:29:09 -0500229/*
Behdad Esfahbod014c5022019-01-09 09:07:01 -0800230 * Adaptors, combiners, etc.
Behdad Esfahbod8c6cbbd2018-12-28 14:29:09 -0500231 */
Behdad Esfahbod7557e342018-12-21 17:21:19 -0500232
Behdad Esfahbod343f5a42019-01-09 12:35:45 -0800233template <typename Lhs, typename Rhs,
234 hb_enable_if (hb_is_iterator (Lhs))>
235static inline decltype (hb_declval (Rhs) (hb_declval (Lhs)))
236operator | (Lhs lhs, const Rhs &rhs) { return rhs (lhs); }
237
Behdad Esfahbod1733e472019-01-09 11:15:49 -0800238/* hb_map(), hb_filter(), hb_reduce() */
239
240template <typename Iter, typename Proj,
241 hb_enable_if (hb_is_iterator (Iter))>
242struct hb_map_iter_t :
Behdad Esfahbod343f5a42019-01-09 12:35:45 -0800243 hb_iter_t<hb_map_iter_t<Iter, Proj>, decltype (hb_declval (Proj) (hb_declval (typename Iter::item_t)))>
Behdad Esfahbod1733e472019-01-09 11:15:49 -0800244{
Behdad Esfahbod471e96e2019-01-09 12:42:01 -0800245 hb_map_iter_t (const Iter& it, Proj&& f) : it (it), f (f) {}
Behdad Esfahbod1733e472019-01-09 11:15:49 -0800246
Behdad Esfahbod343f5a42019-01-09 12:35:45 -0800247 typedef decltype (hb_declval (Proj) (hb_declval (typename Iter::item_t))) __item_t__;
Behdad Esfahbod090fe562019-01-25 15:34:03 +0100248 static constexpr bool is_random_access_iterator = Iter::is_random_access_iterator;
Behdad Esfahbod1733e472019-01-09 11:15:49 -0800249 __item_t__ __item__ () const { return f (*it); }
250 __item_t__ __item_at__ (unsigned i) const { return f (it[i]); }
Behdad Esfahbod343f5a42019-01-09 12:35:45 -0800251 bool __more__ () const { return bool (it); }
Behdad Esfahbod1733e472019-01-09 11:15:49 -0800252 unsigned __len__ () const { return it.len (); }
253 void __next__ () { ++it; }
254 void __forward__ (unsigned n) { it += n; }
255 void __prev__ () { --it; }
256 void __rewind__ (unsigned n) { it -= n; }
257
258 private:
259 Iter it;
260 Proj f;
261};
Behdad Esfahbod6b6783e2019-01-26 22:44:09 +0100262
Behdad Esfahbod1733e472019-01-09 11:15:49 -0800263template <typename Proj>
264struct hb_map_iter_factory_t
265{
Behdad Esfahbod471e96e2019-01-09 12:42:01 -0800266 hb_map_iter_factory_t (Proj&& f) : f (f) {}
Behdad Esfahbod1733e472019-01-09 11:15:49 -0800267
268 template <typename Iterable,
269 hb_enable_if (hb_is_iterable (Iterable))>
Behdad Esfahbod6b6783e2019-01-26 22:44:09 +0100270 hb_map_iter_t<hb_iter_t (Iterable), Proj> operator () (const Iterable &c) const
271 { return hb_map_iter_t<hb_iter_t (Iterable), Proj> (c.iter (), f); }
Behdad Esfahbod1733e472019-01-09 11:15:49 -0800272
273 private:
274 Proj f;
275};
276template <typename Proj>
277inline hb_map_iter_factory_t<Proj>
Behdad Esfahbod471e96e2019-01-09 12:42:01 -0800278hb_map (Proj&& f)
Behdad Esfahbod1733e472019-01-09 11:15:49 -0800279{ return hb_map_iter_factory_t<Proj> (f); }
280
Behdad Esfahbodf35568d2019-01-09 11:32:33 -0800281template <typename Iter, typename Pred, typename Proj,
282 hb_enable_if (hb_is_iterator (Iter))>
283struct hb_filter_iter_t :
Behdad Esfahbod849a0f12019-01-29 17:10:19 -0800284 hb_iter_with_fallback_t<hb_filter_iter_t<Iter, Pred, Proj>,
285 typename Iter::item_t>
Behdad Esfahbodf35568d2019-01-09 11:32:33 -0800286{
Behdad Esfahbod471e96e2019-01-09 12:42:01 -0800287 hb_filter_iter_t (const Iter& it_, Pred&& p, Proj&& f) : it (it_), p (p), f (f)
Behdad Esfahbodf35568d2019-01-09 11:32:33 -0800288 { while (it && !p (f (*it))) ++it; }
289
290 typedef typename Iter::item_t __item_t__;
Behdad Esfahbod090fe562019-01-25 15:34:03 +0100291 static constexpr bool is_sorted_iterator = Iter::is_sorted_iterator;
Behdad Esfahbodf35568d2019-01-09 11:32:33 -0800292 __item_t__ __item__ () const { return *it; }
Behdad Esfahbod343f5a42019-01-09 12:35:45 -0800293 bool __more__ () const { return bool (it); }
Behdad Esfahbodf35568d2019-01-09 11:32:33 -0800294 void __next__ () { do ++it; while (it && !p (f (*it))); }
295 void __prev__ () { --it; }
296
297 private:
298 Iter it;
299 Pred p;
300 Proj f;
301};
302template <typename Pred, typename Proj>
303struct hb_filter_iter_factory_t
304{
Behdad Esfahbod471e96e2019-01-09 12:42:01 -0800305 hb_filter_iter_factory_t (Pred&& p, Proj&& f) : p (p), f (f) {}
Behdad Esfahbodf35568d2019-01-09 11:32:33 -0800306
307 template <typename Iterable,
308 hb_enable_if (hb_is_iterable (Iterable))>
Behdad Esfahbod6b6783e2019-01-26 22:44:09 +0100309 hb_filter_iter_t<hb_iter_t (Iterable), Pred, Proj> operator () (const Iterable &c) const
310 { return hb_filter_iter_t<hb_iter_t (Iterable), Pred, Proj> (c.iter (), p, f); }
Behdad Esfahbodf35568d2019-01-09 11:32:33 -0800311
312 private:
313 Pred p;
314 Proj f;
315};
Behdad Esfahbod71157a42019-01-28 21:20:12 -0500316template <typename Pred = decltype ((hb_bool)), typename Proj = decltype ((hb_identity))>
Behdad Esfahbodf35568d2019-01-09 11:32:33 -0800317inline hb_filter_iter_factory_t<Pred, Proj>
Behdad Esfahbodfbab07f2019-01-27 00:44:45 +0100318hb_filter (Pred&& p = hb_bool, Proj&& f = hb_identity)
Behdad Esfahbodf35568d2019-01-09 11:32:33 -0800319{ return hb_filter_iter_factory_t<Pred, Proj> (p, f); }
Behdad Esfahbod7557e342018-12-21 17:21:19 -0500320
Behdad Esfahbod014c5022019-01-09 09:07:01 -0800321/* hb_zip() */
Behdad Esfahbod7557e342018-12-21 17:21:19 -0500322
Behdad Esfahbod84e5d002019-01-08 23:57:16 -0800323template <typename A, typename B>
Behdad Esfahbod200cdb72019-01-09 09:49:12 -0800324struct hb_zip_iter_t :
325 hb_iter_t<hb_zip_iter_t<A, B>, hb_pair_t<typename A::item_t, typename B::item_t> >
Behdad Esfahbod84e5d002019-01-08 23:57:16 -0800326{
Behdad Esfahbod200cdb72019-01-09 09:49:12 -0800327 hb_zip_iter_t () {}
328 hb_zip_iter_t (A a, B b) : a (a), b (b) {}
Behdad Esfahbod84e5d002019-01-08 23:57:16 -0800329
330 typedef hb_pair_t<typename A::item_t, typename B::item_t> __item_t__;
Behdad Esfahbod090fe562019-01-25 15:34:03 +0100331 static constexpr bool is_random_access_iterator =
Behdad Esfahbod84e5d002019-01-08 23:57:16 -0800332 A::is_random_access_iterator &&
Behdad Esfahbod090fe562019-01-25 15:34:03 +0100333 B::is_random_access_iterator;
334 static constexpr bool is_sorted_iterator =
Behdad Esfahbod84e5d002019-01-08 23:57:16 -0800335 A::is_sorted_iterator &&
Behdad Esfahbod090fe562019-01-25 15:34:03 +0100336 B::is_sorted_iterator;
Behdad Esfahbod84e5d002019-01-08 23:57:16 -0800337 __item_t__ __item__ () const { return __item_t__ (*a, *b); }
338 __item_t__ __item_at__ (unsigned i) const { return __item_t__ (a[i], b[i]); }
339 bool __more__ () const { return a && b; }
340 unsigned __len__ () const { return MIN (a.len (), b.len ()); }
341 void __next__ () { ++a; ++b; }
342 void __forward__ (unsigned n) { a += n; b += n; }
343 void __prev__ () { --a; --b; }
344 void __rewind__ (unsigned n) { a -= n; b -= n; }
345
346 private:
347 A a;
348 B b;
349};
Behdad Esfahbod79870952019-01-09 01:02:38 -0800350template <typename A, typename B,
351 hb_enable_if (hb_is_iterable (A) && hb_is_iterable (B))>
Behdad Esfahbod6b6783e2019-01-26 22:44:09 +0100352inline hb_zip_iter_t<hb_iter_t (A), hb_iter_t (B)>
Behdad Esfahbodf7fcc472019-01-09 11:00:32 -0800353hb_zip (const A& a, const B &b)
Behdad Esfahbod6b6783e2019-01-26 22:44:09 +0100354{ return hb_zip_iter_t<hb_iter_t (A), hb_iter_t (B)> (a.iter (), b.iter ()); }
Behdad Esfahbod84e5d002019-01-08 23:57:16 -0800355
Behdad Esfahbod014c5022019-01-09 09:07:01 -0800356
357/*
358 * Algorithms operating on iterators.
359 */
360
361template <typename C, typename V,
362 hb_enable_if (hb_is_iterable (C))>
363inline void
364hb_fill (C& c, const V &v)
365{
Behdad Esfahbod6b6783e2019-01-26 22:44:09 +0100366 for (auto i = c.iter (); i; i++)
Behdad Esfahbod014c5022019-01-09 09:07:01 -0800367 hb_assign (*i, v);
368}
369
370template <typename S, typename D,
371 hb_enable_if (hb_is_iterator (S) && hb_is_iterator (D))>
372inline bool
373hb_copy (D id, S is)
374{
375 for (; id && is; ++id, ++is)
376 *id = *is;
377 return !is;
378}
379
380
Behdad Esfahbodb80b97b2018-12-21 00:08:05 -0500381#endif /* HB_ITER_HH */