hb-iter.hh 23.5 KB
Newer Older
1 2
/*
 * Copyright © 2018  Google, Inc.
B
Behdad Esfahbod 已提交
3
 * Copyright © 2019  Facebook, Inc.
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
 *
 *  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
B
Behdad Esfahbod 已提交
26
 * Facebook Author(s): Behdad Esfahbod
27 28 29 30 31 32
 */

#ifndef HB_ITER_HH
#define HB_ITER_HH

#include "hb.hh"
33
#include "hb-algs.hh"
34
#include "hb-meta.hh"
35 36 37 38 39 40


/* Unified iterator object.
 *
 * The goal of this template is to make the same iterator interface
 * available to all types, and make it very easy and compact to use.
41
 * hb_iter_tator objects are small, light-weight, objects that can be
42
 * copied by value.  If the collection / object being iterated on
43
 * is writable, then the iterator returns lvalues, otherwise it
44
 * returns rvalues.
45 46 47 48 49 50 51 52 53 54 55
 *
 * TODO Document more.
 *
 * If iterator implementation implements operator!=, then can be
 * used in range-based for loop.  That comes free if the iterator
 * is random-access.  Otherwise, the range-based for loop incurs
 * one traversal to find end(), which can be avoided if written
 * as a while-style for loop, or if iterator implements a faster
 * __end__() method.
 * TODO When opting in for C++17, address this by changing return
 * type of .end()?
56 57
 */

B
Behdad Esfahbod 已提交
58 59 60 61 62

/*
 * Base classes for iterators.
 */

63
/* Base class for all iterators. */
64
template <typename iter_t, typename Item = typename iter_t::__item_t__>
65
struct hb_iter_t
66
{
B
Behdad Esfahbod 已提交
67
  typedef Item item_t;
68
  static constexpr unsigned item_size = hb_static_size (Item);
69 70 71
  static constexpr bool is_iterator = true;
  static constexpr bool is_random_access_iterator = false;
  static constexpr bool is_sorted_iterator = false;
72

73 74
  private:
  /* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */
75 76
  const iter_t* thiz () const { return static_cast<const iter_t *> (this); }
        iter_t* thiz ()       { return static_cast<      iter_t *> (this); }
77
  public:
78

B
Behdad Esfahbod 已提交
79 80
  /* TODO:
   * Port operators below to use hb_enable_if to sniff which method implements
B
Behdad Esfahbod 已提交
81
   * an operator and use it, and remove hb_iter_fallback_mixin_t completely. */
B
Behdad Esfahbod 已提交
82

83
  /* Operators. */
84 85
  iter_t iter () const { return *thiz(); }
  iter_t operator + () const { return *thiz(); }
86 87
  iter_t begin () const { return *thiz(); }
  iter_t end () const { return thiz()->__end__ (); }
88 89
  explicit operator bool () const { return thiz()->__more__ (); }
  unsigned len () const { return thiz()->__len__ (); }
B
Behdad Esfahbod 已提交
90
  /* The following can only be enabled if item_t is reference type.  Otherwise
91 92
   * it will be returning pointer to temporary rvalue.
   * TODO Use a wrapper return type to fix for non-reference type. */
B
Behdad Esfahbod 已提交
93 94
  template <typename T = item_t,
	    hb_enable_if (hb_is_reference (T))>
95
  hb_remove_reference<item_t>* operator -> () const { return hb_addressof (**thiz()); }
96 97 98 99
  item_t operator * () const { return thiz()->__item__ (); }
  item_t operator * () { return thiz()->__item__ (); }
  item_t operator [] (unsigned i) const { return thiz()->__item_at__ (i); }
  item_t operator [] (unsigned i) { return thiz()->__item_at__ (i); }
100 101
  iter_t& operator += (unsigned count) &  { thiz()->__forward__ (count); return *thiz(); }
  iter_t  operator += (unsigned count) && { thiz()->__forward__ (count); return *thiz(); }
102 103
  iter_t& operator ++ () &  { thiz()->__next__ (); return *thiz(); }
  iter_t  operator ++ () && { thiz()->__next__ (); return *thiz(); }
104 105
  iter_t& operator -= (unsigned count) &  { thiz()->__rewind__ (count); return *thiz(); }
  iter_t  operator -= (unsigned count) && { thiz()->__rewind__ (count); return *thiz(); }
106 107
  iter_t& operator -- () &  { thiz()->__prev__ (); return *thiz(); }
  iter_t  operator -- () && { thiz()->__prev__ (); return *thiz(); }
108 109 110 111 112
  iter_t operator + (unsigned count) const { auto c = thiz()->iter (); c += count; return c; }
  friend iter_t operator + (unsigned count, const iter_t &it) { return it + count; }
  iter_t operator ++ (int) { iter_t c (*thiz()); ++*thiz(); return c; }
  iter_t operator - (unsigned count) const { auto c = thiz()->iter (); c -= count; return c; }
  iter_t operator -- (int) { iter_t c (*thiz()); --*thiz(); return c; }
113
  template <typename T>
114
  iter_t& operator >> (T &v) &  { v = **thiz(); ++*thiz(); return *thiz(); }
115
  template <typename T>
116 117 118 119 120
  iter_t  operator >> (T &v) && { v = **thiz(); ++*thiz(); return *thiz(); }
  template <typename T>
  iter_t& operator << (const T v) &  { **thiz() = v; ++*thiz(); return *thiz(); }
  template <typename T>
  iter_t  operator << (const T v) && { **thiz() = v; ++*thiz(); return *thiz(); }
121

122
  protected:
123 124 125
  hb_iter_t () {}
  hb_iter_t (const hb_iter_t &o HB_UNUSED) {}
  void operator = (const hb_iter_t &o HB_UNUSED) {}
126 127
};

128
#define HB_ITER_USING(Name) \
129
  using item_t = typename Name::item_t; \
130 131
  using Name::begin; \
  using Name::end; \
132
  using Name::item_size; \
133
  using Name::is_iterator; \
134 135 136 137 138 139 140 141 142 143
  using Name::iter; \
  using Name::operator bool; \
  using Name::len; \
  using Name::operator ->; \
  using Name::operator *; \
  using Name::operator []; \
  using Name::operator +=; \
  using Name::operator ++; \
  using Name::operator -=; \
  using Name::operator --; \
B
Behdad Esfahbod 已提交
144
  using Name::operator +; \
145
  using Name::operator -; \
B
Behdad Esfahbod 已提交
146 147
  using Name::operator >>; \
  using Name::operator <<; \
148 149
  static_assert (true, "")

150 151 152 153 154
/* Returns iterator / item type of a type. */
template <typename Iterable>
using hb_iter_type = decltype (hb_deref (hb_declval (Iterable)).iter ());
template <typename Iterable>
using hb_item_type = decltype (*hb_deref (hb_declval (Iterable)).iter ());
B
Behdad Esfahbod 已提交
155

156 157

template <typename> struct hb_array_t;
158

B
Behdad Esfahbod 已提交
159
struct
160
{
161
  template <typename T> hb_iter_type<T>
162
  operator () (T&& c) const
163
  { return hb_deref (hb_forward<T> (c)).iter (); }
164 165 166 167

  /* Specialization for C arrays. */

  template <typename Type> inline hb_array_t<Type>
168
  operator () (Type *array, unsigned int length) const
169 170 171
  { return hb_array_t<Type> (array, length); }

  template <typename Type, unsigned int length> hb_array_t<Type>
172
  operator () (Type (&array)[length]) const
173 174
  { return hb_array_t<Type> (array, length); }

B
Behdad Esfahbod 已提交
175 176
}
HB_FUNCOBJ (hb_iter);
177

178
/* Mixin to fill in what the subclass doesn't provide. */
179
template <typename iter_t, typename item_t = typename iter_t::__item_t__>
B
Behdad Esfahbod 已提交
180
struct hb_iter_fallback_mixin_t
181 182 183
{
  private:
  /* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */
184 185
  const iter_t* thiz () const { return static_cast<const iter_t *> (this); }
        iter_t* thiz ()       { return static_cast<      iter_t *> (this); }
186
  public:
187

B
Behdad Esfahbod 已提交
188
  /* Access: Implement __item__(), or __item_at__() if random-access. */
189 190
  item_t __item__ () const { return (*thiz())[0]; }
  item_t __item_at__ (unsigned i) const { return *(*thiz() + i); }
191

192
  /* Termination: Implement __more__(), or __len__() if random-access. */
193 194
  bool __more__ () const { return thiz()->len (); }
  unsigned __len__ () const
195
  { iter_t c (*thiz()); unsigned l = 0; while (c) { c++; l++; }; return l; }
196 197

  /* Advancing: Implement __next__(), or __forward__() if random-access. */
198 199
  void __next__ () { *thiz() += 1; }
  void __forward__ (unsigned n) { while (n--) ++*thiz(); }
200

B
Behdad Esfahbod 已提交
201
  /* Rewinding: Implement __prev__() or __rewind__() if bidirectional. */
202 203
  void __prev__ () { *thiz() -= 1; }
  void __rewind__ (unsigned n) { while (n--) --*thiz(); }
B
Behdad Esfahbod 已提交
204

205 206 207 208 209 210 211 212 213 214 215 216
  /* Range-based for: Implement __end__() if can be done faster,
   * and operator!=. */
  iter_t __end__ () const
  {
    if (thiz()->is_random_access_iterator)
      return *thiz() + thiz()->len ();
    /* Above expression loops twice. Following loops once. */
    auto it = *thiz();
    while (it) ++it;
    return it;
  }

B
Behdad Esfahbod 已提交
217
  protected:
218 219 220
  hb_iter_fallback_mixin_t () {}
  hb_iter_fallback_mixin_t (const hb_iter_fallback_mixin_t &o HB_UNUSED) {}
  void operator = (const hb_iter_fallback_mixin_t &o HB_UNUSED) {}
221 222
};

