Skip to content

Instantly share code, notes, and snippets.

@drott
Created July 4, 2018 15:14
Show Gist options
  • Save drott/533f540ba29642ac8ea3756a4ec91bb8 to your computer and use it in GitHub Desktop.
Save drott/533f540ba29642ac8ea3756a4ec91bb8 to your computer and use it in GitHub Desktop.
Hb Set differences 957e7756634a4fdf1654041e20e883cf964ecac9..2cb075fe26201f3e370fccfff6c1bc242b5acc79
diff --git a/src/hb-set-private.hh b/src/hb-set-private.hh
index 3615c50e..ccd4d8df 100644
--- a/src/hb-set-private.hh
+++ b/src/hb-set-private.hh
@@ -158,21 +158,13 @@ struct hb_set_t
}
typedef unsigned long long elt_t;
- static const unsigned int PAGE_BITS = 1024;
+ static const unsigned int PAGE_BITS = 512;
static_assert ((PAGE_BITS & ((PAGE_BITS) - 1)) == 0, "");
static inline unsigned int elt_get_min (const elt_t &elt) { return _hb_ctz (elt); }
static inline unsigned int elt_get_max (const elt_t &elt) { return _hb_bit_storage (elt) - 1; }
-#if 0 && HAVE_VECTOR_SIZE
- /* The vectorized version does not work with clang as non-const
- * elt() errs "non-const reference cannot bind to vector element". */
- typedef elt_t vector_t __attribute__((vector_size (PAGE_BITS / 8)));
-#else
typedef hb_vector_size_t<elt_t, PAGE_BITS / 8> vector_t;
-#endif
-
- vector_t v;
static const unsigned int ELT_BITS = sizeof (elt_t) * 8;
static const unsigned int ELT_MASK = ELT_BITS - 1;
@@ -183,34 +175,47 @@ struct hb_set_t
elt_t &elt (hb_codepoint_t g) { return v[(g & MASK) / ELT_BITS]; }
elt_t const &elt (hb_codepoint_t g) const { return v[(g & MASK) / ELT_BITS]; }
elt_t mask (hb_codepoint_t g) const { return elt_t (1) << (g & ELT_MASK); }
+
+ vector_t v;
};
static_assert (page_t::PAGE_BITS == sizeof (page_t) * 8, "");
hb_object_header_t header;
- ASSERT_POD ();
- bool in_error;
- hb_prealloced_array_t<page_map_t, 8> page_map;
- hb_prealloced_array_t<page_t, 1> pages;
+ bool successful; /* Allocations successful */
+ mutable unsigned int population;
+ hb_vector_t<page_map_t, 1> page_map;
+ hb_vector_t<page_t, 1> pages;
- inline void init (void)
+ inline void init_shallow (void)
{
- in_error = false;
+ successful = true;
+ population = 0;
page_map.init ();
pages.init ();
}
- inline void finish (void)
+ inline void init (void)
+ {
+ hb_object_init (this);
+ init_shallow ();
+ }
+ inline void fini_shallow (void)
+ {
+ page_map.fini ();
+ pages.fini ();
+ }
+ inline void fini (void)
{
- page_map.finish ();
- pages.finish ();
+ hb_object_fini (this);
+ fini_shallow ();
}
inline bool resize (unsigned int count)
{
- if (unlikely (in_error)) return false;
+ if (unlikely (!successful)) return false;
if (!pages.resize (count) || !page_map.resize (count))
{
pages.resize (page_map.len);
- in_error = true;
+ successful = false;
return false;
}
return true;
@@ -219,7 +224,8 @@ struct hb_set_t
inline void clear (void) {
if (unlikely (hb_object_is_inert (this)))
return;
- in_error = false;
+ successful = true;
+ population = 0;
page_map.resize (0);
pages.resize (0);
}
@@ -231,17 +237,21 @@ struct hb_set_t
return true;
}
+ inline void dirty (void) { population = (unsigned int) -1; }
+
inline void add (hb_codepoint_t g)
{
- if (unlikely (in_error)) return;
+ if (unlikely (!successful)) return;
if (unlikely (g == INVALID)) return;
+ dirty ();
page_t *page = page_for_insert (g); if (unlikely (!page)) return;
page->add (g);
}
inline bool add_range (hb_codepoint_t a, hb_codepoint_t b)
{
- if (unlikely (in_error)) return true; /* https://github.com/harfbuzz/harfbuzz/issues/657 */
+ if (unlikely (!successful)) return true; /* https://github.com/harfbuzz/harfbuzz/issues/657 */
if (unlikely (a > b || a == INVALID || b == INVALID)) return false;
+ dirty ();
unsigned int ma = get_major (a);
unsigned int mb = get_major (b);
if (ma == mb)
@@ -269,8 +279,9 @@ struct hb_set_t
template <typename T>
inline void add_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
{
- if (unlikely (in_error)) return;
+ if (unlikely (!successful)) return;
if (!count) return;
+ dirty ();
hb_codepoint_t g = *array;
while (count)
{
@@ -294,8 +305,9 @@ struct hb_set_t
template <typename T>
inline bool add_sorted_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
{
- if (unlikely (in_error)) return true; /* https://github.com/harfbuzz/harfbuzz/issues/657 */
+ if (unlikely (!successful)) return true; /* https://github.com/harfbuzz/harfbuzz/issues/657 */
if (!count) return true;
+ dirty ();
hb_codepoint_t g = *array;
hb_codepoint_t last_g = g;
while (count)
@@ -321,16 +333,19 @@ struct hb_set_t
inline void del (hb_codepoint_t g)
{
- if (unlikely (in_error)) return;
+ /* TODO perform op even if !successful. */
+ if (unlikely (!successful)) return;
page_t *p = page_for (g);
if (!p)
return;
+ dirty ();
p->del (g);
}
inline void del_range (hb_codepoint_t a, hb_codepoint_t b)
{
+ /* TODO perform op even if !successful. */
/* TODO Optimize, like add_range(). */
- if (unlikely (in_error)) return;
+ if (unlikely (!successful)) return;
for (unsigned int i = a; i < b + 1; i++)
del (i);
}
@@ -349,17 +364,20 @@ struct hb_set_t
}
inline void set (const hb_set_t *other)
{
- if (unlikely (in_error)) return;
+ if (unlikely (!successful)) return;
unsigned int count = other->pages.len;
if (!resize (count))
return;
-
- memcpy (pages.array, other->pages.array, count * sizeof (pages.array[0]));
- memcpy (page_map.array, other->page_map.array, count * sizeof (page_map.array[0]));
+ population = other->population;
+ memcpy (pages.arrayZ, other->pages.arrayZ, count * sizeof (pages.arrayZ[0]));
+ memcpy (page_map.arrayZ, other->page_map.arrayZ, count * sizeof (page_map.arrayZ[0]));
}
inline bool is_equal (const hb_set_t *other) const
{
+ if (get_population () != other->get_population ())
+ return false;
+
unsigned int na = pages.len;
unsigned int nb = other->pages.len;
@@ -382,16 +400,31 @@ struct hb_set_t
return true;
}
+ inline bool is_subset (const hb_set_t *larger_set) const
+ {
+ if (get_population () > larger_set->get_population ())
+ return false;
+
+ hb_codepoint_t c = INVALID;
+ while (next (&c))
+ if (!larger_set->has (c))
+ return false;
+
+ return true;
+ }
+
template <class Op>
inline void process (const hb_set_t *other)
{
- if (unlikely (in_error)) return;
+ if (unlikely (!successful)) return;
+
+ dirty ();
unsigned int na = pages.len;
unsigned int nb = other->pages.len;
unsigned int next_page = na;
- unsigned int count = 0;
+ unsigned int count = 0, newCount = 0;
unsigned int a = 0, b = 0;
for (; a < na && b < nb; )
{
@@ -419,8 +452,10 @@ struct hb_set_t
if (Op::passthru_right)
count += nb - b;
- if (!resize (count))
- return;
+ if (count > pages.len)
+ if (!resize (count))
+ return;
+ newCount = count;
/* Process in-place backward. */
a = na;
@@ -473,6 +508,8 @@ struct hb_set_t
page_at (count).v = other->page_at (b).v;
}
assert (!count);
+ if (pages.len > newCount)
+ resize (newCount);
}
inline void union_ (const hb_set_t *other)
@@ -592,10 +629,15 @@ struct hb_set_t
inline unsigned int get_population (void) const
{
+ if (population != (unsigned int) -1)
+ return population;
+
unsigned int pop = 0;
unsigned int count = pages.len;
for (unsigned int i = 0; i < count; i++)
pop += pages[i].get_population ();
+
+ population = pop;
return pop;
}
inline hb_codepoint_t get_min (void) const
diff --git a/src/hb-set.cc b/src/hb-set.cc
index 07cf9d09..25027e6c 100644
--- a/src/hb-set.cc
+++ b/src/hb-set.cc
@@ -45,18 +45,11 @@ hb_set_create (void)
if (!(set = hb_object_create<hb_set_t> ()))
return hb_set_get_empty ();
- set->init ();
+ set->init_shallow ();
return set;
}
-static const hb_set_t _hb_set_nil = {
- HB_OBJECT_HEADER_STATIC,
- true, /* in_error */
-
- {0} /* elts */
-};
-
/**
* hb_set_get_empty:
*
@@ -67,7 +60,7 @@ static const hb_set_t _hb_set_nil = {
hb_set_t *
hb_set_get_empty (void)
{
- return const_cast<hb_set_t *> (&_hb_set_nil);
+ return const_cast<hb_set_t *> (&Null(hb_set_t));
}
/**
@@ -95,7 +88,7 @@ hb_set_destroy (hb_set_t *set)
{
if (!hb_object_destroy (set)) return;
- set->finish ();
+ set->fini_shallow ();
free (set);
}
@@ -150,9 +143,9 @@ hb_set_get_user_data (hb_set_t *set,
* Since: 0.9.2
**/
hb_bool_t
-hb_set_allocation_successful (const hb_set_t *set HB_UNUSED)
+hb_set_allocation_successful (const hb_set_t *set)
{
- return !set->in_error;
+ return set->successful;
}
/**
@@ -274,11 +267,11 @@ hb_set_del_range (hb_set_t *set,
/**
* hb_set_is_equal:
* @set: a set.
- * @other:
+ * @other: other set.
*
*
*
- * Return value:
+ * Return value: %TRUE if the two sets are equal, %FALSE otherwise.
*
* Since: 0.9.7
**/
@@ -289,6 +282,24 @@ hb_set_is_equal (const hb_set_t *set,
return set->is_equal (other);
}
+/**
+ * hb_set_is_subset:
+ * @set: a set.
+ * @larger_set: other set.
+ *
+ *
+ *
+ * Return value: %TRUE if the @set is a subset of (or equal to) @larger_set, %FALSE otherwise.
+ *
+ * Since: 1.8.1
+ **/
+hb_bool_t
+hb_set_is_subset (const hb_set_t *set,
+ const hb_set_t *larger_set)
+{
+ return set->is_subset (larger_set);
+}
+
/**
* hb_set_set:
* @set: a set.
diff --git a/src/hb-set.h b/src/hb-set.h
index b0f82f82..ed0e05db 100644
--- a/src/hb-set.h
+++ b/src/hb-set.h
@@ -82,8 +82,6 @@ HB_EXTERN hb_bool_t
hb_set_has (const hb_set_t *set,
hb_codepoint_t codepoint);
-/* Right now limited to 16-bit integers. Eventually will do full codepoint range, sans -1
- * which we will use as a sentinel. */
HB_EXTERN void
hb_set_add (hb_set_t *set,
hb_codepoint_t codepoint);
@@ -106,6 +104,10 @@ HB_EXTERN hb_bool_t
hb_set_is_equal (const hb_set_t *set,
const hb_set_t *other);
+HB_EXTERN hb_bool_t
+hb_set_is_subset (const hb_set_t *set,
+ const hb_set_t *larger_set);
+
HB_EXTERN void
hb_set_set (hb_set_t *set,
const hb_set_t *other);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment