Blame src/hb-private.hh

Packit 874993
/*
Packit 874993
 * Copyright © 2007,2008,2009  Red Hat, Inc.
Packit 874993
 * Copyright © 2011,2012  Google, Inc.
Packit 874993
 *
Packit 874993
 *  This is part of HarfBuzz, a text shaping library.
Packit 874993
 *
Packit 874993
 * Permission is hereby granted, without written agreement and without
Packit 874993
 * license or royalty fees, to use, copy, modify, and distribute this
Packit 874993
 * software and its documentation for any purpose, provided that the
Packit 874993
 * above copyright notice and the following two paragraphs appear in
Packit 874993
 * all copies of this software.
Packit 874993
 *
Packit 874993
 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
Packit 874993
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
Packit 874993
 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
Packit 874993
 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
Packit 874993
 * DAMAGE.
Packit 874993
 *
Packit 874993
 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
Packit 874993
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
Packit 874993
 * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
Packit 874993
 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
Packit 874993
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
Packit 874993
 *
Packit 874993
 * Red Hat Author(s): Behdad Esfahbod
Packit 874993
 * Google Author(s): Behdad Esfahbod
Packit 874993
 */
Packit 874993
Packit 874993
#ifndef HB_PRIVATE_HH
Packit 874993
#define HB_PRIVATE_HH
Packit 874993
Packit 874993
#ifdef HAVE_CONFIG_H
Packit 874993
#include "config.h"
Packit 874993
#endif
Packit 874993
Packit 874993
#include "hb.h"
Packit 874993
#define HB_H_IN
Packit 874993
#ifdef HAVE_OT
Packit 874993
#include "hb-ot.h"
Packit 874993
#define HB_OT_H_IN
Packit 874993
#endif
Packit 874993
Packit 874993
#include <stdlib.h>
Packit 874993
#include <stddef.h>
Packit 874993
#include <string.h>
Packit 874993
#include <assert.h>
Packit 874993
Packit 874993
/* We only use these two for debug output.  However, the debug code is
Packit 874993
 * always seen by the compiler (and optimized out in non-debug builds.
Packit 874993
 * If including these becomes a problem, we can start thinking about
Packit 874993
 * someway around that. */
Packit 874993
#include <stdio.h>
Packit 874993
#include <errno.h>
Packit 874993
#include <stdarg.h>
Packit 874993
Packit 874993
Packit 874993
/* Compile-time custom allocator support. */
Packit 874993
Packit 874993
#if defined(hb_malloc_impl) \
Packit 874993
 && defined(hb_calloc_impl) \
Packit 874993
 && defined(hb_realloc_impl) \
Packit 874993
 && defined(hb_free_impl)
Packit 874993
extern "C" void* hb_malloc_impl(size_t size);
Packit 874993
extern "C" void* hb_calloc_impl(size_t nmemb, size_t size);
Packit 874993
extern "C" void* hb_realloc_impl(void *ptr, size_t size);
Packit 874993
extern "C" void  hb_free_impl(void *ptr);
Packit 874993
#define malloc hb_malloc_impl
Packit 874993
#define calloc hb_calloc_impl
Packit 874993
#define realloc hb_realloc_impl
Packit 874993
#define free hb_free_impl
Packit 874993
#endif
Packit 874993
Packit 874993
Packit 874993
/* Compiler attributes */
Packit 874993
Packit 874993
Packit 874993
#if (defined(__GNUC__) || defined(__clang__)) && defined(__OPTIMIZE__)
Packit 874993
#define likely(expr) (__builtin_expect (!!(expr), 1))
Packit 874993
#define unlikely(expr) (__builtin_expect (!!(expr), 0))
Packit 874993
#else
Packit 874993
#define likely(expr) (expr)
Packit 874993
#define unlikely(expr) (expr)
Packit 874993
#endif
Packit 874993
Packit 874993
#if !defined(__GNUC__) && !defined(__clang__)
Packit 874993
#undef __attribute__
Packit 874993
#define __attribute__(x)
Packit 874993
#endif
Packit 874993
Packit 874993
#if __GNUC__ >= 3
Packit 874993
#define HB_PURE_FUNC	__attribute__((pure))
Packit 874993
#define HB_CONST_FUNC	__attribute__((const))
Packit 874993
#define HB_PRINTF_FUNC(format_idx, arg_idx) __attribute__((__format__ (__printf__, format_idx, arg_idx)))
Packit 874993
#else
Packit 874993
#define HB_PURE_FUNC
Packit 874993
#define HB_CONST_FUNC
Packit 874993
#define HB_PRINTF_FUNC(format_idx, arg_idx)
Packit 874993
#endif
Packit 874993
#if __GNUC__ >= 4
Packit 874993
#define HB_UNUSED	__attribute__((unused))
Packit 874993
#else
Packit 874993
#define HB_UNUSED
Packit 874993
#endif
Packit 874993
Packit 874993
#ifndef HB_INTERNAL
Packit 874993
# if !defined(__MINGW32__) && !defined(__CYGWIN__)
Packit 874993
#  define HB_INTERNAL __attribute__((__visibility__("hidden")))
Packit 874993
# else
Packit 874993
#  define HB_INTERNAL
Packit 874993
# endif
Packit 874993
#endif
Packit 874993
Packit 874993
#if __GNUC__ >= 3
Packit 874993
#define HB_FUNC __PRETTY_FUNCTION__
Packit 874993
#elif defined(_MSC_VER)
Packit 874993
#define HB_FUNC __FUNCSIG__
Packit 874993
#else
Packit 874993
#define HB_FUNC __func__
Packit 874993
#endif
Packit 874993
Packit 874993
/*
Packit 874993
 * Borrowed from https://bugzilla.mozilla.org/show_bug.cgi?id=1215411
Packit 874993
 * HB_FALLTHROUGH is an annotation to suppress compiler warnings about switch
Packit 874993
 * cases that fall through without a break or return statement. HB_FALLTHROUGH
Packit 874993
 * is only needed on cases that have code:
Packit 874993
 *
Packit 874993
 * switch (foo) {
Packit 874993
 *   case 1: // These cases have no code. No fallthrough annotations are needed.
Packit 874993
 *   case 2:
Packit 874993
 *   case 3:
Packit 874993
 *     foo = 4; // This case has code, so a fallthrough annotation is needed:
Packit 874993
 *     HB_FALLTHROUGH;
Packit 874993
 *   default:
Packit 874993
 *     return foo;
Packit 874993
 * }
Packit 874993
 */
Packit 874993
#if defined(__clang__) && __cplusplus >= 201103L
Packit 874993
   /* clang's fallthrough annotations are only available starting in C++11. */
Packit 874993
#  define HB_FALLTHROUGH [[clang::fallthrough]]
Packit 874993
#elif defined(_MSC_VER)
Packit 874993
   /*
Packit 874993
    * MSVC's __fallthrough annotations are checked by /analyze (Code Analysis):
Packit 874993
    * https://msdn.microsoft.com/en-us/library/ms235402%28VS.80%29.aspx
Packit 874993
    */
Packit 874993
#  include <sal.h>
Packit 874993
#  define HB_FALLTHROUGH __fallthrough
Packit 874993
#else
Packit 874993
#  define HB_FALLTHROUGH /* FALLTHROUGH */
Packit 874993
#endif
Packit 874993
Packit 874993
#if defined(_WIN32) || defined(__CYGWIN__)
Packit 874993
   /* We need Windows Vista for both Uniscribe backend and for
Packit 874993
    * MemoryBarrier.  We don't support compiling on Windows XP,
Packit 874993
    * though we run on it fine. */
Packit 874993
#  if defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0600
Packit 874993
#    undef _WIN32_WINNT
Packit 874993
#  endif
Packit 874993
#  ifndef _WIN32_WINNT
Packit 874993
#    define _WIN32_WINNT 0x0600
Packit 874993
#  endif
Packit 874993
#  ifndef WIN32_LEAN_AND_MEAN
Packit 874993
#    define WIN32_LEAN_AND_MEAN 1
Packit 874993
#  endif
Packit 874993
#  ifndef STRICT
Packit 874993
#    define STRICT 1
Packit 874993
#  endif
Packit 874993
Packit 874993
#  if defined(_WIN32_WCE)
Packit 874993
     /* Some things not defined on Windows CE. */
Packit 874993
#    define vsnprintf _vsnprintf
Packit 874993
#    define getenv(Name) NULL
Packit 874993
#    if _WIN32_WCE < 0x800
Packit 874993
#      define setlocale(Category, Locale) "C"
Packit 874993
static int errno = 0; /* Use something better? */
Packit 874993
#    endif
Packit 874993
#  elif defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP)
Packit 874993
#    define getenv(Name) NULL
Packit 874993
#  endif
Packit 874993
#  if defined(_MSC_VER) && _MSC_VER < 1900
Packit 874993
#    define snprintf _snprintf
Packit 874993
#  endif
Packit 874993
#endif
Packit 874993
Packit 874993
#if HAVE_ATEXIT
Packit 874993
/* atexit() is only safe to be called from shared libraries on certain
Packit 874993
 * platforms.  Whitelist.
Packit 874993
 * https://bugs.freedesktop.org/show_bug.cgi?id=82246 */
Packit 874993
#  if defined(__linux) && defined(__GLIBC_PREREQ)
Packit 874993
#    if __GLIBC_PREREQ(2,3)
Packit 874993
/* From atexit() manpage, it's safe with glibc 2.2.3 on Linux. */
Packit 874993
#      define HB_USE_ATEXIT 1
Packit 874993
#    endif
Packit 874993
#  elif defined(_MSC_VER) || defined(__MINGW32__)
Packit 874993
/* For MSVC:
Packit 874993
 * http://msdn.microsoft.com/en-ca/library/tze57ck3.aspx
Packit 874993
 * http://msdn.microsoft.com/en-ca/library/zk17ww08.aspx
Packit 874993
 * mingw32 headers say atexit is safe to use in shared libraries.
Packit 874993
 */
Packit 874993
#    define HB_USE_ATEXIT 1
Packit 874993
#  elif defined(__ANDROID__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
Packit 874993
/* This was fixed in Android NKD r8 or r8b:
Packit 874993
 * https://code.google.com/p/android/issues/detail?id=6455
Packit 874993
 * which introduced GCC 4.6:
Packit 874993
 * https://developer.android.com/tools/sdk/ndk/index.html
Packit 874993
 */
