15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright © 2007,2008,2009  Red Hat, Inc.
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright © 2011,2012  Google, Inc.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  This is part of HarfBuzz, a text shaping library.
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Permission is hereby granted, without written agreement and without
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * license or royalty fees, to use, copy, modify, and distribute this
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * software and its documentation for any purpose, provided that the
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * above copyright notice and the following two paragraphs appear in
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * all copies of this software.
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * DAMAGE.
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Red Hat Author(s): Behdad Esfahbod
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Google Author(s): Behdad Esfahbod
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef HB_PRIVATE_HH
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define HB_PRIVATE_HH
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_CONFIG_H
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "config.h"
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "hb.h"
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define HB_H_IN
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_OT
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "hb-ot.h"
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define HB_OT_H_IN
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdlib.h>
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stddef.h>
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string.h>
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <assert.h>
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* We only use these two for debug output.  However, the debug code is
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * always seen by the compiler (and optimized out in non-debug builds.
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * If including these becomes a problem, we can start thinking about
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * someway around that. */
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdio.h>
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <errno.h>
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdarg.h>
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)/* Compiler attributes */
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#if defined(__GNUC__) && (__GNUC__ > 2) && defined(__OPTIMIZE__)
615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#define _HB_BOOLEAN_EXPR(expr) ((expr) ? 1 : 0)
625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#define likely(expr) (__builtin_expect (_HB_BOOLEAN_EXPR(expr), 1))
635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#define unlikely(expr) (__builtin_expect (_HB_BOOLEAN_EXPR(expr), 0))
645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#else
655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#define likely(expr) (expr)
665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#define unlikely(expr) (expr)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#ifndef __GNUC__
705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#undef __attribute__
715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#define __attribute__(x)
725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif
735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#if __GNUC__ >= 3
755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#define HB_PURE_FUNC	__attribute__((pure))
765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#define HB_CONST_FUNC	__attribute__((const))
775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#define HB_PRINTF_FUNC(format_idx, arg_idx) __attribute__((__format__ (__printf__, format_idx, arg_idx)))
785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#else
795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#define HB_PURE_FUNC
805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#define HB_CONST_FUNC
815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#define HB_PRINTF_FUNC(format_idx, arg_idx)
825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif
835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#if __GNUC__ >= 4
845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#define HB_UNUSED	__attribute__((unused))
855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#else
865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#define HB_UNUSED
875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif
885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#ifndef HB_INTERNAL
9003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)# if !defined(__MINGW32__) && !defined(__CYGWIN__)
915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#  define HB_INTERNAL __attribute__((__visibility__("hidden")))
925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)# else
935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#  define HB_INTERNAL
945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)# endif
955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif
965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#if (defined(__WIN32__) && !defined(__WINE__)) || defined(_MSC_VER)
985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#define snprintf _snprintf
9903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)/* Windows CE only has _strdup, while rest of Windows has both. */
10003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#define strdup _strdup
1015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif
1025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#ifdef _MSC_VER
1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#undef inline
1055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#define inline __inline
1065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif
1075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#ifdef __STRICT_ANSI__
1095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#undef inline
1105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#define inline __inline__
1115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif
1125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#if __GNUC__ >= 3
1145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#define HB_FUNC __PRETTY_FUNCTION__
1155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#elif defined(_MSC_VER)
1165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#define HB_FUNC __FUNCSIG__
1175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#else
1185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#define HB_FUNC __func__
1195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#if defined(_WIN32) || defined(__CYGWIN__)
12203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)   /* We need Windows Vista for both Uniscribe backend and for
12303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    * MemoryBarrier.  We don't support compiling on Windows XP,
12403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    * though we run on it fine. */
12503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#  if defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0600
12603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#    undef _WIN32_WINNT
12703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#  endif
12803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#  ifndef _WIN32_WINNT
12903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#    define _WIN32_WINNT 0x0600
13003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#  endif
13103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#  ifndef WIN32_LEAN_AND_MEAN
1321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#    define WIN32_LEAN_AND_MEAN 1
13303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#  endif
13403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#  ifndef STRICT
1351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#    define STRICT 1
13603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#  endif
13703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#endif
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#ifdef _WIN32_WCE
14003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)/* Some things not defined on Windows CE. */
14103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#define MemoryBarrier()
14203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#define getenv(Name) NULL
14303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#define setlocale(Category, Locale) "C"
14403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)static int errno = 0; /* Use something better? */
14503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#endif
14603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
14703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#if HAVE_ATEXIT
14803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)/* atexit() is only safe to be called from shared libraries on certain
14903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) * platforms.  Whitelist.
15003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) * https://bugs.freedesktop.org/show_bug.cgi?id=82246 */
15103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#  if defined(__linux) && defined(__GLIBC_PREREQ)
15203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#    if __GLIBC_PREREQ(2,3)
15303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)/* From atexit() manpage, it's safe with glibc 2.2.3 on Linux. */
15403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#      define HB_USE_ATEXIT 1
15503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#    endif
15603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#  elif defined(_MSC_VER) || defined(__MINGW32__)
15703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)/* For MSVC:
15803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) * http://msdn.microsoft.com/en-ca/library/tze57ck3.aspx
15903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) * http://msdn.microsoft.com/en-ca/library/zk17ww08.aspx
16003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) * mingw32 headers say atexit is safe to use in shared libraries.
16103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) */
16203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#    define HB_USE_ATEXIT 1
16303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#  elif defined(__ANDROID__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
16403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)/* This was fixed in Android NKD r8 or r8b:
16503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) * https://code.google.com/p/android/issues/detail?id=6455
16603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) * which introduced GCC 4.6:
16703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) * https://developer.android.com/tools/sdk/ndk/index.html
16803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) */
16903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#    define HB_USE_ATEXIT 1
17003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#  endif
17103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#endif
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Basics */
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#ifndef NULL
1775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)# define NULL ((void *) 0)
1785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif
1795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef MIN
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename Type>
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline Type MIN (const Type &a, const Type &b) { return a < b ? a : b; }
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef MAX
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename Type>
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline Type MAX (const Type &a, const Type &b) { return a > b ? a : b; }
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
188f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)static inline unsigned int DIV_CEIL (const unsigned int a, unsigned int b)
189f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles){ return (a + (b - 1)) / b; }
190f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef  ARRAY_LENGTH
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename Type, unsigned int n>
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static inline unsigned int ARRAY_LENGTH (const Type (&)[n]) { return n; }
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* A const version, but does not detect erratically being called on pointers. */
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define ARRAY_LENGTH_CONST(__array) ((signed int) (sizeof (__array) / sizeof (__array[0])))
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define HB_STMT_START do
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define HB_STMT_END   while (0)
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#define _ASSERT_STATIC1(_line, _cond)	HB_UNUSED typedef int _static_assert_on_line_##_line##_failed[(_cond)?1:-1]
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define _ASSERT_STATIC0(_line, _cond)	_ASSERT_STATIC1 (_line, (_cond))
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define ASSERT_STATIC(_cond)		_ASSERT_STATIC0 (__LINE__, (_cond))
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define ASSERT_STATIC_EXPR(_cond)((void) sizeof (char[(_cond) ? 1 : -1]))
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define ASSERT_STATIC_EXPR_ZERO(_cond) (0 * sizeof (char[(_cond) ? 1 : -1]))
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define _PASTE1(a,b) a##b
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define PASTE(a,b) _PASTE1(a,b)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Lets assert int types.  Saves trouble down the road. */
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ASSERT_STATIC (sizeof (int8_t) == 1);
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ASSERT_STATIC (sizeof (uint8_t) == 1);
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ASSERT_STATIC (sizeof (int16_t) == 2);
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ASSERT_STATIC (sizeof (uint16_t) == 2);
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ASSERT_STATIC (sizeof (int32_t) == 4);
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ASSERT_STATIC (sizeof (uint32_t) == 4);
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ASSERT_STATIC (sizeof (int64_t) == 8);
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ASSERT_STATIC (sizeof (uint64_t) == 8);
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ASSERT_STATIC (sizeof (hb_codepoint_t) == 4);
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ASSERT_STATIC (sizeof (hb_position_t) == 4);
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ASSERT_STATIC (sizeof (hb_mask_t) == 4);
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ASSERT_STATIC (sizeof (hb_var_int_t) == 4);
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* We like our types POD */
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define _ASSERT_TYPE_POD1(_line, _type)	union _type_##_type##_on_line_##_line##_is_not_POD { _type instance; }
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define _ASSERT_TYPE_POD0(_line, _type)	_ASSERT_TYPE_POD1 (_line, _type)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define ASSERT_TYPE_POD(_type)		_ASSERT_TYPE_POD0 (__LINE__, _type)
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef __GNUC__
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define _ASSERT_INSTANCE_POD1(_line, _instance) \
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	HB_STMT_START { \
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		typedef __typeof__(_instance) _type_##_line; \
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		_ASSERT_TYPE_POD1 (_line, _type_##_line); \
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	} HB_STMT_END
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define _ASSERT_INSTANCE_POD1(_line, _instance)	typedef int _assertion_on_line_##_line##_not_tested
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define _ASSERT_INSTANCE_POD0(_line, _instance)	_ASSERT_INSTANCE_POD1 (_line, _instance)
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define ASSERT_INSTANCE_POD(_instance)			_ASSERT_INSTANCE_POD0 (__LINE__, _instance)
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Check _assertion in a method environment */
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define _ASSERT_POD1(_line) \
2485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	HB_UNUSED inline void _static_assertion_on_line_##_line (void) const \
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{ _ASSERT_INSTANCE_POD1 (_line, *this); /* Make sure it's POD. */ }
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define _ASSERT_POD0(_line)	_ASSERT_POD1 (_line)
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define ASSERT_POD()		_ASSERT_POD0 (__LINE__)
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Misc */
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)/* Void! */
2585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)struct _hb_void_t {};
2595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)typedef const _hb_void_t &hb_void_t;
2605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#define HB_VOID (* (const _hb_void_t *) NULL)
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Return the number of 1 bits in mask. */
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline HB_CONST_FUNC unsigned int
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_hb_popcount32 (uint32_t mask)
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return __builtin_popcount (mask);
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* "HACKMEM 169" */
27023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  uint32_t y;
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  y = (mask >> 1) &033333333333;
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  y = mask - y - ((y >>1) & 033333333333);
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (((y + (y >> 3)) & 030707070707) % 077);
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Returns the number of bits needed to store number */
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline HB_CONST_FUNC unsigned int
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_hb_bit_storage (unsigned int number)
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(__GNUC__) && (__GNUC__ >= 4) && defined(__OPTIMIZE__)
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return likely (number) ? (sizeof (unsigned int) * 8 - __builtin_clz (number)) : 0;
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
28423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  unsigned int n_bits = 0;
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (number) {
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    n_bits++;
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    number >>= 1;
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return n_bits;
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Returns the number of zero bits in the least significant side of number */
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline HB_CONST_FUNC unsigned int
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_hb_ctz (unsigned int number)
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(__GNUC__) && (__GNUC__ >= 4) && defined(__OPTIMIZE__)
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return likely (number) ? __builtin_ctz (number) : 0;
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
30023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  unsigned int n_bits = 0;
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (unlikely (!number)) return 0;
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (!(number & 1)) {
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    n_bits++;
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    number >>= 1;
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return n_bits;
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline bool
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_hb_unsigned_int_mul_overflows (unsigned int count, unsigned int size)
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (size > 0) && (count >= ((unsigned int) -1) / size);
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Type of bsearch() / qsort() compare function */
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef int (*hb_compare_func_t) (const void *, const void *);
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* arrays and maps */
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#define HB_PREALLOCED_ARRAY_INIT {0, 0, NULL}
3275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)template <typename Type, unsigned int StaticSize=16>
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct hb_prealloced_array_t
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int len;
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int allocated;
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Type *array;
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Type static_array[StaticSize];
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void init (void) { memset (this, 0, sizeof (*this)); }
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline Type& operator [] (unsigned int i) { return array[i]; }
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline const Type& operator [] (unsigned int i) const { return array[i]; }
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline Type *push (void)
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!array) {
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      array = static_array;
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      allocated = ARRAY_LENGTH (static_array);
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (likely (len < allocated))
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return &array[len++];
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Need to reallocate */
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int new_allocated = allocated + (allocated >> 1) + 8;
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Type *new_array = NULL;
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (array == static_array) {
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new_array = (Type *) calloc (new_allocated, sizeof (Type));
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (new_array)
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        memcpy (new_array, array, len * sizeof (Type));
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bool overflows = (new_allocated < allocated) || _hb_unsigned_int_mul_overflows (new_allocated, sizeof (Type));
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (likely (!overflows)) {
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	new_array = (Type *) realloc (array, new_allocated * sizeof (Type));
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!new_array))
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return NULL;
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    array = new_array;
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    allocated = new_allocated;
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return &array[len++];
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void pop (void)
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    len--;
375f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
376f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
377f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  inline void remove (unsigned int i)
378f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  {
379f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)     if (unlikely (i >= len))
380f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)       return;
381f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)     memmove (static_cast<void *> (&array[i]),
382f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	      static_cast<void *> (&array[i + 1]),
383f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	      (len - i - 1) * sizeof (Type));
384f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)     len--;
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void shrink (unsigned int l)
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     if (l < len)
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       len = l;
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename T>
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline Type *find (T v) {
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int i = 0; i < len; i++)
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (array[i] == v)
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return &array[i];
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename T>
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline const Type *find (T v) const {
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int i = 0; i < len; i++)
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (array[i] == v)
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return &array[i];
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  inline void qsort (void)
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
4105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ::qsort (array, len, sizeof (Type), (hb_compare_func_t) Type::cmp);
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  inline void qsort (unsigned int start, unsigned int end)
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
4155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ::qsort (array + start, end - start, sizeof (Type), (hb_compare_func_t) Type::cmp);
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename T>
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline Type *bsearch (T *key)
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return (Type *) ::bsearch (key, array, len, sizeof (Type), (hb_compare_func_t) Type::cmp);
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename T>
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline const Type *bsearch (T *key) const
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return (const Type *) ::bsearch (key, array, len, sizeof (Type), (hb_compare_func_t) Type::cmp);
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void finish (void)
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (array != static_array)
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      free (array);
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    array = NULL;
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    allocated = len = 0;
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
438c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)template <typename Type>
4395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)struct hb_auto_array_t : hb_prealloced_array_t <Type>
440c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles){
4415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  hb_auto_array_t (void) { hb_prealloced_array_t<Type>::init (); }
4425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ~hb_auto_array_t (void) { hb_prealloced_array_t<Type>::finish (); }
443c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
444c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define HB_LOCKABLE_SET_INIT {HB_PREALLOCED_ARRAY_INIT}
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename item_t, typename lock_t>
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct hb_lockable_set_t
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hb_prealloced_array_t <item_t, 2> items;
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void init (void) { items.init (); }
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename T>
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline item_t *replace_or_insert (T v, lock_t &l, bool replace)
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    l.lock ();
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    item_t *item = items.find (v);
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (item) {
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (replace) {
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	item_t old = *item;
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	*item = v;
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	l.unlock ();
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	old.finish ();
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else {
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        item = NULL;
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	l.unlock ();
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      item = items.push ();
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (likely (item))
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	*item = v;
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      l.unlock ();
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return item;
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename T>
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void remove (T v, lock_t &l)
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    l.lock ();
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    item_t *item = items.find (v);
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (item) {
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      item_t old = *item;
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *item = items[items.len - 1];
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      items.pop ();
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      l.unlock ();
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      old.finish ();
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      l.unlock ();
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename T>
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool find (T v, item_t *i, lock_t &l)
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    l.lock ();
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    item_t *item = items.find (v);
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (item)
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *i = *item;
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    l.unlock ();
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return !!item;
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename T>
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline item_t *find_or_insert (T v, lock_t &l)
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    l.lock ();
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    item_t *item = items.find (v);
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!item) {
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      item = items.push ();
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (likely (item))
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *item = v;
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    l.unlock ();
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return item;
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void finish (lock_t &l)
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!items.len) {
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* No need for locking. */
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      items.finish ();
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    l.lock ();
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (items.len) {
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      item_t old = items[items.len - 1];
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	items.pop ();
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	l.unlock ();
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	old.finish ();
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	l.lock ();
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    items.finish ();
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    l.unlock ();
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Big-endian handling */
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline uint16_t hb_be_uint16 (const uint16_t v)
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const uint8_t *V = (const uint8_t *) &v;
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (V[0] << 8) | V[1];
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline uint16_t hb_uint16_swap (const uint16_t v)
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (v >> 8) | (v << 8);
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline uint32_t hb_uint32_swap (const uint32_t v)
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (hb_uint16_swap (v) << 16) | hb_uint16_swap (v >> 16);
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Note, of the following macros, uint16_get is the one called many many times.
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * If there is any optimizations to be done, it's in that macro.  However, I
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * already confirmed that on my T400 ThinkPad at least, using bswap_16(), which
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * results in a single ror instruction, does NOT speed this up.  In fact, it
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * resulted in a minor slowdown.  At any rate, note that v may not be correctly
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * aligned, so I think the current implementation is optimal.
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define hb_be_uint16_put(v,V)	HB_STMT_START { v[0] = (V>>8); v[1] = (V); } HB_STMT_END
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define hb_be_uint16_get(v)	(uint16_t) ((v[0] << 8) + v[1])
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define hb_be_uint16_eq(a,b)	(a[0] == b[0] && a[1] == b[1])
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define hb_be_uint32_put(v,V)	HB_STMT_START { v[0] = (V>>24); v[1] = (V>>16); v[2] = (V>>8); v[3] = (V); } HB_STMT_END
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define hb_be_uint32_get(v)	(uint32_t) ((v[0] << 24) + (v[1] << 16) + (v[2] << 8) + v[3])
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define hb_be_uint32_eq(a,b)	(a[0] == b[0] && a[1] == b[1] && a[2] == b[2] && a[3] == b[3])
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#define hb_be_uint24_put(v,V)	HB_STMT_START { v[0] = (V>>16); v[1] = (V>>8); v[2] = (V); } HB_STMT_END
5792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define hb_be_uint24_get(v)	(uint32_t) ((v[0] << 16) + (v[1] << 8) + v[2])
5802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define hb_be_uint24_eq(a,b)	(a[0] == b[0] && a[1] == b[1] && a[2] == b[2])
5812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* ASCII tag/character handling */
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static inline bool ISALPHA (unsigned char c)
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); }
587c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static inline bool ISALNUM (unsigned char c)
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'); }
589c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static inline bool ISSPACE (unsigned char c)
590c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles){ return c == ' ' || c =='\f'|| c =='\n'|| c =='\r'|| c =='\t'|| c =='\v'; }
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline unsigned char TOUPPER (unsigned char c)
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ return (c >= 'a' && c <= 'z') ? c - 'a' + 'A' : c; }
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline unsigned char TOLOWER (unsigned char c)
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ return (c >= 'A' && c <= 'Z') ? c - 'A' + 'a' : c; }
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define HB_TAG_CHAR4(s)   (HB_TAG(((const char *) s)[0], \
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				  ((const char *) s)[1], \
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				  ((const char *) s)[2], \
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				  ((const char *) s)[3]))
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* C++ helpers */
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Makes class uncopyable.  Use in private: section. */
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define NO_COPY(T) \
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  T (const T &o); \
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  T &operator = (const T &o)
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Debug */
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef HB_DEBUG
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define HB_DEBUG 0
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline bool
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_hb_debug (unsigned int level,
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	   unsigned int max_level)
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return level < max_level;
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#define DEBUG_LEVEL_ENABLED(WHAT, LEVEL) (_hb_debug ((LEVEL), HB_DEBUG_##WHAT))
6257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#define DEBUG_ENABLED(WHAT) (DEBUG_LEVEL_ENABLED (WHAT, 0))
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <int max_level> static inline void
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_hb_debug_msg_va (const char *what,
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		  const void *obj,
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		  const char *func,
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		  bool indented,
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		  unsigned int level,
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		  int level_dir,
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		  const char *message,
63503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)		  va_list ap) HB_PRINTF_FUNC(7, 0);
63603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)template <int max_level> static inline void
63703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)_hb_debug_msg_va (const char *what,
63803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)		  const void *obj,
63903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)		  const char *func,
64003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)		  bool indented,
64103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)		  unsigned int level,
64203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)		  int level_dir,
64303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)		  const char *message,
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		  va_list ap)
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!_hb_debug (level, max_level))
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fprintf (stderr, "%-10s", what ? what : "");
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (obj)
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fprintf (stderr, "(%0*lx) ", (unsigned int) (2 * sizeof (void *)), (unsigned long) obj);
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fprintf (stderr, " %*s  ", (unsigned int) (2 * sizeof (void *)), "");
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (indented) {
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* One may want to add ASCII version of these.  See:
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * https://bugs.freedesktop.org/show_bug.cgi?id=50970 */
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define VBAR	"\342\224\202"	/* U+2502 BOX DRAWINGS LIGHT VERTICAL */
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define VRBAR	"\342\224\234"	/* U+251C BOX DRAWINGS LIGHT VERTICAL AND RIGHT */
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define DLBAR	"\342\225\256"	/* U+256E BOX DRAWINGS LIGHT ARC DOWN AND LEFT */
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define ULBAR	"\342\225\257"	/* U+256F BOX DRAWINGS LIGHT ARC UP AND LEFT */
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define LBAR	"\342\225\264"	/* U+2574 BOX DRAWINGS LIGHT LEFT */
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    static const char bars[] = VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR;
665f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    fprintf (stderr, "%2u %s" VRBAR "%s",
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	     level,
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	     bars + sizeof (bars) - 1 - MIN ((unsigned int) sizeof (bars), (unsigned int) (sizeof (VBAR) - 1) * level),
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	     level_dir ? (level_dir > 0 ? DLBAR : ULBAR) : LBAR);
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fprintf (stderr, "   " VRBAR LBAR);
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (func)
6732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
674c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    unsigned int func_len = strlen (func);
675c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#ifndef HB_DEBUG_VERBOSE
6762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    /* Skip "typename" */
6772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (0 == strncmp (func, "typename ", 9))
6782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      func += 9;
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Skip return type */
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char *space = strchr (func, ' ');
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (space)
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      func = space + 1;
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Skip parameter list */
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char *paren = strchr (func, '(');
685c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (paren)
686c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      func_len = paren - func;
687c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fprintf (stderr, "%.*s: ", func_len, func);
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (message)
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    vfprintf (stderr, message, ap);
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fprintf (stderr, "\n");
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <> inline void
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_hb_debug_msg_va<0> (const char *what HB_UNUSED,
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     const void *obj HB_UNUSED,
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     const char *func HB_UNUSED,
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     bool indented HB_UNUSED,
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     unsigned int level HB_UNUSED,
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     int level_dir HB_UNUSED,
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     const char *message HB_UNUSED,
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     va_list ap HB_UNUSED) {}
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <int max_level> static inline void
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_hb_debug_msg (const char *what,
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	       const void *obj,
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	       const char *func,
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	       bool indented,
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	       unsigned int level,
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	       int level_dir,
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	       const char *message,
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	       ...) HB_PRINTF_FUNC(7, 8);
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <int max_level> static inline void
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_hb_debug_msg (const char *what,
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	       const void *obj,
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	       const char *func,
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	       bool indented,
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	       unsigned int level,
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	       int level_dir,
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	       const char *message,
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	       ...)
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  va_list ap;
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  va_start (ap, message);
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  _hb_debug_msg_va<max_level> (what, obj, func, indented, level, level_dir, message, ap);
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  va_end (ap);
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <> inline void
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_hb_debug_msg<0> (const char *what HB_UNUSED,
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		  const void *obj HB_UNUSED,
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		  const char *func HB_UNUSED,
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		  bool indented HB_UNUSED,
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		  unsigned int level HB_UNUSED,
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		  int level_dir HB_UNUSED,
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		  const char *message HB_UNUSED,
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		  ...) HB_PRINTF_FUNC(7, 8);
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <> inline void
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_hb_debug_msg<0> (const char *what HB_UNUSED,
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		  const void *obj HB_UNUSED,
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		  const char *func HB_UNUSED,
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		  bool indented HB_UNUSED,
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		  unsigned int level HB_UNUSED,
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		  int level_dir HB_UNUSED,
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		  const char *message HB_UNUSED,
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		  ...) {}
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define DEBUG_MSG_LEVEL(WHAT, OBJ, LEVEL, LEVEL_DIR, ...)	_hb_debug_msg<HB_DEBUG_##WHAT> (#WHAT, (OBJ), NULL,    true, (LEVEL), (LEVEL_DIR), __VA_ARGS__)
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define DEBUG_MSG(WHAT, OBJ, ...) 				_hb_debug_msg<HB_DEBUG_##WHAT> (#WHAT, (OBJ), NULL,    false, 0, 0, __VA_ARGS__)
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define DEBUG_MSG_FUNC(WHAT, OBJ, ...)				_hb_debug_msg<HB_DEBUG_##WHAT> (#WHAT, (OBJ), HB_FUNC, false, 0, 0, __VA_ARGS__)
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
7552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Printer
7562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */
7572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)template <typename T>
7592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct hb_printer_t {};
7602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)template <>
7622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct hb_printer_t<bool> {
7632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const char *print (bool v) { return v ? "true" : "false"; }
7642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
7652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)template <>
7672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct hb_printer_t<hb_void_t> {
7682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const char *print (hb_void_t) { return ""; }
7692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
7702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/*
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Trace
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)template <typename T>
7772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static inline void _hb_warn_no_return (bool returned)
7782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
7792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (unlikely (!returned)) {
7802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    fprintf (stderr, "OUCH, returned with no call to TRACE_RETURN.  This is a bug, please report.\n");
7812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)template <>
7845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)/*static*/ inline void _hb_warn_no_return<hb_void_t> (bool returned HB_UNUSED)
7852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){}
7862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)template <int max_level, typename ret_t>
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct hb_auto_trace_t {
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit inline hb_auto_trace_t (unsigned int *plevel_,
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   const char *what_,
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   const void *obj_,
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   const char *func,
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   const char *message,
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   ...) : plevel (plevel_), what (what_), obj (obj_), returned (false)
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (plevel) ++*plevel;
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    va_list ap;
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    va_start (ap, message);
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    _hb_debug_msg_va<max_level> (what, obj, func, true, plevel ? *plevel : 0, +1, message, ap);
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    va_end (ap);
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline ~hb_auto_trace_t (void)
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
8052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    _hb_warn_no_return<ret_t> (returned);
8062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!returned) {
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      _hb_debug_msg<max_level> (what, obj, NULL, true, plevel ? *plevel : 1, -1, " ");
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (plevel) --*plevel;
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline ret_t ret (ret_t v, unsigned int line = 0)
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (returned)) {
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      fprintf (stderr, "OUCH, double calls to TRACE_RETURN.  This is a bug, please report.\n");
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return v;
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    _hb_debug_msg<max_level> (what, obj, NULL, true, plevel ? *plevel : 1, -1,
8202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			      "return %s (line %d)",
8212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			      hb_printer_t<ret_t>().print (v), line);
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (plevel) --*plevel;
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    plevel = NULL;
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    returned = true;
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return v;
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  private:
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int *plevel;
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char *what;
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const void *obj;
8322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool returned;
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
8342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)template <typename ret_t> /* Optimize when tracing is disabled */
8352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct hb_auto_trace_t<0, ret_t> {
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit inline hb_auto_trace_t (unsigned int *plevel_ HB_UNUSED,
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   const char *what HB_UNUSED,
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   const void *obj HB_UNUSED,
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   const char *func HB_UNUSED,
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   const char *message HB_UNUSED,
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   ...) {}
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline ret_t ret (ret_t v, unsigned int line HB_UNUSED = 0) { return v; }
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TRACE_RETURN(RET) trace.ret (RET, __LINE__)
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Misc */
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)template <typename T> class hb_assert_unsigned_t;
8515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)template <> class hb_assert_unsigned_t<unsigned char> {};
8525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)template <> class hb_assert_unsigned_t<unsigned short> {};
8535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)template <> class hb_assert_unsigned_t<unsigned int> {};
8545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)template <> class hb_assert_unsigned_t<unsigned long> {};
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename T> static inline bool
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_in_range (T u, T lo, T hi)
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
8595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  /* The sizeof() is here to force template instantiation.
8605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)   * I'm sure there are better ways to do this but can't think of
8615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)   * one right now.  Declaring a variable won't work as HB_UNUSED
8625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)   * is unsable on some platforms and unused types are less likely
8635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)   * to generate a warning than unused variables. */
8645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ASSERT_STATIC (sizeof (hb_assert_unsigned_t<T>) >= 0);
8655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
86603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  /* The casts below are important as if T is smaller than int,
86703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)   * the subtract results will become a signed int! */
86803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  return (T)(u - lo) <= (T)(hi - lo);
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename T> static inline bool
87223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2)
87323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles){
87423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2);
87523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
87623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
87723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)template <typename T> static inline bool
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3)
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2) || hb_in_range (u, lo3, hi3);
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Useful for set-operations on small enums.
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * For example, for testing "x ∈ {x1, x2, x3}" use:
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * (FLAG(x) & (FLAG(x1) | FLAG(x2) | FLAG(x3)))
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define FLAG(x) (1<<(x))
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define FLAG_RANGE(x,y) (ASSERT_STATIC_EXPR_ZERO ((x) < (y)) + FLAG(y+1) - FLAG(x))
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename T, typename T2> inline void
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_bubble_sort (T *array, unsigned int len, int(*compar)(const T *, const T *), T2 *array2)
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (unlikely (!len))
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int k = len - 1;
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int new_k = 0;
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int j = 0; j < k; j++)
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (compar (&array[j], &array[j+1]) > 0)
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	  T t;
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	  t = array[j];
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	  array[j] = array[j + 1];
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	  array[j + 1] = t;
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (array2)
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	  T2 t;
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	  t = array2[j];
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	  array2[j] = array2[j + 1];
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	  array2[j + 1] = t;
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	new_k = j;
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    k = new_k;
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (k);
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename T> inline void
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_bubble_sort (T *array, unsigned int len, int(*compar)(const T *, const T *))
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hb_bubble_sort (array, len, compar, (int *) NULL);
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline hb_bool_t
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_codepoint_parse (const char *s, unsigned int len, int base, hb_codepoint_t *out)
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Pain because we don't know whether s is nul-terminated. */
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char buf[64];
936c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  len = MIN (ARRAY_LENGTH (buf) - 1, len);
937c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  strncpy (buf, s, len);
938c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  buf[len] = '\0';
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char *end;
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  errno = 0;
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned long v = strtoul (buf, &end, base);
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (errno) return false;
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (*end) return false;
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *out = v;
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
950c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/* Global runtime options. */
951c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
952c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)struct hb_options_t
953c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles){
954c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int initialized : 1;
955c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int uniscribe_bug_compatible : 1;
956c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
957c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
958c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)union hb_options_union_t {
959c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int i;
960c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  hb_options_t opts;
961c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
962c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)ASSERT_STATIC (sizeof (int) == sizeof (hb_options_union_t));
963c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
964c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)HB_INTERNAL void
965c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)_hb_options_init (void);
966c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
967c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)extern HB_INTERNAL hb_options_union_t _hb_options;
968c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
969c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static inline hb_options_t
970c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)hb_options (void)
971c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles){
972c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (unlikely (!_hb_options.i))
973c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    _hb_options_init ();
974c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
975c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return _hb_options.opts;
976c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
977c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
978c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* HB_PRIVATE_HH */
980