tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

hb-iter.hh (32141B)


      1 /*
      2 * Copyright © 2018  Google, Inc.
      3 * Copyright © 2019  Facebook, Inc.
      4 *
      5 *  This is part of HarfBuzz, a text shaping library.
      6 *
      7 * Permission is hereby granted, without written agreement and without
      8 * license or royalty fees, to use, copy, modify, and distribute this
      9 * software and its documentation for any purpose, provided that the
     10 * above copyright notice and the following two paragraphs appear in
     11 * all copies of this software.
     12 *
     13 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
     14 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
     15 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
     16 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
     17 * DAMAGE.
     18 *
     19 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
     20 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
     21 * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
     22 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
     23 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
     24 *
     25 * Google Author(s): Behdad Esfahbod
     26 * Facebook Author(s): Behdad Esfahbod
     27 */
     28 
     29 #ifndef HB_ITER_HH
     30 #define HB_ITER_HH
     31 
     32 #include "hb.hh"
     33 #include "hb-algs.hh"
     34 #include "hb-meta.hh"
     35 
     36 
     37 /* Unified iterator object.
     38 *
     39 * The goal of this template is to make the same iterator interface
     40 * 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 * If iterator implementation implements operator!=, then it can be
     47 * used in range-based for loop.  That already happens if the iterator
     48 * is random-access.  Otherwise, the range-based for loop incurs
     49 * one traversal to find end(), which can be avoided if written
     50 * as a while-style for loop, or if iterator implements a faster
     51 * __end__() method. */
     52 
     53 /*
     54 * Base classes for iterators.
     55 */
     56 
     57 /* Base class for all iterators. */
     58 template <typename iter_t, typename Item = typename iter_t::__item_t__>
     59 struct hb_iter_t
     60 {
     61  typedef Item item_t;
     62  constexpr unsigned get_item_size () const { return hb_static_size (Item); }
     63  static constexpr bool is_iterator = true;
     64  static constexpr bool is_random_access_iterator = false;
     65  static constexpr bool is_sorted_iterator = false;
     66  static constexpr bool has_fast_len = false; // Should be checked in combination with is_random_access_iterator.
     67 
     68  private:
     69  /* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */
     70  const iter_t* thiz () const { return static_cast<const iter_t *> (this); }
     71 iter_t* thiz ()       { return static_cast<      iter_t *> (this); }
     72  public:
     73 
     74  /* Operators. */
     75  iter_t iter () const { return *thiz(); }
     76  iter_t operator + () const { return *thiz(); }
     77  iter_t _begin () const { return *thiz(); }
     78  iter_t begin () const { return _begin (); }
     79  iter_t _end () const { return thiz()->__end__ (); }
     80  iter_t end () const { return _end (); }
     81  explicit operator bool () const { return thiz()->__more__ (); }
     82  unsigned len () const { return thiz()->__len__ (); }
     83  /* The following can only be enabled if item_t is reference type.  Otherwise
     84   * it will be returning pointer to temporary rvalue. */
     85  template <typename T = item_t,
     86     hb_enable_if (std::is_reference<T>::value)>
     87  hb_remove_reference<item_t>* operator -> () const { return std::addressof (**thiz()); }
     88  item_t operator * () const { return thiz()->__item__ (); }
     89  item_t operator * () { return thiz()->__item__ (); }
     90  item_t operator [] (unsigned i) const { return thiz()->__item_at__ (i); }
     91  item_t operator [] (unsigned i) { return thiz()->__item_at__ (i); }
     92  iter_t& operator += (unsigned count) &  { thiz()->__forward__ (count); return *thiz(); }
     93  iter_t  operator += (unsigned count) && { thiz()->__forward__ (count); return *thiz(); }
     94  iter_t& operator ++ () &  { thiz()->__next__ (); return *thiz(); }
     95  iter_t  operator ++ () && { thiz()->__next__ (); return *thiz(); }
     96  iter_t& operator -= (unsigned count) &  { thiz()->__rewind__ (count); return *thiz(); }
     97  iter_t  operator -= (unsigned count) && { thiz()->__rewind__ (count); return *thiz(); }
     98  iter_t& operator -- () &  { thiz()->__prev__ (); return *thiz(); }
     99  iter_t  operator -- () && { thiz()->__prev__ (); return *thiz(); }
    100  iter_t operator + (unsigned count) const { auto c = thiz()->iter (); c += count; return c; }
    101  friend iter_t operator + (unsigned count, const iter_t &it) { return it + count; }
    102  iter_t operator ++ (int) { iter_t c (*thiz()); ++*thiz(); return c; }
    103  iter_t operator - (unsigned count) const { auto c = thiz()->iter (); c -= count; return c; }
    104  iter_t operator -- (int) { iter_t c (*thiz()); --*thiz(); return c; }
    105  template <typename T>
    106  iter_t& operator >> (T &v) &  { v = **thiz(); ++*thiz(); return *thiz(); }
    107  template <typename T>
    108  iter_t  operator >> (T &v) && { v = **thiz(); ++*thiz(); return *thiz(); }
    109  template <typename T>
    110  iter_t& operator << (const T v) &  { **thiz() = v; ++*thiz(); return *thiz(); }
    111  template <typename T>
    112  iter_t  operator << (const T v) && { **thiz() = v; ++*thiz(); return *thiz(); }
    113 
    114  protected:
    115  hb_iter_t () = default;
    116  hb_iter_t (const hb_iter_t &o HB_UNUSED) = default;
    117  hb_iter_t (hb_iter_t &&o HB_UNUSED) = default;
    118  hb_iter_t& operator = (const hb_iter_t &o HB_UNUSED) = default;
    119  hb_iter_t& operator = (hb_iter_t &&o HB_UNUSED) = default;
    120 };
    121 
    122 #define HB_ITER_USING(Name) \
    123  using item_t = typename Name::item_t; \
    124  using Name::_begin; \
    125  using Name::begin; \
    126  using Name::_end; \
    127  using Name::end; \
    128  using Name::get_item_size; \
    129  using Name::is_iterator; \
    130  using Name::iter; \
    131  using Name::operator bool; \
    132  using Name::len; \
    133  using Name::operator ->; \
    134  using Name::operator *; \
    135  using Name::operator []; \
    136  using Name::operator +=; \
    137  using Name::operator ++; \
    138  using Name::operator -=; \
    139  using Name::operator --; \
    140  using Name::operator +; \
    141  using Name::operator -; \
    142  using Name::operator >>; \
    143  using Name::operator <<; \
    144  static_assert (true, "")
    145 
    146 /* Returns iterator / item type of a type. */
    147 template <typename Iterable>
    148 using hb_iter_type = decltype (hb_deref (hb_declval (Iterable)).iter ());
    149 template <typename Iterable>
    150 using hb_item_type = decltype (*hb_deref (hb_declval (Iterable)).iter ());
    151 
    152 
    153 template <typename> struct hb_array_t;
    154 template <typename> struct hb_sorted_array_t;
    155 
    156 struct
    157 {
    158  template <typename T> hb_iter_type<T>
    159  operator () (T&& c) const
    160  { return hb_deref (std::forward<T> (c)).iter (); }
    161 
    162  /* Specialization for C arrays. */
    163 
    164  template <typename Type> inline hb_array_t<Type>
    165  operator () (Type *array, unsigned int length) const
    166  { return hb_array_t<Type> (array, length); }
    167 
    168  template <typename Type, unsigned int length> hb_array_t<Type>
    169  operator () (Type (&array)[length]) const
    170  { return hb_array_t<Type> (array, length); }
    171 
    172 }
    173 HB_FUNCOBJ (hb_iter);
    174 struct
    175 {
    176  template <typename T> auto
    177  impl (T&& c, hb_priority<1>) const HB_RETURN (unsigned, c.len ())
    178 
    179  template <typename T> auto
    180  impl (T&& c, hb_priority<0>) const HB_RETURN (unsigned, c.len)
    181 
    182  public:
    183 
    184  template <typename T> auto
    185  operator () (T&& c) const HB_RETURN (unsigned, impl (std::forward<T> (c), hb_prioritize))
    186 }
    187 HB_FUNCOBJ (hb_len);
    188 
    189 /* Mixin to fill in what the subclass doesn't provide. */
    190 template <typename iter_t, typename item_t = typename iter_t::__item_t__>
    191 struct hb_iter_fallback_mixin_t
    192 {
    193  private:
    194  /* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */
    195  const iter_t* thiz () const { return static_cast<const iter_t *> (this); }
    196 iter_t* thiz ()       { return static_cast<      iter_t *> (this); }
    197  public:
    198 
    199  /* Access: Implement __item__(), or __item_at__() if random-access. */
    200  item_t __item__ () const { return (*thiz())[0]; }
    201  item_t __item_at__ (unsigned i) const { return *(*thiz() + i); }
    202 
    203  /* Termination: Implement __more__(), or __len__() if random-access. */
    204  bool __more__ () const { return bool (thiz()->len ()); }
    205  unsigned __len__ () const
    206  { iter_t c (*thiz()); unsigned l = 0; while (c) { c++; l++; } return l; }
    207 
    208  /* Advancing: Implement __next__(), or __forward__() if random-access. */
    209  void __next__ () { *thiz() += 1; }
    210  void __forward__ (unsigned n) { while (*thiz() && n--) ++*thiz(); }
    211 
    212  /* Rewinding: Implement __prev__() or __rewind__() if bidirectional. */
    213  void __prev__ () { *thiz() -= 1; }
    214  void __rewind__ (unsigned n) { while (*thiz() && n--) --*thiz(); }
    215 
    216  /* Range-based for: Implement __end__() if can be done faster,
    217   * and operator!=. */
    218  iter_t __end__ () const
    219  {
    220    if (thiz()->is_random_access_iterator)
    221      return *thiz() + thiz()->len ();
    222    /* Above expression loops twice. Following loops once. */
    223    auto it = *thiz();
    224    while (it) ++it;
    225    return it;
    226  }
    227 
    228  protected:
    229  hb_iter_fallback_mixin_t () = default;
    230  hb_iter_fallback_mixin_t (const hb_iter_fallback_mixin_t &o HB_UNUSED) = default;
    231  hb_iter_fallback_mixin_t (hb_iter_fallback_mixin_t &&o HB_UNUSED) = default;
    232  hb_iter_fallback_mixin_t& operator = (const hb_iter_fallback_mixin_t &o HB_UNUSED) = default;
    233  hb_iter_fallback_mixin_t& operator = (hb_iter_fallback_mixin_t &&o HB_UNUSED) = default;
    234 };
    235 
    236 template <typename iter_t, typename item_t = typename iter_t::__item_t__>
    237 struct hb_iter_with_fallback_t :
    238  hb_iter_t<iter_t, item_t>,
    239  hb_iter_fallback_mixin_t<iter_t, item_t>
    240 {
    241  protected:
    242  hb_iter_with_fallback_t () = default;
    243  hb_iter_with_fallback_t (const hb_iter_with_fallback_t &o HB_UNUSED) = default;
    244  hb_iter_with_fallback_t (hb_iter_with_fallback_t &&o HB_UNUSED) = default;
    245  hb_iter_with_fallback_t& operator = (const hb_iter_with_fallback_t &o HB_UNUSED) = default;
    246  hb_iter_with_fallback_t& operator = (hb_iter_with_fallback_t &&o HB_UNUSED) = default;
    247 };
    248 
    249 /*
    250 * Meta-programming predicates.
    251 */
    252 
    253 /* hb_is_iterator() / hb_is_iterator_of() */
    254 
    255 template<typename Iter, typename Item>
    256 struct hb_is_iterator_of
    257 {
    258  template <typename Item2 = Item>
    259  static hb_true_type impl (hb_priority<2>, hb_iter_t<Iter, hb_type_identity<Item2>> *);
    260  static hb_false_type impl (hb_priority<0>, const void *);
    261 
    262  public:
    263  static constexpr bool value = decltype (impl (hb_prioritize, hb_declval (Iter*)))::value;
    264 };
    265 #define hb_is_iterator_of(Iter, Item) hb_is_iterator_of<Iter, Item>::value
    266 #define hb_is_iterator(Iter) hb_is_iterator_of (Iter, typename Iter::item_t)
    267 #define hb_is_sorted_iterator_of(Iter, Item) (hb_is_iterator_of<Iter, Item>::value && Iter::is_sorted_iterator)
    268 #define hb_is_sorted_iterator(Iter) hb_is_sorted_iterator_of (Iter, typename Iter::item_t)
    269 
    270 /* hb_is_iterable() */
    271 
    272 template <typename T>
    273 struct hb_is_iterable
    274 {
    275  private:
    276 
    277  template <typename U>
    278  static auto impl (hb_priority<1>) -> decltype (hb_declval (U).iter (), hb_true_type ());
    279 
    280  template <typename>
    281  static hb_false_type impl (hb_priority<0>);
    282 
    283  public:
    284  static constexpr bool value = decltype (impl<T> (hb_prioritize))::value;
    285 };
    286 #define hb_is_iterable(Iterable) hb_is_iterable<Iterable>::value
    287 
    288 /* hb_is_source_of() / hb_is_sink_of() */
    289 
    290 template<typename Iter, typename Item>
    291 struct hb_is_source_of
    292 {
    293  private:
    294  template <typename Iter2 = Iter,
    295     hb_enable_if (hb_is_convertible (typename Iter2::item_t, hb_add_lvalue_reference<const Item>))>
    296  static hb_true_type impl (hb_priority<2>);
    297  template <typename Iter2 = Iter>
    298  static auto impl (hb_priority<1>) -> decltype (hb_declval (Iter2) >> hb_declval (Item &), hb_true_type ());
    299  static hb_false_type impl (hb_priority<0>);
    300 
    301  public:
    302  static constexpr bool value = decltype (impl (hb_prioritize))::value;
    303 };
    304 #define hb_is_source_of(Iter, Item) hb_is_source_of<Iter, Item>::value
    305 
    306 template<typename Iter, typename Item>
    307 struct hb_is_sink_of
    308 {
    309  private:
    310  template <typename Iter2 = Iter,
    311     hb_enable_if (hb_is_convertible (typename Iter2::item_t, hb_add_lvalue_reference<Item>))>
    312  static hb_true_type impl (hb_priority<2>);
    313  template <typename Iter2 = Iter>
    314  static auto impl (hb_priority<1>) -> decltype (hb_declval (Iter2) << hb_declval (Item), hb_true_type ());
    315  static hb_false_type impl (hb_priority<0>);
    316 
    317  public:
    318  static constexpr bool value = decltype (impl (hb_prioritize))::value;
    319 };
    320 #define hb_is_sink_of(Iter, Item) hb_is_sink_of<Iter, Item>::value
    321 
    322 /* This is commonly used, so define: */
    323 #define hb_is_sorted_source_of(Iter, Item) \
    324 (hb_is_source_of(Iter, Item) && Iter::is_sorted_iterator)
    325 
    326 
    327 struct
    328 {
    329  template <typename Iterable,
    330     hb_requires (hb_is_iterable (Iterable))>
    331  unsigned operator () (const Iterable &_) const { return hb_len (hb_iter (_)); }
    332 
    333  unsigned operator () (unsigned _) const { return _; }
    334 }
    335 HB_FUNCOBJ (hb_len_of);
    336 
    337 /* Range-based 'for' for iterables. */
    338 
    339 template <typename Iterable,
    340   hb_requires (hb_is_iterable (Iterable))>
    341 static inline auto begin (Iterable&& iterable) HB_AUTO_RETURN (hb_iter (iterable).begin ())
    342 
    343 template <typename Iterable,
    344   hb_requires (hb_is_iterable (Iterable))>
    345 static inline auto end (Iterable&& iterable) HB_AUTO_RETURN (hb_iter (iterable).end ())
    346 
    347 /* begin()/end() are NOT looked up non-ADL.  So each namespace must declare them.
    348 * Do it for namespace OT. */
    349 namespace OT {
    350 
    351 template <typename Iterable,
    352   hb_requires (hb_is_iterable (Iterable))>
    353 static inline auto begin (Iterable&& iterable) HB_AUTO_RETURN (hb_iter (iterable).begin ())
    354 
    355 template <typename Iterable,
    356   hb_requires (hb_is_iterable (Iterable))>
    357 static inline auto end (Iterable&& iterable) HB_AUTO_RETURN (hb_iter (iterable).end ())
    358 
    359 }
    360 
    361 
    362 /*
    363 * Adaptors, combiners, etc.
    364 */
    365 
    366 template <typename Lhs, typename Rhs,
    367   hb_requires (hb_is_iterator (Lhs))>
    368 static inline auto
    369 operator | (Lhs&& lhs, Rhs&& rhs) HB_AUTO_RETURN (std::forward<Rhs> (rhs) (std::forward<Lhs> (lhs)))
    370 
    371 /* hb_map(), hb_filter(), hb_reduce() */
    372 
    373 enum  class hb_function_sortedness_t {
    374  NOT_SORTED,
    375  RETAINS_SORTING,
    376  SORTED,
    377 };
    378 
    379 template <typename Iter, typename Proj, hb_function_sortedness_t Sorted,
    380  hb_requires (hb_is_iterator (Iter))>
    381 struct hb_map_iter_t :
    382  hb_iter_t<hb_map_iter_t<Iter, Proj, Sorted>,
    383     decltype (hb_get (hb_declval (Proj), *hb_declval (Iter)))>
    384 {
    385  hb_map_iter_t (const Iter& it, Proj f_) : it (it), f (f_) {}
    386 
    387  typedef decltype (hb_get (hb_declval (Proj), *hb_declval (Iter))) __item_t__;
    388  static constexpr bool is_random_access_iterator = Iter::is_random_access_iterator;
    389  static constexpr bool is_sorted_iterator =
    390    Sorted == hb_function_sortedness_t::SORTED ? true :
    391    Sorted == hb_function_sortedness_t::RETAINS_SORTING ? Iter::is_sorted_iterator :
    392    false;
    393  __item_t__ __item__ () const { return hb_get (f.get (), *it); }
    394  __item_t__ __item_at__ (unsigned i) const { return hb_get (f.get (), it[i]); }
    395  bool __more__ () const { return bool (it); }
    396  unsigned __len__ () const { return it.len (); }
    397  void __next__ () { ++it; }
    398  void __forward__ (unsigned n) { it += n; }
    399  void __prev__ () { --it; }
    400  void __rewind__ (unsigned n) { it -= n; }
    401  hb_map_iter_t __end__ () const { return hb_map_iter_t (it._end (), f); }
    402  bool operator != (const hb_map_iter_t& o) const
    403  { return it != o.it; }
    404 
    405  private:
    406  Iter it;
    407  mutable hb_reference_wrapper<Proj> f;
    408 };
    409 
    410 template <typename Proj, hb_function_sortedness_t Sorted>
    411 struct hb_map_iter_factory_t
    412 {
    413  hb_map_iter_factory_t (Proj f) : f (f) {}
    414 
    415  template <typename Iter,
    416     hb_requires (hb_is_iterator (Iter))>
    417  hb_map_iter_t<Iter, Proj, Sorted>
    418  operator () (Iter it)
    419  { return hb_map_iter_t<Iter, Proj, Sorted> (it, f); }
    420 
    421  private:
    422  Proj f;
    423 };
    424 struct
    425 {
    426  template <typename Proj>
    427  hb_map_iter_factory_t<Proj, hb_function_sortedness_t::NOT_SORTED>
    428  operator () (Proj&& f) const
    429  { return hb_map_iter_factory_t<Proj, hb_function_sortedness_t::NOT_SORTED> (f); }
    430 }
    431 HB_FUNCOBJ (hb_map);
    432 struct
    433 {
    434  template <typename Proj>
    435  hb_map_iter_factory_t<Proj, hb_function_sortedness_t::RETAINS_SORTING>
    436  operator () (Proj&& f) const
    437  { return hb_map_iter_factory_t<Proj, hb_function_sortedness_t::RETAINS_SORTING> (f); }
    438 }
    439 HB_FUNCOBJ (hb_map_retains_sorting);
    440 struct
    441 {
    442  template <typename Proj>
    443  hb_map_iter_factory_t<Proj, hb_function_sortedness_t::SORTED>
    444  operator () (Proj&& f) const
    445  { return hb_map_iter_factory_t<Proj, hb_function_sortedness_t::SORTED> (f); }
    446 }
    447 HB_FUNCOBJ (hb_map_sorted);
    448 
    449 template <typename Iter, typename Pred, typename Proj,
    450  hb_requires (hb_is_iterator (Iter))>
    451 struct hb_filter_iter_t :
    452  hb_iter_with_fallback_t<hb_filter_iter_t<Iter, Pred, Proj>,
    453 		  typename Iter::item_t>
    454 {
    455  hb_filter_iter_t (const Iter& it_, Pred p_, Proj f_) : it (it_), p (p_), f (f_)
    456  { while (it && !hb_has (p.get (), hb_get (f.get (), *it))) ++it; }
    457 
    458  typedef typename Iter::item_t __item_t__;
    459  static constexpr bool is_sorted_iterator = Iter::is_sorted_iterator;
    460  __item_t__ __item__ () const { return *it; }
    461  bool __more__ () const { return bool (it); }
    462  void __next__ () { do ++it; while (it && !hb_has (p.get (), hb_get (f.get (), *it))); }
    463  void __prev__ () { do --it; while (it && !hb_has (p.get (), hb_get (f.get (), *it))); }
    464  hb_filter_iter_t __end__ () const { return hb_filter_iter_t (it._end (), p, f); }
    465  bool operator != (const hb_filter_iter_t& o) const
    466  { return it != o.it; }
    467 
    468  private:
    469  Iter it;
    470  mutable hb_reference_wrapper<Pred> p;
    471  mutable hb_reference_wrapper<Proj> f;
    472 };
    473 template <typename Pred, typename Proj>
    474 struct hb_filter_iter_factory_t
    475 {
    476  hb_filter_iter_factory_t (Pred p, Proj f) : p (p), f (f) {}
    477 
    478  template <typename Iter,
    479     hb_requires (hb_is_iterator (Iter))>
    480  hb_filter_iter_t<Iter, Pred, Proj>
    481  operator () (Iter it)
    482  { return hb_filter_iter_t<Iter, Pred, Proj> (it, p, f); }
    483 
    484  private:
    485  Pred p;
    486  Proj f;
    487 };
    488 struct
    489 {
    490  template <typename Pred = decltype ((hb_identity)),
    491     typename Proj = decltype ((hb_identity))>
    492  hb_filter_iter_factory_t<Pred, Proj>
    493  operator () (Pred&& p = hb_identity, Proj&& f = hb_identity) const
    494  { return hb_filter_iter_factory_t<Pred, Proj> (p, f); }
    495 }
    496 HB_FUNCOBJ (hb_filter);
    497 
    498 template <typename Redu, typename InitT>
    499 struct hb_reduce_t
    500 {
    501  hb_reduce_t (Redu r, InitT init_value) : r (r), init_value (init_value) {}
    502 
    503  template <typename Iter,
    504     hb_requires (hb_is_iterator (Iter)),
    505     typename AccuT = hb_decay<decltype (hb_declval (Redu) (hb_declval (InitT), hb_declval (typename Iter::item_t)))>>
    506  AccuT
    507  operator () (Iter it)
    508  {
    509    AccuT value = init_value;
    510    for (; it; ++it)
    511      value = r (value, *it);
    512    return value;
    513  }
    514 
    515  private:
    516  Redu r;
    517  InitT init_value;
    518 };
    519 struct
    520 {
    521  template <typename Redu, typename InitT>
    522  hb_reduce_t<Redu, InitT>
    523  operator () (Redu&& r, InitT init_value) const
    524  { return hb_reduce_t<Redu, InitT> (r, init_value); }
    525 }
    526 HB_FUNCOBJ (hb_reduce);
    527 
    528 
    529 /* hb_zip() */
    530 
    531 template <typename A, typename B>
    532 struct hb_zip_iter_t :
    533  hb_iter_t<hb_zip_iter_t<A, B>,
    534     hb_pair_t<typename A::item_t, typename B::item_t>>
    535 {
    536  hb_zip_iter_t () {}
    537  hb_zip_iter_t (const A& a, const B& b) : a (a), b (b) {}
    538 
    539  typedef hb_pair_t<typename A::item_t, typename B::item_t> __item_t__;
    540  static constexpr bool is_random_access_iterator =
    541    A::is_random_access_iterator &&
    542    B::is_random_access_iterator;
    543  /* Note.  The following categorization is only valid if A is strictly sorted,
    544   * ie. does NOT have duplicates.  Previously I tried to categorize sortedness
    545   * more granularly, see commits:
    546   *
    547   *   513762849a683914fc266a17ddf38f133cccf072
    548   *   4d3cf2adb669c345cc43832d11689271995e160a
    549   *
    550   * However, that was not enough, since hb_sorted_array_t, hb_sorted_vector_t,
    551   * SortedArrayOf, etc all needed to be updated to add more variants.  At that
    552   * point I saw it not worth the effort, and instead we now deem all sorted
    553   * collections as essentially strictly-sorted for the purposes of zip.
    554   *
    555   * The above assumption is not as bad as it sounds.  Our "sorted" comes with
    556   * no guarantees.  It's just a contract, put in place to help you remember,
    557   * and think about, whether an iterator you receive is expected to be
    558   * sorted or not.  As such, it's not perfect by definition, and should not
    559   * be treated so.  The inaccuracy here just errs in the direction of being
    560   * more permissive, so your code compiles instead of erring on the side of
    561   * marking your zipped iterator unsorted in which case your code won't
    562   * compile.
    563   *
    564   * This semantical limitation does NOT affect logic in any other place I
    565   * know of as of this writing.
    566   */
    567  static constexpr bool is_sorted_iterator = A::is_sorted_iterator;
    568 
    569  __item_t__ __item__ () const { return __item_t__ (*a, *b); }
    570  __item_t__ __item_at__ (unsigned i) const { return __item_t__ (a[i], b[i]); }
    571  bool __more__ () const { return bool (a) && bool (b); }
    572  unsigned __len__ () const { return hb_min (a.len (), b.len ()); }
    573  void __next__ () { ++a; ++b; }
    574  void __forward__ (unsigned n) { a += n; b += n; }
    575  void __prev__ () { --a; --b; }
    576  void __rewind__ (unsigned n) { a -= n; b -= n; }
    577  hb_zip_iter_t __end__ () const { return hb_zip_iter_t (a._end (), b._end ()); }
    578  /* Note, we should stop if ANY of the iters reaches end.  As such two compare
    579   * unequal if both items are unequal, NOT if either is unequal. */
    580  bool operator != (const hb_zip_iter_t& o) const
    581  { return a != o.a && b != o.b; }
    582 
    583  private:
    584  A a;
    585  B b;
    586 };
    587 struct
    588 { HB_PARTIALIZE(2);
    589  template <typename A, typename B,
    590     hb_requires (hb_is_iterable (A) && hb_is_iterable (B))>
    591  hb_zip_iter_t<hb_iter_type<A>, hb_iter_type<B>>
    592  operator () (A&& a, B&& b) const
    593  { return hb_zip_iter_t<hb_iter_type<A>, hb_iter_type<B>> (hb_iter (a), hb_iter (b)); }
    594 }
    595 HB_FUNCOBJ (hb_zip);
    596 
    597 /* hb_concat() */
    598 
    599 template <typename A, typename B>
    600 struct hb_concat_iter_t :
    601    hb_iter_t<hb_concat_iter_t<A, B>, typename A::item_t>
    602 {
    603  hb_concat_iter_t () {}
    604  hb_concat_iter_t (A& a, B& b) : a (a), b (b) {}
    605  hb_concat_iter_t (const A& a, const B& b) : a (a), b (b) {}
    606 
    607 
    608  typedef typename A::item_t __item_t__;
    609  static constexpr bool is_random_access_iterator =
    610    A::is_random_access_iterator &&
    611    B::is_random_access_iterator;
    612  static constexpr bool is_sorted_iterator = false;
    613 
    614  __item_t__ __item__ () const
    615  {
    616    if (!a)
    617      return *b;
    618    return *a;
    619  }
    620 
    621  __item_t__ __item_at__ (unsigned i) const
    622  {
    623    unsigned a_len = a.len ();
    624    if (i < a_len)
    625      return a[i];
    626    return b[i - a_len];
    627  }
    628 
    629  bool __more__ () const { return bool (a) || bool (b); }
    630 
    631  unsigned __len__ () const { return a.len () + b.len (); }
    632 
    633  void __next__ ()
    634  {
    635    if (a)
    636      ++a;
    637    else
    638      ++b;
    639  }
    640 
    641  void __forward__ (unsigned n)
    642  {
    643    if (!n) return;
    644    if (!is_random_access_iterator) {
    645      while (n-- && *this) {
    646        (*this)++;
    647      }
    648      return;
    649    }
    650 
    651    unsigned a_len = a.len ();
    652    if (n > a_len) {
    653      n -= a_len;
    654      a.__forward__ (a_len);
    655      b.__forward__ (n);
    656    } else {
    657      a.__forward__ (n);
    658    }
    659  }
    660 
    661  hb_concat_iter_t __end__ () const { return hb_concat_iter_t (a._end (), b._end ()); }
    662  bool operator != (const hb_concat_iter_t& o) const
    663  {
    664    return a != o.a
    665        || b != o.b;
    666  }
    667 
    668  private:
    669  A a;
    670  B b;
    671 };
    672 struct
    673 { HB_PARTIALIZE(2);
    674  template <typename A, typename B,
    675     hb_requires (hb_is_iterable (A) && hb_is_iterable (B))>
    676  hb_concat_iter_t<hb_iter_type<A>, hb_iter_type<B>>
    677  operator () (A&& a, B&& b) const
    678  { return hb_concat_iter_t<hb_iter_type<A>, hb_iter_type<B>> (hb_iter (a), hb_iter (b)); }
    679 }
    680 HB_FUNCOBJ (hb_concat);
    681 
    682 /* hb_apply() */
    683 
    684 template <typename Appl>
    685 struct hb_apply_t
    686 {
    687  hb_apply_t (Appl a) : a (a) {}
    688 
    689  template <typename Iter,
    690     hb_requires (hb_is_iterator (Iter))>
    691  void operator () (Iter it)
    692  {
    693    for (; it; ++it)
    694      (void) hb_invoke (a, *it);
    695  }
    696 
    697  private:
    698  Appl a;
    699 };
    700 struct
    701 {
    702  template <typename Appl> hb_apply_t<Appl>
    703  operator () (Appl&& a) const
    704  { return hb_apply_t<Appl> (a); }
    705 
    706  template <typename Appl> hb_apply_t<Appl&>
    707  operator () (Appl *a) const
    708  { return hb_apply_t<Appl&> (*a); }
    709 }
    710 HB_FUNCOBJ (hb_apply);
    711 
    712 /* hb_range()/hb_iota()/hb_repeat() */
    713 
    714 template <typename T, typename S>
    715 struct hb_range_iter_t :
    716  hb_iter_t<hb_range_iter_t<T, S>, T>
    717 {
    718  hb_range_iter_t (T start, T end_, S step) : v (start), end_ (end_for (start, end_, step)), step (step) {}
    719 
    720  typedef T __item_t__;
    721  static constexpr bool is_random_access_iterator = true;
    722  static constexpr bool is_sorted_iterator = true;
    723  __item_t__ __item__ () const { return hb_ridentity (v); }
    724  __item_t__ __item_at__ (unsigned j) const { return v + j * step; }
    725  bool __more__ () const { return v != end_; }
    726  unsigned __len__ () const { return !step ? UINT_MAX : (end_ - v) / step; }
    727  void __next__ () { v += step; }
    728  void __forward__ (unsigned n) { v += n * step; }
    729  void __prev__ () { v -= step; }
    730  void __rewind__ (unsigned n) { v -= n * step; }
    731  hb_range_iter_t __end__ () const { return hb_range_iter_t (end_, end_, step); }
    732  bool operator != (const hb_range_iter_t& o) const
    733  { return v != o.v; }
    734 
    735  private:
    736  static inline T end_for (T start, T end_, S step)
    737  {
    738    if (!step)
    739      return end_;
    740    auto res = (end_ - start) % step;
    741    if (!res)
    742      return end_;
    743    end_ += step - res;
    744    return end_;
    745  }
    746 
    747  private:
    748  T v;
    749  T end_;
    750  S step;
    751 };
    752 struct
    753 {
    754  template <typename T = unsigned> hb_range_iter_t<T, unsigned>
    755  operator () (T end = (unsigned) -1) const
    756  { return hb_range_iter_t<T, unsigned> (0, end, 1u); }
    757 
    758  template <typename T, typename S = unsigned> hb_range_iter_t<T, S>
    759  operator () (T start, T end, S step = 1u) const
    760  { return hb_range_iter_t<T, S> (start, end, step); }
    761 }
    762 HB_FUNCOBJ (hb_range);
    763 
    764 template <typename T, typename S>
    765 struct hb_iota_iter_t :
    766  hb_iter_with_fallback_t<hb_iota_iter_t<T, S>, T>
    767 {
    768  hb_iota_iter_t (T start, S step) : v (start), step (step) {}
    769 
    770  private:
    771 
    772  template <typename S2 = S>
    773  auto
    774  inc (hb_type_identity<S2> s, hb_priority<1>)
    775    -> hb_void_t<decltype (hb_invoke (std::forward<hb_type_identity<S2>> (s),
    776                                      hb_declval<T&> ()))>
    777  { v = hb_invoke (std::forward<hb_type_identity<S2>> (s), v); }
    778 
    779  void
    780  inc (S s, hb_priority<0>)
    781  { v += s; }
    782 
    783  public:
    784 
    785  typedef T __item_t__;
    786  static constexpr bool is_random_access_iterator = true;
    787  static constexpr bool is_sorted_iterator = true;
    788  __item_t__ __item__ () const { return hb_ridentity (v); }
    789  bool __more__ () const { return true; }
    790  unsigned __len__ () const { return UINT_MAX; }
    791  void __next__ () { inc (step, hb_prioritize); }
    792  void __prev__ () { v -= step; }
    793  hb_iota_iter_t __end__ () const { return *this; }
    794  bool operator != (const hb_iota_iter_t& o) const { return true; }
    795 
    796  private:
    797  T v;
    798  S step;
    799 };
    800 struct
    801 {
    802  template <typename T = unsigned, typename S = unsigned> hb_iota_iter_t<T, S>
    803  operator () (T start = 0u, S step = 1u) const
    804  { return hb_iota_iter_t<T, S> (start, step); }
    805 }
    806 HB_FUNCOBJ (hb_iota);
    807 
    808 template <typename T>
    809 struct hb_repeat_iter_t :
    810  hb_iter_t<hb_repeat_iter_t<T>, T>
    811 {
    812  hb_repeat_iter_t (T value) : v (value) {}
    813 
    814  typedef T __item_t__;
    815  static constexpr bool is_random_access_iterator = true;
    816  static constexpr bool is_sorted_iterator = true;
    817  __item_t__ __item__ () const { return v; }
    818  __item_t__ __item_at__ (unsigned j) const { return v; }
    819  bool __more__ () const { return true; }
    820  unsigned __len__ () const { return UINT_MAX; }
    821  void __next__ () {}
    822  void __forward__ (unsigned) {}
    823  void __prev__ () {}
    824  void __rewind__ (unsigned) {}
    825  hb_repeat_iter_t __end__ () const { return *this; }
    826  bool operator != (const hb_repeat_iter_t& o) const { return true; }
    827 
    828  private:
    829  T v;
    830 };
    831 struct
    832 {
    833  template <typename T> hb_repeat_iter_t<T>
    834  operator () (T value) const
    835  { return hb_repeat_iter_t<T> (value); }
    836 }
    837 HB_FUNCOBJ (hb_repeat);
    838 
    839 /* hb_enumerate()/hb_take() */
    840 
    841 struct
    842 {
    843  template <typename Iterable,
    844     typename Index = unsigned,
    845     hb_requires (hb_is_iterable (Iterable))>
    846  auto operator () (Iterable&& it, Index start = 0u) const HB_AUTO_RETURN
    847  ( hb_zip (hb_iota (start), it) )
    848 }
    849 HB_FUNCOBJ (hb_enumerate);
    850 
    851 struct
    852 { HB_PARTIALIZE(2);
    853  template <typename Iterable,
    854     hb_requires (hb_is_iterable (Iterable))>
    855  auto operator () (Iterable&& it, unsigned count) const HB_AUTO_RETURN
    856  ( hb_zip (hb_range (count), it) | hb_map_retains_sorting (hb_second) )
    857 
    858  /* Specialization arrays. */
    859 
    860  template <typename Type> inline hb_array_t<Type>
    861  operator () (hb_array_t<Type> array, unsigned count) const
    862  { return array.sub_array (0, count); }
    863 
    864  template <typename Type> inline hb_sorted_array_t<Type>
    865  operator () (hb_sorted_array_t<Type> array, unsigned count) const
    866  { return array.sub_array (0, count); }
    867 }
    868 HB_FUNCOBJ (hb_take);
    869 
    870 struct
    871 { HB_PARTIALIZE(2);
    872  template <typename Iter,
    873     hb_requires (hb_is_iterator (Iter))>
    874  auto operator () (Iter it, unsigned count) const HB_AUTO_RETURN
    875  (
    876    + hb_iota (it, hb_add (count))
    877    | hb_map (hb_take (count))
    878    | hb_take ((hb_len (it) + count - 1) / count)
    879  )
    880 }
    881 HB_FUNCOBJ (hb_chop);
    882 
    883 /* hb_sink() */
    884 
    885 template <typename Sink>
    886 struct hb_sink_t
    887 {
    888  hb_sink_t (Sink s) : s (s) {}
    889 
    890  template <typename Iter,
    891     hb_requires (hb_is_iterator (Iter))>
    892  void operator () (Iter it)
    893  {
    894    for (; it; ++it)
    895      s << *it;
    896  }
    897 
    898  private:
    899  Sink s;
    900 };
    901 struct
    902 {
    903  template <typename Sink> hb_sink_t<Sink>
    904  operator () (Sink&& s) const
    905  { return hb_sink_t<Sink> (s); }
    906 
    907  template <typename Sink> hb_sink_t<Sink&>
    908  operator () (Sink *s) const
    909  { return hb_sink_t<Sink&> (*s); }
    910 }
    911 HB_FUNCOBJ (hb_sink);
    912 
    913 /* hb-drain: hb_sink to void / blackhole / /dev/null. */
    914 
    915 struct
    916 {
    917  template <typename Iter,
    918     hb_requires (hb_is_iterator (Iter))>
    919  void operator () (Iter it) const
    920  {
    921    for (; it; ++it)
    922      (void) *it;
    923  }
    924 }
    925 HB_FUNCOBJ (hb_drain);
    926 
    927 /* hb_unzip(): unzip and sink to two sinks. */
    928 
    929 template <typename Sink1, typename Sink2>
    930 struct hb_unzip_t
    931 {
    932  hb_unzip_t (Sink1 s1, Sink2 s2) : s1 (s1), s2 (s2) {}
    933 
    934  template <typename Iter,
    935     hb_requires (hb_is_iterator (Iter))>
    936  void operator () (Iter it)
    937  {
    938    for (; it; ++it)
    939    {
    940      const auto &v = *it;
    941      s1 << v.first;
    942      s2 << v.second;
    943    }
    944  }
    945 
    946  private:
    947  Sink1 s1;
    948  Sink2 s2;
    949 };
    950 struct
    951 {
    952  template <typename Sink1, typename Sink2> hb_unzip_t<Sink1, Sink2>
    953  operator () (Sink1&& s1, Sink2&& s2) const
    954  { return hb_unzip_t<Sink1, Sink2> (s1, s2); }
    955 
    956  template <typename Sink1, typename Sink2> hb_unzip_t<Sink1&, Sink2&>
    957  operator () (Sink1 *s1, Sink2 *s2) const
    958  { return hb_unzip_t<Sink1&, Sink2&> (*s1, *s2); }
    959 }
    960 HB_FUNCOBJ (hb_unzip);
    961 
    962 
    963 /* hb-all, hb-any, hb-none. */
    964 
    965 struct
    966 {
    967  template <typename Iterable,
    968     typename Pred = decltype ((hb_identity)),
    969     typename Proj = decltype ((hb_identity)),
    970     hb_requires (hb_is_iterable (Iterable))>
    971  bool operator () (Iterable&& c,
    972 	    Pred&& p = hb_identity,
    973 	    Proj&& f = hb_identity) const
    974  {
    975    for (auto it = hb_iter (c); it; ++it)
    976      if (!hb_match (p, hb_get (f, *it)))
    977 return false;
    978    return true;
    979  }
    980 }
    981 HB_FUNCOBJ (hb_all);
    982 struct
    983 {
    984  template <typename Iterable,
    985     typename Pred = decltype ((hb_identity)),
    986     typename Proj = decltype ((hb_identity)),
    987     hb_requires (hb_is_iterable (Iterable))>
    988  bool operator () (Iterable&& c,
    989 	    Pred&& p = hb_identity,
    990 	    Proj&& f = hb_identity) const
    991  {
    992    for (auto it = hb_iter (c); it; ++it)
    993      if (hb_match (p, hb_get (f, *it)))
    994 return true;
    995    return false;
    996  }
    997 }
    998 HB_FUNCOBJ (hb_any);
    999 struct
   1000 {
   1001  template <typename Iterable,
   1002     typename Pred = decltype ((hb_identity)),
   1003     typename Proj = decltype ((hb_identity)),
   1004     hb_requires (hb_is_iterable (Iterable))>
   1005  bool operator () (Iterable&& c,
   1006 	    Pred&& p = hb_identity,
   1007 	    Proj&& f = hb_identity) const
   1008  {
   1009    for (auto it = hb_iter (c); it; ++it)
   1010      if (hb_match (p, hb_get (f, *it)))
   1011 return false;
   1012    return true;
   1013  }
   1014 }
   1015 HB_FUNCOBJ (hb_none);
   1016 
   1017 /*
   1018 * Algorithms operating on iterators.
   1019 */
   1020 
   1021 template <typename C, typename V,
   1022   hb_requires (hb_is_iterable (C))>
   1023 inline void
   1024 hb_fill (C&& c, const V &v)
   1025 {
   1026  for (auto i = hb_iter (c); i; i++)
   1027    *i = v;
   1028 }
   1029 
   1030 template <typename S, typename D>
   1031 inline void
   1032 hb_copy (S&& is, D&& id)
   1033 {
   1034  hb_iter (is) | hb_sink (id);
   1035 }
   1036 
   1037 
   1038 #endif /* HB_ITER_HH */