223 224 225 226 227 228
template <typename iter_t, typename item_t = typename iter_t::__item_t__>
struct hb_iter_with_fallback_t :
  hb_iter_t<iter_t, item_t>,
  hb_iter_fallback_mixin_t<iter_t, item_t>
{
  protected:
229 230
  hb_iter_with_fallback_t () {}
  hb_iter_with_fallback_t (const hb_iter_with_fallback_t &o HB_UNUSED) :
B
Behdad Esfahbod 已提交
231 232
    hb_iter_t<iter_t, item_t> (o),
    hb_iter_fallback_mixin_t<iter_t, item_t> (o) {}
233
  void operator = (const hb_iter_with_fallback_t &o HB_UNUSED) {}
234 235
};

B
Behdad Esfahbod 已提交
236 237 238 239
/*
 * Meta-programming predicates.
 */

240 241
/* hb_is_iterable() */

242 243 244 245
template <typename T>
struct hb_is_iterable
{
  private:
B
Minor  
Behdad Esfahbod 已提交
246

247
  template <typename U>
B
Minor  
Behdad Esfahbod 已提交
248 249
  static auto impl (hb_priority<1>) -> decltype (hb_declval (U).iter (), hb_true_t ());

250
  template <typename>
B
Minor  
Behdad Esfahbod 已提交
251
  static hb_false_t impl (hb_priority<0>);
252 253

  public:
B
Minor  
Behdad Esfahbod 已提交
254 255

  enum { value = decltype (impl<T> (hb_prioritize))::value };
256
};
B
Behdad Esfahbod 已提交
257
#define hb_is_iterable(Iterable) hb_is_iterable<Iterable>::value
258

B
Behdad Esfahbod 已提交
259 260 261
/* TODO Add hb_is_iterable_of().
 * TODO Add random_access / sorted variants. */

262
/* hb_is_iterator() / hb_is_random_access_iterator() / hb_is_sorted_iterator() */
263

264 265 266 267 268 269 270 271
template <typename Iter, typename Item>
static inline char _hb_is_iterator_of (hb_priority<0>, const void *) { return 0; }
template <typename Iter,
	  typename Item,
	  typename Item2 = typename Iter::item_t,
	  hb_enable_if (hb_is_cr_convertible_to (Item2, Item))>
static inline int _hb_is_iterator_of (hb_priority<2>, hb_iter_t<Iter, Item2> *) { return 0; }

272
template<typename Iter, typename Item>
273
struct hb_is_iterator_of { enum {
274
  value = sizeof (int) == sizeof (_hb_is_iterator_of<Iter, Item> (hb_prioritize, hb_declval (Iter*))) }; };
275 276
#define hb_is_iterator_of(Iter, Item) hb_is_iterator_of<Iter, Item>::value
#define hb_is_iterator(Iter) hb_is_iterator_of (Iter, typename Iter::item_t)
277

278 279 280 281 282
#define hb_is_random_access_iterator_of(Iter, Item) \
  hb_is_iterator_of (Iter, Item) && Iter::is_random_access_iterator
#define hb_is_random_access_iterator(Iter) \
  hb_is_random_access_iterator_of (Iter, typename Iter::item_t)

283
#define hb_is_sorted_iterator_of(Iter, Item) \
284
  hb_is_iterator_of (Iter, Item) && Iter::is_sorted_iterator
285 286
#define hb_is_sorted_iterator(Iter) \
  hb_is_sorted_iterator_of (Iter, typename Iter::item_t)
287

B
Behdad Esfahbod 已提交
288

289 290 291
/* Range-based 'for' for iterables. */

template <typename Iterable,
292
	  hb_requires (hb_is_iterable (Iterable))>
293 294 295
static inline auto begin (Iterable&& iterable) HB_AUTO_RETURN (hb_iter (iterable).begin ())

