1 /*
   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"
  31 #include "hb-null.hh"
  32 
  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.
  38  * hb_iter_tator objects are small, light-weight, objects that can be
  39  * copied by value.  If the collection / object being iterated on
  40  * is writable, then the iterator returns lvalues, otherwise it
  41  * returns rvalues.
  42  */
  43 
  44 /* Base class for all iterators. */
  45 template <typename Iter, typename Item = typename Iter::__item_type__>
  46 struct hb_iter_t
  47 {
  48   typedef Iter iter_t;
  49   typedef iter_t const_iter_t;
  50   typedef Item item_t;
  51   static constexpr unsigned item_size = hb_static_size (Item);
  52 
  53   private:
  54   /* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */
  55   const iter_t* thiz () const { return static_cast<const iter_t *> (this); }
  56         iter_t* thiz ()       { return static_cast<      iter_t *> (this); }
  57   public:
  58 
  59   /* Operators. */
  60   operator iter_t () { return iter(); }
  61   explicit_operator bool () const { return more (); }
  62   item_t& operator * () const { return item (); }
  63   item_t& operator [] (signed i) const { return item_at ((unsigned) i); }
  64   iter_t& operator += (unsigned count) { forward (count); return *thiz(); }
  65   iter_t& operator ++ () { next (); return *thiz(); }
  66   iter_t& operator -= (unsigned count) { rewind (count); return *thiz(); }
  67   iter_t& operator -- () { prev (); return *thiz(); }
  68   iter_t operator + (unsigned count) { iter_t c (*thiz()); c += count; return c; }
  69   iter_t operator ++ (int) { iter_t c (*thiz()); ++*thiz(); return c; }
  70   iter_t operator - (unsigned count) { iter_t c (*thiz()); c -= count; return c; }
  71   iter_t operator -- (int) { iter_t c (*thiz()); --*thiz(); return c; }
  72 
  73   /* Methods. */
  74   iter_t iter () const { return *thiz(); }
  75   const_iter_t const_iter () const { return iter (); }
  76   item_t& item () const { return thiz()->__item__ (); }
  77   item_t& item_at (unsigned i) const { return thiz()->__item_at__ (i); }
  78   bool more () const { return thiz()->__more__ (); }
  79   unsigned len () const { return thiz()->__len__ (); }
  80   void next () { thiz()->__next__ (); }
  81   void forward (unsigned n) { thiz()->__forward__ (n); }
  82   void prev () { thiz()->__prev__ (); }
  83   void rewind (unsigned n) { thiz()->__rewind__ (n); }
  84   bool random_access () const { return thiz()->__random_access__ (); }
  85 
  86   protected:
  87   hb_iter_t () {}
  88   hb_iter_t (const hb_iter_t &o HB_UNUSED) {}
  89   void operator = (const hb_iter_t &o HB_UNUSED) {}
  90 };
  91 
  92 /* Base class for sorted iterators.  Does not enforce anything.
  93  * Just for class taxonomy and requirements. */
  94 template <typename Iter, typename Item = typename Iter::__item_type__>
  95 struct hb_sorted_iter_t : hb_iter_t<Iter, Item>
  96 {
  97   protected:
  98   hb_sorted_iter_t () {}
  99   hb_sorted_iter_t (const hb_sorted_iter_t &o) : hb_iter_t<Iter, Item> (o) {}
 100   void operator = (const hb_sorted_iter_t &o HB_UNUSED) {}
 101 };
 102 
 103 /* Mixin to fill in what the subclass doesn't provide. */
 104 template <typename iter_t, typename item_t = typename iter_t::__item_type__>
 105 struct hb_iter_mixin_t
 106 {
 107   private:
 108   /* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */
 109   const iter_t* thiz () const { return static_cast<const iter_t *> (this); }
 110         iter_t* thiz ()       { return static_cast<      iter_t *> (this); }
 111   public:
 112 
 113   /* Access: Implement __item__(), or __item_at__() if random-access. */
 114   item_t& __item__ () const { return thiz()->item_at (0); }
 115   item_t& __item_at__ (unsigned i) const { return *(thiz() + i); }
 116 
 117   /* Termination: Implement __more__(), or __len__() if random-access. */
 118   bool __more__ () const { return thiz()->__len__ (); }
 119   unsigned __len__ () const
 120   { iter_t c (*thiz()); unsigned l = 0; while (c) { c++; l++; }; return l; }
 121 
 122   /* Advancing: Implement __next__(), or __forward__() if random-access. */
 123   void __next__ () { thiz()->forward (1); }
 124   void __forward__ (unsigned n) { while (n--) thiz()->next (); }
 125 
 126   /* Rewinding: Implement __prev__() or __rewind__() if bidirectional. */
 127   void __prev__ () { thiz()->rewind (1); }
 128   void __rewind__ (unsigned n) { while (n--) thiz()->prev (); }
 129 
 130   /* Random access: Return true if item_at(), len(), forward() are fast. */
 131   bool __random_access__ () const { return false; }
 132 };
 133 
 134 
 135 /* Functions operating on iterators or iteratables. */
 136 
 137 template <typename C, typename V> inline void
 138 hb_fill (const C& c, const V &v)
 139 {
 140   for (typename C::iter_t i (c); i; i++)
 141     hb_assign (*i, v);
 142 }
 143 
 144 template <typename S, typename D> inline bool
 145 hb_copy (hb_iter_t<D> &id, hb_iter_t<S> &is)
 146 {
 147   for (; id && is; ++id, ++is)
 148     *id = *is;
 149   return !is;
 150 }
 151 
 152 
 153 #endif /* HB_ITER_HH */