Packit 874993
#    define HB_USE_ATEXIT 1
Packit 874993
#  endif
Packit 874993
#endif
Packit 874993
Packit 874993
/* Basics */
Packit 874993
Packit 874993
Packit 874993
#ifndef NULL
Packit 874993
# define NULL ((void *) 0)
Packit 874993
#endif
Packit 874993
Packit 874993
#undef MIN
Packit 874993
template <typename Type>
Packit 874993
static inline Type MIN (const Type &a, const Type &b) { return a < b ? a : b; }
Packit 874993
Packit 874993
#undef MAX
Packit 874993
template <typename Type>
Packit 874993
static inline Type MAX (const Type &a, const Type &b) { return a > b ? a : b; }
Packit 874993
Packit 874993
static inline unsigned int DIV_CEIL (const unsigned int a, unsigned int b)
Packit 874993
{ return (a + (b - 1)) / b; }
Packit 874993
Packit 874993
Packit 874993
#undef  ARRAY_LENGTH
Packit 874993
template <typename Type, unsigned int n>
Packit 874993
static inline unsigned int ARRAY_LENGTH (const Type (&)[n]) { return n; }
Packit 874993
/* A const version, but does not detect erratically being called on pointers. */
Packit 874993
#define ARRAY_LENGTH_CONST(__array) ((signed int) (sizeof (__array) / sizeof (__array[0])))
Packit 874993
Packit 874993
#define HB_STMT_START do
Packit 874993
#define HB_STMT_END   while (0)
Packit 874993
Packit 874993
#define _ASSERT_STATIC1(_line, _cond)	HB_UNUSED typedef int _static_assert_on_line_##_line##_failed[(_cond)?1:-1]
Packit 874993
#define _ASSERT_STATIC0(_line, _cond)	_ASSERT_STATIC1 (_line, (_cond))
Packit 874993
#define ASSERT_STATIC(_cond)		_ASSERT_STATIC0 (__LINE__, (_cond))
Packit 874993
Packit 874993
template <unsigned int cond> class hb_assert_constant_t {};
Packit 874993
Packit 874993
#define ASSERT_STATIC_EXPR_ZERO(_cond) (0 * (unsigned int) sizeof (hb_assert_constant_t<_cond>))
Packit 874993
Packit 874993
#define _PASTE1(a,b) a##b
Packit 874993
#define PASTE(a,b) _PASTE1(a,b)
Packit 874993
Packit 874993
/* Lets assert int types.  Saves trouble down the road. */
Packit 874993
Packit 874993
ASSERT_STATIC (sizeof (int8_t) == 1);
Packit 874993
ASSERT_STATIC (sizeof (uint8_t) == 1);
Packit 874993
ASSERT_STATIC (sizeof (int16_t) == 2);
Packit 874993
ASSERT_STATIC (sizeof (uint16_t) == 2);
Packit 874993
ASSERT_STATIC (sizeof (int32_t) == 4);
Packit 874993
ASSERT_STATIC (sizeof (uint32_t) == 4);
Packit 874993
ASSERT_STATIC (sizeof (int64_t) == 8);
Packit 874993
ASSERT_STATIC (sizeof (uint64_t) == 8);
Packit 874993
Packit 874993
ASSERT_STATIC (sizeof (hb_codepoint_t) == 4);
Packit 874993
ASSERT_STATIC (sizeof (hb_position_t) == 4);
Packit 874993
ASSERT_STATIC (sizeof (hb_mask_t) == 4);
Packit 874993
ASSERT_STATIC (sizeof (hb_var_int_t) == 4);
Packit 874993
Packit 874993
Packit 874993
/* We like our types POD */
Packit 874993
Packit 874993
#define _ASSERT_TYPE_POD1(_line, _type)	union _type_##_type##_on_line_##_line##_is_not_POD { _type instance; }
Packit 874993
#define _ASSERT_TYPE_POD0(_line, _type)	_ASSERT_TYPE_POD1 (_line, _type)
Packit 874993
#define ASSERT_TYPE_POD(_type)		_ASSERT_TYPE_POD0 (__LINE__, _type)
Packit 874993
Packit 874993
#ifdef __GNUC__
Packit 874993
# define _ASSERT_INSTANCE_POD1(_line, _instance) \
Packit 874993
	HB_STMT_START { \
Packit 874993
		typedef __typeof__(_instance) _type_##_line; \
Packit 874993
		_ASSERT_TYPE_POD1 (_line, _type_##_line); \
Packit 874993
	} HB_STMT_END
Packit 874993
#else
Packit 874993
# define _ASSERT_INSTANCE_POD1(_line, _instance)	typedef int _assertion_on_line_##_line##_not_tested
Packit 874993
#endif
Packit 874993
# define _ASSERT_INSTANCE_POD0(_line, _instance)	_ASSERT_INSTANCE_POD1 (_line, _instance)
Packit 874993
# define ASSERT_INSTANCE_POD(_instance)			_ASSERT_INSTANCE_POD0 (__LINE__, _instance)
Packit 874993
Packit 874993
/* Check _assertion in a method environment */
Packit 874993
#define _ASSERT_POD1(_line) \
Packit 874993
	HB_UNUSED inline void _static_assertion_on_line_##_line (void) const \
Packit 874993
	{ _ASSERT_INSTANCE_POD1 (_line, *this); /* Make sure it's POD. */ }
Packit 874993
# define _ASSERT_POD0(_line)	_ASSERT_POD1 (_line)
Packit 874993
# define ASSERT_POD()		_ASSERT_POD0 (__LINE__)
Packit 874993
Packit 874993
Packit 874993
Packit 874993
/* Misc */
Packit 874993
Packit 874993
/* Void! */
Packit 874993
struct _hb_void_t {};
Packit 874993
typedef const _hb_void_t *hb_void_t;
Packit 874993
#define HB_VOID ((const _hb_void_t *) NULL)
Packit 874993
Packit 874993
/* Return the number of 1 bits in mask. */
Packit 874993
static inline HB_CONST_FUNC unsigned int
Packit 874993
_hb_popcount32 (uint32_t mask)
Packit 874993
{
Packit 874993
#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
Packit 874993
  return __builtin_popcount (mask);
Packit 874993
#else
Packit 874993
  /* "HACKMEM 169" */
Packit 874993
  uint32_t y;
Packit 874993
  y = (mask >> 1) &033333333333;
Packit 874993
  y = mask - y - ((y >>1) & 033333333333);
Packit 874993
  return (((y + (y >> 3)) & 030707070707) % 077);
Packit 874993
#endif
Packit 874993
}
Packit 874993
Packit 874993
/* Returns the number of bits needed to store number */
Packit 874993
static inline HB_CONST_FUNC unsigned int
Packit 874993
_hb_bit_storage (unsigned int number)
Packit 874993
{
Packit 874993
#if defined(__GNUC__) && (__GNUC__ >= 4) && defined(__OPTIMIZE__)
Packit 874993
  return likely (number) ? (sizeof (unsigned int) * 8 - __builtin_clz (number)) : 0;
Packit 874993
#else
Packit 874993
  unsigned int n_bits = 0;
Packit 874993
  while (number) {
Packit 874993
    n_bits++;
Packit 874993
    number >>= 1;
Packit 874993
  }
Packit 874993
  return n_bits;
Packit 874993
#endif
Packit 874993
}
Packit 874993
Packit 874993
/* Returns the number of zero bits in the least significant side of number */
Packit 874993
static inline HB_CONST_FUNC unsigned int
Packit 874993
_hb_ctz (unsigned int number)
Packit 874993
{
Packit 874993
#if defined(__GNUC__) && (__GNUC__ >= 4) && defined(__OPTIMIZE__)
Packit 874993
  return likely (number) ? __builtin_ctz (number) : 0;
Packit 874993
#else
Packit 874993
  unsigned int n_bits = 0;
Packit 874993
  if (unlikely (!number)) return 0;
Packit 874993
  while (!(number & 1)) {
Packit 874993
    n_bits++;
Packit 874993
    number >>= 1;
Packit 874993
  }
Packit 874993
  return n_bits;
Packit 874993
#endif
Packit 874993
}
Packit 874993
Packit 874993
static inline bool
Packit 874993
_hb_unsigned_int_mul_overflows (unsigned int count, unsigned int size)
Packit 874993
{
Packit 874993
  return (size > 0) && (count >= ((unsigned int) -1) / size);
Packit 874993
}
Packit 874993
Packit 874993
Packit 874993
/* Type of bsearch() / qsort() compare function */
Packit 874993
typedef int (*hb_compare_func_t) (const void *, const void *);
Packit 874993
Packit 874993
Packit 874993
Packit 874993
Packit 874993
/* arrays and maps */
Packit 874993
Packit 874993
Packit 874993
#define HB_PREALLOCED_ARRAY_INIT {0, 0, NULL}
Packit 874993
template <typename Type, unsigned int StaticSize=16>
Packit 874993
struct hb_prealloced_array_t
Packit 874993
{
Packit 874993
  unsigned int len;
Packit 874993
  unsigned int allocated;
Packit 874993
  Type *array;
Packit 874993
  Type static_array[StaticSize];
Packit 874993
Packit 874993
  void init (void) { memset (this, 0, sizeof (*this)); }
Packit 874993
Packit 874993
  inline Type& operator [] (unsigned int i) { return array[i]; }
Packit 874993
  inline const Type& operator [] (unsigned int i) const { return array[i]; }
Packit 874993
Packit 874993
  inline Type *push (void)
Packit 874993
  {
Packit 874993
    if (!array) {
Packit 874993
      array = static_array;
Packit 874993
      allocated = ARRAY_LENGTH (static_array);
Packit 874993
    }
Packit 874993
    if (likely (len < allocated))
Packit 874993
      return &array[len++];
Packit 874993
Packit 874993
    /* Need to reallocate */
Packit 874993
    unsigned int new_allocated = allocated + (allocated >> 1) + 8;
Packit 874993
    Type *new_array = NULL;
Packit 874993
Packit 874993
    if (array == static_array) {
Packit 874993
      new_array = (Type *) calloc (new_allocated, sizeof (Type));
Packit 874993
      if (new_array)
Packit 874993
        memcpy (new_array, array, len * sizeof (Type));
Packit 874993
    } else {
Packit 874993
      bool overflows = (new_allocated < allocated) || _hb_unsigned_int_mul_overflows (new_allocated, sizeof (Type));
Packit 874993
      if (likely (!overflows)) {
Packit 874993
	new_array = (Type *) realloc (array, new_allocated * sizeof (Type));
Packit 874993
      }
Packit 874993
    }
Packit 874993
Packit 874993
    if (unlikely (!new_array))
Packit 874993
      return NULL;
Packit 874993
Packit 874993
    array = new_array;
Packit 874993
    allocated = new_allocated;
Packit 874993
    return &array[len++];
Packit 874993
  }
Packit 874993
Packit 874993
  inline void pop (void)
Packit 874993
  {
Packit 874993
    len--;
Packit 874993
  }
Packit 874993
Packit 874993
  inline void remove (unsigned int i)
Packit 874993
  {
Packit 874993
     if (unlikely (i >= len))
Packit 874993
       return;
Packit 874993
     memmove (static_cast<void *> (&array[i]),
Packit 874993
	      static_cast<void *> (&array[i + 1]),
Packit 874993
	      (len - i - 1) * sizeof (Type));
Packit 874993
     len--;
Packit 874993
  }
Packit 874993
Packit 874993
  inline void shrink (unsigned int l)
Packit 874993
  {
Packit 874993
     if (l < len)
Packit 874993
       len = l;
Packit 874993
  }
Packit 874993
Packit 874993
  template <typename T>
Packit 874993
  inline Type *find (T v) {
Packit 874993
    for (unsigned int i = 0; i < len; i++)
Packit 874993
      if (array[i] == v)
Packit 874993
	return &array[i];
Packit 874993
    return NULL;
Packit 874993
  }
Packit 874993
  template <typename T>
Packit 874993
  inline const Type *find (T v) const {
Packit 874993
    for (unsigned int i = 0; i < len; i++)
Packit 874993
      if (array[i] == v)
Packit 874993
	return &array[i];
Packit 874993
    return NULL;
Packit 874993
  }
Packit 874993
Packit 874993
  inline void qsort (void)
Packit 874993
  {
Packit 874993
    ::qsort (array, len, sizeof (Type), (hb_compare_func_t) Type::cmp);
Packit 874993
  }
Packit 874993
Packit 874993
  inline void qsort (unsigned int start, unsigned int end)
Packit 874993
  {
Packit 874993
    ::qsort (array + start, end - start, sizeof (Type), (hb_compare_func_t) Type::cmp);
Packit 874993
  }
Packit 874993
Packit 874993
  template <typename T>
Packit 874993
  inline Type *bsearch (T *key)
Packit 874993
  {
Packit 874993
    return (Type *) ::bsearch (key, array, len, sizeof (Type), (hb_compare_func_t) Type::cmp);
Packit 874993
  }
Packit 874993
  template <typename T>
Packit 874993
  inline const Type *bsearch (T *key) const
Packit 874993
  {
Packit 874993
    return (const Type *) ::bsearch (key, array, len, sizeof (Type), (hb_compare_func_t) Type::cmp);
Packit 874993
  }
Packit 874993
Packit 874993
  inline void finish (void)
Packit 874993
  {
Packit 874993
    if (array != static_array)
Packit 874993
      free (array);
Packit 874993
    array = NULL;
Packit 874993
    allocated = len = 0;
Packit 874993
  }
Packit 874993
};
Packit 874993
Packit 874993
template <typename Type>
Packit 874993
struct hb_auto_array_t : hb_prealloced_array_t <Type>
Packit 874993
{
Packit 874993
  hb_auto_array_t (void) { hb_prealloced_array_t<Type>::init (); }
Packit 874993
  ~hb_auto_array_t (void) { hb_prealloced_array_t<Type>::finish (); }
Packit 874993
};
Packit 874993
Packit 874993
Packit 874993
#define HB_LOCKABLE_SET_INIT {HB_PREALLOCED_ARRAY_INIT}
Packit 874993
template <typename item_t, typename lock_t>
Packit 874993
struct hb_lockable_set_t
Packit 874993
{
Packit 874993
  hb_prealloced_array_t <item_t, 2> items;
Packit 874993
Packit 874993
  inline void init (void) { items.init (); }
Packit 874993
Packit 874993
  template <typename T>
Packit 874993
  inline item_t *replace_or_insert (T v, lock_t &l, bool replace)
Packit 874993
  {
Packit 874993
    l.lock ();
Packit 874993
    item_t *item = items.find (v);
Packit 874993
    if (item) {
Packit 874993
      if (replace) {
Packit 874993
	item_t old = *item;
Packit 874993
	*item = v;
Packit 874993
	l.unlock ();
Packit 874993
	old.finish ();
Packit 874993
      }
Packit 874993
      else {
Packit 874993
        item = NULL;
Packit 874993
	l.unlock ();
Packit 874993
      }
Packit 874993
    } else {
Packit 874993
      item = items.push ();
Packit 874993
      if (likely (item))
Packit 874993
	*item = v;
Packit 874993
      l.unlock ();
Packit 874993
    }
Packit 874993
    return item;
Packit 874993
  }
Packit 874993
Packit 874993
  template <typename T>
Packit 874993
  inline void remove (T v, lock_t &l)
Packit 874993
  {
Packit 874993
    l.lock ();
Packit 874993
    item_t *item = items.find (v);
Packit 874993
    if (item) {
Packit 874993
      item_t old = *item;
Packit 874993
      *item = items[items.len - 1];
Packit 874993
      items.pop ();
Packit 874993
      l.unlock ();
Packit 874993
      old.finish ();
Packit 874993
    } else {
Packit 874993
      l.unlock ();
Packit 874993
    }
Packit 874993
  }
Packit 874993
Packit 874993
  template <typename T>
Packit 874993
  inline bool find (T v, item_t *i, lock_t &l)
Packit 874993
  {
Packit 874993
    l.lock ();
Packit 874993
    item_t *item = items.find (v);
Packit 874993
    if (item)
Packit 874993
      *i = *item;
Packit 874993
    l.unlock ();
Packit 874993
    return !!item;
Packit 874993
  }
Packit 874993
Packit 874993
  template <typename T>
Packit 874993
  inline item_t *find_or_insert (T v, lock_t &l)
Packit 874993
  {
Packit 874993
    l.lock ();
Packit 874993
    item_t *item = items.find (v);
Packit 874993
    if (!item) {
Packit 874993
      item = items.push ();
Packit 874993
      if (likely (item))
Packit 874993
        *item = v;
Packit 874993
    }
Packit 874993
    l.unlock ();
Packit 874993
    return item;
Packit 874993
  }
Packit 874993
Packit 874993
  inline void finish (lock_t &l)
Packit 874993
  {
Packit 874993
    if (!items.len) {
Packit 874993
      /* No need for locking. */
Packit 874993
      items.finish ();
Packit 874993
      return;
Packit 874993
    }
Packit 874993
    l.lock ();
Packit 874993
    while (items.len) {
Packit 874993
      item_t old = items[items.len - 1];
Packit 874993
	items.pop ();
Packit 874993
	l.unlock ();
Packit 874993
	old.finish ();
Packit 874993
	l.lock ();
Packit 874993
    }
Packit 874993
    items.finish ();
Packit 874993
    l.unlock ();
Packit 874993
  }
Packit 874993
Packit 874993
};
Packit 874993
Packit 874993
Packit 874993
/* ASCII tag/character handling */
Packit 874993
Packit 874993
static inline bool ISALPHA (unsigned char c)
Packit 874993
{ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); }
Packit 874993
static inline bool ISALNUM (unsigned char c)
Packit 874993
{ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'); }
Packit 874993
static inline bool ISSPACE (unsigned char c)
Packit 874993
{ return c == ' ' || c =='\f'|| c =='\n'|| c =='\r'|| c =='\t'|| c =='\v'; }
Packit 874993
static inline unsigned char TOUPPER (unsigned char c)
Packit 874993
{ return (c >= 'a' && c <= 'z') ? c - 'a' + 'A' : c; }
Packit 874993
static inline unsigned char TOLOWER (unsigned char c)
Packit 874993
{ return (c >= 'A' && c <= 'Z') ? c - 'A' + 'a' : c; }
Packit 874993
Packit 874993
#define HB_TAG_CHAR4(s)   (HB_TAG(((const char *) s)[0], \
Packit 874993
				  ((const char *) s)[1], \
Packit 874993
				  ((const char *) s)[2], \
Packit 874993
				  ((const char *) s)[3]))
