Merge pull request #3626 from harfbuzz/fix-map

Fix map
This commit is contained in:
Behdad Esfahbod 2022-06-03 08:56:20 +01:00 committed by GitHub
commit 51ca1c9b59
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 187 additions and 200 deletions

View File

@ -227,14 +227,6 @@ struct
}
HB_FUNCOBJ (hb_bool);
template <typename T>
static inline
constexpr 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>) && std::is_pointer<V>::value)>
static inline
constexpr T hb_coerce (const V v) { return *v; }
struct
{
private:
@ -247,6 +239,11 @@ struct
{
return v.get () ? v.get ()->hash () : 0;
}
template <typename T> constexpr uint32_t
impl (const hb::unique_ptr<T>& v, hb_priority<1>) const
{
return v.get () ? v.get ()->hash () : 0;
}
template <typename T> constexpr auto
impl (const T& v, hb_priority<0>) const HB_RETURN (uint32_t, std::hash<hb_decay<decltype (hb_deref (v))>>{} (hb_deref (v)))

View File

@ -56,7 +56,6 @@ struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&>
hb_array_t& operator= (const hb_array_t&) = default;
hb_array_t& operator= (hb_array_t&&) = default;
constexpr hb_array_t (std::nullptr_t) : hb_array_t () {}
constexpr hb_array_t (Type *array_, unsigned int length_) : arrayZ (array_), length (length_) {}
template <unsigned int length_>
constexpr hb_array_t (Type (&array_)[length_]) : hb_array_t (array_, length_) {}
@ -314,7 +313,6 @@ struct hb_sorted_array_t :
hb_sorted_array_t& operator= (const hb_sorted_array_t&) = default;
hb_sorted_array_t& operator= (hb_sorted_array_t&&) = default;
constexpr hb_sorted_array_t (std::nullptr_t) : hb_sorted_array_t () {}
constexpr hb_sorted_array_t (Type *array_, unsigned int length_) : hb_array_t<Type> (array_, length_) {}
template <unsigned int length_>
constexpr hb_sorted_array_t (Type (&array_)[length_]) : hb_array_t<Type> (array_) {}

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 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)
{

View File

@ -58,8 +58,8 @@ struct shared_ptr
shared_ptr (const shared_ptr &o) : p (v::reference (o.p)) {}
shared_ptr (shared_ptr &&o) : p (o.p) { o.p = nullptr; }
shared_ptr& operator = (const shared_ptr &o) { if (p != o.p) { destroy (); p = o.p; reference (); } return *this; }
shared_ptr& operator = (shared_ptr &&o) { destroy (); p = o.p; o.p = nullptr; return *this; }
~shared_ptr () { v::destroy (p); }
shared_ptr& operator = (shared_ptr &&o) { v::destroy (p); p = o.p; o.p = nullptr; return *this; }
~shared_ptr () { v::destroy (p); p = nullptr; }
T* get() const { return p; }
@ -89,6 +89,38 @@ struct shared_ptr
template<typename T> struct is_shared_ptr : std::false_type {};
template<typename T> struct is_shared_ptr<shared_ptr<T>> : std::true_type {};
template <typename T>
struct unique_ptr
{
using element_type = T;
using v = vtable<T>;
explicit unique_ptr (T *p = nullptr) : p (p) {}
unique_ptr (const unique_ptr &o) = delete;
unique_ptr (unique_ptr &&o) : p (o.p) { o.p = nullptr; }
unique_ptr& operator = (const unique_ptr &o) = delete;
unique_ptr& operator = (unique_ptr &&o) { v::destroy (p); p = o.p; o.p = nullptr; return *this; }
~unique_ptr () { v::destroy (p); p = nullptr; }
T* get() const { return p; }
T* release () { T* v = p; p = nullptr; return v; }
void swap (unique_ptr &o) { std::swap (p, o.p); }
friend void swap (unique_ptr &a, unique_ptr &b) { std::swap (a.p, b.p); }
operator T * () const { return p; }
T& operator * () const { return *get (); }
T* operator -> () const { return get (); }
operator bool () { return p; }
private:
T *p;
};
template<typename T> struct is_unique_ptr : std::false_type {};
template<typename T> struct is_unique_ptr<unique_ptr<T>> : std::true_type {};
template <typename T,
T * (*_get_empty) (void),
T * (*_reference) (T *),
@ -144,6 +176,16 @@ struct std::hash<hb::shared_ptr<T>>
}
};
template<typename T>
struct std::hash<hb::unique_ptr<T>>
{
std::size_t operator()(const hb::unique_ptr<T>& v) const noexcept
{
std::size_t h = std::hash<decltype (v.get ())>{}(v.get ());
return h;
}
};
#endif /* __cplusplus */

