diff --git a/src/hb-dsalgs.hh b/src/hb-dsalgs.hh index 68b1fd111..0e44d7cca 100644 --- a/src/hb-dsalgs.hh +++ b/src/hb-dsalgs.hh @@ -209,4 +209,315 @@ hb_codepoint_parse (const char *s, unsigned int len, int base, hb_codepoint_t *o } +#define HB_VECTOR_INIT {0, 0, false, nullptr} +template +struct hb_vector_t +{ + unsigned int len; + unsigned int allocated; + bool successful; + Type *arrayZ; + Type static_array[StaticSize]; + + void init (void) + { + len = 0; + allocated = ARRAY_LENGTH (static_array); + successful = true; + arrayZ = static_array; + } + + inline Type& operator [] (unsigned int i) + { + if (unlikely (i >= len)) + return Crap (Type); + return arrayZ[i]; + } + inline const Type& operator [] (unsigned int i) const + { + if (unlikely (i >= len)) + return Null(Type); + return arrayZ[i]; + } + + inline Type *push (void) + { + if (unlikely (!resize (len + 1))) + return &Crap(Type); + return &arrayZ[len - 1]; + } + inline Type *push (const Type& v) + { + Type *p = push (); + *p = v; + return p; + } + + /* Allocate for size but don't adjust len. */ + inline bool alloc (unsigned int size) + { + if (unlikely (!successful)) + return false; + + if (likely (size <= allocated)) + return true; + + /* Reallocate */ + + unsigned int new_allocated = allocated; + while (size >= new_allocated) + new_allocated += (new_allocated >> 1) + 8; + + Type *new_array = nullptr; + + if (arrayZ == static_array) + { + new_array = (Type *) calloc (new_allocated, sizeof (Type)); + if (new_array) + memcpy (new_array, arrayZ, len * sizeof (Type)); + } + else + { + bool overflows = (new_allocated < allocated) || _hb_unsigned_int_mul_overflows (new_allocated, sizeof (Type)); + if (likely (!overflows)) + new_array = (Type *) realloc (arrayZ, new_allocated * sizeof (Type)); + } + + if (unlikely (!new_array)) + { + successful = false; + return false; + } + + arrayZ = new_array; + allocated = new_allocated; + + return true; + } + + inline bool resize (int size_) + { + unsigned int size = size_ < 0 ? 0u : (unsigned int) size_; + if (!alloc (size)) + return false; + + if (size > len) + memset (arrayZ + len, 0, (size - len) * sizeof (*arrayZ)); + + len = size; + return true; + } + + inline void pop (void) + { + if (!len) return; + len--; + } + + inline void remove (unsigned int i) + { + if (unlikely (i >= len)) + return; + memmove (static_cast (&arrayZ[i]), + static_cast (&arrayZ[i + 1]), + (len - i - 1) * sizeof (Type)); + len--; + } + + inline void shrink (int size_) + { + unsigned int size = size_ < 0 ? 0u : (unsigned int) size_; + if (size < len) + len = size; + } + + template + inline Type *find (T v) { + for (unsigned int i = 0; i < len; i++) + if (arrayZ[i] == v) + return &arrayZ[i]; + return nullptr; + } + template + inline const Type *find (T v) const { + for (unsigned int i = 0; i < len; i++) + if (arrayZ[i] == v) + return &arrayZ[i]; + return nullptr; + } + + inline void qsort (int (*cmp)(const void*, const void*)) + { + ::qsort (arrayZ, len, sizeof (Type), cmp); + } + + inline void qsort (void) + { + ::qsort (arrayZ, len, sizeof (Type), Type::cmp); + } + + inline void qsort (unsigned int start, unsigned int end) + { + ::qsort (arrayZ + start, end - start, sizeof (Type), Type::cmp); + } + + template + inline Type *lsearch (const T &x) + { + for (unsigned int i = 0; i < len; i++) + if (0 == this->arrayZ[i].cmp (&x)) + return &arrayZ[i]; + return nullptr; + } + + template + inline Type *bsearch (const T &x) + { + unsigned int i; + return bfind (x, &i) ? &arrayZ[i] : nullptr; + } + template + inline const Type *bsearch (const T &x) const + { + unsigned int i; + return bfind (x, &i) ? &arrayZ[i] : nullptr; + } + template + inline bool bfind (const T &x, unsigned int *i) const + { + int min = 0, max = (int) this->len - 1; + while (min <= max) + { + int mid = (min + max) / 2; + int c = this->arrayZ[mid].cmp (&x); + if (c < 0) + max = mid - 1; + else if (c > 0) + min = mid + 1; + else + { + *i = mid; + return true; + } + } + if (max < 0 || (max < (int) this->len && this->arrayZ[max].cmp (&x) > 0)) + max++; + *i = max; + return false; + } + + inline void fini (void) + { + if (arrayZ != static_array) + free (arrayZ); + arrayZ = nullptr; + allocated = len = 0; + } +}; + +template +struct hb_auto_t : Type +{ + hb_auto_t (void) { Type::init (); } + ~hb_auto_t (void) { Type::fini (); } + private: /* Hide */ + void init (void) {} + void fini (void) {} +}; +template +struct hb_auto_array_t : hb_auto_t > {}; + + +#define HB_LOCKABLE_SET_INIT {HB_VECTOR_INIT} +template +struct hb_lockable_set_t +{ + hb_vector_t items; + + inline void init (void) { items.init (); } + + template + inline item_t *replace_or_insert (T v, lock_t &l, bool replace) + { + l.lock (); + item_t *item = items.find (v); + if (item) { + if (replace) { + item_t old = *item; + *item = v; + l.unlock (); + old.fini (); + } + else { + item = nullptr; + l.unlock (); + } + } else { + item = items.push (v); + l.unlock (); + } + return item; + } + + template + inline void remove (T v, lock_t &l) + { + l.lock (); + item_t *item = items.find (v); + if (item) { + item_t old = *item; + *item = items[items.len - 1]; + items.pop (); + l.unlock (); + old.fini (); + } else { + l.unlock (); + } + } + + template + inline bool find (T v, item_t *i, lock_t &l) + { + l.lock (); + item_t *item = items.find (v); + if (item) + *i = *item; + l.unlock (); + return !!item; + } + + template + inline item_t *find_or_insert (T v, lock_t &l) + { + l.lock (); + item_t *item = items.find (v); + if (!item) { + item = items.push (v); + } + l.unlock (); + return item; + } + + inline void fini (lock_t &l) + { + if (!items.len) { + /* No need for locking. */ + items.fini (); + return; + } + l.lock (); + while (items.len) { + item_t old = items[items.len - 1]; + items.pop (); + l.unlock (); + old.fini (); + l.lock (); + } + items.fini (); + l.unlock (); + } + +}; + + #endif /* HB_DSALGS_HH */ diff --git a/src/hb-private.hh b/src/hb-private.hh index 49ce6fef6..65d4bae2f 100644 --- a/src/hb-private.hh +++ b/src/hb-private.hh @@ -652,321 +652,6 @@ struct CrapOrNull { #define CrapOrNull(Type) CrapOrNull::get () - -/* arrays and maps */ - - -#define HB_VECTOR_INIT {0, 0, false, nullptr} -template -struct hb_vector_t -{ - unsigned int len; - unsigned int allocated; - bool successful; - Type *arrayZ; - Type static_array[StaticSize]; - - void init (void) - { - len = 0; - allocated = ARRAY_LENGTH (static_array); - successful = true; - arrayZ = static_array; - } - - inline Type& operator [] (unsigned int i) - { - if (unlikely (i >= len)) - return Crap (Type); - return arrayZ[i]; - } - inline const Type& operator [] (unsigned int i) const - { - if (unlikely (i >= len)) - return Null(Type); - return arrayZ[i]; - } - - inline Type *push (void) - { - if (unlikely (!resize (len + 1))) - return &Crap(Type); - return &arrayZ[len - 1]; - } - inline Type *push (const Type& v) - { - Type *p = push (); - *p = v; - return p; - } - - /* Allocate for size but don't adjust len. */ - inline bool alloc (unsigned int size) - { - if (unlikely (!successful)) - return false; - - if (likely (size <= allocated)) - return true; - - /* Reallocate */ - - unsigned int new_allocated = allocated; - while (size >= new_allocated) - new_allocated += (new_allocated >> 1) + 8; - - Type *new_array = nullptr; - - if (arrayZ == static_array) - { - new_array = (Type *) calloc (new_allocated, sizeof (Type)); - if (new_array) - memcpy (new_array, arrayZ, len * sizeof (Type)); - } - else - { - bool overflows = (new_allocated < allocated) || _hb_unsigned_int_mul_overflows (new_allocated, sizeof (Type)); - if (likely (!overflows)) - new_array = (Type *) realloc (arrayZ, new_allocated * sizeof (Type)); - } - - if (unlikely (!new_array)) - { - successful = false; - return false; - } - - arrayZ = new_array; - allocated = new_allocated; - - return true; - } - - inline bool resize (int size_) - { - unsigned int size = size_ < 0 ? 0u : (unsigned int) size_; - if (!alloc (size)) - return false; - - if (size > len) - memset (arrayZ + len, 0, (size - len) * sizeof (*arrayZ)); - - len = size; - return true; - } - - inline void pop (void) - { - if (!len) return; - len--; - } - - inline void remove (unsigned int i) - { - if (unlikely (i >= len)) - return; - memmove (static_cast (&arrayZ[i]), - static_cast (&arrayZ[i + 1]), - (len - i - 1) * sizeof (Type)); - len--; - } - - inline void shrink (int size_) - { - unsigned int size = size_ < 0 ? 0u : (unsigned int) size_; - if (size < len) - len = size; - } - - template - inline Type *find (T v) { - for (unsigned int i = 0; i < len; i++) - if (arrayZ[i] == v) - return &arrayZ[i]; - return nullptr; - } - template - inline const Type *find (T v) const { - for (unsigned int i = 0; i < len; i++) - if (arrayZ[i] == v) - return &arrayZ[i]; - return nullptr; - } - - inline void qsort (int (*cmp)(const void*, const void*)) - { - ::qsort (arrayZ, len, sizeof (Type), cmp); - } - - inline void qsort (void) - { - ::qsort (arrayZ, len, sizeof (Type), Type::cmp); - } - - inline void qsort (unsigned int start, unsigned int end) - { - ::qsort (arrayZ + start, end - start, sizeof (Type), Type::cmp); - } - - template - inline Type *lsearch (const T &x) - { - for (unsigned int i = 0; i < len; i++) - if (0 == this->arrayZ[i].cmp (&x)) - return &arrayZ[i]; - return nullptr; - } - - template - inline Type *bsearch (const T &x) - { - unsigned int i; - return bfind (x, &i) ? &arrayZ[i] : nullptr; - } - template - inline const Type *bsearch (const T &x) const - { - unsigned int i; - return bfind (x, &i) ? &arrayZ[i] : nullptr; - } - template - inline bool bfind (const T &x, unsigned int *i) const - { - int min = 0, max = (int) this->len - 1; - while (min <= max) - { - int mid = (min + max) / 2; - int c = this->arrayZ[mid].cmp (&x); - if (c < 0) - max = mid - 1; - else if (c > 0) - min = mid + 1; - else - { - *i = mid; - return true; - } - } - if (max < 0 || (max < (int) this->len && this->arrayZ[max].cmp (&x) > 0)) - max++; - *i = max; - return false; - } - - inline void fini (void) - { - if (arrayZ != static_array) - free (arrayZ); - arrayZ = nullptr; - allocated = len = 0; - } -}; - -template -struct hb_auto_t : Type -{ - hb_auto_t (void) { Type::init (); } - ~hb_auto_t (void) { Type::fini (); } - private: /* Hide */ - void init (void) {} - void fini (void) {} -}; -template -struct hb_auto_array_t : hb_auto_t > {}; - - -#define HB_LOCKABLE_SET_INIT {HB_VECTOR_INIT} -template -struct hb_lockable_set_t -{ - hb_vector_t items; - - inline void init (void) { items.init (); } - - template - inline item_t *replace_or_insert (T v, lock_t &l, bool replace) - { - l.lock (); - item_t *item = items.find (v); - if (item) { - if (replace) { - item_t old = *item; - *item = v; - l.unlock (); - old.fini (); - } - else { - item = nullptr; - l.unlock (); - } - } else { - item = items.push (v); - l.unlock (); - } - return item; - } - - template - inline void remove (T v, lock_t &l) - { - l.lock (); - item_t *item = items.find (v); - if (item) { - item_t old = *item; - *item = items[items.len - 1]; - items.pop (); - l.unlock (); - old.fini (); - } else { - l.unlock (); - } - } - - template - inline bool find (T v, item_t *i, lock_t &l) - { - l.lock (); - item_t *item = items.find (v); - if (item) - *i = *item; - l.unlock (); - return !!item; - } - - template - inline item_t *find_or_insert (T v, lock_t &l) - { - l.lock (); - item_t *item = items.find (v); - if (!item) { - item = items.push (v); - } - l.unlock (); - return item; - } - - inline void fini (lock_t &l) - { - if (!items.len) { - /* No need for locking. */ - items.fini (); - return; - } - l.lock (); - while (items.len) { - item_t old = items[items.len - 1]; - items.pop (); - l.unlock (); - old.fini (); - l.lock (); - } - items.fini (); - l.unlock (); - } - -}; - - /* ASCII tag/character handling */ static inline bool ISALPHA (unsigned char c)