diff --git a/src/hb-map.hh b/src/hb-map.hh index f2a65a821..406730831 100644 --- a/src/hb-map.hh +++ b/src/hb-map.hh @@ -31,22 +31,28 @@ /* - * hb_map_t + * hb_hashmap_t */ -struct hb_map_t +template +struct hb_hashmap_t { - HB_NO_COPY_ASSIGN (hb_map_t); - hb_map_t () { init (); } - ~hb_map_t () { fini (); } + HB_NO_COPY_ASSIGN (hb_hashmap_t); + hb_hashmap_t () { init (); } + ~hb_hashmap_t () { fini (); } + + static_assert (hb_is_integer (K) || hb_is_pointer (K), ""); + static_assert (hb_is_integer (V) || hb_is_pointer (V), ""); struct item_t { - hb_codepoint_t key; - hb_codepoint_t value; + K key; + V value; - bool is_unused () const { return key == INVALID; } - bool is_tombstone () const { return key != INVALID && value == INVALID; } + bool is_unused () const { return key == kINVALID; } + bool is_tombstone () const { return key != kINVALID && value == vINVALID; } }; hb_object_header_t header; @@ -110,7 +116,7 @@ struct hb_map_t /* Insert back old items. */ if (old_items) for (unsigned int i = 0; i < old_size; i++) - if (old_items[i].key != INVALID && old_items[i].value != INVALID) + if (old_items[i].key != kINVALID && old_items[i].value != vINVALID) set (old_items[i].key, old_items[i].value); free (old_items); @@ -118,14 +124,14 @@ struct hb_map_t return true; } - void set (hb_codepoint_t key, hb_codepoint_t value) + void set (K key, V value) { if (unlikely (!successful)) return; - if (unlikely (key == INVALID)) return; + if (unlikely (key == kINVALID)) return; if ((occupancy + occupancy / 2) >= mask && !resize ()) return; unsigned int i = bucket_for (key); - if (value == INVALID && items[i].key != key) + if (value == vINVALID && items[i].key != key) return; /* Trying to delete non-existent key. */ if (!items[i].is_unused ()) @@ -143,24 +149,22 @@ struct hb_map_t population++; } - hb_codepoint_t get (hb_codepoint_t key) const + V get (K key) const { - if (unlikely (!items)) return INVALID; + if (unlikely (!items)) return vINVALID; unsigned int i = bucket_for (key); - return items[i].key == key ? items[i].value : INVALID; + return items[i].key == key ? items[i].value : vINVALID; } - void del (hb_codepoint_t key) { set (key, INVALID); } - - static constexpr hb_codepoint_t INVALID = HB_MAP_VALUE_INVALID; + void del (K key) { set (key, vINVALID); } /* Has interface. */ - static constexpr hb_codepoint_t SENTINEL = INVALID; - typedef hb_codepoint_t value_t; - value_t operator [] (hb_codepoint_t k) const { return get (k); } - bool has (hb_codepoint_t k) const { return (*this)[k] != SENTINEL; } + static constexpr V SENTINEL = vINVALID; + typedef V value_t; + value_t operator [] (K k) const { return get (k); } + bool has (K k) const { return (*this)[k] != SENTINEL; } /* Projection. */ - hb_codepoint_t operator () (hb_codepoint_t k) const { return get (k); } + V operator () (K k) const { return get (k); } void clear () { @@ -174,20 +178,20 @@ struct hb_map_t protected: - unsigned int bucket_for (hb_codepoint_t key) const + unsigned int bucket_for (K key) const { unsigned int i = hb_hash (key) % prime; unsigned int step = 0; - unsigned int tombstone = INVALID; + unsigned int tombstone = (unsigned) -1; while (!items[i].is_unused ()) { if (items[i].key == key) return i; - if (tombstone == INVALID && items[i].is_tombstone ()) + if (tombstone == (unsigned) -1 && items[i].is_tombstone ()) tombstone = i; i = (i + ++step) & mask; } - return tombstone == INVALID ? i : tombstone; + return tombstone == (unsigned) -1 ? i : tombstone; } static unsigned int prime_for (unsigned int shift) @@ -242,5 +246,10 @@ struct hb_map_t } }; +struct hb_map_t : hb_hashmap_t {}; + #endif /* HB_MAP_HH */