View File

@ -35,14 +35,10 @@
*/
template <typename K, typename V,
typename k_invalid_t = K,
typename v_invalid_t = V,
k_invalid_t kINVALID = std::is_pointer<K>::value ? 0 : std::is_signed<K>::value ? hb_int_min (K) : (K) -1,
v_invalid_t vINVALID = std::is_pointer<V>::value ? 0 : std::is_signed<V>::value ? hb_int_min (V) : (V) -1>
bool minus_one = false>
struct hb_hashmap_t
{
hb_hashmap_t () { init (); }
hb_hashmap_t (std::nullptr_t) : hb_hashmap_t () {}
~hb_hashmap_t () { fini (); }
hb_hashmap_t (const hb_hashmap_t& o) : hb_hashmap_t () { resize (population); hb_copy (o, *this); }
@ -68,38 +64,37 @@ struct hb_hashmap_t
struct item_t
{
K key;
uint32_t hash;
uint32_t hash : 30;
uint32_t is_used_ : 1;
uint32_t is_tombstone_ : 1;
V value;
bool is_used () const { return is_used_; }
void set_used (bool is_used) { is_used_ = is_used; }
bool is_tombstone () const { return is_tombstone_; }
void set_tombstone (bool is_tombstone) { is_tombstone_ = is_tombstone; }
bool is_real () const { return is_used_ && !is_tombstone_; }
template <bool v = minus_one,
hb_enable_if (v == false)>
static const V& default_value () { return Null(V); };
template <bool v = minus_one,
hb_enable_if (v == true)>
static const V& default_value () { static const V minus_1 = -1; return minus_1; };
void clear ()
{
new (std::addressof (key)) K ();
key = hb_coerce<K> (kINVALID);
new (std::addressof (value)) V ();
value = hb_coerce<V> (vINVALID);
hash = 0;
is_used_ = false;
is_tombstone_ = false;
}
bool operator == (const K &o) { return hb_deref (key) == hb_deref (o); }
bool operator == (const item_t &o) { return *this == o.key; }
bool is_unused () const
{
const K inv = hb_coerce<K> (kINVALID);
return key == inv;
}
bool is_tombstone () const
{
const K kinv = hb_coerce<K> (kINVALID);
const V vinv = hb_coerce<V> (vINVALID);
return key != kinv && value == vinv;
}
bool is_real () const
{
const K kinv = hb_coerce<K> (kINVALID);
const V vinv = hb_coerce<V> (vINVALID);
return key != kinv && value != vinv;
}
hb_pair_t<K, V> get_pair() const { return hb_pair_t<K, V> (key, value); }
hb_pair_t<const K &, const V &> get_pair_ref() const { return hb_pair_t<const K &, const V &> (key, value); }
uint32_t total_hash () const
{ return (hash * 31) + hb_hash (value); }
@ -203,27 +198,39 @@ struct hb_hashmap_t
return true;
}
bool set (K key, const V& value) { return set_with_hash (key, hb_hash (key), value); }
bool set (K key, V&& value) { return set_with_hash (key, hb_hash (key), std::move (value)); }
template <typename VV>
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 hb_coerce<V> (vINVALID);
if (unlikely (!items)) return item_t::default_value ();
unsigned int i = bucket_for (key);
return items[i].is_real () && items[i] == key ? items[i].value : hb_coerce<V> (vINVALID);
return items[i].is_real () && items[i] == key ? items[i].value : item_t::default_value ();
}
void del (K key) { set (key, hb_coerce<V> (vINVALID)); }
void del (K key) { set_with_hash (key, hb_hash (key), item_t::default_value (), true); }
/* Has interface. */
typedef V value_t;
value_t operator [] (K k) const { return get (k); }
bool has (K k, V *vp = nullptr) const
bool has (K key, const V **vp = nullptr) const
{
const V &v = (*this)[k];
if (vp) *vp = v;
const V vinv = hb_coerce<V> (vINVALID);
return v != vinv;
if (unlikely (!items))
{
if (vp) *vp = &item_t::default_value ();
return false;
}
unsigned int i = bucket_for (key);
if (items[i].is_real () && items[i] == key)
{
if (vp) *vp = &items[i].value;
return true;
}
else
{
if (vp) *vp = &item_t::default_value ();
return false;
}
}
/* Projection. */
V operator () (K k) const { return get (k); }
@ -275,6 +282,12 @@ struct hb_hashmap_t
| hb_filter (&item_t::is_real)
| hb_map (&item_t::get_pair)
)
auto iter_ref () const HB_AUTO_RETURN
(
+ hb_array (items, mask ? mask + 1 : 0)
| hb_filter (&item_t::is_real)
| hb_map (&item_t::get_pair_ref)
)
auto keys () const HB_AUTO_RETURN
(
+ hb_array (items, mask ? mask + 1 : 0)
@ -297,19 +310,16 @@ struct hb_hashmap_t
protected:
template <typename VV>
bool set_with_hash (K key, uint32_t hash, VV&& value)
bool set_with_hash (K key, uint32_t hash, VV&& value, bool is_delete=false)
{
if (unlikely (!successful)) return false;
const K kinv = hb_coerce<K> (kINVALID);
if (unlikely (key == kinv)) return true;
if (unlikely ((occupancy + occupancy / 2) >= mask && !resize ())) return false;
unsigned int i = bucket_for_hash (key, hash);
const V vinv = hb_coerce<V> (vINVALID);
if (value == vinv && items[i].key != key)
if (is_delete && items[i].key != key)
return true; /* Trying to delete non-existent key. */
if (!items[i].is_unused ())
if (items[i].is_used ())
{
occupancy--;
if (!items[i].is_tombstone ())
@ -317,27 +327,30 @@ struct hb_hashmap_t
}
items[i].key = key;
items[i].value = value;
items[i].value = std::forward<VV> (value);
items[i].hash = hash;
items[i].set_used (true);
items[i].set_tombstone (is_delete);
occupancy++;
if (!items[i].is_tombstone ())
if (!is_delete)
population++;
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));
}
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
unsigned int i = hash % prime;
unsigned int step = 0;
unsigned int tombstone = (unsigned) -1;
while (!items[i].is_unused ())
while (items[i].is_used ())
{
if (items[i].hash == hash && items[i] == key)
return i;
@ -406,21 +419,14 @@ struct hb_hashmap_t
struct hb_map_t : hb_hashmap_t<hb_codepoint_t,
hb_codepoint_t,
hb_codepoint_t,
hb_codepoint_t,
HB_MAP_VALUE_INVALID,
HB_MAP_VALUE_INVALID>
true>
{
using hashmap = hb_hashmap_t<hb_codepoint_t,
hb_codepoint_t,
hb_codepoint_t,
hb_codepoint_t,
HB_MAP_VALUE_INVALID,
HB_MAP_VALUE_INVALID>;
true>;
~hb_map_t () = default;
hb_map_t () : hashmap () {}
hb_map_t (std::nullptr_t) : hb_map_t () {}
hb_map_t (const hb_map_t &o) : hashmap ((hashmap &) o) {}
hb_map_t (hb_map_t &&o) : hashmap (std::move ((hashmap &) o)) {}
hb_map_t& operator= (const hb_map_t&) = default;

View File

@ -1476,27 +1476,26 @@ struct SubtableUnicodesCache {
private:
const void* base;
hb_hashmap_t<intptr_t, hb_set_t*> cached_unicodes;
hb_hashmap_t<intptr_t, hb::unique_ptr<hb_set_t>> cached_unicodes;
public:
SubtableUnicodesCache(const void* cmap_base)
: base(cmap_base), cached_unicodes() {}
~SubtableUnicodesCache()
{
for (hb_set_t* s : cached_unicodes.values()) {
hb_set_destroy (s);
}
}
hb_set_t* set_for(const EncodingRecord* record)
hb_set_t* set_for (const EncodingRecord* record)
{
if (!cached_unicodes.has ((intptr_t) record)) {
hb_set_t* new_set = hb_set_create ();
if (!cached_unicodes.set ((intptr_t) record, new_set)) {
hb_set_destroy (new_set);
if (!cached_unicodes.has ((intptr_t) record))
{
hb_set_t *s = hb_set_create ();
if (unlikely (s->in_error ()))
return hb_set_get_empty ();
(base+record->subtable).collect_unicodes (s);
if (unlikely (!cached_unicodes.set ((intptr_t) record, hb::unique_ptr<hb_set_t> {s})))
return hb_set_get_empty ();
}
(base+record->subtable).collect_unicodes (cached_unicodes.get ((intptr_t) record));
return s;
}
return cached_unicodes.get ((intptr_t) record);
}

View File

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

View File

@ -102,7 +102,7 @@ static void ClassDef_remap_and_serialize (
struct hb_prune_langsys_context_t
{
hb_prune_langsys_context_t (const void *table_,
hb_hashmap_t<unsigned, hb_set_t *> *script_langsys_map_,
hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> *script_langsys_map_,
const hb_map_t *duplicate_feature_map_,
hb_set_t *new_collected_feature_indexes_)
:table (table_),
@ -122,7 +122,7 @@ struct hb_prune_langsys_context_t
public:
const void *table;
hb_hashmap_t<unsigned, hb_set_t *> *script_langsys_map;
hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> *script_langsys_map;
const hb_map_t *duplicate_feature_map;
hb_set_t *new_feature_indexes;
@ -162,14 +162,14 @@ struct hb_subset_layout_context_t :
hb_subset_context_t *subset_context;
const hb_tag_t table_tag;
const hb_map_t *lookup_index_map;
const hb_hashmap_t<unsigned, hb_set_t *> *script_langsys_map;
const hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> *script_langsys_map;
const hb_map_t *feature_index_map;
unsigned cur_script_index;
hb_subset_layout_context_t (hb_subset_context_t *c_,
hb_tag_t tag_,
hb_map_t *lookup_map_,
hb_hashmap_t<unsigned, hb_set_t *> *script_langsys_map_,
hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> *script_langsys_map_,
hb_map_t *feature_index_map_) :
subset_context (c_),
table_tag (tag_),
@ -659,8 +659,8 @@ struct LangSys
auto *out = c->serializer->start_embed (*this);
if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
unsigned v;
out->reqFeatureIndex = l->feature_index_map->has (reqFeatureIndex, &v) ? v : 0xFFFFu;
const unsigned *v;
out->reqFeatureIndex = l->feature_index_map->has (reqFeatureIndex, &v) ? *v : 0xFFFFu;
if (!l->visitFeatureIndex (featureIndex.len))
return_trace (false);
@ -723,12 +723,8 @@ struct Script
if (!c->script_langsys_map->has (script_index))
{
hb_set_t* empty_set = hb_set_create ();
if (unlikely (!c->script_langsys_map->set (script_index, empty_set)))
{
hb_set_destroy (empty_set);
if (unlikely (!c->script_langsys_map->set (script_index, hb::unique_ptr<hb_set_t> {hb_set_create ()})))
return;
}
}
unsigned langsys_count = get_lang_sys_count ();

View File

@ -109,14 +109,10 @@ struct hb_closure_context_t :
{
done_lookups_glyph_count->set (lookup_index, glyphs->get_population ());
if (!done_lookups_glyph_set->get (lookup_index))
if (!done_lookups_glyph_set->has (lookup_index))
{
hb_set_t* empty_set = hb_set_create ();
if (unlikely (!done_lookups_glyph_set->set (lookup_index, empty_set)))
{
hb_set_destroy (empty_set);
if (unlikely (!done_lookups_glyph_set->set (lookup_index, hb::unique_ptr<hb_set_t> {hb_set_create ()})))
return true;
}
}
hb_set_clear (done_lookups_glyph_set->get (lookup_index));
@ -171,7 +167,7 @@ struct hb_closure_context_t :
hb_closure_context_t (hb_face_t *face_,
hb_set_t *glyphs_,
hb_map_t *done_lookups_glyph_count_,
hb_hashmap_t<unsigned, 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) :
face (face_),
glyphs (glyphs_),
@ -195,7 +191,7 @@ struct hb_closure_context_t :
private:
hb_map_t *done_lookups_glyph_count;
hb_hashmap_t<unsigned, 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;
};
@ -3733,7 +3729,7 @@ struct GSUBGPOS
}
void prune_langsys (const hb_map_t *duplicate_feature_map,
hb_hashmap_t<unsigned, hb_set_t *> *script_langsys_map,
hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> *script_langsys_map,
hb_set_t *new_feature_indexes /* OUT */) const
{
hb_prune_langsys_context_t c (this, script_langsys_map, duplicate_feature_map, new_feature_indexes);
@ -3791,7 +3787,7 @@ struct GSUBGPOS
hb_map_t *duplicate_feature_map /* OUT */) const
{
if (feature_indices->is_empty ()) return;
hb_hashmap_t<hb_tag_t, hb_set_t *> unique_features;
hb_hashmap_t<hb_tag_t, hb::unique_ptr<hb_set_t>> unique_features;
//find out duplicate features after subset
for (unsigned i : feature_indices->iter ())
{
@ -3799,16 +3795,9 @@ struct GSUBGPOS
if (t == HB_MAP_VALUE_INVALID) continue;
if (!unique_features.has (t))
{
hb_set_t* indices = hb_set_create ();
if (unlikely (indices == hb_set_get_empty () ||
!unique_features.set (t, indices)))
{
hb_set_destroy (indices);
for (auto _ : unique_features.iter ())
hb_set_destroy (_.second);
if (unlikely (!unique_features.set (t, hb::unique_ptr<hb_set_t> {hb_set_create ()})))
return;
}
if (unique_features.get (t))
if (unique_features.has (t))
unique_features.get (t)->add (i);
duplicate_feature_map->set (i, i);
continue;
@ -3853,9 +3842,6 @@ struct GSUBGPOS
duplicate_feature_map->set (i, i);
}
}
for (auto _ : unique_features.iter ())
hb_set_destroy (_.second);
}
void prune_features (const hb_map_t *lookup_indices, /* IN */

View File

@ -1501,15 +1501,12 @@ hb_ot_layout_lookup_substitute_closure (hb_face_t *face,
hb_set_t *glyphs /* OUT */)
{
hb_map_t done_lookups_glyph_count;
hb_hashmap_t<unsigned, 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);
const OT::SubstLookup& l = face->table.GSUB->table->get_lookup (lookup_index);
l.closure (&c, lookup_index);
for (auto _ : done_lookups_glyph_set.iter ())
hb_set_destroy (_.second);
}
/**
@ -1529,7 +1526,7 @@ hb_ot_layout_lookups_substitute_closure (hb_face_t *face,
hb_set_t *glyphs /* OUT */)
{
hb_map_t done_lookups_glyph_count;
hb_hashmap_t<unsigned, 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);
const GSUB& gsub = *face->table.GSUB->table;
@ -1551,9 +1548,6 @@ hb_ot_layout_lookups_substitute_closure (hb_face_t *face,
}
} while (iteration_count++ <= HB_CLOSURE_MAX_STAGES &&
glyphs_length != glyphs->get_population ());
for (auto _ : done_lookups_glyph_set.iter ())
hb_set_destroy (_.second);
}
/*

View File

@ -78,16 +78,18 @@ HB_INTERNAL bool postV2Tail::subset (hb_subset_context_t *c) const
post::accelerator_t _post (c->plan->source);
hb_hashmap_t<hb_bytes_t, unsigned, std::nullptr_t, unsigned, nullptr, (unsigned)-1> glyph_name_to_new_index;
hb_hashmap_t<hb_bytes_t, unsigned, true> glyph_name_to_new_index;
for (hb_codepoint_t new_gid = 0; new_gid < num_glyphs; new_gid++)
{
hb_codepoint_t old_gid = reverse_glyph_map.get (new_gid);
unsigned old_index = glyphNameIndex[old_gid];
unsigned new_index;
const unsigned *new_index2;
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);
new_index = glyph_name_to_new_index.get (s);
if (new_index == (unsigned)-1)

View File

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

View File

@ -719,9 +719,7 @@ struct hb_serialize_context_t
hb_vector_t<object_t *> packed;
/* Map view of packed objects. */
hb_hashmap_t<const object_t *, objidx_t,
const object_t *, objidx_t,
nullptr, 0> packed_map;
hb_hashmap_t<const object_t *, objidx_t> packed_map;
};
#endif /* HB_SERIALIZE_HH */

View File

@ -166,7 +166,6 @@ struct hb_set_t : hb_sparseset_t<hb_bit_set_invertible_t>
~hb_set_t () = default;
hb_set_t () : sparseset () {};
hb_set_t (std::nullptr_t) : hb_set_t () {};
hb_set_t (const hb_set_t &o) : sparseset ((sparseset &) o) {};
hb_set_t (hb_set_t&& o) : sparseset (std::move ((sparseset &) o)) {}
hb_set_t& operator = (const hb_set_t&) = default;

View File

@ -43,7 +43,7 @@
using OT::Layout::GSUB::GSUB;
typedef hb_hashmap_t<unsigned, hb_set_t *> script_langsys_map;
typedef hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> script_langsys_map;
#ifndef HB_NO_SUBSET_CFF
static inline void
_add_cff_seac_components (const OT::cff1::accelerator_t &cff,
@ -630,9 +630,6 @@ hb_subset_plan_destroy (hb_subset_plan_t *plan)
if (plan->gsub_langsys)
{
for (auto _ : plan->gsub_langsys->iter ())
hb_set_destroy (_.second);
hb_object_destroy (plan->gsub_langsys);
plan->gsub_langsys->fini_shallow ();
hb_free (plan->gsub_langsys);
@ -640,9 +637,6 @@ hb_subset_plan_destroy (hb_subset_plan_t *plan)
if (plan->gpos_langsys)
{
for (auto _ : plan->gpos_langsys->iter ())
hb_set_destroy (_.second);
hb_object_destroy (plan->gpos_langsys);
plan->gpos_langsys->fini_shallow ();
hb_free (plan->gpos_langsys);

View File

@ -87,8 +87,8 @@ struct hb_subset_plan_t
hb_map_t *gpos_lookups;
//active langsys we'd like to retain
hb_hashmap_t<unsigned, hb_set_t *> *gsub_langsys;
hb_hashmap_t<unsigned, hb_set_t *> *gpos_langsys;
hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> *gsub_langsys;
hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> *gpos_langsys;
//active features after removing redundant langsys and prune_features
hb_map_t *gsub_features;

View File

@ -27,11 +27,6 @@
#include "hb-set.hh"
#include <string>
static const std::string invalid{"invalid"};
static const hb_map_t invalid_map{};
static const hb_set_t invalid_set{};
static const hb_vector_t<unsigned> invalid_vector{};
int
main (int argc, char **argv)
{
@ -127,19 +122,19 @@ main (int argc, char **argv)
/* Test class key / value types. */
{
hb_hashmap_t<hb_bytes_t, int, std::nullptr_t, int, nullptr, 0> m1;
hb_hashmap_t<int, hb_bytes_t, int, std::nullptr_t, 0, nullptr> m2;
hb_hashmap_t<hb_bytes_t, hb_bytes_t, std::nullptr_t, std::nullptr_t, nullptr, nullptr> m3;
hb_hashmap_t<hb_bytes_t, int> m1;
hb_hashmap_t<int, hb_bytes_t> m2;
hb_hashmap_t<hb_bytes_t, hb_bytes_t> m3;
assert (m1.get_population () == 0);
assert (m2.get_population () == 0);
assert (m3.get_population () == 0);
}
{
hb_hashmap_t<int, int, int, int, 0, 0> m0;
hb_hashmap_t<std::string, int, const std::string*, int, &invalid, 0> m1;
hb_hashmap_t<int, std::string, int, const std::string*, 0, &invalid> m2;
hb_hashmap_t<std::string, std::string, const std::string*, const std::string*, &invalid, &invalid> m3;
hb_hashmap_t<int, int> m0;
hb_hashmap_t<std::string, int> m1;
hb_hashmap_t<int, std::string> m2;
hb_hashmap_t<std::string, std::string> m3;
std::string s;
for (unsigned i = 1; i < 1000; i++)
@ -156,82 +151,60 @@ main (int argc, char **argv)
{
using pair = hb_pair_t<hb_codepoint_t, hb_codepoint_t>;
hb_hashmap_t<hb_map_t, hb_map_t, const hb_map_t *, const hb_map_t *, &invalid_map, &invalid_map> m1;
hb_hashmap_t<hb_map_t, hb_map_t, std::nullptr_t, std::nullptr_t, nullptr, nullptr> m2;
hb_hashmap_t<hb_map_t, hb_map_t> m1;
m1.set (hb_map_t (), hb_map_t {});
m2.set (hb_map_t (), hb_map_t {});
m1.set (hb_map_t (), hb_map_t {pair (1u, 2u)});
m2.set (hb_map_t (), hb_map_t {pair (1u, 2u)});
m1.set (hb_map_t {pair (1u, 2u)}, hb_map_t {pair (2u, 3u)});
m2.set (hb_map_t {pair (1u, 2u)}, hb_map_t {pair (2u, 3u)});
/* Cannot override empty map. */
assert (m1.get (hb_map_t ()) == hb_map_t ());
assert (m2.get (hb_map_t ()) == hb_map_t ());
assert (m1.get (hb_map_t ()) == hb_map_t {pair (1u, 2u)});
assert (m1.get (hb_map_t {pair (1u, 2u)}) == hb_map_t {pair (2u, 3u)});
assert (m2.get (hb_map_t {pair (1u, 2u)}) == hb_map_t {pair (2u, 3u)});
}
/* Test hashing sets. */
{
hb_hashmap_t<hb_set_t, hb_set_t, const hb_set_t *, const hb_set_t *, &invalid_set, &invalid_set> m1;
hb_hashmap_t<hb_set_t, hb_set_t, std::nullptr_t, std::nullptr_t, nullptr, nullptr> m2;
hb_hashmap_t<hb_set_t, hb_set_t> m1;
m1.set (hb_set_t (), hb_set_t ());
m2.set (hb_set_t (), hb_set_t ());
m1.set (hb_set_t (), hb_set_t {1});
m2.set (hb_set_t (), hb_set_t {1});
m1.set (hb_set_t {1, 1000}, hb_set_t {2});
m2.set (hb_set_t {1, 1000}, hb_set_t {2});
/* Cannot override empty set. */
assert (m1.get (hb_set_t ()) == hb_set_t ());
assert (m2.get (hb_set_t ()) == hb_set_t ());
assert (m1.get (hb_set_t ()) == hb_set_t {1});
assert (m1.get (hb_set_t {1000, 1}) == hb_set_t {2});
assert (m2.get (hb_set_t {1000, 1}) == hb_set_t {2});
}
/* Test hashing vectors. */
{
using vector_t = hb_vector_t<unsigned>;
hb_hashmap_t<vector_t, vector_t, const vector_t *, const vector_t *, &invalid_vector, &invalid_vector> m1;
hb_hashmap_t<vector_t, vector_t, std::nullptr_t, std::nullptr_t, nullptr, nullptr> m2;
hb_hashmap_t<vector_t, vector_t> m1;
m1.set (vector_t (), vector_t ());
m2.set (vector_t (), vector_t ());
m1.set (vector_t (), vector_t {1});
m2.set (vector_t (), vector_t {1});
m1.set (vector_t {1}, vector_t {2});
m2.set (vector_t {1}, vector_t {2});
/* Cannot override empty vector. */
assert (m1.get (vector_t ()) == vector_t ());
assert (m2.get (vector_t ()) == vector_t ());
assert (m1.get (vector_t ()) == vector_t {1});
assert (m1.get (vector_t {1}) == vector_t {2});
assert (m2.get (vector_t {1}) == vector_t {2});
}
/* Test hb::shared_ptr. */
hb_hash (hb::shared_ptr<hb_set_t> ());
#if 0
{
hb_hashmap_t<hb::shared_ptr<hb_set_t>, hb::shared_ptr<hb_set_t>, std::nullptr_t, std::nullptr_t, nullptr, nullptr> m;
hb_hashmap_t<hb::shared_ptr<hb_set_t>, hb::shared_ptr<hb_set_t>> m;
m.get (hb::shared_ptr<hb_set_t> ());
m.get (hb::shared_ptr<hb_set_t> (hb_set_get_empty ()));
m.iter ();
}
/* 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 ()));
m.iter_ref ();
}
#endif
return 0;
}

View File

@ -106,5 +106,7 @@ main ()
pb.set_user_data (&key, b, nullptr, true);
(void) pb.get_user_data (&key);
hb::unique_ptr<hb_buffer_t> pb5 {pb3.reference ()};
return pb == pb.get_empty () || pb == pb2;
}