tor-browser

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

hb-bit-vector.hh (5355B)


      1 /*
      2 *  This is part of HarfBuzz, a text shaping library.
      3 *
      4 * Permission is hereby granted, without written agreement and without
      5 * license or royalty fees, to use, copy, modify, and distribute this
      6 * software and its documentation for any purpose, provided that the
      7 * above copyright notice and the following two paragraphs appear in
      8 * all copies of this software.
      9 *
     10 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
     11 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
     12 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
     13 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
     14 * DAMAGE.
     15 *
     16 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
     17 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
     18 * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
     19 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
     20 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
     21 *
     22 * Author(s): Behdad Esfahbod
     23 */
     24 
     25 #ifndef HB_BIT_VECTOR_HH
     26 #define HB_BIT_VECTOR_HH
     27 
     28 #include "hb.hh"
     29 
     30 #include "hb-atomic.hh"
     31 
     32 struct hb_min_max_t
     33 {
     34  void add (hb_codepoint_t v) { min_v = hb_min (min_v, v); max_v = hb_max (max_v, v); }
     35  void add_range (hb_codepoint_t a, hb_codepoint_t b)
     36  {
     37    min_v = hb_min (min_v, a);
     38    max_v = hb_max (max_v, b);
     39  }
     40 
     41  template <typename set_t>
     42  void union_ (const set_t &set)
     43  {
     44    hb_codepoint_t set_min = set.get_min ();
     45    if (unlikely (set_min == HB_CODEPOINT_INVALID))
     46      return;
     47    hb_codepoint_t set_max = set.get_max ();
     48    min_v = hb_min (min_v, set_min);
     49    max_v = hb_max (max_v, set_max);
     50  }
     51 
     52  hb_codepoint_t get_min () const { return min_v; }
     53  hb_codepoint_t get_max () const { return max_v; }
     54 
     55  private:
     56  hb_codepoint_t min_v = HB_CODEPOINT_INVALID;
     57  hb_codepoint_t max_v = 0;
     58 };
     59 
     60 template <bool atomic = false>
     61 struct hb_bit_vector_t
     62 {
     63  using int_t = uint64_t;
     64  using elt_t = typename std::conditional<atomic, hb_atomic_t<int_t>, int_t>::type;
     65 
     66  hb_bit_vector_t () = delete;
     67  hb_bit_vector_t (const hb_bit_vector_t &other) = delete;
     68  hb_bit_vector_t &operator= (const hb_bit_vector_t &other) = delete;
     69 
     70  // Move
     71  hb_bit_vector_t (hb_bit_vector_t &&other)
     72 	: min_v (other.min_v), max_v (other.max_v), count (other.count), elts (other.elts)
     73  {
     74    other.min_v = other.max_v = other.count = 0;
     75    other.elts = nullptr;
     76  }
     77  hb_bit_vector_t &operator= (hb_bit_vector_t &&other)
     78  {
     79    hb_swap (min_v, other.min_v);
     80    hb_swap (max_v, other.max_v);
     81    hb_swap (count, other.count);
     82    hb_swap (elts, other.elts);
     83    return *this;
     84  }
     85 
     86  hb_bit_vector_t (unsigned min_v, unsigned max_v)
     87    : min_v (min_v), max_v (max_v)
     88  {
     89    if (unlikely (min_v >= max_v))
     90    {
     91      min_v = max_v = count = 0;
     92      return;
     93    }
     94 
     95    unsigned num = (max_v - min_v + sizeof (int_t) * 8) / (sizeof (int_t) * 8);
     96    elts = (elt_t *) hb_calloc (num, sizeof (int_t));
     97    if (unlikely (!elts))
     98    {
     99      min_v = max_v = count = 0;
    100      return;
    101    }
    102 
    103    count = max_v - min_v + 1;
    104  }
    105  ~hb_bit_vector_t ()
    106  {
    107    hb_free (elts);
    108  }
    109 
    110  void add (hb_codepoint_t g) { elt (g) |= mask (g); }
    111  void del (hb_codepoint_t g) { elt (g) &= ~mask (g); }
    112  void set (hb_codepoint_t g, bool value) { if (value) add (g); else del (g); }
    113  bool get (hb_codepoint_t g) const { return elt (g) & mask (g); }
    114  bool has (hb_codepoint_t g) const { return get (g); }
    115  bool may_have (hb_codepoint_t g) const { return get (g); }
    116 
    117  bool operator [] (hb_codepoint_t g) const { return get (g); }
    118  bool operator () (hb_codepoint_t g) const { return get (g); }
    119 
    120  void add_range (hb_codepoint_t a, hb_codepoint_t b)
    121  {
    122    if (unlikely (!count || a > b || a < min_v || b > max_v))
    123      return;
    124 
    125    elt_t *la = &elt (a);
    126    elt_t *lb = &elt (b);
    127    if (la == lb)
    128      *la |= (mask (b) << 1) - mask(a);
    129    else
    130    {
    131      *la |= ~(mask (a) - 1llu);
    132      la++;
    133 
    134      hb_memset (la, 0xff, (char *) lb - (char *) la);
    135 
    136      *lb |= ((mask (b) << 1) - 1llu);
    137    }
    138  }
    139  void del_range (hb_codepoint_t a, hb_codepoint_t b)
    140  {
    141    if (unlikely (!count || a > b || a < min_v || b > max_v))
    142      return;
    143 
    144    elt_t *la = &elt (a);
    145    elt_t *lb = &elt (b);
    146    if (la == lb)
    147      *la &= ~((mask (b) << 1llu) - mask(a));
    148    else
    149    {
    150      *la &= mask (a) - 1;
    151      la++;
    152 
    153      hb_memset (la, 0, (char *) lb - (char *) la);
    154 
    155      *lb &= ~((mask (b) << 1) - 1llu);
    156    }
    157  }
    158  void set_range (hb_codepoint_t a, hb_codepoint_t b, bool v)
    159  { if (v) add_range (a, b); else del_range (a, b); }
    160 
    161  template <typename set_t>
    162  void union_ (const set_t &set)
    163  {
    164    for (hb_codepoint_t g : set)
    165      add (g);
    166  }
    167 
    168  static const unsigned int ELT_BITS = sizeof (elt_t) * 8;
    169  static constexpr unsigned ELT_MASK = ELT_BITS - 1;
    170 
    171  static constexpr elt_t zero = 0;
    172 
    173  elt_t &elt (hb_codepoint_t g)
    174  {
    175    g -= min_v;
    176    if (unlikely (g >= count))
    177      return Crap(elt_t);
    178    return elts[g / ELT_BITS];
    179  }
    180  const elt_t& elt (hb_codepoint_t g) const
    181  {
    182    g -= min_v;
    183    if (unlikely (g >= count))
    184      return Null(elt_t);
    185    return elts[g / ELT_BITS];
    186  }
    187 
    188  static constexpr int_t mask (hb_codepoint_t g) { return elt_t (1) << (g & ELT_MASK); }
    189 
    190  hb_codepoint_t min_v = 0, max_v = 0, count = 0;
    191  elt_t *elts = nullptr;
    192 };
    193 
    194 
    195 #endif /* HB_BIT_VECTOR_HH */