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 | 351 |
1 files changed, 258 insertions, 93 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 daa496e98cd..429bab0035a 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-private.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-private.hh @@ -51,7 +51,7 @@ #include <stdio.h> #include <stdarg.h> -#if defined(_MSC_VER) || defined(__MINGW32__) +#if (defined(_MSC_VER) && _MSC_VER >= 1500) || defined(__MINGW32__) #include <intrin.h> #endif @@ -90,6 +90,14 @@ extern "C" void hb_free_impl(void *ptr); HB_UNUSED typedef int HB_PASTE(static_assertion_failed_at_line_, __LINE__) [(e) ? 1 : -1] #endif // static_assert +#ifdef __GNUC__ +#if (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 8)) +#define thread_local __thread +#endif +#else +#define thread_local +#endif + #endif // __cplusplus < 201103L #if (defined(__GNUC__) || defined(__clang__)) && defined(__OPTIMIZE__) @@ -221,16 +229,14 @@ static int errno = 0; /* Use something better? */ # endif # elif defined(_MSC_VER) || defined(__MINGW32__) /* For MSVC: - * http://msdn.microsoft.com/en-ca/library/tze57ck3.aspx - * http://msdn.microsoft.com/en-ca/library/zk17ww08.aspx + * https://msdn.microsoft.com/en-us/library/tze57ck3.aspx + * https://msdn.microsoft.com/en-us/library/zk17ww08.aspx * mingw32 headers say atexit is safe to use in shared libraries. */ # define HB_USE_ATEXIT 1 -# elif defined(__ANDROID__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) -/* This was fixed in Android NKD r8 or r8b: - * https://code.google.com/p/android/issues/detail?id=6455 - * which introduced GCC 4.6: - * https://developer.android.com/tools/sdk/ndk/index.html +# elif defined(__ANDROID__) +/* This is available since Android NKD r8 or r8b: + * https://issuetracker.google.com/code/p/android/issues/detail?id=6455 */ # define HB_USE_ATEXIT 1 # elif defined(__APPLE__) @@ -241,6 +247,9 @@ static int errno = 0; /* Use something better? */ # define HB_USE_ATEXIT 1 # endif #endif +#ifdef HB_NO_ATEXIT +# undef HB_USE_ATEXIT +#endif /* Basics */ @@ -314,7 +323,7 @@ static_assert ((sizeof (hb_var_int_t) == 4), ""); -/* Misc */ +/* Tiny functions */ /* * Void! @@ -380,7 +389,7 @@ _hb_bit_storage (T v) return sizeof (unsigned long long) * 8 - __builtin_clzll (v); #endif -#if defined(_MSC_VER) || defined(__MINGW32__) +#if (defined(_MSC_VER) && _MSC_VER >= 1500) || defined(__MINGW32__) if (sizeof (T) <= sizeof (unsigned int)) { unsigned long where; @@ -414,7 +423,7 @@ _hb_bit_storage (T v) if (sizeof (T) <= 8) { /* "bithacks" */ - const uint64_t b[] = {0x2, 0xC, 0xF0, 0xFF00, 0xFFFF0000, 0xFFFFFFFF00000000}; + const uint64_t b[] = {0x2ULL, 0xCULL, 0xF0ULL, 0xFF00ULL, 0xFFFF0000ULL, 0xFFFFFFFF00000000ULL}; const unsigned int S[] = {1, 2, 4, 8, 16, 32}; unsigned int r = 0; for (int i = 5; i >= 0; i--) @@ -453,7 +462,7 @@ _hb_ctz (T v) return __builtin_ctzll (v); #endif -#if defined(_MSC_VER) || defined(__MINGW32__) +#if (defined(_MSC_VER) && _MSC_VER >= 1500) || defined(__MINGW32__) if (sizeof (T) <= sizeof (unsigned int)) { unsigned long where; @@ -489,12 +498,12 @@ _hb_ctz (T v) 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; + if (v & 0x00000000FFFFFFFFULL) c -= 32; + if (v & 0x0000FFFF0000FFFFULL) c -= 16; + if (v & 0x00FF00FF00FF00FFULL) c -= 8; + if (v & 0x0F0F0F0F0F0F0F0FULL) c -= 4; + if (v & 0x3333333333333333ULL) c -= 2; + if (v & 0x5555555555555555ULL) c -= 1; return c; } if (sizeof (T) == 16) @@ -521,39 +530,147 @@ _hb_ceil_to_4 (unsigned int v) +/* + * + * Utility types + * + */ + +#define HB_DISALLOW_COPY_AND_ASSIGN(TypeName) \ + TypeName(const TypeName&); \ + void operator=(const TypeName&) + +/* + * Static pools + */ + +/* Global nul-content Null pool. Enlarge as necessary. */ + +#define HB_NULL_POOL_SIZE 264 +static_assert (HB_NULL_POOL_SIZE % sizeof (void *) == 0, "Align HB_NULL_POOL_SIZE."); + +#ifdef HB_NO_VISIBILITY +static +#else +extern HB_INTERNAL +#endif +void * const _hb_NullPool[HB_NULL_POOL_SIZE / sizeof (void *)] +#ifdef HB_NO_VISIBILITY += {} +#endif +; +/* Generic nul-content Null objects. */ +template <typename Type> +static inline Type const & Null (void) { + static_assert (sizeof (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE."); + return *reinterpret_cast<Type const *> (_hb_NullPool); +} +#define Null(Type) Null<Type>() + +/* Specializaiton for arbitrary-content arbitrary-sized Null objects. */ +#define DEFINE_NULL_DATA(Namespace, Type, data) \ +} /* Close namespace. */ \ +static const char _Null##Type[sizeof (Namespace::Type) + 1] = data; /* +1 is for nul-termination in data */ \ +template <> \ +/*static*/ inline const Namespace::Type& Null<Namespace::Type> (void) { \ + return *reinterpret_cast<const Namespace::Type *> (_Null##Type); \ +} \ +namespace Namespace { \ +/* The following line really exists such that we end in a place needing semicolon */ \ +static_assert (Namespace::Type::min_size + 1 <= sizeof (_Null##Type), "Null pool too small. Enlarge.") + + +/* Global writable pool. Enlarge as necessary. */ + +/* To be fully correct, CrapPool must be thread_local. However, we do not rely on CrapPool + * for correct operation. It only exist to catch and divert program logic bugs instead of + * causing bad memory access. So, races there are not actually introducing incorrectness + * in the code. Has ~12kb binary size overhead to have it, also clang build fails with it. */ +#ifdef HB_NO_VISIBILITY +static +#else +extern HB_INTERNAL +#endif +/*thread_local*/ void * _hb_CrapPool[HB_NULL_POOL_SIZE / sizeof (void *)] +#ifdef HB_NO_VISIBILITY += {} +#endif +; +/* CRAP pool: Common Region for Access Protection. */ +template <typename Type> +static inline Type& Crap (void) { + static_assert (sizeof (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE."); + Type *obj = reinterpret_cast<Type *> (_hb_CrapPool); + *obj = Null(Type); + return *obj; +} +#define Crap(Type) Crap<Type>() + +template <typename Type> +struct CrapOrNull { + static inline Type & get (void) { return Crap(Type); } +}; +template <typename Type> +struct CrapOrNull<const Type> { + static inline Type const & get (void) { return Null(Type); } +}; +#define CrapOrNull(Type) CrapOrNull<Type>::get () + + + /* arrays and maps */ #define HB_PREALLOCED_ARRAY_INIT {0, 0, nullptr} -template <typename Type, unsigned int StaticSize=16> -struct hb_prealloced_array_t +template <typename Type, unsigned int StaticSize=8> +struct hb_vector_t { unsigned int len; unsigned int allocated; - Type *array; + bool successful; + Type *arrayZ; Type static_array[StaticSize]; void init (void) { len = 0; allocated = ARRAY_LENGTH (static_array); - array = static_array; + successful = true; + arrayZ = static_array; } - inline Type& operator [] (unsigned int i) { return array[i]; } - inline const Type& operator [] (unsigned int i) const { return array[i]; } + 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 nullptr; - - return &array[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) + inline bool alloc (unsigned int size) { + if (unlikely (!successful)) + return false; + if (likely (size <= allocated)) return true; @@ -565,28 +682,34 @@ struct hb_prealloced_array_t Type *new_array = nullptr; - if (array == static_array) { + if (arrayZ == static_array) + { new_array = (Type *) calloc (new_allocated, sizeof (Type)); if (new_array) - memcpy (new_array, array, len * sizeof (Type)); - } else { + 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 (array, new_allocated * sizeof (Type)); - } + if (likely (!overflows)) + new_array = (Type *) realloc (arrayZ, new_allocated * sizeof (Type)); } if (unlikely (!new_array)) + { + successful = false; return false; + } - array = new_array; + arrayZ = new_array; allocated = new_allocated; return true; } - inline bool resize (unsigned int size) + inline bool resize (int size_) { + unsigned int size = size_ < 0 ? 0u : (unsigned int) size_; if (!alloc (size)) return false; @@ -596,6 +719,7 @@ struct hb_prealloced_array_t inline void pop (void) { + if (!len) return; len--; } @@ -603,54 +727,55 @@ struct hb_prealloced_array_t { if (unlikely (i >= len)) return; - memmove (static_cast<void *> (&array[i]), - static_cast<void *> (&array[i + 1]), + memmove (static_cast<void *> (&arrayZ[i]), + static_cast<void *> (&arrayZ[i + 1]), (len - i - 1) * sizeof (Type)); len--; } - inline void shrink (unsigned int l) + inline void shrink (int size_) { - if (l < len) - len = l; + unsigned int size = size_ < 0 ? 0u : (unsigned int) size_; + if (size < len) + len = size; } template <typename T> inline Type *find (T v) { for (unsigned int i = 0; i < len; i++) - if (array[i] == v) - return &array[i]; + if (arrayZ[i] == v) + return &arrayZ[i]; return nullptr; } template <typename T> inline const Type *find (T v) const { for (unsigned int i = 0; i < len; i++) - if (array[i] == v) - return &array[i]; + if (arrayZ[i] == v) + return &arrayZ[i]; return nullptr; } inline void qsort (int (*cmp)(const void*, const void*)) { - ::qsort (array, len, sizeof (Type), cmp); + ::qsort (arrayZ, len, sizeof (Type), cmp); } inline void qsort (void) { - ::qsort (array, len, sizeof (Type), Type::cmp); + ::qsort (arrayZ, len, sizeof (Type), Type::cmp); } inline void qsort (unsigned int start, unsigned int end) { - ::qsort (array + start, end - start, sizeof (Type), Type::cmp); + ::qsort (arrayZ + start, end - start, sizeof (Type), Type::cmp); } template <typename T> inline Type *lsearch (const T &x) { for (unsigned int i = 0; i < len; i++) - if (0 == this->array[i].cmp (&x)) - return &array[i]; + if (0 == this->arrayZ[i].cmp (&x)) + return &arrayZ[i]; return nullptr; } @@ -658,13 +783,13 @@ struct hb_prealloced_array_t inline Type *bsearch (const T &x) { unsigned int i; - return bfind (x, &i) ? &array[i] : nullptr; + return bfind (x, &i) ? &arrayZ[i] : nullptr; } template <typename T> inline const Type *bsearch (const T &x) const { unsigned int i; - return bfind (x, &i) ? &array[i] : nullptr; + return bfind (x, &i) ? &arrayZ[i] : nullptr; } template <typename T> inline bool bfind (const T &x, unsigned int *i) const @@ -673,7 +798,7 @@ struct hb_prealloced_array_t while (min <= max) { int mid = (min + max) / 2; - int c = this->array[mid].cmp (&x); + int c = this->arrayZ[mid].cmp (&x); if (c < 0) max = mid - 1; else if (c > 0) @@ -684,34 +809,39 @@ 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->arrayZ[max].cmp (&x) > 0)) max++; *i = max; return false; } - inline void finish (void) + inline void fini (void) { - if (array != static_array) - free (array); - array = nullptr; + if (arrayZ != static_array) + free (arrayZ); + arrayZ = nullptr; allocated = len = 0; } }; template <typename Type> -struct hb_auto_array_t : hb_prealloced_array_t <Type> +struct hb_auto_t : Type { - hb_auto_array_t (void) { hb_prealloced_array_t<Type>::init (); } - ~hb_auto_array_t (void) { hb_prealloced_array_t<Type>::finish (); } + hb_auto_t (void) { Type::init (); } + ~hb_auto_t (void) { Type::fini (); } + private: /* Hide */ + void init (void) {} + void fini (void) {} }; +template <typename Type> +struct hb_auto_array_t : hb_auto_t <hb_vector_t <Type> > {}; #define HB_LOCKABLE_SET_INIT {HB_PREALLOCED_ARRAY_INIT} template <typename item_t, typename lock_t> struct hb_lockable_set_t { - hb_prealloced_array_t <item_t, 1> items; + hb_vector_t <item_t, 1> items; inline void init (void) { items.init (); } @@ -725,16 +855,14 @@ struct hb_lockable_set_t item_t old = *item; *item = v; l.unlock (); - old.finish (); + old.fini (); } else { item = nullptr; l.unlock (); } } else { - item = items.push (); - if (likely (item)) - *item = v; + item = items.push (v); l.unlock (); } return item; @@ -750,7 +878,7 @@ struct hb_lockable_set_t *item = items[items.len - 1]; items.pop (); l.unlock (); - old.finish (); + old.fini (); } else { l.unlock (); } @@ -773,19 +901,17 @@ struct hb_lockable_set_t l.lock (); item_t *item = items.find (v); if (!item) { - item = items.push (); - if (likely (item)) - *item = v; + item = items.push (v); } l.unlock (); return item; } - inline void finish (lock_t &l) + inline void fini (lock_t &l) { if (!items.len) { /* No need for locking. */ - items.finish (); + items.fini (); return; } l.lock (); @@ -793,10 +919,10 @@ struct hb_lockable_set_t item_t old = items[items.len - 1]; items.pop (); l.unlock (); - old.finish (); + old.fini (); l.lock (); } - items.finish (); + items.fini (); l.unlock (); } @@ -823,7 +949,7 @@ static inline unsigned char TOLOWER (unsigned char c) * light-weight) to be enabled, then HB_DEBUG can be defined to disable * the costlier checks. */ #ifdef NDEBUG -#define HB_NDEBUG +#define HB_NDEBUG 1 #endif @@ -972,19 +1098,35 @@ struct HbOpXor template <typename T> static void process (T &o, const T &a, const T &b) { o = a ^ b; } }; + +/* Compiler-assisted vectorization. */ + +/* The `vector_size' attribute was introduced in gcc 3.1. */ +#if defined( __GNUC__ ) && ( __GNUC__ >= 4 ) +#define HB_VECTOR_SIZE 128 +#elif !defined(HB_VECTOR_SIZE) +#define HB_VECTOR_SIZE 0 +#endif + /* Type behaving similar to vectorized vars defined using __attribute__((vector_size(...))). */ template <typename elt_t, unsigned int byte_size> struct hb_vector_size_t { - elt_t& operator [] (unsigned int i) { return v[i]; } - const elt_t& operator [] (unsigned int i) const { return v[i]; } + elt_t& operator [] (unsigned int i) { return u.v[i]; } + const elt_t& operator [] (unsigned int i) const { return u.v[i]; } template <class Op> inline hb_vector_size_t process (const hb_vector_size_t &o) const { hb_vector_size_t r; - for (unsigned int i = 0; i < ARRAY_LENGTH (v); i++) - Op::process (r.v[i], v[i], o.v[i]); +#if HB_VECTOR_SIZE + if (HB_VECTOR_SIZE && 0 == (byte_size * 8) % HB_VECTOR_SIZE) + for (unsigned int i = 0; i < ARRAY_LENGTH (u.vec); i++) + Op::process (r.u.vec[i], u.vec[i], o.u.vec[i]); + else +#endif + for (unsigned int i = 0; i < ARRAY_LENGTH (u.v); i++) + Op::process (r.u.v[i], u.v[i], o.u.v[i]); return r; } inline hb_vector_size_t operator | (const hb_vector_size_t &o) const @@ -996,20 +1138,27 @@ struct hb_vector_size_t inline hb_vector_size_t operator ~ () const { hb_vector_size_t r; - for (unsigned int i = 0; i < ARRAY_LENGTH (v); i++) - r.v[i] = ~v[i]; +#if HB_VECTOR_SIZE && 0 + if (HB_VECTOR_SIZE && 0 == (byte_size * 8) % HB_VECTOR_SIZE) + for (unsigned int i = 0; i < ARRAY_LENGTH (u.vec); i++) + r.u.vec[i] = ~u.vec[i]; + else +#endif + for (unsigned int i = 0; i < ARRAY_LENGTH (u.v); i++) + r.u.v[i] = ~u.v[i]; return r; } private: static_assert (byte_size / sizeof (elt_t) * sizeof (elt_t) == byte_size, ""); - elt_t v[byte_size / sizeof (elt_t)]; -}; - -/* The `vector_size' attribute was introduced in gcc 3.1. */ -#if defined( __GNUC__ ) && ( __GNUC__ >= 4 ) -#define HAVE_VECTOR_SIZE 1 + union { + elt_t v[byte_size / sizeof (elt_t)]; +#if HB_VECTOR_SIZE + typedef unsigned long vec_t __attribute__((vector_size (HB_VECTOR_SIZE / 8))); + vec_t vec[byte_size / sizeof (vec_t)]; #endif + } u; +}; /* Global runtime options. */ @@ -1046,12 +1195,12 @@ hb_options (void) /* String type. */ -struct hb_string_t +struct hb_bytes_t { - inline hb_string_t (void) : bytes (nullptr), len (0) {} - inline hb_string_t (const char *bytes_, unsigned int len_) : bytes (bytes_), len (len_) {} + inline hb_bytes_t (void) : bytes (nullptr), len (0) {} + inline hb_bytes_t (const char *bytes_, unsigned int len_) : bytes (bytes_), len (len_) {} - inline int cmp (const hb_string_t &a) const + inline int cmp (const hb_bytes_t &a) const { if (len != a.len) return (int) a.len - (int) len; @@ -1060,8 +1209,8 @@ struct hb_string_t } static inline int cmp (const void *pa, const void *pb) { - hb_string_t *a = (hb_string_t *) pa; - hb_string_t *b = (hb_string_t *) pb; + hb_bytes_t *a = (hb_bytes_t *) pa; + hb_bytes_t *b = (hb_bytes_t *) pb; return b->cmp (*a); } @@ -1070,4 +1219,20 @@ struct hb_string_t }; +/* fallback for round() */ +#if !defined (HAVE_ROUND) && !defined (HAVE_DECL_ROUND) +static inline double +round (double x) +{ + if (x >= 0) + return floor (x + 0.5); + else + return ceil (x - 0.5); +} +#endif + + +HB_INTERNAL unsigned int _hb_prime_for (unsigned int shift); + + #endif /* HB_PRIVATE_HH */ |