Merge pull request #2874 from harfbuzz/constexpr2
Some more cleanup towards using constexpr to simplify our internal datastrcutures. https://github.com/harfbuzz/harfbuzz/pull/2874
This commit is contained in:
commit
021a1725ed
|
@ -54,14 +54,13 @@ jobs:
|
|||
executor: autotools-executor
|
||||
steps:
|
||||
- checkout
|
||||
- run: sudo apt update && DEBIAN_FRONTEND=noninteractive sudo apt install -y git ninja-build binutils libtool autoconf automake make gcc g++ pkg-config ragel gtk-doc-tools gobject-introspection libfontconfig1-dev libfreetype6-dev libglib2.0-dev libgirepository1.0-dev libcairo2-dev libicu-dev libgraphite2-dev python3 python3-pip cmake
|
||||
- run: sudo apt update && DEBIAN_FRONTEND=noninteractive sudo apt install -y git ninja-build binutils libtool autoconf automake make gcc g++ pkg-config ragel gtk-doc-tools gobject-introspection libfontconfig1-dev libfreetype6-dev libglib2.0-dev libgirepository1.0-dev libcairo2-dev libicu-dev libgraphite2-dev python3 python3-pip
|
||||
- run: pip3 install fonttools meson --upgrade
|
||||
- run: ./autogen.sh
|
||||
- run: make -j32
|
||||
- run: make distcheck
|
||||
- run: rm harfbuzz-* && make distdir
|
||||
- run: cd harfbuzz-* && meson build && ninja -Cbuild test
|
||||
- run: cd harfbuzz-* && cmake -Bcmakebuild -H. && cmake --build cmakebuild
|
||||
- run: make dist
|
||||
- persist_to_workspace:
|
||||
root: .
|
||||
|
|
|
@ -19,12 +19,12 @@ jobs:
|
|||
tar xzf cov-analysis-linux64.tar.gz --strip 1 -C cov-analysis-linux64
|
||||
env:
|
||||
TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }}
|
||||
|
||||
|
||||
# ideally we should've used meson and ninja here but it complains about coverage or something
|
||||
- run: cov-analysis-linux64/bin/cov-build --dir cov-int clang src/hb-*.cc -DHAVE_FREETYPE -DHAVE_GRAPHITE2 -DHAVE_GLIB -DHAVE_ICU `pkg-config --cflags freetype2 graphite2 glib-2.0 icu-uc` -DHAVE_INTEL_ATOMIC_PRIMITIVES -DHAVE_ROUNDF -DHAVE_SYS_MMAN_H -DHAVE_UNISTD_H -DHAVE_GETPAGESIZE -DHB_EXPERIMENTAL_API -c
|
||||
- run: cov-analysis-linux64/bin/cov-build --dir cov-int clang src/hb-*.cc -DHAVE_FREETYPE -DHAVE_GRAPHITE2 -DHAVE_GLIB -DHAVE_ICU `pkg-config --cflags freetype2 graphite2 glib-2.0 icu-uc` -DHAVE_ROUNDF -DHAVE_SYS_MMAN_H -DHAVE_UNISTD_H -DHAVE_GETPAGESIZE -DHB_EXPERIMENTAL_API -c
|
||||
|
||||
- run: tar czvf harfbuzz.tgz cov-int
|
||||
|
||||
|
||||
- name: submit to coverity
|
||||
run: |
|
||||
curl \
|
||||
|
|
|
@ -102,6 +102,8 @@ if (${HAVE_STDBOOL_H})
|
|||
add_definitions(-DHAVE_STDBOOL_H)
|
||||
endif ()
|
||||
|
||||
# https://github.com/harfbuzz/harfbuzz/pull/2874#issuecomment-782859099
|
||||
if (NOT WIN32) add_definitions("-DHAVE_PTHREAD") endif ()
|
||||
|
||||
if (MSVC)
|
||||
add_definitions(-wd4244 -wd4267 -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_WARNINGS)
|
||||
|
@ -406,37 +408,6 @@ if (HB_HAVE_GOBJECT)
|
|||
)
|
||||
endif ()
|
||||
|
||||
## Atomic ops availability detection
|
||||
file(WRITE "${PROJECT_BINARY_DIR}/try_compile_intel_atomic_primitives.c"
|
||||
" void memory_barrier (void) { __sync_synchronize (); }
|
||||
int atomic_add (int *i) { return __sync_fetch_and_add (i, 1); }
|
||||
int mutex_trylock (int *m) { return __sync_lock_test_and_set (m, 1); }
|
||||
void mutex_unlock (int *m) { __sync_lock_release (m); }
|
||||
int main () { return 0; }
|
||||
")
|
||||
try_compile(HB_HAVE_INTEL_ATOMIC_PRIMITIVES
|
||||
${PROJECT_BINARY_DIR}/try_compile_intel_atomic_primitives
|
||||
${PROJECT_BINARY_DIR}/try_compile_intel_atomic_primitives.c)
|
||||
if (HB_HAVE_INTEL_ATOMIC_PRIMITIVES)
|
||||
add_definitions(-DHAVE_INTEL_ATOMIC_PRIMITIVES)
|
||||
endif ()
|
||||
|
||||
file(WRITE "${PROJECT_BINARY_DIR}/try_compile_solaris_atomic_ops.c"
|
||||
" #include <atomic.h>
|
||||
/* This requires Solaris Studio 12.2 or newer: */
|
||||
#include <mbarrier.h>
|
||||
void memory_barrier (void) { __machine_rw_barrier (); }
|
||||
int atomic_add (volatile unsigned *i) { return atomic_add_int_nv (i, 1); }
|
||||
void *atomic_ptr_cmpxchg (volatile void **target, void *cmp, void *newval) { return atomic_cas_ptr (target, cmp, newval); }
|
||||
int main () { return 0; }
|
||||
")
|
||||
try_compile(HB_HAVE_SOLARIS_ATOMIC_OPS
|
||||
${PROJECT_BINARY_DIR}/try_compile_solaris_atomic_ops
|
||||
${PROJECT_BINARY_DIR}/try_compile_solaris_atomic_ops.c)
|
||||
if (HB_HAVE_SOLARIS_ATOMIC_OPS)
|
||||
add_definitions(-DHAVE_SOLARIS_ATOMIC_OPS)
|
||||
endif ()
|
||||
|
||||
|
||||
## Define harfbuzz library
|
||||
add_library(harfbuzz ${project_sources} ${project_extra_sources} ${project_headers})
|
||||
|
|
|
@ -40,8 +40,6 @@ EXTRA_DIST = \
|
|||
perf/texts/en-words.txt \
|
||||
perf/texts/fa-monologue.txt \
|
||||
perf/texts/fa-thelittleprince.txt \
|
||||
meson-cc-tests/intel-atomic-primitives-test.c \
|
||||
meson-cc-tests/solaris-atomic-operations.c \
|
||||
mingw-configure.sh \
|
||||
$(NULL)
|
||||
|
||||
|
|
39
configure.ac
39
configure.ac
|
@ -417,45 +417,6 @@ AM_CONDITIONAL(HAVE_CORETEXT, $have_coretext)
|
|||
|
||||
dnl ===========================================================================
|
||||
|
||||
AC_CACHE_CHECK([for Intel atomic primitives], hb_cv_have_intel_atomic_primitives, [
|
||||
hb_cv_have_intel_atomic_primitives=false
|
||||
AC_TRY_LINK([
|
||||
void memory_barrier (void) { __sync_synchronize (); }
|
||||
int atomic_add (int *i) { return __sync_fetch_and_add (i, 1); }
|
||||
int mutex_trylock (int *m) { return __sync_lock_test_and_set (m, 1); }
|
||||
void mutex_unlock (int *m) { __sync_lock_release (m); }
|
||||
], [], hb_cv_have_intel_atomic_primitives=true
|
||||
)
|
||||
])
|
||||
if $hb_cv_have_intel_atomic_primitives; then
|
||||
AC_DEFINE(HAVE_INTEL_ATOMIC_PRIMITIVES, 1, [Have Intel __sync_* atomic primitives])
|
||||
fi
|
||||
|
||||
dnl ===========================================================================
|
||||
|
||||
AC_CACHE_CHECK([for Solaris atomic operations], hb_cv_have_solaris_atomic_ops, [
|
||||
hb_cv_have_solaris_atomic_ops=false
|
||||
AC_TRY_LINK([
|
||||
#include <atomic.h>
|
||||
/* This requires Solaris Studio 12.2 or newer: */
|
||||
#include <mbarrier.h>
|
||||
void memory_barrier (void) { __machine_rw_barrier (); }
|
||||
int atomic_add (volatile unsigned *i) { return atomic_add_int_nv (i, 1); }
|
||||
void *atomic_ptr_cmpxchg (volatile void **target, void *cmp, void *newval) { return atomic_cas_ptr (target, cmp, newval); }
|
||||
], [], hb_cv_have_solaris_atomic_ops=true
|
||||
)
|
||||
])
|
||||
if $hb_cv_have_solaris_atomic_ops; then
|
||||
AC_DEFINE(HAVE_SOLARIS_ATOMIC_OPS, 1, [Have Solaris __machine_*_barrier and atomic_* operations])
|
||||
fi
|
||||
|
||||
if test "$os_win32" = no && ! $have_pthread; then
|
||||
AC_CHECK_HEADERS(sched.h)
|
||||
AC_SEARCH_LIBS(sched_yield,rt,AC_DEFINE(HAVE_SCHED_YIELD, 1, [Have sched_yield]))
|
||||
fi
|
||||
|
||||
dnl ===========================================================================
|
||||
|
||||
AC_CONFIG_FILES([
|
||||
Makefile
|
||||
src/Makefile
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
void memory_barrier (void) { __sync_synchronize (); }
|
||||
int atomic_add (int *i) { return __sync_fetch_and_add (i, 1); }
|
||||
int mutex_trylock (int *m) { return __sync_lock_test_and_set (m, 1); }
|
||||
void mutex_unlock (int *m) { __sync_lock_release (m); }
|
||||
|
||||
int main(void) { return 0;}
|
|
@ -1,8 +0,0 @@
|
|||
#include <atomic.h>
|
||||
/* This requires Solaris Studio 12.2 or newer: */
|
||||
#include <mbarrier.h>
|
||||
void memory_barrier (void) { __machine_rw_barrier (); }
|
||||
int atomic_add (volatile unsigned *i) { return atomic_add_int_nv (i, 1); }
|
||||
void *atomic_ptr_cmpxchg (volatile void **target, void *cmp, void *newval) { return atomic_cas_ptr (target, cmp, newval); }
|
||||
|
||||
int main(void) { return 0; }
|
11
meson.build
11
meson.build
|
@ -285,9 +285,6 @@ if host_machine.system() != 'windows'
|
|||
|
||||
if thread_dep.found()
|
||||
conf.set('HAVE_PTHREAD', 1)
|
||||
else
|
||||
check_headers += ['sched.h']
|
||||
check_funcs += ['sched_yield', {'link_with': 'rt'}]
|
||||
endif
|
||||
endif
|
||||
|
||||
|
@ -337,14 +334,6 @@ foreach check : check_funcs
|
|||
endif
|
||||
endforeach
|
||||
|
||||
if cpp.links(files('meson-cc-tests/intel-atomic-primitives-test.c'), name: 'Intel atomics')
|
||||
conf.set('HAVE_INTEL_ATOMIC_PRIMITIVES', 1)
|
||||
endif
|
||||
|
||||
if cpp.links(files('meson-cc-tests/solaris-atomic-operations.c'), name: 'Solaris atomic ops')
|
||||
conf.set('HAVE_SOLARIS_ATOMIC_OPS', 1)
|
||||
endif
|
||||
|
||||
subdir('src')
|
||||
subdir('util')
|
||||
|
||||
|
|
130
src/hb-algs.hh
130
src/hb-algs.hh
|
@ -35,6 +35,129 @@
|
|||
#include "hb-number.hh"
|
||||
|
||||
|
||||
/*
|
||||
* Flags
|
||||
*/
|
||||
|
||||
/* Enable bitwise ops on enums marked as flags_t */
|
||||
/* To my surprise, looks like the function resolver is happy to silently cast
|
||||
* one enum to another... So this doesn't provide the type-checking that I
|
||||
* originally had in mind... :(.
|
||||
*
|
||||
* For MSVC warnings, see: https://github.com/harfbuzz/harfbuzz/pull/163
|
||||
*/
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning(disable:4200)
|
||||
# pragma warning(disable:4800)
|
||||
#endif
|
||||
#define HB_MARK_AS_FLAG_T(T) \
|
||||
extern "C++" { \
|
||||
static inline constexpr T operator | (T l, T r) { return T ((unsigned) l | (unsigned) r); } \
|
||||
static inline constexpr T operator & (T l, T r) { return T ((unsigned) l & (unsigned) r); } \
|
||||
static inline constexpr T operator ^ (T l, T r) { return T ((unsigned) l ^ (unsigned) r); } \
|
||||
static inline constexpr T operator ~ (T r) { return T (~(unsigned int) r); } \
|
||||
static inline T& operator |= (T &l, T r) { l = l | r; return l; } \
|
||||
static inline T& operator &= (T& l, T r) { l = l & r; return l; } \
|
||||
static inline T& operator ^= (T& l, T r) { l = l ^ r; return l; } \
|
||||
} \
|
||||
static_assert (true, "")
|
||||
|
||||
/* Useful for set-operations on small enums.
|
||||
* For example, for testing "x ∈ {x1, x2, x3}" use:
|
||||
* (FLAG_UNSAFE(x) & (FLAG(x1) | FLAG(x2) | FLAG(x3)))
|
||||
*/
|
||||
#define FLAG(x) (static_assert_expr ((unsigned)(x) < 32) + (((uint32_t) 1U) << (unsigned)(x)))
|
||||
#define FLAG_UNSAFE(x) ((unsigned)(x) < 32 ? (((uint32_t) 1U) << (unsigned)(x)) : 0)
|
||||
#define FLAG_RANGE(x,y) (static_assert_expr ((x) < (y)) + FLAG(y+1) - FLAG(x))
|
||||
#define FLAG64(x) (static_assert_expr ((unsigned)(x) < 64) + (((uint64_t) 1ULL) << (unsigned)(x)))
|
||||
#define FLAG64_UNSAFE(x) ((unsigned)(x) < 64 ? (((uint64_t) 1ULL) << (unsigned)(x)) : 0)
|
||||
|
||||
|
||||
/*
|
||||
* Big-endian integers.
|
||||
*/
|
||||
|
||||
/* Endian swap, used in Windows related backends */
|
||||
static inline constexpr uint16_t hb_uint16_swap (uint16_t v)
|
||||
{ return (v >> 8) | (v << 8); }
|
||||
static inline constexpr uint32_t hb_uint32_swap (uint32_t v)
|
||||
{ return (hb_uint16_swap (v) << 16) | hb_uint16_swap (v >> 16); }
|
||||
|
||||
template <typename Type, int Bytes = sizeof (Type)> struct BEInt;
|
||||
template <typename Type>
|
||||
struct BEInt<Type, 1>
|
||||
{
|
||||
public:
|
||||
BEInt () = default;
|
||||
constexpr BEInt (Type V) : v {uint8_t (V)} {}
|
||||
constexpr operator Type () const { return v; }
|
||||
private: uint8_t v;
|
||||
};
|
||||
template <typename Type>
|
||||
struct BEInt<Type, 2>
|
||||
{
|
||||
public:
|
||||
BEInt () = default;
|
||||
constexpr BEInt (Type V) : v {uint8_t ((V >> 8) & 0xFF),
|
||||
uint8_t ((V ) & 0xFF)} {}
|
||||
|
||||
struct __attribute__((packed)) packed_uint16_t { uint16_t v; };
|
||||
constexpr operator Type () const
|
||||
{
|
||||
#if ((defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__)) && \
|
||||
defined(__BYTE_ORDER) && \
|
||||
(__BYTE_ORDER == __LITTLE_ENDIAN || __BYTE_ORDER == __BIG_ENDIAN)
|
||||
/* Spoon-feed the compiler a big-endian integer with alignment 1.
|
||||
* https://github.com/harfbuzz/harfbuzz/pull/1398 */
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
return __builtin_bswap16 (((packed_uint16_t *) this)->v);
|
||||
#else /* __BYTE_ORDER == __BIG_ENDIAN */
|
||||
return ((packed_uint16_t *) this)->v;
|
||||
#endif
|
||||
#else
|
||||
return (v[0] << 8)
|
||||
+ (v[1] );
|
||||
#endif
|
||||
}
|
||||
private: uint8_t v[2];
|
||||
};
|
||||
template <typename Type>
|
||||
struct BEInt<Type, 3>
|
||||
{
|
||||
public:
|
||||
BEInt () = default;
|
||||
constexpr BEInt (Type V) : v {uint8_t ((V >> 16) & 0xFF),
|
||||
uint8_t ((V >> 8) & 0xFF),
|
||||
uint8_t ((V ) & 0xFF)} {}
|
||||
constexpr operator Type () const { return (v[0] << 16)
|
||||
+ (v[1] << 8)
|
||||
+ (v[2] ); }
|
||||
private: uint8_t v[3];
|
||||
};
|
||||
template <typename Type>
|
||||
struct BEInt<Type, 4>
|
||||
{
|
||||
public:
|
||||
BEInt () = default;
|
||||
constexpr BEInt (Type V) : v {uint8_t ((V >> 24) & 0xFF),
|
||||
uint8_t ((V >> 16) & 0xFF),
|
||||
uint8_t ((V >> 8) & 0xFF),
|
||||
uint8_t ((V ) & 0xFF)} {}
|
||||
constexpr operator Type () const { return (v[0] << 24)
|
||||
+ (v[1] << 16)
|
||||
+ (v[2] << 8)
|
||||
+ (v[3] ); }
|
||||
private: uint8_t v[4];
|
||||
};
|
||||
|
||||
/* Floats. */
|
||||
|
||||
/* We want our rounding towards +infinity. */
|
||||
static inline float
|
||||
_hb_roundf (float x) { return floorf (x + .5f); }
|
||||
#define roundf(x) _hb_roundf(x)
|
||||
|
||||
|
||||
/* Encodes three unsigned integers in one 64-bit number. If the inputs have more than 21 bits,
|
||||
* values will be truncated / overlap, and might not decode exactly. */
|
||||
#define HB_CODEPOINT_ENCODE3(x,y,z) (((uint64_t) (x) << 42) | ((uint64_t) (y) << 21) | (uint64_t) (z))
|
||||
|
@ -48,6 +171,7 @@
|
|||
#define HB_CODEPOINT_DECODE3_11_7_14_2(v) ((hb_codepoint_t) (((v) >> 14) & 0x007Fu) | 0x0300)
|
||||
#define HB_CODEPOINT_DECODE3_11_7_14_3(v) ((hb_codepoint_t) (v) & 0x3FFFu)
|
||||
|
||||
|
||||
struct
|
||||
{
|
||||
/* Note. This is dangerous in that if it's passed an rvalue, it returns rvalue-reference. */
|
||||
|
@ -413,7 +537,7 @@ HB_FUNCOBJ (hb_clamp);
|
|||
|
||||
/* Return the number of 1 bits in v. */
|
||||
template <typename T>
|
||||
static inline HB_CONST_FUNC unsigned int
|
||||
static inline unsigned int
|
||||
hb_popcount (T v)
|
||||
{
|
||||
#if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__)
|
||||
|
@ -454,7 +578,7 @@ hb_popcount (T v)
|
|||
|
||||
/* Returns the number of bits needed to store number */
|
||||
template <typename T>
|
||||
static inline HB_CONST_FUNC unsigned int
|
||||
static inline unsigned int
|
||||
hb_bit_storage (T v)
|
||||
{
|
||||
if (unlikely (!v)) return 0;
|
||||
|
@ -528,7 +652,7 @@ hb_bit_storage (T v)
|
|||
|
||||
/* Returns the number of zero bits in the least significant side of v */
|
||||
template <typename T>
|
||||
static inline HB_CONST_FUNC unsigned int
|
||||
static inline unsigned int
|
||||
hb_ctz (T v)
|
||||
{
|
||||
if (unlikely (!v)) return 8 * sizeof (T);
|
||||
|
|
129
src/hb-atomic.hh
129
src/hb-atomic.hh
|
@ -52,7 +52,7 @@
|
|||
|
||||
#elif !defined(HB_NO_MT) && defined(__ATOMIC_ACQUIRE)
|
||||
|
||||
/* C++11-style GCC primitives. */
|
||||
/* C++11-style GCC primitives. We prefer these as they don't require linking to libstdc++ / libc++. */
|
||||
|
||||
#define _hb_memory_barrier() __sync_synchronize ()
|
||||
|
||||
|
@ -73,7 +73,8 @@ _hb_atomic_ptr_impl_cmplexch (const void **P, const void *O_, const void *N)
|
|||
}
|
||||
#define hb_atomic_ptr_impl_cmpexch(P,O,N) _hb_atomic_ptr_impl_cmplexch ((const void **) (P), (O), (N))
|
||||
|
||||
#elif !defined(HB_NO_MT) && __cplusplus >= 201103L
|
||||
|
||||
#elif !defined(HB_NO_MT)
|
||||
|
||||
/* C++11 atomics. */
|
||||
|
||||
|
@ -101,117 +102,6 @@ _hb_atomic_ptr_impl_cmplexch (const void **P, const void *O_, const void *N)
|
|||
#define hb_atomic_ptr_impl_cmpexch(P,O,N) _hb_atomic_ptr_impl_cmplexch ((const void **) (P), (O), (N))
|
||||
|
||||
|
||||
#elif !defined(HB_NO_MT) && defined(_WIN32)
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
static inline void _hb_memory_barrier ()
|
||||
{
|
||||
#if !defined(MemoryBarrier) && !defined(__MINGW32_VERSION)
|
||||
/* MinGW has a convoluted history of supporting MemoryBarrier. */
|
||||
LONG dummy = 0;
|
||||
InterlockedExchange (&dummy, 1);
|
||||
#else
|
||||
MemoryBarrier ();
|
||||
#endif
|
||||
}
|
||||
#define _hb_memory_barrier() _hb_memory_barrier ()
|
||||
|
||||
#define hb_atomic_int_impl_add(AI, V) InterlockedExchangeAdd ((LONG *) (AI), (V))
|
||||
static_assert ((sizeof (LONG) == sizeof (int)), "");
|
||||
|
||||
#define hb_atomic_ptr_impl_cmpexch(P,O,N) (InterlockedCompareExchangePointer ((P), (N), (O)) == (O))
|
||||
|
||||
|
||||
#elif !defined(HB_NO_MT) && defined(HAVE_INTEL_ATOMIC_PRIMITIVES)
|
||||
|
||||
#define _hb_memory_barrier() __sync_synchronize ()
|
||||
|
||||
#define hb_atomic_int_impl_add(AI, V) __sync_fetch_and_add ((AI), (V))
|
||||
|
||||
#define hb_atomic_ptr_impl_cmpexch(P,O,N) __sync_bool_compare_and_swap ((P), (O), (N))
|
||||
|
||||
|
||||
#elif !defined(HB_NO_MT) && defined(HAVE_SOLARIS_ATOMIC_OPS)
|
||||
|
||||
#include <atomic.h>
|
||||
#include <mbarrier.h>
|
||||
|
||||
#define _hb_memory_r_barrier() __machine_r_barrier ()
|
||||
#define _hb_memory_w_barrier() __machine_w_barrier ()
|
||||
#define _hb_memory_barrier() __machine_rw_barrier ()
|
||||
|
||||
static inline int _hb_fetch_and_add (int *AI, int V)
|
||||
{
|
||||
_hb_memory_w_barrier ();
|
||||
int result = atomic_add_int_nv ((uint_t *) AI, V) - V;
|
||||
_hb_memory_r_barrier ();
|
||||
return result;
|
||||
}
|
||||
static inline bool _hb_compare_and_swap_ptr (void **P, void *O, void *N)
|
||||
{
|
||||
_hb_memory_w_barrier ();
|
||||
bool result = atomic_cas_ptr (P, O, N) == O;
|
||||
_hb_memory_r_barrier ();
|
||||
return result;
|
||||
}
|
||||
|
||||
#define hb_atomic_int_impl_add(AI, V) _hb_fetch_and_add ((AI), (V))
|
||||
|
||||
#define hb_atomic_ptr_impl_cmpexch(P,O,N) _hb_compare_and_swap_ptr ((P), (O), (N))
|
||||
|
||||
|
||||
#elif !defined(HB_NO_MT) && defined(__APPLE__)
|
||||
|
||||
#include <libkern/OSAtomic.h>
|
||||
#ifdef __MAC_OS_X_MIN_REQUIRED
|
||||
#include <AvailabilityMacros.h>
|
||||
#elif defined(__IPHONE_OS_MIN_REQUIRED)
|
||||
#include <Availability.h>
|
||||
#endif
|
||||
|
||||
#define _hb_memory_barrier() OSMemoryBarrier ()
|
||||
|
||||
#define hb_atomic_int_impl_add(AI, V) (OSAtomicAdd32Barrier ((V), (AI)) - (V))
|
||||
|
||||
#if (MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_4 || __IPHONE_VERSION_MIN_REQUIRED >= 20100)
|
||||
#define hb_atomic_ptr_impl_cmpexch(P,O,N) OSAtomicCompareAndSwapPtrBarrier ((O), (N), (P))
|
||||
#else
|
||||
#if __ppc64__ || __x86_64__ || __aarch64__
|
||||
#define hb_atomic_ptr_impl_cmpexch(P,O,N) OSAtomicCompareAndSwap64Barrier ((int64_t) (O), (int64_t) (N), (int64_t*) (P))
|
||||
#else
|
||||
#define hb_atomic_ptr_impl_cmpexch(P,O,N) OSAtomicCompareAndSwap32Barrier ((int32_t) (O), (int32_t) (N), (int32_t*) (P))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#elif !defined(HB_NO_MT) && defined(_AIX) && (defined(__IBMCPP__) || defined(__ibmxl__))
|
||||
|
||||
#include <builtins.h>
|
||||
|
||||
#define _hb_memory_barrier() __lwsync ()
|
||||
|
||||
static inline int _hb_fetch_and_add (int *AI, int V)
|
||||
{
|
||||
_hb_memory_barrier ();
|
||||
int result = __fetch_and_add (AI, V);
|
||||
_hb_memory_barrier ();
|
||||
return result;
|
||||
}
|
||||
static inline bool _hb_compare_and_swaplp (long *P, long O, long N)
|
||||
{
|
||||
_hb_memory_barrier ();
|
||||
bool result = __compare_and_swaplp (P, &O, N);
|
||||
_hb_memory_barrier ();
|
||||
return result;
|
||||
}
|
||||
|
||||
#define hb_atomic_int_impl_add(AI, V) _hb_fetch_and_add ((AI), (V))
|
||||
|
||||
#define hb_atomic_ptr_impl_cmpexch(P,O,N) _hb_compare_and_swaplp ((long *) (P), (long) (O), (long) (N))
|
||||
static_assert ((sizeof (long) == sizeof (void *)), "");
|
||||
|
||||
|
||||
#elif defined(HB_NO_MT)
|
||||
|
||||
#define hb_atomic_int_impl_add(AI, V) ((*(AI) += (V)) - (V))
|
||||
|
@ -259,9 +149,11 @@ inline void *hb_atomic_ptr_impl_get (void ** const P) { void *v = *P; _hb_memory
|
|||
#endif
|
||||
|
||||
|
||||
#define HB_ATOMIC_INT_INIT(V) {V}
|
||||
struct hb_atomic_int_t
|
||||
{
|
||||
hb_atomic_int_t () = default;
|
||||
constexpr hb_atomic_int_t (int v) : v (v) {}
|
||||
|
||||
void set_relaxed (int v_) { hb_atomic_int_impl_set_relaxed (&v, v_); }
|
||||
void set (int v_) { hb_atomic_int_impl_set (&v, v_); }
|
||||
int get_relaxed () const { return hb_atomic_int_impl_get_relaxed (&v); }
|
||||
|
@ -269,16 +161,17 @@ struct hb_atomic_int_t
|
|||
int inc () { return hb_atomic_int_impl_add (&v, 1); }
|
||||
int dec () { return hb_atomic_int_impl_add (&v, -1); }
|
||||
|
||||
int v;
|
||||
int v = 0;
|
||||
};
|
||||
|
||||
|
||||
#define HB_ATOMIC_PTR_INIT(V) {V}
|
||||
template <typename P>
|
||||
struct hb_atomic_ptr_t
|
||||
{
|
||||
typedef hb_remove_pointer<P> T;
|
||||
|
||||
hb_atomic_ptr_t () = default;
|
||||
constexpr hb_atomic_ptr_t (T* v) : v (v) {}
|
||||
|
||||
void init (T* v_ = nullptr) { set_relaxed (v_); }
|
||||
void set_relaxed (T* v_) { hb_atomic_ptr_impl_set_relaxed (&v, v_); }
|
||||
T *get_relaxed () const { return (T *) hb_atomic_ptr_impl_get_relaxed (&v); }
|
||||
|
@ -288,7 +181,7 @@ struct hb_atomic_ptr_t
|
|||
T * operator -> () const { return get (); }
|
||||
template <typename C> operator C * () const { return get (); }
|
||||
|
||||
T *v;
|
||||
T *v = nullptr;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -89,8 +89,8 @@ DEFINE_NULL_INSTANCE (hb_face_t) =
|
|||
nullptr, /* destroy */
|
||||
|
||||
0, /* index */
|
||||
HB_ATOMIC_INT_INIT (1000), /* upem */
|
||||
HB_ATOMIC_INT_INIT (0), /* num_glyphs */
|
||||
1000, /* upem */
|
||||
0, /* num_glyphs */
|
||||
|
||||
/* Zero for the rest is fine. */
|
||||
};
|
||||
|
|
|
@ -81,7 +81,7 @@ struct hb_face_t
|
|||
return blob;
|
||||
}
|
||||
|
||||
HB_PURE_FUNC unsigned int get_upem () const
|
||||
unsigned int get_upem () const
|
||||
{
|
||||
unsigned int ret = upem.get_relaxed ();
|
||||
if (unlikely (!ret))
|
||||
|
|
|
@ -80,6 +80,11 @@ static inline Type& StructAfter(TObject &X)
|
|||
* Size checking
|
||||
*/
|
||||
|
||||
/* Size signifying variable-sized array */
|
||||
#ifndef HB_VAR_ARRAY
|
||||
#define HB_VAR_ARRAY 1
|
||||
#endif
|
||||
|
||||
/* Check _assertion in a method environment */
|
||||
#define _DEFINE_INSTANCE_ASSERTION1(_line, _assertion) \
|
||||
void _instance_assertion_on_line_##_line () const \
|
||||
|
|
|
@ -49,6 +49,10 @@ template <bool b> using hb_bool_constant = hb_integral_constant<bool, b>;
|
|||
using hb_true_type = hb_bool_constant<true>;
|
||||
using hb_false_type = hb_bool_constant<false>;
|
||||
|
||||
/* Static-assert as expression. */
|
||||
template <bool cond> struct static_assert_expr;
|
||||
template <> struct static_assert_expr<true> : hb_false_type {};
|
||||
#define static_assert_expr(C) static_assert_expr<C>::value
|
||||
|
||||
/* Basic type SFINAE. */
|
||||
|
||||
|
@ -220,6 +224,8 @@ struct hb_reference_wrapper<T&>
|
|||
};
|
||||
|
||||
|
||||
/* Type traits */
|
||||
|
||||
template <typename T>
|
||||
using hb_is_integral = hb_bool_constant<
|
||||
hb_is_same (hb_decay<T>, char) ||
|
||||
|
@ -292,6 +298,15 @@ template <> struct hb_int_max<unsigned long long> : hb_integral_constant<unsigne
|
|||
#define hb_int_max(T) hb_int_max<T>::value
|
||||
|
||||
|
||||
/* Class traits. */
|
||||
|
||||
#define HB_DELETE_COPY_ASSIGN(TypeName) \
|
||||
TypeName(const TypeName&) = delete; \
|
||||
void operator=(const TypeName&) = delete
|
||||
#define HB_DELETE_CREATE_COPY_ASSIGN(TypeName) \
|
||||
TypeName() = delete; \
|
||||
TypeName(const TypeName&) = delete; \
|
||||
void operator=(const TypeName&) = delete
|
||||
|
||||
template <typename T, typename>
|
||||
struct _hb_is_destructible : hb_false_type {};
|
||||
|
|
|
@ -73,24 +73,6 @@ typedef CRITICAL_SECTION hb_mutex_impl_t;
|
|||
#define hb_mutex_impl_finish(M) DeleteCriticalSection (M)
|
||||
|
||||
|
||||
#elif !defined(HB_NO_MT) && defined(HAVE_INTEL_ATOMIC_PRIMITIVES)
|
||||
|
||||
#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_YIELD)
|
||||
# include <sched.h>
|
||||
# define HB_SCHED_YIELD() sched_yield ()
|
||||
#else
|
||||
# define HB_SCHED_YIELD() HB_STMT_START {} HB_STMT_END
|
||||
#endif
|
||||
|
||||
/* This actually is not a totally awful implementation. */
|
||||
typedef volatile int hb_mutex_impl_t;
|
||||
#define HB_MUTEX_IMPL_INIT 0
|
||||
#define hb_mutex_impl_init(M) *(M) = 0
|
||||
#define hb_mutex_impl_lock(M) HB_STMT_START { while (__sync_lock_test_and_set((M), 1)) HB_SCHED_YIELD (); } HB_STMT_END
|
||||
#define hb_mutex_impl_unlock(M) __sync_lock_release (M)
|
||||
#define hb_mutex_impl_finish(M) HB_STMT_START {} HB_STMT_END
|
||||
|
||||
|
||||
#elif defined(HB_NO_MT)
|
||||
|
||||
typedef int hb_mutex_impl_t;
|
||||
|
|
|
@ -140,9 +140,7 @@ struct hb_lockable_set_t
|
|||
* Reference-count.
|
||||
*/
|
||||
|
||||
#define HB_REFERENCE_COUNT_INERT_VALUE 0
|
||||
#define HB_REFERENCE_COUNT_POISON_VALUE -0x0000DEAD
|
||||
#define HB_REFERENCE_COUNT_INIT {HB_ATOMIC_INT_INIT (HB_REFERENCE_COUNT_INERT_VALUE)}
|
||||
#define HB_REFERENCE_COUNT_INIT {0}
|
||||
|
||||
struct hb_reference_count_t
|
||||
{
|
||||
|
@ -152,9 +150,9 @@ struct hb_reference_count_t
|
|||
int get_relaxed () const { return ref_count.get_relaxed (); }
|
||||
int inc () const { return ref_count.inc (); }
|
||||
int dec () const { return ref_count.dec (); }
|
||||
void fini () { ref_count.set_relaxed (HB_REFERENCE_COUNT_POISON_VALUE); }
|
||||
void fini () { ref_count.set_relaxed (-0x0000DEAD); }
|
||||
|
||||
bool is_inert () const { return ref_count.get_relaxed () == HB_REFERENCE_COUNT_INERT_VALUE; }
|
||||
bool is_inert () const { return !ref_count.get_relaxed (); }
|
||||
bool is_valid () const { return ref_count.get_relaxed () > 0; }
|
||||
};
|
||||
|
||||
|
@ -197,15 +195,10 @@ struct hb_user_data_array_t
|
|||
struct hb_object_header_t
|
||||
{
|
||||
hb_reference_count_t ref_count;
|
||||
mutable hb_atomic_int_t writable;
|
||||
mutable hb_atomic_int_t writable = 0;
|
||||
hb_atomic_ptr_t<hb_user_data_array_t> user_data;
|
||||
};
|
||||
#define HB_OBJECT_HEADER_STATIC \
|
||||
{ \
|
||||
HB_REFERENCE_COUNT_INIT, \
|
||||
HB_ATOMIC_INT_INIT (false), \
|
||||
HB_ATOMIC_PTR_INIT (nullptr) \
|
||||
}
|
||||
#define HB_OBJECT_HEADER_STATIC {}
|
||||
|
||||
|
||||
/*
|
||||
|
|
|
@ -53,7 +53,7 @@ namespace OT {
|
|||
*/
|
||||
|
||||
/* Integer types in big-endian order and no alignment requirement */
|
||||
template <typename Type, unsigned int Size>
|
||||
template <typename Type, unsigned int Size = sizeof (Type)>
|
||||
struct IntType
|
||||
{
|
||||
typedef Type type;
|
||||
|
@ -107,12 +107,12 @@ struct IntType
|
|||
DEFINE_SIZE_STATIC (Size);
|
||||
};
|
||||
|
||||
typedef IntType<uint8_t, 1> HBUINT8; /* 8-bit unsigned integer. */
|
||||
typedef IntType<int8_t, 1> HBINT8; /* 8-bit signed integer. */
|
||||
typedef IntType<uint16_t, 2> HBUINT16; /* 16-bit unsigned integer. */
|
||||
typedef IntType<int16_t, 2> HBINT16; /* 16-bit signed integer. */
|
||||
typedef IntType<uint32_t, 4> HBUINT32; /* 32-bit unsigned integer. */
|
||||
typedef IntType<int32_t, 4> HBINT32; /* 32-bit signed integer. */
|
||||
typedef IntType<uint8_t> HBUINT8; /* 8-bit unsigned integer. */
|
||||
typedef IntType<int8_t> HBINT8; /* 8-bit signed integer. */
|
||||
typedef IntType<uint16_t> HBUINT16; /* 16-bit unsigned integer. */
|
||||
typedef IntType<int16_t> HBINT16; /* 16-bit signed integer. */
|
||||
typedef IntType<uint32_t> HBUINT32; /* 32-bit unsigned integer. */
|
||||
typedef IntType<int32_t> HBINT32; /* 32-bit signed integer. */
|
||||
/* Note: we cannot defined a signed HBINT24 because there's no corresponding C type.
|
||||
* Works for unsigned, but not signed, since we rely on compiler for sign-extension. */
|
||||
typedef IntType<uint32_t, 3> HBUINT24; /* 24-bit unsigned integer. */
|
||||
|
|
|
@ -142,7 +142,7 @@
|
|||
OT_UARRAY(Name##Substitute, OT_LIST(ToGlyphs)) \
|
||||
) \
|
||||
OT_COVERAGE1(Name##Coverage, OT_LIST(FromGlyphs)) \
|
||||
/* ASSERT_STATIC_EXPR_ZERO (len(FromGlyphs) == len(ToGlyphs)) */
|
||||
/* static_assert_expr (len(FromGlyphs) == len(ToGlyphs)) */
|
||||
|
||||
#define OT_SUBLOOKUP_LIGATURE_SUBST_FORMAT1(Name, FirstGlyphs, LigatureSetOffsets) \
|
||||
OT_SUBLOOKUP(Name, 1, \
|
||||
|
@ -151,7 +151,7 @@
|
|||
OT_UARRAY(Name##LigatureSetOffsetsArray, OT_LIST(LigatureSetOffsets)) \
|
||||
) \
|
||||
OT_COVERAGE1(Name##Coverage, OT_LIST(FirstGlyphs)) \
|
||||
/* ASSERT_STATIC_EXPR_ZERO (len(FirstGlyphs) == len(LigatureSetOffsets)) */
|
||||
/* static_assert_expr (len(FirstGlyphs) == len(LigatureSetOffsets)) */
|
||||
|
||||
#define OT_LIGATURE_SET(Name, LigatureSetOffsets) \
|
||||
OT_UARRAY(Name, OT_LIST(LigatureSetOffsets))
|
||||
|
|
|
@ -175,7 +175,7 @@ enum indic_matra_category_t {
|
|||
|
||||
#define INDIC_COMBINE_CATEGORIES(S,M) \
|
||||
( \
|
||||
ASSERT_STATIC_EXPR_ZERO (S < 255 && M < 255) + \
|
||||
static_assert_expr (S < 255 && M < 255) + \
|
||||
( S | \
|
||||
( \
|
||||
( \
|
||||
|
|
|
@ -265,8 +265,9 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
|
|||
return &_hb_ot_complex_shaper_myanmar;
|
||||
|
||||
|
||||
/* https://github.com/harfbuzz/harfbuzz/issues/1162 */
|
||||
#define HB_SCRIPT_MYANMAR_ZAWGYI ((hb_script_t) HB_TAG ('Q','a','a','g'))
|
||||
case HB_SCRIPT_MYANMAR_ZAWGYI:
|
||||
/* https://github.com/harfbuzz/harfbuzz/issues/1162 */
|
||||
|
||||
return &_hb_ot_complex_shaper_myanmar_zawgyi;
|
||||
|
||||
|
|
|
@ -524,7 +524,7 @@ struct hb_serialize_context_t
|
|||
template <typename T>
|
||||
void assign_offset (const object_t* parent, const object_t::link_t &link, unsigned offset)
|
||||
{
|
||||
auto &off = * ((BEInt<T, sizeof (T)> *) (parent->head + link.position));
|
||||
auto &off = * ((BEInt<T> *) (parent->head + link.position));
|
||||
assert (0 == off);
|
||||
check_assign (off, offset);
|
||||
}
|
||||
|
|
175
src/hb.hh
175
src/hb.hh
|
@ -62,7 +62,6 @@
|
|||
|
||||
/* Error. Should never happen. */
|
||||
#ifndef HB_NO_PRAGMA_GCC_DIAGNOSTIC_ERROR
|
||||
#pragma GCC diagnostic error "-Wc++11-narrowing"
|
||||
#pragma GCC diagnostic error "-Wcast-align"
|
||||
#pragma GCC diagnostic error "-Wcast-function-type"
|
||||
#pragma GCC diagnostic error "-Wdelete-non-virtual-dtor"
|
||||
|
@ -75,6 +74,7 @@
|
|||
#pragma GCC diagnostic error "-Wmissing-braces"
|
||||
#pragma GCC diagnostic error "-Wmissing-declarations"
|
||||
#pragma GCC diagnostic error "-Wmissing-prototypes"
|
||||
#pragma GCC diagnostic error "-Wnarrowing"
|
||||
#pragma GCC diagnostic error "-Wnested-externs"
|
||||
#pragma GCC diagnostic error "-Wold-style-definition"
|
||||
#pragma GCC diagnostic error "-Wpointer-arith"
|
||||
|
@ -245,12 +245,8 @@ extern "C" void hb_free_impl(void *ptr);
|
|||
#endif
|
||||
|
||||
#if defined(__GNUC__) && (__GNUC__ >= 3)
|
||||
#define HB_PURE_FUNC __attribute__((pure))
|
||||
#define HB_CONST_FUNC __attribute__((const))
|
||||
#define HB_PRINTF_FUNC(format_idx, arg_idx) __attribute__((__format__ (__printf__, format_idx, arg_idx)))
|
||||
#else
|
||||
#define HB_PURE_FUNC
|
||||
#define HB_CONST_FUNC
|
||||
#define HB_PRINTF_FUNC(format_idx, arg_idx)
|
||||
#endif
|
||||
#if defined(__GNUC__) && (__GNUC__ >= 4) || (__clang__)
|
||||
|
@ -441,181 +437,12 @@ static int HB_UNUSED _hb_errno = 0;
|
|||
#define HB_STMT_START do
|
||||
#define HB_STMT_END while (0)
|
||||
|
||||
/* Static-assert as expression. */
|
||||
template <unsigned int cond> class hb_assert_constant_t;
|
||||
template <> class hb_assert_constant_t<1> {};
|
||||
#define ASSERT_STATIC_EXPR_ZERO(_cond) (0 * (unsigned int) sizeof (hb_assert_constant_t<_cond>))
|
||||
|
||||
/* Lets assert int types. Saves trouble down the road. */
|
||||
static_assert ((sizeof (int8_t) == 1), "");
|
||||
static_assert ((sizeof (uint8_t) == 1), "");
|
||||
static_assert ((sizeof (int16_t) == 2), "");
|
||||
static_assert ((sizeof (uint16_t) == 2), "");
|
||||
static_assert ((sizeof (int32_t) == 4), "");
|
||||
static_assert ((sizeof (uint32_t) == 4), "");
|
||||
static_assert ((sizeof (int64_t) == 8), "");
|
||||
static_assert ((sizeof (uint64_t) == 8), "");
|
||||
static_assert ((sizeof (hb_codepoint_t) == 4), "");
|
||||
static_assert ((sizeof (hb_position_t) == 4), "");
|
||||
static_assert ((sizeof (hb_mask_t) == 4), "");
|
||||
static_assert ((sizeof (hb_var_int_t) == 4), "");
|
||||
|
||||
#define HB_DELETE_COPY_ASSIGN(TypeName) \
|
||||
TypeName(const TypeName&) = delete; \
|
||||
void operator=(const TypeName&) = delete
|
||||
#define HB_DELETE_CREATE_COPY_ASSIGN(TypeName) \
|
||||
TypeName() = delete; \
|
||||
TypeName(const TypeName&) = delete; \
|
||||
void operator=(const TypeName&) = delete
|
||||
|
||||
|
||||
/* Flags */
|
||||
|
||||
/* Enable bitwise ops on enums marked as flags_t */
|
||||
/* To my surprise, looks like the function resolver is happy to silently cast
|
||||
* one enum to another... So this doesn't provide the type-checking that I
|
||||
* originally had in mind... :(.
|
||||
*
|
||||
* For MSVC warnings, see: https://github.com/harfbuzz/harfbuzz/pull/163
|
||||
*/
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning(disable:4200)
|
||||
# pragma warning(disable:4800)
|
||||
#endif
|
||||
#define HB_MARK_AS_FLAG_T(T) \
|
||||
extern "C++" { \
|
||||
static inline T operator | (T l, T r) { return T ((unsigned) l | (unsigned) r); } \
|
||||
static inline T operator & (T l, T r) { return T ((unsigned) l & (unsigned) r); } \
|
||||
static inline T operator ^ (T l, T r) { return T ((unsigned) l ^ (unsigned) r); } \
|
||||
static inline T operator ~ (T r) { return T (~(unsigned int) r); } \
|
||||
static inline T& operator |= (T &l, T r) { l = l | r; return l; } \
|
||||
static inline T& operator &= (T& l, T r) { l = l & r; return l; } \
|
||||
static inline T& operator ^= (T& l, T r) { l = l ^ r; return l; } \
|
||||
} \
|
||||
static_assert (true, "")
|
||||
|
||||
/* Useful for set-operations on small enums.
|
||||
* For example, for testing "x ∈ {x1, x2, x3}" use:
|
||||
* (FLAG_UNSAFE(x) & (FLAG(x1) | FLAG(x2) | FLAG(x3)))
|
||||
*/
|
||||
#define FLAG(x) (ASSERT_STATIC_EXPR_ZERO ((unsigned)(x) < 32) + (((uint32_t) 1U) << (unsigned)(x)))
|
||||
#define FLAG_UNSAFE(x) ((unsigned)(x) < 32 ? (((uint32_t) 1U) << (unsigned)(x)) : 0)
|
||||
#define FLAG_RANGE(x,y) (ASSERT_STATIC_EXPR_ZERO ((x) < (y)) + FLAG(y+1) - FLAG(x))
|
||||
#define FLAG64(x) (ASSERT_STATIC_EXPR_ZERO ((unsigned)(x) < 64) + (((uint64_t) 1ULL) << (unsigned)(x)))
|
||||
#define FLAG64_UNSAFE(x) ((unsigned)(x) < 64 ? (((uint64_t) 1ULL) << (unsigned)(x)) : 0)
|
||||
|
||||
|
||||
/* Size signifying variable-sized array */
|
||||
#ifndef HB_VAR_ARRAY
|
||||
#define HB_VAR_ARRAY 1
|
||||
#endif
|
||||
|
||||
static inline float
|
||||
_hb_roundf (float x) { return floorf (x + .5f); }
|
||||
#define roundf(x) _hb_roundf(x)
|
||||
|
||||
/* Endian swap, used in Windows related backends */
|
||||
static inline uint16_t hb_uint16_swap (const uint16_t v)
|
||||
{ return (v >> 8) | (v << 8); }
|
||||
static inline uint32_t hb_uint32_swap (const uint32_t v)
|
||||
{ return (hb_uint16_swap (v) << 16) | hb_uint16_swap (v >> 16); }
|
||||
|
||||
/*
|
||||
* Big-endian integers. Here because fundamental.
|
||||
*/
|
||||
|
||||
template <typename Type, int Bytes> struct BEInt;
|
||||
|
||||
template <typename Type>
|
||||
struct BEInt<Type, 1>
|
||||
{
|
||||
public:
|
||||
BEInt<Type, 1>& operator = (Type V)
|
||||
{
|
||||
v = V;
|
||||
return *this;
|
||||
}
|
||||
operator Type () const { return v; }
|
||||
private: uint8_t v;
|
||||
};
|
||||
template <typename Type>
|
||||
struct BEInt<Type, 2>
|
||||
{
|
||||
public:
|
||||
BEInt<Type, 2>& operator = (Type V)
|
||||
{
|
||||
v[0] = (V >> 8) & 0xFF;
|
||||
v[1] = (V ) & 0xFF;
|
||||
return *this;
|
||||
}
|
||||
operator Type () const
|
||||
{
|
||||
#if ((defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__)) && \
|
||||
defined(__BYTE_ORDER) && \
|
||||
(__BYTE_ORDER == __LITTLE_ENDIAN || __BYTE_ORDER == __BIG_ENDIAN)
|
||||
/* Spoon-feed the compiler a big-endian integer with alignment 1.
|
||||
* https://github.com/harfbuzz/harfbuzz/pull/1398 */
|
||||
struct __attribute__((packed)) packed_uint16_t { uint16_t v; };
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
return __builtin_bswap16 (((packed_uint16_t *) this)->v);
|
||||
#else /* __BYTE_ORDER == __BIG_ENDIAN */
|
||||
return ((packed_uint16_t *) this)->v;
|
||||
#endif
|
||||
#endif
|
||||
return (v[0] << 8)
|
||||
+ (v[1] );
|
||||
}
|
||||
private: uint8_t v[2];
|
||||
};
|
||||
template <typename Type>
|
||||
struct BEInt<Type, 3>
|
||||
{
|
||||
public:
|
||||
BEInt<Type, 3>& operator = (Type V)
|
||||
{
|
||||
v[0] = (V >> 16) & 0xFF;
|
||||
v[1] = (V >> 8) & 0xFF;
|
||||
v[2] = (V ) & 0xFF;
|
||||
return *this;
|
||||
}
|
||||
operator Type () const
|
||||
{
|
||||
return (v[0] << 16)
|
||||
+ (v[1] << 8)
|
||||
+ (v[2] );
|
||||
}
|
||||
private: uint8_t v[3];
|
||||
};
|
||||
template <typename Type>
|
||||
struct BEInt<Type, 4>
|
||||
{
|
||||
public:
|
||||
BEInt<Type, 4>& operator = (Type V)
|
||||
{
|
||||
v[0] = (V >> 24) & 0xFF;
|
||||
v[1] = (V >> 16) & 0xFF;
|
||||
v[2] = (V >> 8) & 0xFF;
|
||||
v[3] = (V ) & 0xFF;
|
||||
return *this;
|
||||
}
|
||||
operator Type () const
|
||||
{
|
||||
return (v[0] << 24)
|
||||
+ (v[1] << 16)
|
||||
+ (v[2] << 8)
|
||||
+ (v[3] );
|
||||
}
|
||||
private: uint8_t v[4];
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* For lack of a better place, put Zawgyi script hack here.
|
||||
* https://github.com/harfbuzz/harfbuzz/issues/1162
|
||||
*/
|
||||
|
||||
#define HB_SCRIPT_MYANMAR_ZAWGYI ((hb_script_t) HB_TAG ('Q','a','a','g'))
|
||||
|
||||
|
||||
/* Headers we include for everyone. Keep topologically sorted by dependency.
|
||||
* They express dependency amongst themselves, but no other file should include
|
||||
|
|
Loading…
Reference in New Issue