template <typename Iterable,
296
	  hb_requires (hb_is_iterable (Iterable))>
297 298 299 300 301 302 303
static inline auto end (Iterable&& iterable) HB_AUTO_RETURN (hb_iter (iterable).end ())

/* begin()/end() are NOT looked up non-ADL.  So each namespace must declare them.
 * Do it for namespace OT. */
namespace OT {

template <typename Iterable,
304
	  hb_requires (hb_is_iterable (Iterable))>
305 306 307
static inline auto begin (Iterable&& iterable) HB_AUTO_RETURN (hb_iter (iterable).begin ())

template <typename Iterable,
308
	  hb_requires (hb_is_iterable (Iterable))>
309 310 311 312 313
static inline auto end (Iterable&& iterable) HB_AUTO_RETURN (hb_iter (iterable).end ())

}


B
Behdad Esfahbod 已提交
314
/*
B
Behdad Esfahbod 已提交
315
 * Adaptors, combiners, etc.
B
Behdad Esfahbod 已提交
316
 */
317

318
template <typename Lhs, typename Rhs,
319
	  hb_requires (hb_is_iterator (Lhs))>
B
Behdad Esfahbod 已提交
320
static inline auto
321
operator | (Lhs&& lhs, Rhs&& rhs) HB_AUTO_RETURN (hb_forward<Rhs> (rhs) (hb_forward<Lhs> (lhs)))
322

B
Behdad Esfahbod 已提交
323 324 325
/* hb_map(), hb_filter(), hb_reduce() */

template <typename Iter, typename Proj,
326
	 hb_requires (hb_is_iterator (Iter))>
B
Behdad Esfahbod 已提交
327
struct hb_map_iter_t :
B
Behdad Esfahbod 已提交
328
  hb_iter_t<hb_map_iter_t<Iter, Proj>,
329
	    decltype (hb_get (hb_declval (Proj), *hb_declval (Iter)))>
B
Behdad Esfahbod 已提交
330
{
331
  hb_map_iter_t (const Iter& it, Proj f_) : it (it), f (f_) {}
B
Behdad Esfahbod 已提交
332

333
  typedef decltype (hb_get (hb_declval (Proj), *hb_declval (Iter))) __item_t__;
334
  static constexpr bool is_random_access_iterator = Iter::is_random_access_iterator;
335 336
  __item_t__ __item__ () const { return hb_get (f.get (), *it); }
  __item_t__ __item_at__ (unsigned i) const { return hb_get (f.get (), it[i]); }
337
  bool __more__ () const { return bool (it); }
B
Behdad Esfahbod 已提交
338 339 340 341 342
  unsigned __len__ () const { return it.len (); }
  void __next__ () { ++it; }
  void __forward__ (unsigned n) { it += n; }
  void __prev__ () { --it; }
  void __rewind__ (unsigned n) { it -= n; }
B
Behdad Esfahbod 已提交
343
  hb_map_iter_t __end__ () const { return hb_map_iter_t (it.end (), f); }
344 345
  bool operator != (const hb_map_iter_t& o) const
  { return it != o.it || f != o.f; }
B
Behdad Esfahbod 已提交
346 347 348

  private:
  Iter it;
349
  hb_reference_wrapper<Proj> f;
B
Behdad Esfahbod 已提交
350
};
351

B
Behdad Esfahbod 已提交
352 353 354
template <typename Proj>
struct hb_map_iter_factory_t
{
355
  hb_map_iter_factory_t (Proj f) : f (f) {}
B
Behdad Esfahbod 已提交
356

357
  template <typename Iter,
358
	    hb_requires (hb_is_iterator (Iter))>
359
  hb_map_iter_t<Iter, Proj>
360
  operator () (Iter it)
361
  { return hb_map_iter_t<Iter, Proj> (it, f); }
B
Behdad Esfahbod 已提交
362 363 364 365

  private:
  Proj f;
};
B
Behdad Esfahbod 已提交
366
struct
367 368 369 370 371
{
  template <typename Proj>
  hb_map_iter_factory_t<Proj>
  operator () (Proj&& f) const
  { return hb_map_iter_factory_t<Proj> (f); }
B
Behdad Esfahbod 已提交
372 373
}
HB_FUNCOBJ (hb_map);
B
Behdad Esfahbod 已提交
374

B
Behdad Esfahbod 已提交
375
template <typename Iter, typename Pred, typename Proj,
376
	 hb_requires (hb_is_iterator (Iter))>
B
Behdad Esfahbod 已提交
377
struct hb_filter_iter_t :
378 379
  hb_iter_with_fallback_t<hb_filter_iter_t<Iter, Pred, Proj>,
			  typename Iter::item_t>
