From e604306f2829804e9016966c1378166253b19d29 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 24 Nov 2018 01:24:48 -0500 Subject: [PATCH] [arrays] Port hb_vector_t.bsearch/bfind to (new) hb_sorted_array_t's --- src/hb-dsalgs.hh | 63 ++++++++++++++++++++++++++++++++++++++++++--- src/hb-open-type.hh | 12 ++++++--- src/hb-vector.hh | 57 ++++++++++++++++------------------------ 3 files changed, 89 insertions(+), 43 deletions(-) diff --git a/src/hb-dsalgs.hh b/src/hb-dsalgs.hh index 1d5bb3520..a7592828a 100644 --- a/src/hb-dsalgs.hh +++ b/src/hb-dsalgs.hh @@ -564,7 +564,6 @@ struct hb_array_t { static_assert ((bool) (unsigned) hb_static_size (Type), ""); - inline hb_array_t (void) : arrayZ (nullptr), len (0) {} inline hb_array_t (Type *array_, unsigned int len_) : arrayZ (array_), len (len_) {} inline Type& operator [] (unsigned int i) const @@ -576,7 +575,8 @@ struct hb_array_t inline unsigned int get_size (void) const { return len * sizeof (Type); } template - inline Type *lsearch (const T &x, Type *not_found = nullptr) + inline Type *lsearch (const T &x, + Type *not_found = nullptr) { unsigned int count = len; for (unsigned int i = 0; i < count; i++) @@ -585,7 +585,8 @@ struct hb_array_t return not_found; } template - inline const Type *lsearch (const T &x, const Type *not_found = nullptr) const + inline const Type *lsearch (const T &x, + const Type *not_found = nullptr) const { unsigned int count = len; for (unsigned int i = 0; i < count; i++) @@ -625,7 +626,61 @@ struct hb_array_t unsigned int len; }; template -inline hb_array_t hb_array (T *array, unsigned int len) { return hb_array_t (array, len); } +inline hb_array_t hb_array (T *array, unsigned int len) +{ return hb_array_t (array, len); } + +template +struct hb_sorted_array_t : hb_array_t +{ + inline hb_sorted_array_t (Type *array_, unsigned int len_) : hb_array_t (array_, len_) {} + + template + inline Type *bsearch (const T &x, + Type *not_found = nullptr) + { + unsigned int i; + return bfind (x, &i) ? &this->arrayZ[i] : not_found; + } + template + inline const Type *bsearch (const T &x, + const Type *not_found = nullptr) const + { + unsigned int i; + return bfind (x, &i) ? &this->arrayZ[i] : not_found; + } + template + inline bool bfind (const T &x, + unsigned int *i = nullptr) const + { + int min = 0, max = (int) this->len - 1; + const Type *array = this->arrayZ; + while (min <= max) + { + int mid = ((unsigned int) min + (unsigned int) max) / 2; + int c = array[mid].cmp (x); + if (c < 0) + max = mid - 1; + else if (c > 0) + min = mid + 1; + else + { + if (i) + *i = mid; + return true; + } + } + if (i) + { + if (max < 0 || (max < (int) this->len && array[max].cmp (x) > 0)) + max++; + *i = max; + } + return false; + } +}; +template +inline hb_sorted_array_t hb_sorted_array (T *array, unsigned int len) +{ return hb_sorted_array_t (array, len); } struct HbOpOr diff --git a/src/hb-open-type.hh b/src/hb-open-type.hh index 7fa38b1ca..e384a7ad5 100644 --- a/src/hb-open-type.hh +++ b/src/hb-open-type.hh @@ -370,8 +370,10 @@ struct UnsizedArrayOf inline unsigned int get_size (unsigned int len) const { return len * Type::static_size; } - inline hb_array_t as_array (unsigned int len) { return hb_array_t (arrayZ, len); } - inline hb_array_t as_array (unsigned int len) const { return hb_array_t (arrayZ, len); } + inline hb_array_t as_array (unsigned int len) + { return hb_array (arrayZ, len); } + inline hb_array_t as_array (unsigned int len) const + { return hb_array (arrayZ, len); } inline bool sanitize (hb_sanitize_context_t *c, unsigned int count) const { @@ -483,8 +485,10 @@ struct ArrayOf inline unsigned int get_size (void) const { return len.static_size + len * Type::static_size; } - inline hb_array_t as_array (void) { return hb_array_t (arrayZ, len); } - inline hb_array_t as_array (void) const { return hb_array_t (arrayZ, len); } + inline hb_array_t as_array (void) + { return hb_array (arrayZ, len); } + inline hb_array_t as_array (void) const + { return hb_array (arrayZ, len); } inline bool serialize (hb_serialize_context_t *c, unsigned int items_len) diff --git a/src/hb-vector.hh b/src/hb-vector.hh index d1fb65df8..14967a410 100644 --- a/src/hb-vector.hh +++ b/src/hb-vector.hh @@ -91,8 +91,15 @@ struct hb_vector_t return arrayZ()[i]; } - inline hb_array_t as_array (void) { return hb_array_t (arrayZ(), len); } - inline hb_array_t as_array (void) const { return hb_array_t (arrayZ(), len); } + inline hb_array_t as_array (void) + { return hb_array (arrayZ(), len); } + inline hb_array_t as_array (void) const + { return hb_array (arrayZ(), len); } + + inline hb_sorted_array_t as_sorted_array (void) + { return hb_sorted_array (arrayZ(), len); } + inline hb_sorted_array_t as_sorted_array (void) const + { return hb_sorted_array (arrayZ(), len); } template inline operator T * (void) { return arrayZ(); } template inline operator const T * (void) const { return arrayZ(); } @@ -229,55 +236,35 @@ struct hb_vector_t } template - inline Type *lsearch (const T &x, Type *not_found = nullptr) + inline Type *lsearch (const T &x, + Type *not_found = nullptr) { return as_array ().lsearch (x, not_found); } template - inline const Type *lsearch (const T &x, const Type *not_found = nullptr) const + inline const Type *lsearch (const T &x, + const Type *not_found = nullptr) const { return as_array ().lsearch (x, not_found); } template - inline Type *bsearch (const T &x) + inline Type *bsearch (const T &x, + Type *not_found = nullptr) { - unsigned int i; - return bfind (x, &i) ? &arrayZ()[i] : nullptr; + return as_sorted_array ().bsearch (x, not_found); } template - inline const Type *bsearch (const T &x) const + inline const Type *bsearch (const T &x, + const Type *not_found = nullptr) const { - unsigned int i; - return bfind (x, &i) ? &arrayZ()[i] : nullptr; + return as_sorted_array ().bsearch (x, not_found); } template - inline bool bfind (const T &x, unsigned int *i = nullptr) const + inline bool bfind (const T &x, + unsigned int *i = nullptr) const { - int min = 0, max = (int) this->len - 1; - const Type *array = this->arrayZ(); - while (min <= max) - { - int mid = ((unsigned int) min + (unsigned int) max) / 2; - int c = array[mid].cmp (x); - if (c < 0) - max = mid - 1; - else if (c > 0) - min = mid + 1; - else - { - if (i) - *i = mid; - return true; - } - } - if (i) - { - if (max < 0 || (max < (int) this->len && array[max].cmp (x) > 0)) - max++; - *i = max; - } - return false; + return as_sorted_array ().bfind (x, i); } };