Packit 874993
Packit 874993
Packit 874993
/* C++ helpers */
Packit 874993
Packit 874993
/* Makes class uncopyable.  Use in private: section. */
Packit 874993
#define NO_COPY(T) \
Packit 874993
  T (const T &o); \
Packit 874993
  T &operator = (const T &o)
Packit 874993
Packit 874993
Packit 874993
/* Debug */
Packit 874993
Packit 874993
Packit 874993
/* HB_NDEBUG disables some sanity checks that are very safe to disable and
Packit 874993
 * should be disabled in production systems.  If NDEBUG is defined, enable
Packit 874993
 * HB_NDEBUG; but if it's desirable that normal assert()s (which are very
Packit 874993
 * light-weight) to be enabled, then HB_DEBUG can be defined to disable
Packit 874993
 * the costlier checks. */
Packit 874993
#ifdef NDEBUG
Packit 874993
#define HB_NDEBUG
Packit 874993
#endif
Packit 874993
Packit 874993
#ifndef HB_DEBUG
Packit 874993
#define HB_DEBUG 0
Packit 874993
#endif
Packit 874993
Packit 874993
static inline bool
Packit 874993
_hb_debug (unsigned int level,
Packit 874993
	   unsigned int max_level)
Packit 874993
{
Packit 874993
  return level < max_level;
Packit 874993
}
Packit 874993
Packit 874993
#define DEBUG_LEVEL_ENABLED(WHAT, LEVEL) (_hb_debug ((LEVEL), HB_DEBUG_##WHAT))
Packit 874993
#define DEBUG_ENABLED(WHAT) (DEBUG_LEVEL_ENABLED (WHAT, 0))
Packit 874993
Packit 874993
static inline void
Packit 874993
_hb_print_func (const char *func)
Packit 874993
{
Packit 874993
  if (func)
Packit 874993
  {
Packit 874993
    unsigned int func_len = strlen (func);
Packit 874993
    /* Skip "static" */
Packit 874993
    if (0 == strncmp (func, "static ", 7))
Packit 874993
      func += 7;
Packit 874993
    /* Skip "typename" */
Packit 874993
    if (0 == strncmp (func, "typename ", 9))
Packit 874993
      func += 9;
Packit 874993
    /* Skip return type */
Packit 874993
    const char *space = strchr (func, ' ');
Packit 874993
    if (space)
Packit 874993
      func = space + 1;
Packit 874993
    /* Skip parameter list */
Packit 874993
    const char *paren = strchr (func, '(');
Packit 874993
    if (paren)
Packit 874993
      func_len = paren - func;
Packit 874993
    fprintf (stderr, "%.*s", func_len, func);
Packit 874993
  }
Packit 874993
}
Packit 874993
Packit 874993
template <int max_level> static inline void
Packit 874993
_hb_debug_msg_va (const char *what,
Packit 874993
		  const void *obj,
Packit 874993
		  const char *func,
Packit 874993
		  bool indented,
Packit 874993
		  unsigned int level,
Packit 874993
		  int level_dir,
Packit 874993
		  const char *message,
Packit 874993
		  va_list ap) HB_PRINTF_FUNC(7, 0);
Packit 874993
template <int max_level> static inline void
Packit 874993
_hb_debug_msg_va (const char *what,
Packit 874993
		  const void *obj,
Packit 874993
		  const char *func,
Packit 874993
		  bool indented,
Packit 874993
		  unsigned int level,
Packit 874993
		  int level_dir,
Packit 874993
		  const char *message,
Packit 874993
		  va_list ap)
Packit 874993
{
Packit 874993
  if (!_hb_debug (level, max_level))
Packit 874993
    return;
Packit 874993
Packit 874993
  fprintf (stderr, "%-10s", what ? what : "");
Packit 874993
Packit 874993
  if (obj)
Packit 874993
    fprintf (stderr, "(%0*lx) ", (unsigned int) (2 * sizeof (void *)), (unsigned long) obj);
Packit 874993
  else
Packit 874993
    fprintf (stderr, " %*s  ", (unsigned int) (2 * sizeof (void *)), "");
Packit 874993
Packit 874993
  if (indented) {
Packit 874993
#define VBAR	"\342\224\202"	/* U+2502 BOX DRAWINGS LIGHT VERTICAL */
Packit 874993
#define VRBAR	"\342\224\234"	/* U+251C BOX DRAWINGS LIGHT VERTICAL AND RIGHT */
Packit 874993
#define DLBAR	"\342\225\256"	/* U+256E BOX DRAWINGS LIGHT ARC DOWN AND LEFT */
Packit 874993
#define ULBAR	"\342\225\257"	/* U+256F BOX DRAWINGS LIGHT ARC UP AND LEFT */
Packit 874993
#define LBAR	"\342\225\264"	/* U+2574 BOX DRAWINGS LIGHT LEFT */
Packit 874993
    static const char bars[] =
Packit 874993
      VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR
Packit 874993
      VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR
Packit 874993
      VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR
Packit 874993
      VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR
Packit 874993
      VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR;
Packit 874993
    fprintf (stderr, "%2u %s" VRBAR "%s",
Packit 874993
	     level,
Packit 874993
	     bars + sizeof (bars) - 1 - MIN ((unsigned int) sizeof (bars) - 1, (unsigned int) (sizeof (VBAR) - 1) * level),
Packit 874993
	     level_dir ? (level_dir > 0 ? DLBAR : ULBAR) : LBAR);
Packit 874993
  } else
Packit 874993
    fprintf (stderr, "   " VRBAR LBAR);
Packit 874993
Packit 874993
  _hb_print_func (func);
Packit 874993
Packit 874993
  if (message)
Packit 874993
  {
Packit 874993
    fprintf (stderr, ": ");
Packit 874993
    vfprintf (stderr, message, ap);
Packit 874993
  }
Packit 874993
Packit 874993
  fprintf (stderr, "\n");
Packit 874993
}
Packit 874993
template <> inline void
Packit 874993
_hb_debug_msg_va<0> (const char *what HB_UNUSED,
Packit 874993
		     const void *obj HB_UNUSED,
Packit 874993
		     const char *func HB_UNUSED,
Packit 874993
		     bool indented HB_UNUSED,
Packit 874993
		     unsigned int level HB_UNUSED,
Packit 874993
		     int level_dir HB_UNUSED,
Packit 874993
		     const char *message HB_UNUSED,
Packit 874993
		     va_list ap HB_UNUSED) {}
