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.hh351
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 */