15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright © 2012  Google, Inc.
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  This is part of HarfBuzz, a text shaping library.
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Permission is hereby granted, without written agreement and without
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * license or royalty fees, to use, copy, modify, and distribute this
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * software and its documentation for any purpose, provided that the
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * above copyright notice and the following two paragraphs appear in
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * all copies of this software.
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * DAMAGE.
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Google Author(s): Behdad Esfahbod
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef HB_SET_PRIVATE_HH
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define HB_SET_PRIVATE_HH
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "hb-private.hh"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "hb-object-private.hh"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)/*
357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) * The set digests here implement various "filters" that support
367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) * "approximate member query".  Conceptually these are like Bloom
377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) * Filter and Quotient Filter, however, much smaller, faster, and
387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) * designed to fit the requirements of our uses for glyph coverage
397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) * queries.  As a result, our filters have much higher.
407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) */
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)template <typename mask_t, unsigned int shift>
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct hb_set_digest_lowest_bits_t
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_POD ();
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  static const unsigned int mask_bytes = sizeof (mask_t);
487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  static const unsigned int mask_bits = sizeof (mask_t) * 8;
497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  static const unsigned int num_bits = 0
507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)				     + (mask_bytes >= 1 ? 3 : 0)
517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)				     + (mask_bytes >= 2 ? 1 : 0)
527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)				     + (mask_bytes >= 4 ? 1 : 0)
537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)				     + (mask_bytes >= 8 ? 1 : 0)
547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)				     + (mask_bytes >= 16? 1 : 0)
557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)				     + 0;
567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ASSERT_STATIC (shift < sizeof (hb_codepoint_t) * 8);
587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ASSERT_STATIC (shift + num_bits <= sizeof (hb_codepoint_t) * 8);
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void init (void) {
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mask = 0;
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void add (hb_codepoint_t g) {
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mask |= mask_for (g);
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void add_range (hb_codepoint_t a, hb_codepoint_t b) {
697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if ((b >> shift) - (a >> shift) >= mask_bits - 1)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mask = (mask_t) -1;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else {
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mask_t ma = mask_for (a);
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mask_t mb = mask_for (b);
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mask |= mb + (mb - ma) - (mb < ma);
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool may_have (hb_codepoint_t g) const {
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return !!(mask & mask_for (g));
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  private:
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  static inline mask_t mask_for (hb_codepoint_t g) {
857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return ((mask_t) 1) << ((g >> shift) & (mask_bits - 1));
867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mask_t mask;
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)template <typename head_t, typename tail_t>
917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)struct hb_set_digest_combiner_t
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_POD ();
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void init (void) {
967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    head.init ();
977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    tail.init ();
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void add (hb_codepoint_t g) {
1017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    head.add (g);
1027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    tail.add (g);
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void add_range (hb_codepoint_t a, hb_codepoint_t b) {
1067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    head.add_range (a, b);
1077d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    tail.add_range (a, b);
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool may_have (hb_codepoint_t g) const {
1117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return head.may_have (g) && tail.may_have (g);
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  private:
1157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  head_t head;
1167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  tail_t tail;
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)/*
1217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) * hb_set_digest_t
1227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) *
1237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) * This is a combination of digests that performs "best".
1247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) * There is not much science to this: it's a result of intuition
1257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) * and testing.
1267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) */
1277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)typedef hb_set_digest_combiner_t
1287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)<
1297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  hb_set_digest_lowest_bits_t<unsigned long, 4>,
1307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  hb_set_digest_combiner_t
1317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  <
1327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    hb_set_digest_lowest_bits_t<unsigned long, 0>,
1337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    hb_set_digest_lowest_bits_t<unsigned long, 9>
1347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  >
1357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)> hb_set_digest_t;
1367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)/*
1407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) * hb_set_t
1417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) */
1427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* TODO Make this faster and memmory efficient. */
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct hb_set_t
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hb_object_header_t header;
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_POD ();
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool in_error;
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void init (void) {
15303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    hb_object_init (this);
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    clear ();
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void fini (void) {
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void clear (void) {
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (unlikely (hb_object_is_inert (this)))
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    in_error = false;
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memset (elts, 0, sizeof elts);
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline bool is_empty (void) const {
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int i = 0; i < ARRAY_LENGTH (elts); i++)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (elts[i])
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void add (hb_codepoint_t g)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (unlikely (in_error)) return;
173f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (unlikely (g == INVALID)) return;
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (g > MAX_G)) return;
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    elt (g) |= mask (g);
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void add_range (hb_codepoint_t a, hb_codepoint_t b)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (unlikely (in_error)) return;
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    /* TODO Speedup */
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int i = a; i < b + 1; i++)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      add (i);
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void del (hb_codepoint_t g)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (unlikely (in_error)) return;
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (g > MAX_G)) return;
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    elt (g) &= ~mask (g);
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline void del_range (hb_codepoint_t a, hb_codepoint_t b)
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (unlikely (in_error)) return;
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    /* TODO Speedup */
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (unsigned int i = a; i < b + 1; i++)
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      del (i);
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool has (hb_codepoint_t g) const
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (g > MAX_G)) return false;
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return !!(elt (g) & mask (g));
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool intersects (hb_codepoint_t first,
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			  hb_codepoint_t last) const
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (first > MAX_G)) return false;
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (last  > MAX_G)) last = MAX_G;
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int end = last + 1;
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (hb_codepoint_t i = first; i < end; i++)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (has (i))
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return true;
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline bool is_equal (const hb_set_t *other) const
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int i = 0; i < ELTS; i++)
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (elts[i] != other->elts[i])
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void set (const hb_set_t *other)
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (unlikely (in_error)) return;
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int i = 0; i < ELTS; i++)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      elts[i] = other->elts[i];
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void union_ (const hb_set_t *other)
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (unlikely (in_error)) return;
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int i = 0; i < ELTS; i++)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      elts[i] |= other->elts[i];
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void intersect (const hb_set_t *other)
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (unlikely (in_error)) return;
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int i = 0; i < ELTS; i++)
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      elts[i] &= other->elts[i];
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void subtract (const hb_set_t *other)
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (unlikely (in_error)) return;
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int i = 0; i < ELTS; i++)
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      elts[i] &= ~other->elts[i];
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void symmetric_difference (const hb_set_t *other)
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (unlikely (in_error)) return;
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int i = 0; i < ELTS; i++)
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      elts[i] ^= other->elts[i];
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline void invert (void)
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (unlikely (in_error)) return;
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (unsigned int i = 0; i < ELTS; i++)
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      elts[i] = ~elts[i];
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline bool next (hb_codepoint_t *codepoint) const
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
258f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (unlikely (*codepoint == INVALID)) {
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      hb_codepoint_t i = get_min ();
260f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (i != INVALID) {
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *codepoint = i;
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return true;
263f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      } else {
264f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	*codepoint = INVALID;
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
266f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      }
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (hb_codepoint_t i = *codepoint + 1; i < MAX_G + 1; i++)
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (has (i)) {
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *codepoint = i;
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return true;
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
273f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    *codepoint = INVALID;
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline bool next_range (hb_codepoint_t *first, hb_codepoint_t *last) const
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    hb_codepoint_t i;
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    i = *last;
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!next (&i))
282f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    {
283f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      *last = *first = INVALID;
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return false;
285f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    *last = *first = i;
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    while (next (&i) && i == *last + 1)
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      (*last)++;
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return true;
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline unsigned int get_population (void) const
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    unsigned int count = 0;
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (unsigned int i = 0; i < ELTS; i++)
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      count += _hb_popcount32 (elts[i]);
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return count;
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline hb_codepoint_t get_min (void) const
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int i = 0; i < ELTS; i++)
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (elts[i])
3057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)	for (unsigned int j = 0; j < BITS; j++)
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	  if (elts[i] & (1 << j))
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return i * BITS + j;
308f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return INVALID;
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline hb_codepoint_t get_max (void) const
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int i = ELTS; i; i--)
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (elts[i - 1])
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	for (unsigned int j = BITS; j; j--)
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	  if (elts[i - 1] & (1 << (j - 1)))
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return (i - 1) * BITS + (j - 1);
317f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return INVALID;
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef uint32_t elt_t;
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const unsigned int MAX_G = 65536 - 1; /* XXX Fix this... */
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const unsigned int SHIFT = 5;
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const unsigned int BITS = (1 << SHIFT);
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const unsigned int MASK = BITS - 1;
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const unsigned int ELTS = (MAX_G + 1 + (BITS - 1)) / BITS;
326f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  static  const hb_codepoint_t INVALID = HB_SET_VALUE_INVALID;
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  elt_t &elt (hb_codepoint_t g) { return elts[g >> SHIFT]; }
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  elt_t elt (hb_codepoint_t g) const { return elts[g >> SHIFT]; }
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  elt_t mask (hb_codepoint_t g) const { return elt_t (1) << (g & MASK); }
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  elt_t elts[ELTS]; /* XXX 8kb */
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_STATIC (sizeof (elt_t) * 8 == BITS);
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_STATIC (sizeof (elt_t) * 8 * ELTS > MAX_G);
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* HB_SET_PRIVATE_HH */
341