Packit 874993
Packit 874993
template <int max_level> static inline void
Packit 874993
_hb_debug_msg (const char *what,
Packit 874993
	       const void *obj,
Packit 874993
	       const char *func,
Packit 874993
	       bool indented,
Packit 874993
	       unsigned int level,
Packit 874993
	       int level_dir,
Packit 874993
	       const char *message,
Packit 874993
	       ...) HB_PRINTF_FUNC(7, 8);
Packit 874993
template <int max_level> static inline void
Packit 874993
_hb_debug_msg (const char *what,
Packit 874993
	       const void *obj,
Packit 874993
	       const char *func,
Packit 874993
	       bool indented,
Packit 874993
	       unsigned int level,
Packit 874993
	       int level_dir,
Packit 874993
	       const char *message,
Packit 874993
	       ...)
Packit 874993
{
Packit 874993
  va_list ap;
Packit 874993
  va_start (ap, message);
Packit 874993
  _hb_debug_msg_va<max_level> (what, obj, func, indented, level, level_dir, message, ap);
Packit 874993
  va_end (ap);
Packit 874993
}
Packit 874993
template <> inline void
Packit 874993
_hb_debug_msg<0> (const char *what HB_UNUSED,
Packit 874993
		  const void *obj HB_UNUSED,
Packit 874993
		  const char *func HB_UNUSED,
Packit 874993
		  bool indented HB_UNUSED,
Packit 874993
		  unsigned int level HB_UNUSED,
Packit 874993
		  int level_dir HB_UNUSED,
Packit 874993
		  const char *message HB_UNUSED,
Packit 874993
		  ...) HB_PRINTF_FUNC(7, 8);
Packit 874993
template <> inline void
Packit 874993
_hb_debug_msg<0> (const char *what HB_UNUSED,
Packit 874993
		  const void *obj HB_UNUSED,
Packit 874993
		  const char *func HB_UNUSED,
Packit 874993
		  bool indented HB_UNUSED,
Packit 874993
		  unsigned int level HB_UNUSED,
Packit 874993
		  int level_dir HB_UNUSED,
Packit 874993
		  const char *message HB_UNUSED,
Packit 874993
		  ...) {}
Packit 874993
Packit 874993
#define DEBUG_MSG_LEVEL(WHAT, OBJ, LEVEL, LEVEL_DIR, ...)	_hb_debug_msg<HB_DEBUG_##WHAT> (#WHAT, (OBJ), NULL,    true, (LEVEL), (LEVEL_DIR), __VA_ARGS__)
Packit 874993
#define DEBUG_MSG(WHAT, OBJ, ...) 				_hb_debug_msg<HB_DEBUG_##WHAT> (#WHAT, (OBJ), NULL,    false, 0, 0, __VA_ARGS__)
Packit 874993
#define DEBUG_MSG_FUNC(WHAT, OBJ, ...)				_hb_debug_msg<HB_DEBUG_##WHAT> (#WHAT, (OBJ), HB_FUNC, false, 0, 0, __VA_ARGS__)
Packit 874993
Packit 874993
Packit 874993
/*
Packit 874993
 * Printer
Packit 874993
 */
Packit 874993
Packit 874993
template <typename T>
Packit 874993
struct hb_printer_t {
Packit 874993
  const char *print (const T&) { return "something"; }
Packit 874993
};
Packit 874993
Packit 874993
template <>
Packit 874993
struct hb_printer_t<bool> {
Packit 874993
  const char *print (bool v) { return v ? "true" : "false"; }
Packit 874993
};
Packit 874993
Packit 874993
template <>
Packit 874993
struct hb_printer_t<hb_void_t> {
Packit 874993
  const char *print (hb_void_t) { return ""; }
Packit 874993
};
Packit 874993
Packit 874993
Packit 874993
/*
Packit 874993
 * Trace
Packit 874993
 */
Packit 874993
Packit 874993
template <typename T>
Packit 874993
static inline void _hb_warn_no_return (bool returned)
Packit 874993
{
Packit 874993
  if (unlikely (!returned)) {
Packit 874993
    fprintf (stderr, "OUCH, returned with no call to return_trace().  This is a bug, please report.\n");
Packit 874993
  }
Packit 874993
}
Packit 874993
template <>
Packit 874993
/*static*/ inline void _hb_warn_no_return<hb_void_t> (bool returned HB_UNUSED)
Packit 874993
{}
Packit 874993
Packit 874993
template <int max_level, typename ret_t>
Packit 874993
struct hb_auto_trace_t {
Packit 874993
  explicit inline hb_auto_trace_t (unsigned int *plevel_,
Packit 874993
				   const char *what_,
Packit 874993
				   const void *obj_,
Packit 874993
				   const char *func,
Packit 874993
				   const char *message,
Packit 874993
				   ...) : plevel (plevel_), what (what_), obj (obj_), returned (false)
Packit 874993
  {
Packit 874993
    if (plevel) ++*plevel;
Packit 874993
Packit 874993
    va_list ap;
Packit 874993
    va_start (ap, message);
Packit 874993
    _hb_debug_msg_va<max_level> (what, obj, func, true, plevel ? *plevel : 0, +1, message, ap);
Packit 874993
    va_end (ap);
Packit 874993
  }
Packit 874993
  inline ~hb_auto_trace_t (void)
Packit 874993
  {
Packit 874993
    _hb_warn_no_return<ret_t> (returned);
Packit 874993
    if (!returned) {
Packit 874993
      _hb_debug_msg<max_level> (what, obj, NULL, true, plevel ? *plevel : 1, -1, " ");
Packit 874993
    }
Packit 874993
    if (plevel) --*plevel;
Packit 874993
  }
Packit 874993
Packit 874993
  inline ret_t ret (ret_t v, unsigned int line = 0)
Packit 874993
  {
Packit 874993
    if (unlikely (returned)) {
Packit 874993
      fprintf (stderr, "OUCH, double calls to return_trace().  This is a bug, please report.\n");
Packit 874993
      return v;
Packit 874993
    }
Packit 874993
Packit 874993
    _hb_debug_msg<max_level> (what, obj, NULL, true, plevel ? *plevel : 1, -1,
Packit 874993
			      "return %s (line %d)",
Packit 874993
			      hb_printer_t<ret_t>().print (v), line);
Packit 874993
    if (plevel) --*plevel;
Packit 874993
    plevel = NULL;
Packit 874993
    returned = true;
Packit 874993
    return v;
Packit 874993
  }
Packit 874993
Packit 874993
  private:
Packit 874993
  unsigned int *plevel;
Packit 874993
  const char *what;
Packit 874993
  const void *obj;
Packit 874993
  bool returned;
Packit 874993
};
Packit 874993
template <typename ret_t> /* Optimize when tracing is disabled */
Packit 874993
struct hb_auto_trace_t<0, ret_t> {
Packit 874993
  explicit inline hb_auto_trace_t (unsigned int *plevel_ HB_UNUSED,
Packit 874993
				   const char *what HB_UNUSED,
Packit 874993
				   const void *obj HB_UNUSED,
Packit 874993
				   const char *func HB_UNUSED,
Packit 874993
				   const char *message HB_UNUSED,
Packit 874993
				   ...) {}
Packit 874993
Packit 874993
  inline ret_t ret (ret_t v, unsigned int line HB_UNUSED = 0) { return v; }
Packit 874993
};
Packit 874993
Packit 874993
#define return_trace(RET) return trace.ret (RET, __LINE__)
Packit 874993
Packit 874993
/* Misc */
Packit 874993
Packit 874993
template <typename T> class hb_assert_unsigned_t;
Packit 874993
template <> class hb_assert_unsigned_t<unsigned char> {};
Packit 874993
template <> class hb_assert_unsigned_t<unsigned short> {};
Packit 874993
template <> class hb_assert_unsigned_t<unsigned int> {};
Packit 874993
template <> class hb_assert_unsigned_t<unsigned long> {};
Packit 874993
Packit 874993
template <typename T> static inline bool
Packit 874993
hb_in_range (T u, T lo, T hi)
Packit 874993
{
Packit 874993
  /* The sizeof() is here to force template instantiation.
Packit 874993
   * I'm sure there are better ways to do this but can't think of
Packit 874993
   * one right now.  Declaring a variable won't work as HB_UNUSED
Packit 874993
   * is unusable on some platforms and unused types are less likely
Packit 874993
   * to generate a warning than unused variables. */
Packit 874993
  ASSERT_STATIC (sizeof (hb_assert_unsigned_t<T>) >= 0);
Packit 874993
Packit 874993
  /* The casts below are important as if T is smaller than int,
Packit 874993
   * the subtract results will become a signed int! */
Packit 874993
  return (T)(u - lo) <= (T)(hi - lo);
Packit 874993
}
Packit 874993
Packit 874993
template <typename T> static inline bool
Packit 874993
hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2)
Packit 874993
{
Packit 874993
  return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2);
