From 6c6ccaf575392f6e6bb9a15534026e4ea462705b Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 24 Apr 2012 14:21:15 -0400 Subject: [PATCH] Add a few more set operations TODO: Tests for hb_set_t. --- src/hb-set-private.hh | 54 +++++++++++++++++++++++++++++++++++++++++- src/hb-set.cc | 55 +++++++++++++++++++++++++++++++++++++++++++ src/hb-set.h | 34 +++++++++++++++++++++++--- 3 files changed, 139 insertions(+), 4 deletions(-) diff --git a/src/hb-set-private.hh b/src/hb-set-private.hh index a6239e4ed..660aaee64 100644 --- a/src/hb-set-private.hh +++ b/src/hb-set-private.hh @@ -38,6 +38,12 @@ struct _hb_set_t inline void clear (void) { memset (elts, 0, sizeof elts); } + inline bool empty (void) const { + for (unsigned int i = 0; i < ARRAY_LENGTH (elts); i++) + if (elts[i]) + return false; + return true; + } inline void add (hb_codepoint_t g) { if (unlikely (g > MAX_G)) return; @@ -64,19 +70,65 @@ struct _hb_set_t return true; return false; } + inline bool equal (const hb_set_t *other) const + { + for (unsigned int i = 0; i < ELTS; i++) + if (elts[i] != other->elts[i]) + return false; + return true; + } + inline void set (const hb_set_t *other) + { + for (unsigned int i = 0; i < ELTS; i++) + elts[i] = other->elts[i]; + } + inline void union_ (const hb_set_t *other) + { + for (unsigned int i = 0; i < ELTS; i++) + elts[i] |= other->elts[i]; + } + inline void intersect (const hb_set_t *other) + { + for (unsigned int i = 0; i < ELTS; i++) + elts[i] &= other->elts[i]; + } + inline void subtract (const hb_set_t *other) + { + for (unsigned int i = 0; i < ELTS; i++) + elts[i] &= ~other->elts[i]; + } + inline hb_codepoint_t min (void) const + { + for (unsigned int i = 0; i < ELTS; i++) + if (elts[i]) + for (unsigned int j = 0; i < BITS; j++) + if (elts[i] & (1 << j)) + return i * BITS + j; + return 0; + } + inline hb_codepoint_t max (void) const + { + for (unsigned int i = ELTS; i; i--) + if (elts[i - 1]) + for (unsigned int j = BITS; j; j--) + if (elts[i - 1] & (1 << (j - 1))) + return (i - 1) * BITS + (j - 1); + return 0; + } typedef uint32_t elt_t; static const unsigned int MAX_G = 65536 - 1; static const unsigned int SHIFT = 5; static const unsigned int BITS = (1 << SHIFT); static const unsigned int MASK = BITS - 1; + static const unsigned int ELTS = (MAX_G + 1 + (BITS - 1)) / BITS; 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 mask (hb_codepoint_t g) const { return elt_t (1) << (g & MASK); } hb_object_header_t header; - elt_t elts[(MAX_G + 1 + (BITS - 1)) / BITS]; /* 8kb */ + elt_t elts[ELTS]; /* 8kb */ ASSERT_STATIC (sizeof (elt_t) * 8 == BITS); ASSERT_STATIC (sizeof (elts) * 8 > MAX_G); diff --git a/src/hb-set.cc b/src/hb-set.cc index 353489be2..3b1c5bdcb 100644 --- a/src/hb-set.cc +++ b/src/hb-set.cc @@ -28,6 +28,8 @@ +/* Public API */ + static hb_set_t _hb_set_nil = { HB_OBJECT_HEADER_STATIC, @@ -98,6 +100,12 @@ hb_set_clear (hb_set_t *set) set->clear (); } +hb_bool_t +hb_set_empty (hb_set_t *set) +{ + return set->empty (); +} + hb_bool_t hb_set_has (hb_set_t *set, hb_codepoint_t codepoint) @@ -118,3 +126,50 @@ hb_set_del (hb_set_t *set, { set->del (codepoint); } + +hb_bool_t +hb_set_equal (hb_set_t *set, + hb_set_t *other) +{ + return set->equal (other); +} + +void +hb_set_set (hb_set_t *set, + hb_set_t *other) +{ + set->set (other); +} + +void +hb_set_union (hb_set_t *set, + hb_set_t *other) +{ + set->union_ (other); +} + +void +hb_set_intersect (hb_set_t *set, + hb_set_t *other) +{ + set->intersect (other); +} + +void +hb_set_subtract (hb_set_t *set, + hb_set_t *other) +{ + set->subtract (other); +} + +hb_codepoint_t +hb_set_min (hb_set_t *set) +{ + return set->min (); +} + +hb_codepoint_t +hb_set_max (hb_set_t *set) +{ + return set->max (); +} diff --git a/src/hb-set.h b/src/hb-set.h index a9c734bbf..35c77b8f0 100644 --- a/src/hb-set.h +++ b/src/hb-set.h @@ -52,14 +52,14 @@ void hb_set_destroy (hb_set_t *set); hb_bool_t -hb_set_set_user_data (hb_set_t *set, +hb_set_set_user_data (hb_set_t *set, hb_user_data_key_t *key, void * data, hb_destroy_func_t destroy, hb_bool_t replace); void * -hb_set_get_user_data (hb_set_t *set, +hb_set_get_user_data (hb_set_t *set, hb_user_data_key_t *key); @@ -70,6 +70,9 @@ hb_set_allocation_successful (hb_set_t *set); void hb_set_clear (hb_set_t *set); +hb_bool_t +hb_set_empty (hb_set_t *set); + hb_bool_t hb_set_has (hb_set_t *set, hb_codepoint_t codepoint); @@ -82,8 +85,33 @@ void hb_set_del (hb_set_t *set, hb_codepoint_t codepoint); -/* TODO: add union, intersect, subtract, equal, empty, min, max, iter, etc */ +hb_bool_t +hb_set_equal (hb_set_t *set, + hb_set_t *other); +void +hb_set_set (hb_set_t *set, + hb_set_t *other); + +void +hb_set_union (hb_set_t *set, + hb_set_t *other); + +void +hb_set_intersect (hb_set_t *set, + hb_set_t *other); + +void +hb_set_subtract (hb_set_t *set, + hb_set_t *other); + +hb_codepoint_t +hb_set_min (hb_set_t *set); + +hb_codepoint_t +hb_set_max (hb_set_t *set); + +/* TODO: Add faster iteration API? */ HB_END_DECLS