[map] Allow invalid items to be pointer to static object
By derefencing them when necessary. Also, we do not rely on trivially-copyable, so remove that assertion.
This commit is contained in:
parent
98b26eedf5
commit
985b63b3ee
|
@ -211,8 +211,11 @@ struct
|
||||||
}
|
}
|
||||||
HB_FUNCOBJ (hb_bool);
|
HB_FUNCOBJ (hb_bool);
|
||||||
|
|
||||||
template <typename T> T hb_coerce (const T v) { return v; }
|
template <typename T>
|
||||||
template <typename T> T hb_coerce (const T *v) { return *v; }
|
T hb_coerce (const T v) { return v; }
|
||||||
|
template <typename T, typename V,
|
||||||
|
hb_enable_if (!hb_is_same (hb_decay<T>, hb_decay<V>) && hb_is_pointer(V))>
|
||||||
|
T hb_coerce (const V v) { return *v; }
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
|
|
|
@ -61,8 +61,6 @@ struct hb_hashmap_t
|
||||||
hb_copy (o, *this);
|
hb_copy (o, *this);
|
||||||
}
|
}
|
||||||
|
|
||||||
static_assert (std::is_trivially_copyable<K>::value, "");
|
|
||||||
static_assert (std::is_trivially_copyable<V>::value, "");
|
|
||||||
static_assert (std::is_trivially_destructible<K>::value, "");
|
static_assert (std::is_trivially_destructible<K>::value, "");
|
||||||
static_assert (std::is_trivially_destructible<V>::value, "");
|
static_assert (std::is_trivially_destructible<V>::value, "");
|
||||||
|
|
||||||
|
@ -75,9 +73,9 @@ struct hb_hashmap_t
|
||||||
void clear ()
|
void clear ()
|
||||||
{
|
{
|
||||||
new (hb_addressof (key)) K ();
|
new (hb_addressof (key)) K ();
|
||||||
key = kINVALID;
|
key = hb_coerce<K> (kINVALID);
|
||||||
new (hb_addressof (value)) V ();
|
new (hb_addressof (value)) V ();
|
||||||
value = vINVALID;
|
value = hb_coerce<V> (vINVALID);
|
||||||
hash = 0;
|
hash = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,19 +83,19 @@ struct hb_hashmap_t
|
||||||
bool operator == (const item_t &o) { return *this == o.key; }
|
bool operator == (const item_t &o) { return *this == o.key; }
|
||||||
bool is_unused () const
|
bool is_unused () const
|
||||||
{
|
{
|
||||||
const K inv = kINVALID;
|
const K inv = hb_coerce<K> (kINVALID);
|
||||||
return key == inv;
|
return key == inv;
|
||||||
}
|
}
|
||||||
bool is_tombstone () const
|
bool is_tombstone () const
|
||||||
{
|
{
|
||||||
const K kinv = kINVALID;
|
const K kinv = hb_coerce<K> (kINVALID);
|
||||||
const V vinv = vINVALID;
|
const V vinv = hb_coerce<V> (vINVALID);
|
||||||
return key != kinv && value == vinv;
|
return key != kinv && value == vinv;
|
||||||
}
|
}
|
||||||
bool is_real () const
|
bool is_real () const
|
||||||
{
|
{
|
||||||
const K kinv = kINVALID;
|
const K kinv = hb_coerce<K> (kINVALID);
|
||||||
const V vinv = vINVALID;
|
const V vinv = hb_coerce<V> (vINVALID);
|
||||||
return key != kinv && value != vinv;
|
return key != kinv && value != vinv;
|
||||||
}
|
}
|
||||||
hb_pair_t<K, V> get_pair() const { return hb_pair_t<K, V> (key, value); }
|
hb_pair_t<K, V> get_pair() const { return hb_pair_t<K, V> (key, value); }
|
||||||
|
@ -196,12 +194,12 @@ struct hb_hashmap_t
|
||||||
|
|
||||||
V get (K key) const
|
V get (K key) const
|
||||||
{
|
{
|
||||||
if (unlikely (!items)) return vINVALID;
|
if (unlikely (!items)) return hb_coerce<V> (vINVALID);
|
||||||
unsigned int i = bucket_for (key);
|
unsigned int i = bucket_for (key);
|
||||||
return items[i].is_real () && items[i] == key ? items[i].value : vINVALID;
|
return items[i].is_real () && items[i] == key ? items[i].value : hb_coerce<V> (vINVALID);
|
||||||
}
|
}
|
||||||
|
|
||||||
void del (K key) { set (key, vINVALID); }
|
void del (K key) { set (key, hb_coerce<V> (vINVALID)); }
|
||||||
|
|
||||||
/* Has interface. */
|
/* Has interface. */
|
||||||
typedef V value_t;
|
typedef V value_t;
|
||||||
|
@ -210,7 +208,7 @@ struct hb_hashmap_t
|
||||||
{
|
{
|
||||||
V v = (*this)[k];
|
V v = (*this)[k];
|
||||||
if (vp) *vp = v;
|
if (vp) *vp = v;
|
||||||
const V vinv = vINVALID;
|
const V vinv = hb_coerce<V> (vINVALID);
|
||||||
return v != vinv;
|
return v != vinv;
|
||||||
}
|
}
|
||||||
/* Projection. */
|
/* Projection. */
|
||||||
|
@ -266,12 +264,12 @@ struct hb_hashmap_t
|
||||||
bool set_with_hash (K key, uint32_t hash, VV&& value)
|
bool set_with_hash (K key, uint32_t hash, VV&& value)
|
||||||
{
|
{
|
||||||
if (unlikely (!successful)) return false;
|
if (unlikely (!successful)) return false;
|
||||||
const K kinv = kINVALID;
|
const K kinv = hb_coerce<K> (kINVALID);
|
||||||
if (unlikely (key == kinv)) return true;
|
if (unlikely (key == kinv)) return true;
|
||||||
if (unlikely ((occupancy + occupancy / 2) >= mask && !resize ())) return false;
|
if (unlikely ((occupancy + occupancy / 2) >= mask && !resize ())) return false;
|
||||||
unsigned int i = bucket_for_hash (key, hash);
|
unsigned int i = bucket_for_hash (key, hash);
|
||||||
|
|
||||||
const V vinv = vINVALID;
|
const V vinv = hb_coerce<V> (vINVALID);
|
||||||
if (value == vinv && items[i].key != key)
|
if (value == vinv && items[i].key != key)
|
||||||
return true; /* Trying to delete non-existent key. */
|
return true; /* Trying to delete non-existent key. */
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue