From 5a552f75468d777d8d4bd3168e28f56a3369eafd Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sun, 16 Dec 2018 20:07:44 -0500 Subject: [PATCH] [array] Move hb_array_t and related types to hb-array.hh --- src/Makefile.sources | 1 + src/hb-array.hh | 241 +++++++++++++++++++++++++++++++++++++++++++ src/hb-dsalgs.hh | 206 ------------------------------------ src/hb-machinery.hh | 1 + src/hb-vector.hh | 2 +- 5 files changed, 244 insertions(+), 207 deletions(-) create mode 100644 src/hb-array.hh diff --git a/src/Makefile.sources b/src/Makefile.sources index 01ce0aca2..0da4abe05 100644 --- a/src/Makefile.sources +++ b/src/Makefile.sources @@ -16,6 +16,7 @@ HB_BASE_sources = \ hb-aat-ltag-table.hh \ hb-aat-map.cc \ hb-aat-map.hh \ + hb-array.hh \ hb-atomic.hh \ hb-blob.cc \ hb-blob.hh \ diff --git a/src/hb-array.hh b/src/hb-array.hh new file mode 100644 index 000000000..9b9f85854 --- /dev/null +++ b/src/hb-array.hh @@ -0,0 +1,241 @@ +/* + * Copyright © 2018 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ + +#ifndef HB_ARRAY_HH +#define HB_ARRAY_HH + +#include "hb.hh" + + +struct hb_bytes_t +{ + hb_bytes_t (void) : arrayZ (nullptr), len (0) {} + hb_bytes_t (const char *bytes_, unsigned int len_) : arrayZ (bytes_), len (len_) {} + hb_bytes_t (const void *bytes_, unsigned int len_) : arrayZ ((const char *) bytes_), len (len_) {} + template + hb_bytes_t (const T& array) : arrayZ ((const char *) array.arrayZ), len (array.len * sizeof (array.arrayZ[0])) {} + + operator const void * (void) const { return arrayZ; } + operator const char * (void) const { return arrayZ; } + + void free (void) { ::free ((void *) arrayZ); arrayZ = nullptr; len = 0; } + + int cmp (const hb_bytes_t &a) const + { + if (len != a.len) + return (int) a.len - (int) len; + return hb_memcmp (a.arrayZ, arrayZ, len); + } + static int cmp (const void *pa, const void *pb) + { + hb_bytes_t *a = (hb_bytes_t *) pa; + hb_bytes_t *b = (hb_bytes_t *) pb; + return b->cmp (*a); + } + + const char *arrayZ; + unsigned int len; +}; + + +template +struct hb_sorted_array_t; + +template +struct hb_array_t +{ + static_assert ((bool) (unsigned) hb_static_size (Type), ""); + + hb_array_t (void) : arrayZ (nullptr), len (0) {} + hb_array_t (const hb_array_t &o) : arrayZ (o.arrayZ), len (o.len) {} + hb_array_t (Type *array_, unsigned int len_) : arrayZ (array_), len (len_) {} + + Type& operator [] (int i_) const + { + unsigned int i = (unsigned int) i_; + if (unlikely (i >= len)) return Null(Type); + return arrayZ[i]; + } + + template operator T * (void) const { return arrayZ; } + + Type * operator & (void) const { return arrayZ; } + + unsigned int get_size (void) const { return len * sizeof (Type); } + + hb_array_t sub_array (unsigned int start_offset = 0, unsigned int *seg_count = nullptr /* IN/OUT */) const + { + if (!start_offset && !seg_count) + return *this; + + unsigned int count = len; + if (unlikely (start_offset > count)) + count = 0; + else + count -= start_offset; + if (seg_count) + count = *seg_count = MIN (count, *seg_count); + return hb_array_t (arrayZ + start_offset, count); + } + hb_array_t sub_array (unsigned int start_offset, unsigned int seg_count) const + { return sub_array (start_offset, &seg_count); } + + hb_bytes_t as_bytes (void) const + { return hb_bytes_t (arrayZ, len * sizeof (Type)); } + + template + Type *lsearch (const T &x, + Type *not_found = nullptr) + { + unsigned int count = len; + for (unsigned int i = 0; i < count; i++) + if (!this->arrayZ[i].cmp (x)) + return &this->arrayZ[i]; + return not_found; + } + template + const Type *lsearch (const T &x, const Type *not_found = nullptr) const + { + unsigned int count = len; + for (unsigned int i = 0; i < count; i++) + if (!this->arrayZ[i].cmp (x)) + return &this->arrayZ[i]; + return not_found; + } + + hb_sorted_array_t qsort (int (*cmp)(const void*, const void*)) + { + ::qsort (arrayZ, len, sizeof (Type), cmp); + return hb_sorted_array_t (*this); + } + hb_sorted_array_t qsort (void) + { + ::qsort (arrayZ, len, sizeof (Type), Type::cmp); + return hb_sorted_array_t (*this); + } + void qsort (unsigned int start, unsigned int end) + { + end = MIN (end, len); + assert (start <= end); + ::qsort (arrayZ + start, end - start, sizeof (Type), Type::cmp); + } + + void free (void) + { ::free ((void *) arrayZ); arrayZ = nullptr; len = 0; } + + template + bool sanitize (hb_sanitize_context_t *c) const + { return c->check_array (arrayZ, len); } + + public: + Type *arrayZ; + unsigned int len; +}; +template +inline hb_array_t hb_array (T *array, unsigned int len) +{ return hb_array_t (array, len); } + + +enum hb_bfind_not_found_t +{ + HB_BFIND_NOT_FOUND_DONT_STORE, + HB_BFIND_NOT_FOUND_STORE, + HB_BFIND_NOT_FOUND_STORE_CLOSEST, +}; + +template +struct hb_sorted_array_t : hb_array_t +{ + hb_sorted_array_t (void) : hb_array_t () {} + hb_sorted_array_t (const hb_array_t &o) : hb_array_t (o) {} + hb_sorted_array_t (Type *array_, unsigned int len_) : hb_array_t (array_, len_) {} + + hb_sorted_array_t sub_array (unsigned int start_offset, unsigned int *seg_count /* IN/OUT */) const + { return hb_sorted_array_t (((const hb_array_t *) (this))->sub_array (start_offset, seg_count)); } + hb_sorted_array_t sub_array (unsigned int start_offset, unsigned int seg_count) const + { return sub_array (start_offset, &seg_count); } + + template + Type *bsearch (const T &x, Type *not_found = nullptr) + { + unsigned int i; + return bfind (x, &i) ? &this->arrayZ[i] : not_found; + } + template + 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 + bool bfind (const T &x, unsigned int *i = nullptr, + hb_bfind_not_found_t not_found = HB_BFIND_NOT_FOUND_DONT_STORE, + unsigned int to_store = (unsigned int) -1) 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) + { + switch (not_found) + { + case HB_BFIND_NOT_FOUND_DONT_STORE: + break; + + case HB_BFIND_NOT_FOUND_STORE: + *i = to_store; + break; + + case HB_BFIND_NOT_FOUND_STORE_CLOSEST: + if (max < 0 || (max < (int) this->len && array[max].cmp (x) > 0)) + max++; + *i = max; + break; + } + } + return false; + } +}; +template +inline hb_sorted_array_t hb_sorted_array (T *array, unsigned int len) +{ return hb_sorted_array_t (array, len); } + + +#endif /* HB_ARRAY_HH */ diff --git a/src/hb-dsalgs.hh b/src/hb-dsalgs.hh index 77c158f80..7273c7ec2 100644 --- a/src/hb-dsalgs.hh +++ b/src/hb-dsalgs.hh @@ -533,212 +533,6 @@ hb_codepoint_parse (const char *s, unsigned int len, int base, hb_codepoint_t *o } -struct hb_bytes_t -{ - hb_bytes_t (void) : arrayZ (nullptr), len (0) {} - hb_bytes_t (const char *bytes_, unsigned int len_) : arrayZ (bytes_), len (len_) {} - hb_bytes_t (const void *bytes_, unsigned int len_) : arrayZ ((const char *) bytes_), len (len_) {} - template - hb_bytes_t (const T& array) : arrayZ ((const char *) array.arrayZ), len (array.len * sizeof (array.arrayZ[0])) {} - - operator const void * (void) const { return arrayZ; } - operator const char * (void) const { return arrayZ; } - - void free (void) { ::free ((void *) arrayZ); arrayZ = nullptr; len = 0; } - - int cmp (const hb_bytes_t &a) const - { - if (len != a.len) - return (int) a.len - (int) len; - return hb_memcmp (a.arrayZ, arrayZ, len); - } - static int cmp (const void *pa, const void *pb) - { - hb_bytes_t *a = (hb_bytes_t *) pa; - hb_bytes_t *b = (hb_bytes_t *) pb; - return b->cmp (*a); - } - - const char *arrayZ; - unsigned int len; -}; - -template -struct hb_sorted_array_t; - -template -struct hb_array_t -{ - static_assert ((bool) (unsigned) hb_static_size (Type), ""); - - hb_array_t (void) : arrayZ (nullptr), len (0) {} - hb_array_t (const hb_array_t &o) : arrayZ (o.arrayZ), len (o.len) {} - hb_array_t (Type *array_, unsigned int len_) : arrayZ (array_), len (len_) {} - - Type& operator [] (int i_) const - { - unsigned int i = (unsigned int) i_; - if (unlikely (i >= len)) return Null(Type); - return arrayZ[i]; - } - - template operator T * (void) const { return arrayZ; } - - Type * operator & (void) const { return arrayZ; } - - unsigned int get_size (void) const { return len * sizeof (Type); } - - hb_array_t sub_array (unsigned int start_offset = 0, unsigned int *seg_count = nullptr /* IN/OUT */) const - { - if (!start_offset && !seg_count) - return *this; - - unsigned int count = len; - if (unlikely (start_offset > count)) - count = 0; - else - count -= start_offset; - if (seg_count) - count = *seg_count = MIN (count, *seg_count); - return hb_array_t (arrayZ + start_offset, count); - } - hb_array_t sub_array (unsigned int start_offset, unsigned int seg_count) const - { return sub_array (start_offset, &seg_count); } - - hb_bytes_t as_bytes (void) const - { return hb_bytes_t (arrayZ, len * sizeof (Type)); } - - template - Type *lsearch (const T &x, - Type *not_found = nullptr) - { - unsigned int count = len; - for (unsigned int i = 0; i < count; i++) - if (!this->arrayZ[i].cmp (x)) - return &this->arrayZ[i]; - return not_found; - } - template - const Type *lsearch (const T &x, const Type *not_found = nullptr) const - { - unsigned int count = len; - for (unsigned int i = 0; i < count; i++) - if (!this->arrayZ[i].cmp (x)) - return &this->arrayZ[i]; - return not_found; - } - - hb_sorted_array_t qsort (int (*cmp)(const void*, const void*)) - { - ::qsort (arrayZ, len, sizeof (Type), cmp); - return hb_sorted_array_t (*this); - } - hb_sorted_array_t qsort (void) - { - ::qsort (arrayZ, len, sizeof (Type), Type::cmp); - return hb_sorted_array_t (*this); - } - void qsort (unsigned int start, unsigned int end) - { - end = MIN (end, len); - assert (start <= end); - ::qsort (arrayZ + start, end - start, sizeof (Type), Type::cmp); - } - - void free (void) - { ::free ((void *) arrayZ); arrayZ = nullptr; len = 0; } - - template - bool sanitize (hb_sanitize_context_t *c) const - { return c->check_array (arrayZ, len); } - - public: - Type *arrayZ; - unsigned int len; -}; -template -inline hb_array_t hb_array (T *array, unsigned int len) -{ return hb_array_t (array, len); } - -enum hb_bfind_not_found_t -{ - HB_BFIND_NOT_FOUND_DONT_STORE, - HB_BFIND_NOT_FOUND_STORE, - HB_BFIND_NOT_FOUND_STORE_CLOSEST, -}; - -template -struct hb_sorted_array_t : hb_array_t -{ - hb_sorted_array_t (void) : hb_array_t () {} - hb_sorted_array_t (const hb_array_t &o) : hb_array_t (o) {} - hb_sorted_array_t (Type *array_, unsigned int len_) : hb_array_t (array_, len_) {} - - hb_sorted_array_t sub_array (unsigned int start_offset, unsigned int *seg_count /* IN/OUT */) const - { return hb_sorted_array_t (((const hb_array_t *) (this))->sub_array (start_offset, seg_count)); } - hb_sorted_array_t sub_array (unsigned int start_offset, unsigned int seg_count) const - { return sub_array (start_offset, &seg_count); } - - template - Type *bsearch (const T &x, Type *not_found = nullptr) - { - unsigned int i; - return bfind (x, &i) ? &this->arrayZ[i] : not_found; - } - template - 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 - bool bfind (const T &x, unsigned int *i = nullptr, - hb_bfind_not_found_t not_found = HB_BFIND_NOT_FOUND_DONT_STORE, - unsigned int to_store = (unsigned int) -1) 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) - { - switch (not_found) - { - case HB_BFIND_NOT_FOUND_DONT_STORE: - break; - - case HB_BFIND_NOT_FOUND_STORE: - *i = to_store; - break; - - case HB_BFIND_NOT_FOUND_STORE_CLOSEST: - if (max < 0 || (max < (int) this->len && array[max].cmp (x) > 0)) - max++; - *i = max; - break; - } - } - 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 { enum { passthru_left = true }; diff --git a/src/hb-machinery.hh b/src/hb-machinery.hh index d761db638..e3ca05546 100644 --- a/src/hb-machinery.hh +++ b/src/hb-machinery.hh @@ -33,6 +33,7 @@ #include "hb-blob.hh" #include "hb-iter.hh" +#include "hb-array.hh" #include "hb-vector.hh" diff --git a/src/hb-vector.hh b/src/hb-vector.hh index ba9d1419f..cc45be206 100644 --- a/src/hb-vector.hh +++ b/src/hb-vector.hh @@ -21,7 +21,6 @@ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. * - * Red Hat Author(s): Behdad Esfahbod * Google Author(s): Behdad Esfahbod */ @@ -29,6 +28,7 @@ #define HB_VECTOR_HH #include "hb.hh" +#include "hb-array.hh" template