[set] Make hb_set_t hashable

This commit is contained in:
Behdad Esfahbod 2022-05-19 12:58:02 -06:00
parent 3ab2c7935f
commit 124f9aeb9b
5 changed files with 42 additions and 0 deletions

View File

@ -45,6 +45,13 @@ struct hb_bit_page_t
return false;
return true;
}
unsigned hash () const
{
unsigned h = 0;
for (unsigned int i = 0; i < len (); i++)
h ^= hb_hash (v[i] ^ i);
return h;
}
void add (hb_codepoint_t g) { elt (g) |= mask (g); }
void del (hb_codepoint_t g) { elt (g) &= ~mask (g); }

View File

@ -80,6 +80,8 @@ struct hb_bit_set_invertible_t
next (&v);
return v == INVALID;
}
unsigned hash () const { return s.hash () ^ inverted; }
hb_codepoint_t get_min () const
{
hb_codepoint_t v = INVALID;

View File

@ -71,6 +71,7 @@ struct hb_bit_set_t
{
int cmp (const page_map_t &o) const { return cmp (o.major); }
int cmp (uint32_t o_major) const { return (int) o_major - (int) major; }
unsigned hash () const { return major ^ index; }
uint32_t major;
uint32_t index;
@ -126,6 +127,11 @@ struct hb_bit_set_t
}
explicit operator bool () const { return !is_empty (); }
unsigned hash () const
{
return page_map.hash () ^ pages.hash ();
}
private:
void dirty () { population = UINT_MAX; }
public:

View File

@ -82,6 +82,7 @@ struct hb_sparseset_t
void clear () { s.clear (); }
void invert () { s.invert (); }
bool is_empty () const { return s.is_empty (); }
unsigned hash () const { return s.hash (); }
void add (hb_codepoint_t g) { s.add (g); }
bool add_range (hb_codepoint_t a, hb_codepoint_t b) { return s.add_range (a, b); }
@ -126,6 +127,8 @@ struct hb_sparseset_t
void set (const hb_sparseset_t &other) { s.set (other.s); }
bool is_equal (const hb_sparseset_t &other) const { return s.is_equal (other.s); }
bool operator == (const hb_set_t &other) const { return is_equal (other); }
bool operator != (const hb_set_t &other) const { return !is_equal (other); }
bool is_subset (const hb_sparseset_t &larger_set) const { return s.is_subset (larger_set.s); }
@ -163,6 +166,7 @@ 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

@ -25,9 +25,11 @@
#include "hb.hh"
#include "hb-map.hh"
#include "hb-set.hh"
#include <string>
static const std::string invalid{"invalid"};
static const hb_set_t invalid_set{};
int
main (int argc, char **argv)
@ -149,5 +151,26 @@ main (int argc, char **argv)
}
}
{
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;
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}, hb_set_t {2});
m2.set (hb_set_t {1}, 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 {1}) == hb_set_t {2});
assert (m2.get (hb_set_t {1}) == hb_set_t {2});
}
return 0;
}