B
Behdad Esfahbod 已提交
380
{
381 382
  hb_filter_iter_t (const Iter& it_, Pred p_, Proj f_) : it (it_), p (p_), f (f_)
  { while (it && !hb_has (p.get (), hb_get (f.get (), *it))) ++it; }
B
Behdad Esfahbod 已提交
383 384

  typedef typename Iter::item_t __item_t__;
385
  static constexpr bool is_sorted_iterator = Iter::is_sorted_iterator;
B
Behdad Esfahbod 已提交
386
  __item_t__ __item__ () const { return *it; }
387
  bool __more__ () const { return bool (it); }
388
  void __next__ () { do ++it; while (it && !hb_has (p.get (), hb_get (f.get (), *it))); }
B
Behdad Esfahbod 已提交
389
  void __prev__ () { --it; }
B
Behdad Esfahbod 已提交
390
  hb_filter_iter_t __end__ () const { return hb_filter_iter_t (it.end (), p, f); }
391 392
  bool operator != (const hb_filter_iter_t& o) const
  { return it != o.it || p != o.p || f != o.f; }
B
Behdad Esfahbod 已提交
393 394 395

  private:
  Iter it;
396 397
  hb_reference_wrapper<Pred> p;
  hb_reference_wrapper<Proj> f;
B
Behdad Esfahbod 已提交
398 399 400 401
};
template <typename Pred, typename Proj>
struct hb_filter_iter_factory_t
{
402
  hb_filter_iter_factory_t (Pred p, Proj f) : p (p), f (f) {}
B
Behdad Esfahbod 已提交
403

404
  template <typename Iter,
405
	    hb_requires (hb_is_iterator (Iter))>
406
  hb_filter_iter_t<Iter, Pred, Proj>
407
  operator () (Iter it)
408
  { return hb_filter_iter_t<Iter, Pred, Proj> (it, p, f); }
B
Behdad Esfahbod 已提交
409 410 411 412 413

  private:
  Pred p;
  Proj f;
};
B
Behdad Esfahbod 已提交
414
struct
415
{
416
  template <typename Pred = decltype ((hb_identity)),
417 418
	    typename Proj = decltype ((hb_identity))>
  hb_filter_iter_factory_t<Pred, Proj>
419
  operator () (Pred&& p = hb_identity, Proj&& f = hb_identity) const
420
  { return hb_filter_iter_factory_t<Pred, Proj> (p, f); }
B
Behdad Esfahbod 已提交
421 422
}
HB_FUNCOBJ (hb_filter);
423

424
template <typename Redu, typename InitT>
E
Ebrahim Byagowi 已提交
425 426
struct hb_reduce_t
{
427
  hb_reduce_t (Redu r, InitT init_value) : r (r), init_value (init_value) {}
E
Ebrahim Byagowi 已提交
428 429

  template <typename Iter,
430
	    hb_requires (hb_is_iterator (Iter)),
431 432
	    typename AccuT = decltype (hb_declval (Redu) (hb_declval (InitT), hb_declval (typename Iter::item_t)))>
  AccuT
433
  operator () (Iter it)
E
Ebrahim Byagowi 已提交
434
  {
435
    AccuT value = init_value;
E
Ebrahim Byagowi 已提交
436
    for (; it; ++it)
437
      value = r (value, *it);
E
Ebrahim Byagowi 已提交
438 439 440 441 442
    return value;
  }

  private:
  Redu r;
443
  InitT init_value;
E
Ebrahim Byagowi 已提交
444
};
B
Behdad Esfahbod 已提交
445
struct
E
Ebrahim Byagowi 已提交
446
{
447 448 449 450
  template <typename Redu, typename InitT>
  hb_reduce_t<Redu, InitT>
  operator () (Redu&& r, InitT init_value) const
  { return hb_reduce_t<Redu, InitT> (r, init_value); }
B
Behdad Esfahbod 已提交
451 452
}
HB_FUNCOBJ (hb_reduce);
E
Ebrahim Byagowi 已提交
453 454


B
Behdad Esfahbod 已提交
455
/* hb_zip() */
456

B
Behdad Esfahbod 已提交
457
template <typename A, typename B>
458
struct hb_zip_iter_t :
B
Behdad Esfahbod 已提交
459
  hb_iter_t<hb_zip_iter_t<A, B>,
460
	    hb_pair_t<typename A::item_t, typename B::item_t>>
