diff --git a/src/hb-set-private.hh b/src/hb-set-private.hh index 59e8f4559f5921e1ccaf766c421bbb0cc0f58df2..acba4e946b6c4d581c99d1bc838599b83f73ec81 100644 --- a/src/hb-set-private.hh +++ b/src/hb-set-private.hh @@ -145,6 +145,8 @@ typedef hb_set_digest_combiner_t struct hb_set_t { + friend struct hb_frozen_set_t; + hb_object_header_t header; ASSERT_POD (); bool in_error; @@ -326,7 +328,7 @@ struct hb_set_t static const hb_codepoint_t INVALID = HB_SET_VALUE_INVALID; elt_t &elt (hb_codepoint_t g) { return elts[g >> SHIFT]; } - elt_t elt (hb_codepoint_t g) const { return elts[g >> SHIFT]; } + elt_t const &elt (hb_codepoint_t g) const { return elts[g >> SHIFT]; } elt_t mask (hb_codepoint_t g) const { return elt_t (1) << (g & MASK); } elt_t elts[ELTS]; /* XXX 8kb */ @@ -335,6 +337,59 @@ struct hb_set_t ASSERT_STATIC (sizeof (elt_t) * 8 * ELTS > MAX_G); }; +struct hb_frozen_set_t +{ + static const unsigned int SHIFT = hb_set_t::SHIFT; + static const unsigned int BITS = hb_set_t::BITS; + static const unsigned int MASK = hb_set_t::MASK; + typedef hb_set_t::elt_t elt_t; + + inline void init (const hb_set_t &set) + { + start = count = 0; + elts = NULL; + + unsigned int max = set.get_max (); + if (max == set.INVALID) + return; + unsigned int min = set.get_min (); + const elt_t &min_elt = set.elt (min); + const elt_t &max_elt = set.elt (max); + + start = min & ~MASK; + count = max - start + 1; + unsigned int num_elts = (count + BITS - 1) / BITS; + unsigned int elts_size = num_elts * sizeof (elt_t); + elts = (elt_t *) malloc (elts_size); + if (unlikely (!elts)) + { + start = count = 0; + return; + } + memcpy (elts, &min_elt, elts_size); + } + + inline void fini (void) + { + if (elts) + free (elts); + } + + inline bool has (hb_codepoint_t g) const + { + /* hb_codepoint_t is unsigned. */ + g -= start; + if (unlikely (g > count)) return false; + return !!(elt (g) & mask (g)); + } + + elt_t const &elt (hb_codepoint_t g) const { return elts[g >> SHIFT]; } + elt_t mask (hb_codepoint_t g) const { return elt_t (1) << (g & MASK); } + + private: + hb_codepoint_t start, count; + elt_t *elts; +}; #endif /* HB_SET_PRIVATE_HH */