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-set.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "hb-object-private.hh"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)/*
367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) * The set digests here implement various "filters" that support
377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) * "approximate member query".  Conceptually these are like Bloom
387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) * Filter and Quotient Filter, however, much smaller, faster, and
397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) * designed to fit the requirements of our uses for glyph coverage
407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) * queries.  As a result, our filters have much higher.
417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) */
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)template <typename mask_t, unsigned int shift>
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct hb_set_digest_lowest_bits_t
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_POD ();
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  static const unsigned int mask_bytes = sizeof (mask_t);
497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  static const unsigned int mask_bits = sizeof (mask_t) * 8;
507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  static const unsigned int num_bits = 0
517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)				     + (mask_bytes >= 1 ? 3 : 0)
527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)				     + (mask_bytes >= 2 ? 1 : 0)
537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)				     + (mask_bytes >= 4 ? 1 : 0)
547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)				     + (mask_bytes >= 8 ? 1 : 0)
557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)				     + (mask_bytes >= 16? 1 : 0)
567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)				     + 0;
577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ASSERT_STATIC (shift < sizeof (hb_codepoint_t) * 8);
597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ASSERT_STATIC (shift + num_bits <= sizeof (hb_codepoint_t) * 8);
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void init (void) {
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mask = 0;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void add (hb_codepoint_t g) {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mask |= mask_for (g);
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void add_range (hb_codepoint_t a, hb_codepoint_t b) {
707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if ((b >> shift) - (a >> shift) >= mask_bits - 1)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mask = (mask_t) -1;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else {
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mask_t ma = mask_for (a);
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mask_t mb = mask_for (b);
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mask |= mb + (mb - ma) - (mb < ma);
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool may_have (hb_codepoint_t g) const {
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return !!(mask & mask_for (g));
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  private:
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  static inline mask_t mask_for (hb_codepoint_t g) {
867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return ((mask_t) 1) << ((g >> shift) & (mask_bits - 1));
877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mask_t mask;
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)template <typename head_t, typename tail_t>
927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)struct hb_set_digest_combiner_t
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_POD ();
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void init (void) {
977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    head.init ();
987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    tail.init ();
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void add (hb_codepoint_t g) {
1027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    head.add (g);
1037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    tail.add (g);
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void add_range (hb_codepoint_t a, hb_codepoint_t b) {
1077d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    head.add_range (a, b);
1087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    tail.add_range (a, b);
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool may_have (hb_codepoint_t g) const {
1127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return head.may_have (g) && tail.may_have (g);
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  private:
1167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  head_t head;
1177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  tail_t tail;
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)/*
1227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) * hb_set_digest_t
1237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) *
1247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) * This is a combination of digests that performs "best".
1257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) * There is not much science to this: it's a result of intuition
1267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) * and testing.
1277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) */
1287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)typedef hb_set_digest_combiner_t
1297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)<
1307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  hb_set_digest_lowest_bits_t<unsigned long, 4>,
1317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  hb_set_digest_combiner_t
1327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  <
1337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    hb_set_digest_lowest_bits_t<unsigned long, 0>,
1347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    hb_set_digest_lowest_bits_t<unsigned long, 9>
1357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  >
1367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)> hb_set_digest_t;
1377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)/*
1417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) * hb_set_t
1427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) */
1437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* TODO Make this faster and memmory efficient. */
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct hb_set_t
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hb_object_header_t header;
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_POD ();
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool in_error;
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void init (void) {
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    header.init ();
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    clear ();
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void fini (void) {
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void clear (void) {
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (unlikely (hb_object_is_inert (this)))
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    in_error = false;
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memset (elts, 0, sizeof elts);
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline bool is_empty (void) const {
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int i = 0; i < ARRAY_LENGTH (elts); i++)
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (elts[i])
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void add (hb_codepoint_t g)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (unlikely (in_error)) return;
174f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (unlikely (g == INVALID)) return;
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (g > MAX_G)) return;
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    elt (g) |= mask (g);
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void add_range (hb_codepoint_t a, hb_codepoint_t b)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (unlikely (in_error)) return;
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    /* TODO Speedup */
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int i = a; i < b + 1; i++)
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      add (i);
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void del (hb_codepoint_t g)
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (unlikely (in_error)) return;
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (g > MAX_G)) return;
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    elt (g) &= ~mask (g);
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline void del_range (hb_codepoint_t a, hb_codepoint_t b)
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (unlikely (in_error)) return;
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    /* TODO Speedup */
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (unsigned int i = a; i < b + 1; i++)
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      del (i);
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool has (hb_codepoint_t g) const
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (g > MAX_G)) return false;
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return !!(elt (g) & mask (g));
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool intersects (hb_codepoint_t first,
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			  hb_codepoint_t last) const
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (first > MAX_G)) return false;
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (last  > MAX_G)) last = MAX_G;
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int end = last + 1;
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (hb_codepoint_t i = first; i < end; i++)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (has (i))
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return true;
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline bool is_equal (const hb_set_t *other) const
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int i = 0; i < ELTS; i++)
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (elts[i] != other->elts[i])
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void set (const hb_set_t *other)
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (unlikely (in_error)) return;
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int i = 0; i < ELTS; i++)
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      elts[i] = other->elts[i];
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void union_ (const hb_set_t *other)
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (unlikely (in_error)) return;
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int i = 0; i < ELTS; i++)
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      elts[i] |= other->elts[i];
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void intersect (const hb_set_t *other)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (unlikely (in_error)) return;
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int i = 0; i < ELTS; i++)
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      elts[i] &= other->elts[i];
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void subtract (const hb_set_t *other)
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (unlikely (in_error)) return;
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int i = 0; i < ELTS; i++)
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      elts[i] &= ~other->elts[i];
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void symmetric_difference (const hb_set_t *other)
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (unlikely (in_error)) return;
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int i = 0; i < ELTS; i++)
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      elts[i] ^= other->elts[i];
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline void invert (void)
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (unlikely (in_error)) return;
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (unsigned int i = 0; i < ELTS; i++)
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      elts[i] = ~elts[i];
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline bool next (hb_codepoint_t *codepoint) const
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
259f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (unlikely (*codepoint == INVALID)) {
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      hb_codepoint_t i = get_min ();
261f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (i != INVALID) {
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *codepoint = i;
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return true;
264f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      } else {
265f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	*codepoint = INVALID;
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
267f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      }
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (hb_codepoint_t i = *codepoint + 1; i < MAX_G + 1; i++)
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (has (i)) {
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *codepoint = i;
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return true;
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
274f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    *codepoint = INVALID;
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline bool next_range (hb_codepoint_t *first, hb_codepoint_t *last) const
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    hb_codepoint_t i;
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    i = *last;
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!next (&i))
283f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    {
284f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      *last = *first = INVALID;
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return false;
286f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    *last = *first = i;
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    while (next (&i) && i == *last + 1)
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      (*last)++;
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return true;
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline unsigned int get_population (void) const
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    unsigned int count = 0;
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (unsigned int i = 0; i < ELTS; i++)
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      count += _hb_popcount32 (elts[i]);
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return count;
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline hb_codepoint_t get_min (void) const
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int i = 0; i < ELTS; i++)
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (elts[i])
3067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)	for (unsigned int j = 0; j < BITS; j++)
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	  if (elts[i] & (1 << j))
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return i * BITS + j;
309f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return INVALID;
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline hb_codepoint_t get_max (void) const
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int i = ELTS; i; i--)
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (elts[i - 1])
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	for (unsigned int j = BITS; j; j--)
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	  if (elts[i - 1] & (1 << (j - 1)))
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return (i - 1) * BITS + (j - 1);
318f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return INVALID;
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef uint32_t elt_t;
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const unsigned int MAX_G = 65536 - 1; /* XXX Fix this... */
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const unsigned int SHIFT = 5;
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const unsigned int BITS = (1 << SHIFT);
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const unsigned int MASK = BITS - 1;
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const unsigned int ELTS = (MAX_G + 1 + (BITS - 1)) / BITS;
327f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  static  const hb_codepoint_t INVALID = HB_SET_VALUE_INVALID;
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  elt_t &elt (hb_codepoint_t g) { return elts[g >> SHIFT]; }
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  elt_t elt (hb_codepoint_t g) const { return elts[g >> SHIFT]; }
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  elt_t mask (hb_codepoint_t g) const { return elt_t (1) << (g & MASK); }
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  elt_t elts[ELTS]; /* XXX 8kb */
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_STATIC (sizeof (elt_t) * 8 == BITS);
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_STATIC (sizeof (elt_t) * 8 * ELTS > MAX_G);
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* HB_SET_PRIVATE_HH */
342