B
Behdad Esfahbod 已提交
461
{
462
  hb_zip_iter_t () {}
463
  hb_zip_iter_t (const A& a, const B& b) : a (a), b (b) {}
B
Behdad Esfahbod 已提交
464 465

  typedef hb_pair_t<typename A::item_t, typename B::item_t> __item_t__;
466
  static constexpr bool is_random_access_iterator =
B
Behdad Esfahbod 已提交
467 468
    A::is_random_access_iterator &&
    B::is_random_access_iterator;
469
  static constexpr bool is_sorted_iterator =
B
Behdad Esfahbod 已提交
470 471
    A::is_sorted_iterator &&
    B::is_sorted_iterator;
B
Behdad Esfahbod 已提交
472 473 474
  __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 a && b; }
475
  unsigned __len__ () const { return hb_min (a.len (), b.len ()); }
B
Behdad Esfahbod 已提交
476 477 478 479
  void __next__ () { ++a; ++b; }
  void __forward__ (unsigned n) { a += n; b += n; }
  void __prev__ () { --a; --b; }
  void __rewind__ (unsigned n) { a -= n; b -= n; }
480 481 482
  hb_zip_iter_t __end__ () const { return hb_zip_iter_t (a.end (), b.end ()); }
  bool operator != (const hb_zip_iter_t& o) const
  { return a != o.a || b != o.b; }
B
Behdad Esfahbod 已提交
483 484 485 486 487

  private:
  A a;
  B b;
};
B
Behdad Esfahbod 已提交
488
struct
489 490
{
  template <typename A, typename B,
491
	    hb_requires (hb_is_iterable (A) && hb_is_iterable (B))>
492
  hb_zip_iter_t<hb_iter_type<A>, hb_iter_type<B>>
493
  operator () (A& a, B &b) const
494
  { return hb_zip_iter_t<hb_iter_type<A>, hb_iter_type<B>> (hb_iter (a), hb_iter (b)); }
B
Behdad Esfahbod 已提交
495 496
}
HB_FUNCOBJ (hb_zip);
B
Behdad Esfahbod 已提交
497

498 499 500
/* hb_enumerate */

template <typename Iter,
501
	 hb_requires (hb_is_iterator (Iter))>
502 503
struct hb_enumerate_iter_t :
  hb_iter_t<hb_enumerate_iter_t<Iter>,
504
	    hb_pair_t<unsigned, typename Iter::item_t>>
505 506 507 508 509 510 511 512 513 514 515 516 517 518
{
  hb_enumerate_iter_t (const Iter& it) : i (0), it (it) {}

  typedef hb_pair_t<unsigned, typename Iter::item_t> __item_t__;
  static constexpr bool is_random_access_iterator = Iter::is_random_access_iterator;
  static constexpr bool is_sorted_iterator = true;
  __item_t__ __item__ () const { return __item_t__ (+i, *it); }
  __item_t__ __item_at__ (unsigned j) const { return __item_t__ (i + j, it[j]); }
  bool __more__ () const { return bool (it); }
  unsigned __len__ () const { return it.len (); }
  void __next__ () { ++i; ++it; }
  void __forward__ (unsigned n) { i += n; it += n; }
  void __prev__ () { --i; --it; }
  void __rewind__ (unsigned n) { i -= n; it -= n; }
519 520 521 522 523 524 525 526 527 528 529
  hb_enumerate_iter_t __end__ () const
  {
    if (is_random_access_iterator)
      return *this + this->len ();
    /* Above expression loops twice. Following loops once. */
    auto it = *this;
    while (it) ++it;
    return it;
  }
  bool operator != (const hb_enumerate_iter_t& o) const
  { return i != o.i || it != o.it; }
530 531 532 533 534

  private:
  unsigned i;
  Iter it;
};
B
Behdad Esfahbod 已提交
535
struct
536 537
{
  template <typename Iterable,
538
	    hb_requires (hb_is_iterable (Iterable))>
539
  hb_enumerate_iter_t<hb_iter_type<Iterable>>
540
  operator () (Iterable&& it) const
541
  { return hb_enumerate_iter_t<hb_iter_type<Iterable>> (hb_iter (it)); }
B
Behdad Esfahbod 已提交
542 543
}
HB_FUNCOBJ (hb_enumerate);
544

B
Behdad Esfahbod 已提交
545 546 547 548 549
/* hb_apply() */

template <typename Appl>
struct hb_apply_t
{
550
  hb_apply_t (Appl a) : a (a) {}
B
Behdad Esfahbod 已提交
551 552

  template <typename Iter,
553
	    hb_requires (hb_is_iterator (Iter))>
554
  void operator () (Iter it)
B
Behdad Esfahbod 已提交
555 556
  {
    for (; it; ++it)
B
Behdad Esfahbod 已提交
557
      (void) hb_invoke (a, *it);
B
Behdad Esfahbod 已提交
558 559 560 561 562
  }

