diff options
Diffstat (limited to 'Build/source/libs/harfbuzz/harfbuzz-src/src/hb-private.hh')
-rw-r--r-- | Build/source/libs/harfbuzz/harfbuzz-src/src/hb-private.hh | 314 |
1 files changed, 243 insertions, 71 deletions
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-private.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-private.hh index 62c9fb278fc..daa496e98cd 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-private.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-private.hh @@ -51,6 +51,9 @@ #include <stdio.h> #include <stdarg.h> +#if defined(_MSC_VER) || defined(__MINGW32__) +#include <intrin.h> +#endif #define HB_PASTE1(a,b) a##b #define HB_PASTE(a,b) HB_PASTE1(a,b) @@ -120,10 +123,11 @@ extern "C" void hb_free_impl(void *ptr); #endif #ifndef HB_INTERNAL -# if !defined(__MINGW32__) && !defined(__CYGWIN__) +# if !defined(HB_NO_VISIBILITY) && !defined(__MINGW32__) && !defined(__CYGWIN__) && !defined(_MSC_VER) && !defined(__SUNPRO_CC) # define HB_INTERNAL __attribute__((__visibility__("hidden"))) # else # define HB_INTERNAL +# define HB_NO_VISIBILITY 1 # endif #endif @@ -135,6 +139,11 @@ extern "C" void hb_free_impl(void *ptr); #define HB_FUNC __func__ #endif +#ifdef __SUNPRO_CC +/* https://github.com/harfbuzz/harfbuzz/issues/630 */ +#define __restrict +#endif + /* * Borrowed from https://bugzilla.mozilla.org/show_bug.cgi?id=1215411 * HB_FALLTHROUGH is an annotation to suppress compiler warnings about switch @@ -154,6 +163,9 @@ extern "C" void hb_free_impl(void *ptr); #if defined(__clang__) && __cplusplus >= 201103L /* clang's fallthrough annotations are only available starting in C++11. */ # define HB_FALLTHROUGH [[clang::fallthrough]] +#elif __GNUC__ >= 7 + /* GNU fallthrough attribute is available from GCC7 */ +# define HB_FALLTHROUGH __attribute__((fallthrough)) #elif defined(_MSC_VER) /* * MSVC's __fallthrough annotations are checked by /analyze (Code Analysis): @@ -221,6 +233,12 @@ static int errno = 0; /* Use something better? */ * https://developer.android.com/tools/sdk/ndk/index.html */ # define HB_USE_ATEXIT 1 +# elif defined(__APPLE__) +/* For macOS and related platforms, the atexit man page indicates + * that it will be invoked when the library is unloaded, not only + * at application exit. + */ +# define HB_USE_ATEXIT 1 # endif #endif @@ -304,64 +322,189 @@ static_assert ((sizeof (hb_var_int_t) == 4), ""); typedef const struct _hb_void_t *hb_void_t; #define HB_VOID ((const _hb_void_t *) nullptr) -/* Return the number of 1 bits in mask. */ -static inline HB_CONST_FUNC unsigned int -_hb_popcount32 (uint32_t mask) -{ -#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) - return __builtin_popcount (mask); -#else - /* "HACKMEM 169" */ - uint32_t y; - y = (mask >> 1) &033333333333; - y = mask - y - ((y >>1) & 033333333333); - return (((y + (y >> 3)) & 030707070707) % 077); -#endif -} +/* Return the number of 1 bits in v. */ +template <typename T> static inline HB_CONST_FUNC unsigned int -_hb_popcount64 (uint64_t mask) +_hb_popcount (T v) { -#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) - if (sizeof (long) >= sizeof (mask)) - return __builtin_popcountl (mask); +#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) && defined(__OPTIMIZE__) + if (sizeof (T) <= sizeof (unsigned int)) + return __builtin_popcount (v); + + if (sizeof (T) <= sizeof (unsigned long)) + return __builtin_popcountl (v); + + if (sizeof (T) <= sizeof (unsigned long long)) + return __builtin_popcountll (v); #endif - return _hb_popcount32 (mask & 0xFFFFFFFF) + _hb_popcount32 (mask >> 32); + + if (sizeof (T) <= 4) + { + /* "HACKMEM 169" */ + uint32_t y; + y = (v >> 1) &033333333333; + y = v - y - ((y >>1) & 033333333333); + return (((y + (y >> 3)) & 030707070707) % 077); + } + + if (sizeof (T) == 8) + { + unsigned int shift = 32; + return _hb_popcount<uint32_t> ((uint32_t) v) + _hb_popcount ((uint32_t) (v >> shift)); + } + + if (sizeof (T) == 16) + { + unsigned int shift = 64; + return _hb_popcount<uint64_t> ((uint64_t) v) + _hb_popcount ((uint64_t) (v >> shift)); + } + + assert (0); } -template <typename T> static inline unsigned int _hb_popcount (T mask); -template <> inline unsigned int _hb_popcount<uint32_t> (uint32_t mask) { return _hb_popcount32 (mask); } -template <> inline unsigned int _hb_popcount<uint64_t> (uint64_t mask) { return _hb_popcount64 (mask); } /* Returns the number of bits needed to store number */ +template <typename T> static inline HB_CONST_FUNC unsigned int -_hb_bit_storage (unsigned int number) +_hb_bit_storage (T v) { + if (unlikely (!v)) return 0; + #if defined(__GNUC__) && (__GNUC__ >= 4) && defined(__OPTIMIZE__) - return likely (number) ? (sizeof (unsigned int) * 8 - __builtin_clz (number)) : 0; -#else - unsigned int n_bits = 0; - while (number) { - n_bits++; - number >>= 1; + if (sizeof (T) <= sizeof (unsigned int)) + return sizeof (unsigned int) * 8 - __builtin_clz (v); + + if (sizeof (T) <= sizeof (unsigned long)) + return sizeof (unsigned long) * 8 - __builtin_clzl (v); + + if (sizeof (T) <= sizeof (unsigned long long)) + return sizeof (unsigned long long) * 8 - __builtin_clzll (v); +#endif + +#if defined(_MSC_VER) || defined(__MINGW32__) + if (sizeof (T) <= sizeof (unsigned int)) + { + unsigned long where; + _BitScanReverse (&where, v); + return 1 + where; } - return n_bits; +# if _WIN64 + if (sizeof (T) <= 8) + { + unsigned long where; + _BitScanReverse64 (&where, v); + return 1 + where; + } +# endif #endif + + if (sizeof (T) <= 4) + { + /* "bithacks" */ + const unsigned int b[] = {0x2, 0xC, 0xF0, 0xFF00, 0xFFFF0000}; + const unsigned int S[] = {1, 2, 4, 8, 16}; + unsigned int r = 0; + for (int i = 4; i >= 0; i--) + if (v & b[i]) + { + v >>= S[i]; + r |= S[i]; + } + return r + 1; + } + if (sizeof (T) <= 8) + { + /* "bithacks" */ + const uint64_t b[] = {0x2, 0xC, 0xF0, 0xFF00, 0xFFFF0000, 0xFFFFFFFF00000000}; + const unsigned int S[] = {1, 2, 4, 8, 16, 32}; + unsigned int r = 0; + for (int i = 5; i >= 0; i--) + if (v & b[i]) + { + v >>= S[i]; + r |= S[i]; + } + return r + 1; + } + if (sizeof (T) == 16) + { + unsigned int shift = 64; + return (v >> shift) ? _hb_bit_storage<uint64_t> ((uint64_t) v >> shift) + shift : + _hb_bit_storage<uint64_t> ((uint64_t) v); + } + + assert (0); } -/* Returns the number of zero bits in the least significant side of number */ +/* Returns the number of zero bits in the least significant side of v */ +template <typename T> static inline HB_CONST_FUNC unsigned int -_hb_ctz (unsigned int number) +_hb_ctz (T v) { + if (unlikely (!v)) return 0; + #if defined(__GNUC__) && (__GNUC__ >= 4) && defined(__OPTIMIZE__) - return likely (number) ? __builtin_ctz (number) : 0; -#else - unsigned int n_bits = 0; - if (unlikely (!number)) return 0; - while (!(number & 1)) { - n_bits++; - number >>= 1; + if (sizeof (T) <= sizeof (unsigned int)) + return __builtin_ctz (v); + + if (sizeof (T) <= sizeof (unsigned long)) + return __builtin_ctzl (v); + + if (sizeof (T) <= sizeof (unsigned long long)) + return __builtin_ctzll (v); +#endif + +#if defined(_MSC_VER) || defined(__MINGW32__) + if (sizeof (T) <= sizeof (unsigned int)) + { + unsigned long where; + _BitScanForward (&where, v); + return where; } - return n_bits; +# if _WIN64 + if (sizeof (T) <= 8) + { + unsigned long where; + _BitScanForward64 (&where, v); + return where; + } +# endif #endif + + if (sizeof (T) <= 4) + { + /* "bithacks" */ + unsigned int c = 32; + v &= - (int32_t) v; + if (v) c--; + if (v & 0x0000FFFF) c -= 16; + if (v & 0x00FF00FF) c -= 8; + if (v & 0x0F0F0F0F) c -= 4; + if (v & 0x33333333) c -= 2; + if (v & 0x55555555) c -= 1; + return c; + } + if (sizeof (T) <= 8) + { + /* "bithacks" */ + unsigned int c = 64; + v &= - (int64_t) (v); + if (v) c--; + if (v & 0x00000000FFFFFFFF) c -= 32; + if (v & 0x0000FFFF0000FFFF) c -= 16; + if (v & 0x00FF00FF00FF00FF) c -= 8; + if (v & 0x0F0F0F0F0F0F0F0F) c -= 4; + if (v & 0x3333333333333333) c -= 2; + if (v & 0x5555555555555555) c -= 1; + return c; + } + if (sizeof (T) == 16) + { + unsigned int shift = 64; + return (uint64_t) v ? _hb_bit_storage<uint64_t> ((uint64_t) v) : + _hb_bit_storage<uint64_t> ((uint64_t) v >> shift) + shift; + } + + assert (0); } static inline bool @@ -370,6 +513,12 @@ _hb_unsigned_int_mul_overflows (unsigned int count, unsigned int size) return (size > 0) && (count >= ((unsigned int) -1) / size); } +static inline unsigned int +_hb_ceil_to_4 (unsigned int v) +{ + return ((v - 1) | 3) + 1; +} + /* arrays and maps */ @@ -402,36 +551,45 @@ struct hb_prealloced_array_t return &array[len - 1]; } - inline bool resize (unsigned int size) + /* Allocate for size but don't adjust len. */ + inline bool alloc(unsigned int size) { - if (unlikely (size > allocated)) - { - /* Need to reallocate */ - - unsigned int new_allocated = allocated; - while (size >= new_allocated) - new_allocated += (new_allocated >> 1) + 8; - - Type *new_array = nullptr; - - if (array == static_array) { - new_array = (Type *) calloc (new_allocated, sizeof (Type)); - if (new_array) - memcpy (new_array, array, 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 (array, new_allocated * sizeof (Type)); - } - } + if (likely (size <= allocated)) + return true; + + /* Reallocate */ + + unsigned int new_allocated = allocated; + while (size >= new_allocated) + new_allocated += (new_allocated >> 1) + 8; - if (unlikely (!new_array)) - return false; + Type *new_array = nullptr; - array = new_array; - allocated = new_allocated; + if (array == static_array) { + new_array = (Type *) calloc (new_allocated, sizeof (Type)); + if (new_array) + memcpy (new_array, array, 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 (array, new_allocated * sizeof (Type)); + } } + if (unlikely (!new_array)) + return false; + + array = new_array; + allocated = new_allocated; + + return true; + } + + inline bool resize (unsigned int size) + { + if (!alloc (size)) + return false; + len = size; return true; } @@ -472,6 +630,11 @@ struct hb_prealloced_array_t return nullptr; } + inline void qsort (int (*cmp)(const void*, const void*)) + { + ::qsort (array, len, sizeof (Type), cmp); + } + inline void qsort (void) { ::qsort (array, len, sizeof (Type), Type::cmp); @@ -483,25 +646,34 @@ struct hb_prealloced_array_t } template <typename T> - inline Type *bsearch (T *x) + inline Type *lsearch (const T &x) + { + for (unsigned int i = 0; i < len; i++) + if (0 == this->array[i].cmp (&x)) + return &array[i]; + return nullptr; + } + + template <typename T> + inline Type *bsearch (const T &x) { unsigned int i; return bfind (x, &i) ? &array[i] : nullptr; } template <typename T> - inline const Type *bsearch (T *x) const + inline const Type *bsearch (const T &x) const { unsigned int i; return bfind (x, &i) ? &array[i] : nullptr; } template <typename T> - inline bool bfind (T *x, unsigned int *i) const + 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->array[mid].cmp (x); + int c = this->array[mid].cmp (&x); if (c < 0) max = mid - 1; else if (c > 0) @@ -512,7 +684,7 @@ struct hb_prealloced_array_t return true; } } - if (max < 0 || (max < (int) this->len && this->array[max].cmp (x) > 0)) + if (max < 0 || (max < (int) this->len && this->array[max].cmp (&x) > 0)) max++; *i = max; return false; |