[map] Make unique_ptr hashable

This commit is contained in:
Behdad Esfahbod 2022-06-02 18:04:12 -06:00
parent 8bb2a3326e
commit 997d9cc466
9 changed files with 42 additions and 32 deletions

View File

@ -64,7 +64,8 @@ struct hb_bimap_t
hb_codepoint_t backward (hb_codepoint_t rhs) const { return back_map.get (rhs); } hb_codepoint_t backward (hb_codepoint_t rhs) const { return back_map.get (rhs); }
hb_codepoint_t operator [] (hb_codepoint_t lhs) const { return get (lhs); } hb_codepoint_t operator [] (hb_codepoint_t lhs) const { return get (lhs); }
bool has (hb_codepoint_t lhs, hb_codepoint_t *vp = nullptr) const { return forw_map.has (lhs, vp); } bool has (hb_codepoint_t lhs) const { return forw_map.has (lhs); }
void del (hb_codepoint_t lhs) void del (hb_codepoint_t lhs)
{ {

View File

@ -77,10 +77,10 @@ struct hb_hashmap_t
template <bool v = minus_one, template <bool v = minus_one,
hb_enable_if (v == false)> hb_enable_if (v == false)>
static V default_value () { return V(); }; static const V& default_value () { return Null(V); };
template <bool v = minus_one, template <bool v = minus_one,
hb_enable_if (v == true)> hb_enable_if (v == true)>
static V default_value () { return V(-1); }; static const V& default_value () { static const V minus_1 = -1; return minus_1; };
void clear () void clear ()
{ {
@ -197,10 +197,10 @@ struct hb_hashmap_t
return true; return true;
} }
bool set (K key, const V &value) { return set_with_hash (key, hb_hash (key), value); } template <typename VV>
bool set (K key, V&& value) { return set_with_hash (key, hb_hash (key), std::move (value)); } bool set (K key, VV&& value) { return set_with_hash (key, hb_hash (key), std::forward<VV> (value)); }
V get (K key) const const V& get (K key) const
{ {
if (unlikely (!items)) return item_t::default_value (); if (unlikely (!items)) return item_t::default_value ();
unsigned int i = bucket_for (key); unsigned int i = bucket_for (key);
@ -212,22 +212,22 @@ struct hb_hashmap_t
/* Has interface. */ /* Has interface. */
typedef V value_t; typedef V value_t;
value_t operator [] (K k) const { return get (k); } value_t operator [] (K k) const { return get (k); }
bool has (K key, V *vp = nullptr) const bool has (K key, const V **vp = nullptr) const
{ {
if (unlikely (!items)) if (unlikely (!items))
{ {
if (vp) *vp = item_t::default_value (); if (vp) *vp = &item_t::default_value ();
return false; return false;
} }
unsigned int i = bucket_for (key); unsigned int i = bucket_for (key);
if (items[i].is_real () && items[i] == key) if (items[i].is_real () && items[i] == key)
{ {
if (vp) *vp = items[i].value; if (vp) *vp = &items[i].value;
return true; return true;
} }
else else
{ {
if (vp) *vp = item_t::default_value (); if (vp) *vp = &item_t::default_value ();
return false; return false;
} }
} }
@ -320,7 +320,7 @@ struct hb_hashmap_t
} }
items[i].key = key; items[i].key = key;
items[i].value = value; items[i].value = std::forward<VV> (value);
items[i].hash = hash; items[i].hash = hash;
items[i].set_used (true); items[i].set_used (true);
items[i].set_tombstone (is_delete); items[i].set_tombstone (is_delete);
@ -332,12 +332,12 @@ struct hb_hashmap_t
return true; return true;
} }
unsigned int bucket_for (K key) const unsigned int bucket_for (const K &key) const
{ {
return bucket_for_hash (key, hb_hash (key)); return bucket_for_hash (key, hb_hash (key));
} }
unsigned int bucket_for_hash (K key, uint32_t hash) const unsigned int bucket_for_hash (const K &key, uint32_t hash) const
{ {
hash &= 0x3FFFFFFF; // We only store lower 30bit of hash hash &= 0x3FFFFFFF; // We only store lower 30bit of hash
unsigned int i = hash % prime; unsigned int i = hash % prime;

View File

@ -97,10 +97,10 @@ struct CPALV1Tail
c->push (); c->push ();
for (const auto _ : colorLabels) for (const auto _ : colorLabels)
{ {
hb_codepoint_t v; const hb_codepoint_t *v;
if (!color_index_map->has (_, &v)) continue; if (!color_index_map->has (_, &v)) continue;
NameID new_color_idx; NameID new_color_idx;
new_color_idx = v; new_color_idx = *v;
if (!c->copy<NameID> (new_color_idx)) if (!c->copy<NameID> (new_color_idx))
{ {
c->pop_discard (); c->pop_discard ();

View File

@ -659,8 +659,8 @@ struct LangSys
auto *out = c->serializer->start_embed (*this); auto *out = c->serializer->start_embed (*this);
if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false); if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
unsigned v; const unsigned *v;
out->reqFeatureIndex = l->feature_index_map->has (reqFeatureIndex, &v) ? v : 0xFFFFu; out->reqFeatureIndex = l->feature_index_map->has (reqFeatureIndex, &v) ? *v : 0xFFFFu;
if (!l->visitFeatureIndex (featureIndex.len)) if (!l->visitFeatureIndex (featureIndex.len))
return_trace (false); return_trace (false);

View File

@ -111,8 +111,7 @@ struct hb_closure_context_t :
if (!done_lookups_glyph_set->has (lookup_index)) if (!done_lookups_glyph_set->has (lookup_index))
{ {
hb::shared_ptr<hb_set_t> empty_set {hb_set_create ()}; if (unlikely (!done_lookups_glyph_set->set (lookup_index, hb::unique_ptr<hb_set_t> {hb_set_create ()})))
if (unlikely (!done_lookups_glyph_set->set (lookup_index, empty_set)))
return true; return true;
} }
@ -168,7 +167,7 @@ struct hb_closure_context_t :
hb_closure_context_t (hb_face_t *face_, hb_closure_context_t (hb_face_t *face_,
hb_set_t *glyphs_, hb_set_t *glyphs_,
hb_map_t *done_lookups_glyph_count_, hb_map_t *done_lookups_glyph_count_,
hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *done_lookups_glyph_set_, hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> *done_lookups_glyph_set_,
unsigned int nesting_level_left_ = HB_MAX_NESTING_LEVEL) : unsigned int nesting_level_left_ = HB_MAX_NESTING_LEVEL) :
face (face_), face (face_),
glyphs (glyphs_), glyphs (glyphs_),
@ -192,7 +191,7 @@ struct hb_closure_context_t :
private: private:
hb_map_t *done_lookups_glyph_count; hb_map_t *done_lookups_glyph_count;
hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *done_lookups_glyph_set; hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> *done_lookups_glyph_set;
unsigned int lookup_count = 0; unsigned int lookup_count = 0;
}; };

View File

@ -1501,7 +1501,7 @@ hb_ot_layout_lookup_substitute_closure (hb_face_t *face,
hb_set_t *glyphs /* OUT */) hb_set_t *glyphs /* OUT */)
{ {
hb_map_t done_lookups_glyph_count; hb_map_t done_lookups_glyph_count;
hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> done_lookups_glyph_set; hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> done_lookups_glyph_set;
OT::hb_closure_context_t c (face, glyphs, &done_lookups_glyph_count, &done_lookups_glyph_set); OT::hb_closure_context_t c (face, glyphs, &done_lookups_glyph_count, &done_lookups_glyph_set);
const OT::SubstLookup& l = face->table.GSUB->table->get_lookup (lookup_index); const OT::SubstLookup& l = face->table.GSUB->table->get_lookup (lookup_index);
@ -1526,7 +1526,7 @@ hb_ot_layout_lookups_substitute_closure (hb_face_t *face,
hb_set_t *glyphs /* OUT */) hb_set_t *glyphs /* OUT */)
{ {
hb_map_t done_lookups_glyph_count; hb_map_t done_lookups_glyph_count;
hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> done_lookups_glyph_set; hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> done_lookups_glyph_set;
OT::hb_closure_context_t c (face, glyphs, &done_lookups_glyph_count, &done_lookups_glyph_set); OT::hb_closure_context_t c (face, glyphs, &done_lookups_glyph_count, &done_lookups_glyph_set);
const GSUB& gsub = *face->table.GSUB->table; const GSUB& gsub = *face->table.GSUB->table;

View File

@ -85,9 +85,11 @@ HB_INTERNAL bool postV2Tail::subset (hb_subset_context_t *c) const
unsigned old_index = glyphNameIndex[old_gid]; unsigned old_index = glyphNameIndex[old_gid];
unsigned new_index; unsigned new_index;
const unsigned *new_index2;
if (old_index <= 257) new_index = old_index; if (old_index <= 257) new_index = old_index;
else if (!old_new_index_map.has (old_index, &new_index)) else if (!old_new_index_map.has (old_index, &new_index2))
{ {
new_index = *new_index2;
hb_bytes_t s = _post.find_glyph_name (old_gid); hb_bytes_t s = _post.find_glyph_name (old_gid);
new_index = glyph_name_to_new_index.get (s); new_index = glyph_name_to_new_index.get (s);
if (new_index == (unsigned)-1) if (new_index == (unsigned)-1)

View File

@ -430,8 +430,8 @@ struct graph_t
auto new_subgraph = auto new_subgraph =
+ subgraph.keys () + subgraph.keys ()
| hb_map([&] (unsigned node_idx) { | hb_map([&] (unsigned node_idx) {
unsigned v; const unsigned *v;
if (index_map.has (node_idx, &v)) return v; if (index_map.has (node_idx, &v)) return *v;
return node_idx; return node_idx;
}) })
; ;
@ -443,11 +443,11 @@ struct graph_t
unsigned next = HB_SET_VALUE_INVALID; unsigned next = HB_SET_VALUE_INVALID;
while (roots.next (&next)) while (roots.next (&next))
{ {
unsigned v; const unsigned *v;
if (index_map.has (next, &v)) if (index_map.has (next, &v))
{ {
roots.del (next); roots.del (next);
roots.add (v); roots.add (*v);
} }
} }
@ -458,10 +458,10 @@ struct graph_t
{ {
for (const auto& link : vertices_[node_idx].obj.all_links ()) for (const auto& link : vertices_[node_idx].obj.all_links ())
{ {
unsigned v; const unsigned *v;
if (subgraph.has (link.objidx, &v)) if (subgraph.has (link.objidx, &v))
{ {
subgraph.set (link.objidx, v + 1); subgraph.set (link.objidx, *v + 1);
continue; continue;
} }
subgraph.set (link.objidx, 1); subgraph.set (link.objidx, 1);
@ -943,11 +943,11 @@ struct graph_t
{ {
for (auto& link : vertices_[i].obj.all_links_writer ()) for (auto& link : vertices_[i].obj.all_links_writer ())
{ {
unsigned v; const unsigned *v;
if (!id_map.has (link.objidx, &v)) continue; if (!id_map.has (link.objidx, &v)) continue;
if (only_wide && !(link.width == 4 && !link.is_signed)) continue; if (only_wide && !(link.width == 4 && !link.is_signed)) continue;
reassign_link (link, i, v); reassign_link (link, i, *v);
} }
} }
} }

View File

@ -195,6 +195,14 @@ main (int argc, char **argv)
m.get (hb::shared_ptr<hb_set_t> ()); m.get (hb::shared_ptr<hb_set_t> ());
m.get (hb::shared_ptr<hb_set_t> (hb_set_get_empty ())); m.get (hb::shared_ptr<hb_set_t> (hb_set_get_empty ()));
} }
/* Test hb::unique_ptr. */
hb_hash (hb::unique_ptr<hb_set_t> ());
{
hb_hashmap_t<hb::unique_ptr<hb_set_t>, hb::unique_ptr<hb_set_t>> m;
m.get (hb::unique_ptr<hb_set_t> ());
m.get (hb::unique_ptr<hb_set_t> (hb_set_get_empty ()));
}
return 0; return 0;
} }