  private:
  Appl a;
};
B
Behdad Esfahbod 已提交
563
struct
B
Behdad Esfahbod 已提交
564 565 566 567 568 569 570 571
{
  template <typename Appl> hb_apply_t<Appl>
  operator () (Appl&& a) const
  { return hb_apply_t<Appl> (a); }

  template <typename Appl> hb_apply_t<Appl&>
  operator () (Appl *a) const
  { return hb_apply_t<Appl&> (*a); }
B
Behdad Esfahbod 已提交
572 573
}
HB_FUNCOBJ (hb_apply);
B
Behdad Esfahbod 已提交
574

B
Behdad Esfahbod 已提交
575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625
/* hb_iota() */

template <typename T, typename S>
struct hb_iota_iter_t :
  hb_iter_t<hb_iota_iter_t<T, S>, T>
{
  hb_iota_iter_t (T start, T end, S step) : v (start), end (end_for (start, end, step)), step (step) {}

  typedef T __item_t__;
  static constexpr bool is_random_access_iterator = true;
  static constexpr bool is_sorted_iterator = true;
  __item_t__ __item__ () const { return v; }
  __item_t__ __item_at__ (unsigned j) const { return v + j * step; }
  bool __more__ () const { return v != end; }
  unsigned __len__ () const { return (end - v) / step; }
  void __next__ () { v += step; }
  void __forward__ (unsigned n) { v += n * step; }
  void __prev__ () { v -= step; }
  void __rewind__ (unsigned n) { v -= n * step; }
  hb_iota_iter_t __end__ () const { hb_iota_iter_t (end, end, step); }
  bool operator != (const hb_iota_iter_t& o) const
  { return v != o.v || end != o.end || step != o.step; }

  private:
  static inline T end_for (T start, T end, S step)
  {
    auto res = (end - start) % step;
    if (!res)
      return end;
    end += step - res;
    return end;
  }

  private:
  T v;
  T end;
  S step;
};
struct
{
  template <typename T = unsigned> hb_iota_iter_t<T, unsigned>
  operator () (T end = (unsigned) -1) const
  { return hb_iota_iter_t<T, unsigned> (0, end, 1u); }

  template <typename T, typename S = unsigned> hb_iota_iter_t<T, S>
  operator () (T start, T end, S&& step = 1u) const
  { return hb_iota_iter_t<T, S> (start, end, step); }
}
HB_FUNCOBJ (hb_iota);


B
Behdad Esfahbod 已提交
626 627 628 629 630
/* hb_sink() */

template <typename Sink>
struct hb_sink_t
{
631
  hb_sink_t (Sink s) : s (s) {}
B
Behdad Esfahbod 已提交
632

633
  template <typename Iter,
634
	    hb_requires (hb_is_iterator (Iter))>
635
  void operator () (Iter it)
B
Behdad Esfahbod 已提交
636
  {
637
    for (; it; ++it)
B
Behdad Esfahbod 已提交
638 639 640 641 642 643
      s << *it;
  }

  private:
  Sink s;
};
B
Behdad Esfahbod 已提交
644
struct
645 646 647 648
{
  template <typename Sink> hb_sink_t<Sink>
  operator () (Sink&& s) const
  { return hb_sink_t<Sink> (s); }
649 650 651 652

  template <typename Sink> hb_sink_t<Sink&>
  operator () (Sink *s) const
  { return hb_sink_t<Sink&> (*s); }
B
Behdad Esfahbod 已提交
653 654
}
HB_FUNCOBJ (hb_sink);
B
Behdad Esfahbod 已提交
655

B
Behdad Esfahbod 已提交
656 657
/* hb-drain: hb_sink to void / blackhole / /dev/null. */

B
Behdad Esfahbod 已提交
658
struct
B
Behdad Esfahbod 已提交
659 660
{
  template <typename Iter,
661 662
	    hb_requires (hb_is_iterator (Iter))>
  void operator () (Iter it) const
B
Behdad Esfahbod 已提交
663 664 665 666
  {
    for (; it; ++it)
      (void) *it;
  }
B
Behdad Esfahbod 已提交
667 668
}
HB_FUNCOBJ (hb_drain);
B
Behdad Esfahbod 已提交
669

B
Behdad Esfahbod 已提交
670 671 672 673 674
/* hb_unzip(): unzip and sink to two sinks. */

template <typename Sink1, typename Sink2>
struct hb_unzip_t
{
675
  hb_unzip_t (Sink1 s1, Sink2 s2) : s1 (s1), s2 (s2) {}
B
Behdad Esfahbod 已提交
676 677