Packit 874993
}
Packit 874993
Packit 874993
template <typename T> static inline bool
Packit 874993
hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3)
Packit 874993
{
Packit 874993
  return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2) || hb_in_range (u, lo3, hi3);
Packit 874993
}
Packit 874993
Packit 874993
Packit 874993
/* Enable bitwise ops on enums marked as flags_t */
Packit 874993
/* To my surprise, looks like the function resolver is happy to silently cast
Packit 874993
 * one enum to another...  So this doesn't provide the type-checking that I
Packit 874993
 * originally had in mind... :(.
Packit 874993
 *
Packit 874993
 * For MSVC warnings, see: https://github.com/behdad/harfbuzz/pull/163
Packit 874993
 */
Packit 874993
#ifdef _MSC_VER
Packit 874993
# pragma warning(disable:4200)
Packit 874993
# pragma warning(disable:4800)
Packit 874993
#endif
Packit 874993
#define HB_MARK_AS_FLAG_T(T) \
Packit 874993
	extern "C++" { \
Packit 874993
	  static inline T operator | (T l, T r) { return T ((unsigned) l | (unsigned) r); } \
Packit 874993
	  static inline T operator & (T l, T r) { return T ((unsigned) l & (unsigned) r); } \
Packit 874993
	  static inline T operator ^ (T l, T r) { return T ((unsigned) l ^ (unsigned) r); } \
Packit 874993
	  static inline T operator ~ (T r) { return T (~(unsigned int) r); } \
Packit 874993
	  static inline T& operator |= (T &l, T r) { l = l | r; return l; } \
Packit 874993
	  static inline T& operator &= (T& l, T r) { l = l & r; return l; } \
Packit 874993
	  static inline T& operator ^= (T& l, T r) { l = l ^ r; return l; } \
Packit 874993
	}
Packit 874993
Packit 874993
Packit 874993
/* Useful for set-operations on small enums.
Packit 874993
 * For example, for testing "x ∈ {x1, x2, x3}" use:
Packit 874993
 * (FLAG_SAFE(x) & (FLAG(x1) | FLAG(x2) | FLAG(x3)))
Packit 874993
 */
Packit 874993
#define FLAG(x) (ASSERT_STATIC_EXPR_ZERO ((x) < 32) + (1U << (x)))
Packit 874993
#define FLAG_SAFE(x) (1U << (x))
Packit 874993
#define FLAG_UNSAFE(x) ((x) < 32 ? FLAG_SAFE(x) : 0)
Packit 874993
#define FLAG_RANGE(x,y) (ASSERT_STATIC_EXPR_ZERO ((x) < (y)) + FLAG(y+1) - FLAG(x))
Packit 874993
Packit 874993
Packit 874993
template <typename T, typename T2> static inline void
Packit 874993
hb_stable_sort (T *array, unsigned int len, int(*compar)(const T *, const T *), T2 *array2)
Packit 874993
{
Packit 874993
  for (unsigned int i = 1; i < len; i++)
Packit 874993
  {
Packit 874993
    unsigned int j = i;
Packit 874993
    while (j && compar (&array[j - 1], &array[i]) > 0)
Packit 874993
      j--;
Packit 874993
    if (i == j)
Packit 874993
      continue;
Packit 874993
    /* Move item i to occupy place for item j, shift what's in between. */
Packit 874993
    {
Packit 874993
      T t = array[i];
Packit 874993
      memmove (&array[j + 1], &array[j], (i - j) * sizeof (T));
Packit 874993
      array[j] = t;
Packit 874993
    }
Packit 874993
    if (array2)
Packit 874993
    {
Packit 874993
      T2 t = array2[i];
Packit 874993
      memmove (&array2[j + 1], &array2[j], (i - j) * sizeof (T2));
Packit 874993
      array2[j] = t;
Packit 874993
    }
Packit 874993
  }
Packit 874993
}
Packit 874993
Packit 874993
template <typename T> static inline void
Packit 874993
hb_stable_sort (T *array, unsigned int len, int(*compar)(const T *, const T *))
Packit 874993
{
Packit 874993
  hb_stable_sort (array, len, compar, (int *) NULL);
Packit 874993
}
Packit 874993
Packit 874993
static inline hb_bool_t
Packit 874993
hb_codepoint_parse (const char *s, unsigned int len, int base, hb_codepoint_t *out)
Packit 874993
{
Packit 874993
  /* Pain because we don't know whether s is nul-terminated. */
Packit 874993
  char buf[64];
Packit 874993
  len = MIN (ARRAY_LENGTH (buf) - 1, len);
Packit 874993
  strncpy (buf, s, len);
Packit 874993
  buf[len] = '\0';
Packit 874993
Packit 874993
  char *end;
Packit 874993
  errno = 0;
Packit 874993
  unsigned long v = strtoul (buf, &end, base);
Packit 874993
  if (errno) return false;
Packit 874993
  if (*end) return false;
Packit 874993
  *out = v;
Packit 874993
  return true;
Packit 874993
}
Packit 874993
Packit 874993
Packit 874993
/* Global runtime options. */
Packit 874993
Packit 874993
struct hb_options_t
Packit 874993
{
Packit 874993
  unsigned int initialized : 1;
Packit 874993
  unsigned int uniscribe_bug_compatible : 1;
Packit 874993
};
Packit 874993
Packit 874993
union hb_options_union_t {
Packit 874993
  unsigned int i;
Packit 874993
  hb_options_t opts;
Packit 874993
};
Packit 874993
ASSERT_STATIC (sizeof (int) == sizeof (hb_options_union_t));
Packit 874993
Packit 874993
HB_INTERNAL void
Packit 874993
_hb_options_init (void);
Packit 874993
Packit 874993
extern HB_INTERNAL hb_options_union_t _hb_options;
Packit 874993
Packit 874993
static inline hb_options_t
Packit 874993
hb_options (void)
Packit 874993
{
Packit 874993
  if (unlikely (!_hb_options.i))
Packit 874993
    _hb_options_init ();
Packit 874993
Packit 874993
  return _hb_options.opts;
Packit 874993
}
Packit 874993
Packit 874993
/* Size signifying variable-sized array */
Packit 874993
#define VAR 1
Packit 874993
Packit 874993
#endif /* HB_PRIVATE_HH */