summaryrefslogtreecommitdiff
path: root/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-private.hh
diff options
context:
space:
mode:
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.hh314
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;