  template <typename Iter,
678
	    hb_requires (hb_is_iterator (Iter))>
679
  void operator () (Iter it)
B
Behdad Esfahbod 已提交
680 681 682 683 684 685 686 687 688 689 690 691 692
  {
    for (; it; ++it)
    {
      const auto &v = *it;
      s1 << v.first;
      s2 << v.second;
    }
  }

  private:
  Sink1 s1;
  Sink2 s2;
};
B
Behdad Esfahbod 已提交
693
struct
B
Behdad Esfahbod 已提交
694 695 696 697 698 699 700 701
{
  template <typename Sink1, typename Sink2> hb_unzip_t<Sink1, Sink2>
  operator () (Sink1&& s1, Sink2&& s2) const
  { return hb_unzip_t<Sink1, Sink2> (s1, s2); }

  template <typename Sink1, typename Sink2> hb_unzip_t<Sink1&, Sink2&>
  operator () (Sink1 *s1, Sink2 *s2) const
  { return hb_unzip_t<Sink1&, Sink2&> (*s1, *s2); }
B
Behdad Esfahbod 已提交
702 703
}
HB_FUNCOBJ (hb_unzip);
B
Behdad Esfahbod 已提交
704 705


706 707
/* hb-all, hb-any, hb-none. */

B
Behdad Esfahbod 已提交
708
struct
709 710
{
  template <typename Iterable,
711
	    typename Pred = decltype ((hb_identity)),
712
	    typename Proj = decltype ((hb_identity)),
713
	    hb_requires (hb_is_iterable (Iterable))>
714
  bool operator () (Iterable&& c,
715
		    Pred&& p = hb_identity,
716
		    Proj&& f = hb_identity) const
717 718
  {
    for (auto it = hb_iter (c); it; ++it)
B
Behdad Esfahbod 已提交
719
      if (!hb_match (hb_forward<Pred> (p), hb_get (hb_forward<Proj> (f), *it)))
720 721 722
	return false;
    return true;
  }
B
Behdad Esfahbod 已提交
723 724
}
HB_FUNCOBJ (hb_all);
B
Behdad Esfahbod 已提交
725
struct
726 727
{
  template <typename Iterable,
728
	    typename Pred = decltype ((hb_identity)),
729
	    typename Proj = decltype ((hb_identity)),
730
	    hb_requires (hb_is_iterable (Iterable))>
731
  bool operator () (Iterable&& c,
732
		    Pred&& p = hb_identity,
733
		    Proj&& f = hb_identity) const
734 735
  {
    for (auto it = hb_iter (c); it; ++it)
B
Behdad Esfahbod 已提交
736
      if (hb_match (hb_forward<Pred> (p), hb_get (hb_forward<Proj> (f), *it)))
737 738 739
	return true;
    return false;
  }
B
Behdad Esfahbod 已提交
740 741
}
HB_FUNCOBJ (hb_any);
B
Behdad Esfahbod 已提交
742
struct
743 744
{
  template <typename Iterable,
745
	    typename Pred = decltype ((hb_identity)),
746
	    typename Proj = decltype ((hb_identity)),
747
	    hb_requires (hb_is_iterable (Iterable))>
748
  bool operator () (Iterable&& c,
749
		    Pred&& p = hb_identity,
750
		    Proj&& f = hb_identity) const
751 752
  {
    for (auto it = hb_iter (c); it; ++it)
B
Behdad Esfahbod 已提交
753
      if (hb_match (hb_forward<Pred> (p), hb_get (hb_forward<Proj> (f), *it)))
754 755 756
	return false;
    return true;
  }
B
Behdad Esfahbod 已提交
757 758
}
HB_FUNCOBJ (hb_none);
759

B
Behdad Esfahbod 已提交
760 761 762 763 764
/*
 * Algorithms operating on iterators.
 */

template <typename C, typename V,
765
	  hb_requires (hb_is_iterable (C))>
B
Behdad Esfahbod 已提交
766 767 768
inline void
hb_fill (C& c, const V &v)
{
B
Behdad Esfahbod 已提交
769
  for (auto i = hb_iter (c); i; i++)
B
Behdad Esfahbod 已提交
770
    *i = v;
B
Behdad Esfahbod 已提交
771 772
}

773 774
template <typename S, typename D>
inline void
B
Behdad Esfahbod 已提交
775
hb_copy (S&& is, D&& id)
B
Behdad Esfahbod 已提交
776
{
B
Behdad Esfahbod 已提交
777
  hb_iter (is) | hb_sink (id);
B
Behdad Esfahbod 已提交
778 779 780
}


781
#endif /* HB_ITER_HH */