[map] Templatize hb_map_t
Template name is hb_hashmap_t<K,V>.
This commit is contained in:
parent
4b7f4dbc0c
commit
c98f51da71
|
@ -31,22 +31,28 @@
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* hb_map_t
|
* hb_hashmap_t
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct hb_map_t
|
template <typename K, typename V,
|
||||||
|
K kINVALID = hb_is_pointer (K) ? 0 : (K) -1,
|
||||||
|
V vINVALID = hb_is_pointer (V) ? 0 : (V) -1>
|
||||||
|
struct hb_hashmap_t
|
||||||
{
|
{
|
||||||
HB_NO_COPY_ASSIGN (hb_map_t);
|
HB_NO_COPY_ASSIGN (hb_hashmap_t);
|
||||||
hb_map_t () { init (); }
|
hb_hashmap_t () { init (); }
|
||||||
~hb_map_t () { fini (); }
|
~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
|
struct item_t
|
||||||
{
|
{
|
||||||
hb_codepoint_t key;
|
K key;
|
||||||
hb_codepoint_t value;
|
V value;
|
||||||
|
|
||||||
bool is_unused () const { return key == INVALID; }
|
bool is_unused () const { return key == kINVALID; }
|
||||||
bool is_tombstone () const { return key != INVALID && value == INVALID; }
|
bool is_tombstone () const { return key != kINVALID && value == vINVALID; }
|
||||||
};
|
};
|
||||||
|
|
||||||
hb_object_header_t header;
|
hb_object_header_t header;
|
||||||
|
@ -110,7 +116,7 @@ struct hb_map_t
|
||||||
/* Insert back old items. */
|
/* Insert back old items. */
|
||||||
if (old_items)
|
if (old_items)
|
||||||
for (unsigned int i = 0; i < old_size; i++)
|
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);
|
set (old_items[i].key, old_items[i].value);
|
||||||
|
|
||||||
free (old_items);
|
free (old_items);
|
||||||
|
@ -118,14 +124,14 @@ struct hb_map_t
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void set (hb_codepoint_t key, hb_codepoint_t value)
|
void set (K key, V value)
|
||||||
{
|
{
|
||||||
if (unlikely (!successful)) return;
|
if (unlikely (!successful)) return;
|
||||||
if (unlikely (key == INVALID)) return;
|
if (unlikely (key == kINVALID)) return;
|
||||||
if ((occupancy + occupancy / 2) >= mask && !resize ()) return;
|
if ((occupancy + occupancy / 2) >= mask && !resize ()) return;
|
||||||
unsigned int i = bucket_for (key);
|
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. */
|
return; /* Trying to delete non-existent key. */
|
||||||
|
|
||||||
if (!items[i].is_unused ())
|
if (!items[i].is_unused ())
|
||||||
|
@ -143,24 +149,22 @@ struct hb_map_t
|
||||||
population++;
|
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);
|
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); }
|
void del (K key) { set (key, vINVALID); }
|
||||||
|
|
||||||
static constexpr hb_codepoint_t INVALID = HB_MAP_VALUE_INVALID;
|
|
||||||
|
|
||||||
/* Has interface. */
|
/* Has interface. */
|
||||||
static constexpr hb_codepoint_t SENTINEL = INVALID;
|
static constexpr V SENTINEL = vINVALID;
|
||||||
typedef hb_codepoint_t value_t;
|
typedef V value_t;
|
||||||
value_t operator [] (hb_codepoint_t k) const { return get (k); }
|
value_t operator [] (K k) const { return get (k); }
|
||||||
bool has (hb_codepoint_t k) const { return (*this)[k] != SENTINEL; }
|
bool has (K k) const { return (*this)[k] != SENTINEL; }
|
||||||
/* Projection. */
|
/* Projection. */
|
||||||
hb_codepoint_t operator () (hb_codepoint_t k) const { return get (k); }
|
V operator () (K k) const { return get (k); }
|
||||||
|
|
||||||
void clear ()
|
void clear ()
|
||||||
{
|
{
|
||||||
|
@ -174,20 +178,20 @@ struct hb_map_t
|
||||||
|
|
||||||
protected:
|
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 i = hb_hash (key) % prime;
|
||||||
unsigned int step = 0;
|
unsigned int step = 0;
|
||||||
unsigned int tombstone = INVALID;
|
unsigned int tombstone = (unsigned) -1;
|
||||||
while (!items[i].is_unused ())
|
while (!items[i].is_unused ())
|
||||||
{
|
{
|
||||||
if (items[i].key == key)
|
if (items[i].key == key)
|
||||||
return i;
|
return i;
|
||||||
if (tombstone == INVALID && items[i].is_tombstone ())
|
if (tombstone == (unsigned) -1 && items[i].is_tombstone ())
|
||||||
tombstone = i;
|
tombstone = i;
|
||||||
i = (i + ++step) & mask;
|
i = (i + ++step) & mask;
|
||||||
}
|
}
|
||||||
return tombstone == INVALID ? i : tombstone;
|
return tombstone == (unsigned) -1 ? i : tombstone;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int prime_for (unsigned int shift)
|
static unsigned int prime_for (unsigned int shift)
|
||||||
|
@ -242,5 +246,10 @@ struct hb_map_t
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct hb_map_t : hb_hashmap_t<hb_codepoint_t,
|
||||||
|
hb_codepoint_t,
|
||||||
|
HB_MAP_VALUE_INVALID,
|
||||||
|
HB_MAP_VALUE_INVALID> {};
|
||||||
|
|
||||||
|
|
||||||
#endif /* HB_MAP_HH */
|
#endif /* HB_MAP_HH */
|
||||||
|
|
Loading…
Reference in New Issue