hb-private.hh revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
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)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Essentials */
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef NULL
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define NULL ((void *) 0)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/* Void! */
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct _hb_void_t {};
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)typedef const _hb_void_t &hb_void_t;
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define HB_VOID (* (const _hb_void_t *) NULL)
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Basics */
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef MIN
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename Type>
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline Type MIN (const Type &a, const Type &b) { return a < b ? a : b; }
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef MAX
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename Type>
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline Type MAX (const Type &a, const Type &b) { return a > b ? a : b; }
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef  ARRAY_LENGTH
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename Type, unsigned int n>
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static inline unsigned int ARRAY_LENGTH (const Type (&)[n]) { return n; }
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* A const version, but does not detect erratically being called on pointers. */
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define ARRAY_LENGTH_CONST(__array) ((signed int) (sizeof (__array) / sizeof (__array[0])))
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define HB_STMT_START do
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define HB_STMT_END   while (0)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define _ASSERT_STATIC1(_line, _cond)	typedef int _static_assert_on_line_##_line##_failed[(_cond)?1:-1]
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define _ASSERT_STATIC0(_line, _cond)	_ASSERT_STATIC1 (_line, (_cond))
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define ASSERT_STATIC(_cond)		_ASSERT_STATIC0 (__LINE__, (_cond))
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define ASSERT_STATIC_EXPR(_cond)((void) sizeof (char[(_cond) ? 1 : -1]))
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define ASSERT_STATIC_EXPR_ZERO(_cond) (0 * sizeof (char[(_cond) ? 1 : -1]))
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define _PASTE1(a,b) a##b
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define PASTE(a,b) _PASTE1(a,b)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Lets assert int types.  Saves trouble down the road. */
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ASSERT_STATIC (sizeof (int8_t) == 1);
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ASSERT_STATIC (sizeof (uint8_t) == 1);
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ASSERT_STATIC (sizeof (int16_t) == 2);
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ASSERT_STATIC (sizeof (uint16_t) == 2);
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ASSERT_STATIC (sizeof (int32_t) == 4);
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ASSERT_STATIC (sizeof (uint32_t) == 4);
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ASSERT_STATIC (sizeof (int64_t) == 8);
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ASSERT_STATIC (sizeof (uint64_t) == 8);
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ASSERT_STATIC (sizeof (hb_codepoint_t) == 4);
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ASSERT_STATIC (sizeof (hb_position_t) == 4);
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ASSERT_STATIC (sizeof (hb_mask_t) == 4);
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ASSERT_STATIC (sizeof (hb_var_int_t) == 4);
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* We like our types POD */
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define _ASSERT_TYPE_POD1(_line, _type)	union _type_##_type##_on_line_##_line##_is_not_POD { _type instance; }
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define _ASSERT_TYPE_POD0(_line, _type)	_ASSERT_TYPE_POD1 (_line, _type)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define ASSERT_TYPE_POD(_type)		_ASSERT_TYPE_POD0 (__LINE__, _type)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef __GNUC__
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define _ASSERT_INSTANCE_POD1(_line, _instance) \
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	HB_STMT_START { \
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		typedef __typeof__(_instance) _type_##_line; \
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		_ASSERT_TYPE_POD1 (_line, _type_##_line); \
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	} HB_STMT_END
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define _ASSERT_INSTANCE_POD1(_line, _instance)	typedef int _assertion_on_line_##_line##_not_tested
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define _ASSERT_INSTANCE_POD0(_line, _instance)	_ASSERT_INSTANCE_POD1 (_line, _instance)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define ASSERT_INSTANCE_POD(_instance)			_ASSERT_INSTANCE_POD0 (__LINE__, _instance)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Check _assertion in a method environment */
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define _ASSERT_POD1(_line) \
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	inline void _static_assertion_on_line_##_line (void) const \
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{ _ASSERT_INSTANCE_POD1 (_line, *this); /* Make sure it's POD. */ }
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define _ASSERT_POD0(_line)	_ASSERT_POD1 (_line)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define ASSERT_POD()		_ASSERT_POD0 (__LINE__)
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Misc */
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(__GNUC__) && (__GNUC__ > 2) && defined(__OPTIMIZE__)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define _HB_BOOLEAN_EXPR(expr) ((expr) ? 1 : 0)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define likely(expr) (__builtin_expect (_HB_BOOLEAN_EXPR(expr), 1))
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define unlikely(expr) (__builtin_expect (_HB_BOOLEAN_EXPR(expr), 0))
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define likely(expr) (expr)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define unlikely(expr) (expr)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef __GNUC__
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef __attribute__
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define __attribute__(x)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if __GNUC__ >= 3
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define HB_PURE_FUNC	__attribute__((pure))
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define HB_CONST_FUNC	__attribute__((const))
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define HB_PRINTF_FUNC(format_idx, arg_idx) __attribute__((__format__ (__printf__, format_idx, arg_idx)))
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define HB_PURE_FUNC
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define HB_CONST_FUNC
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define HB_PRINTF_FUNC(format_idx, arg_idx)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if __GNUC__ >= 4
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define HB_UNUSED	__attribute__((unused))
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define HB_UNUSED
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef HB_INTERNAL
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# ifndef __MINGW32__
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#  define HB_INTERNAL __attribute__((__visibility__("hidden")))
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# else
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#  define HB_INTERNAL
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# endif
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if (defined(__WIN32__) && !defined(__WINE__)) || defined(_MSC_VER)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define snprintf _snprintf
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef _MSC_VER
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef inline
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define inline __inline
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef __STRICT_ANSI__
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef inline
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define inline __inline__
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if __GNUC__ >= 3
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define HB_FUNC __PRETTY_FUNCTION__
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(_MSC_VER)
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define HB_FUNC __FUNCSIG__
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define HB_FUNC __func__
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Return the number of 1 bits in mask. */
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline HB_CONST_FUNC unsigned int
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_hb_popcount32 (uint32_t mask)
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return __builtin_popcount (mask);
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* "HACKMEM 169" */
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  register uint32_t y;
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  y = (mask >> 1) &033333333333;
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  y = mask - y - ((y >>1) & 033333333333);
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (((y + (y >> 3)) & 030707070707) % 077);
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Returns the number of bits needed to store number */
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline HB_CONST_FUNC unsigned int
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_hb_bit_storage (unsigned int number)
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(__GNUC__) && (__GNUC__ >= 4) && defined(__OPTIMIZE__)
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return likely (number) ? (sizeof (unsigned int) * 8 - __builtin_clz (number)) : 0;
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  register unsigned int n_bits = 0;
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (number) {
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    n_bits++;
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    number >>= 1;
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return n_bits;
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Returns the number of zero bits in the least significant side of number */
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline HB_CONST_FUNC unsigned int
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_hb_ctz (unsigned int number)
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(__GNUC__) && (__GNUC__ >= 4) && defined(__OPTIMIZE__)
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return likely (number) ? __builtin_ctz (number) : 0;
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  register unsigned int n_bits = 0;
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (unlikely (!number)) return 0;
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (!(number & 1)) {
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    n_bits++;
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    number >>= 1;
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return n_bits;
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline bool
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_hb_unsigned_int_mul_overflows (unsigned int count, unsigned int size)
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (size > 0) && (count >= ((unsigned int) -1) / size);
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Type of bsearch() / qsort() compare function */
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef int (*hb_compare_func_t) (const void *, const void *);
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* arrays and maps */
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define HB_PREALLOCED_ARRAY_INIT {0}
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename Type, unsigned int StaticSize>
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct hb_prealloced_array_t
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int len;
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int allocated;
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Type *array;
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Type static_array[StaticSize];
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void init (void) { memset (this, 0, sizeof (*this)); }
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline Type& operator [] (unsigned int i) { return array[i]; }
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline const Type& operator [] (unsigned int i) const { return array[i]; }
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline Type *push (void)
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!array) {
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      array = static_array;
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      allocated = ARRAY_LENGTH (static_array);
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (likely (len < allocated))
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return &array[len++];
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Need to reallocate */
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int new_allocated = allocated + (allocated >> 1) + 8;
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Type *new_array = NULL;
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (array == static_array) {
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new_array = (Type *) calloc (new_allocated, sizeof (Type));
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (new_array)
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        memcpy (new_array, array, len * sizeof (Type));
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bool overflows = (new_allocated < allocated) || _hb_unsigned_int_mul_overflows (new_allocated, sizeof (Type));
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (likely (!overflows)) {
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	new_array = (Type *) realloc (array, new_allocated * sizeof (Type));
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!new_array))
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return NULL;
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    array = new_array;
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    allocated = new_allocated;
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return &array[len++];
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void pop (void)
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    len--;
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* TODO: shrink array if needed */
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void shrink (unsigned int l)
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     if (l < len)
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       len = l;
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* TODO: shrink array if needed */
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename T>
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline Type *find (T v) {
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int i = 0; i < len; i++)
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (array[i] == v)
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return &array[i];
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename T>
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline const Type *find (T v) const {
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int i = 0; i < len; i++)
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (array[i] == v)
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return &array[i];
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void sort (void)
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    qsort (array, len, sizeof (Type), (hb_compare_func_t) Type::cmp);
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void sort (unsigned int start, unsigned int end)
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    qsort (array + start, end - start, sizeof (Type), (hb_compare_func_t) Type::cmp);
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename T>
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline Type *bsearch (T *key)
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return (Type *) ::bsearch (key, array, len, sizeof (Type), (hb_compare_func_t) Type::cmp);
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename T>
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline const Type *bsearch (T *key) const
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return (const Type *) ::bsearch (key, array, len, sizeof (Type), (hb_compare_func_t) Type::cmp);
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void finish (void)
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (array != static_array)
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      free (array);
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    array = NULL;
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    allocated = len = 0;
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define HB_LOCKABLE_SET_INIT {HB_PREALLOCED_ARRAY_INIT}
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename item_t, typename lock_t>
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct hb_lockable_set_t
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hb_prealloced_array_t <item_t, 2> items;
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void init (void) { items.init (); }
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename T>
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline item_t *replace_or_insert (T v, lock_t &l, bool replace)
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    l.lock ();
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    item_t *item = items.find (v);
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (item) {
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (replace) {
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	item_t old = *item;
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	*item = v;
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	l.unlock ();
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	old.finish ();
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else {
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        item = NULL;
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	l.unlock ();
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      item = items.push ();
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (likely (item))
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	*item = v;
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      l.unlock ();
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return item;
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename T>
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void remove (T v, lock_t &l)
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    l.lock ();
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    item_t *item = items.find (v);
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (item) {
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      item_t old = *item;
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *item = items[items.len - 1];
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      items.pop ();
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      l.unlock ();
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      old.finish ();
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      l.unlock ();
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename T>
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool find (T v, item_t *i, lock_t &l)
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    l.lock ();
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    item_t *item = items.find (v);
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (item)
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *i = *item;
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    l.unlock ();
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return !!item;
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename T>
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline item_t *find_or_insert (T v, lock_t &l)
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    l.lock ();
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    item_t *item = items.find (v);
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!item) {
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      item = items.push ();
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (likely (item))
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *item = v;
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    l.unlock ();
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return item;
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void finish (lock_t &l)
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!items.len) {
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* No need for locking. */
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      items.finish ();
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    l.lock ();
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (items.len) {
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      item_t old = items[items.len - 1];
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	items.pop ();
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	l.unlock ();
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	old.finish ();
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	l.lock ();
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    items.finish ();
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    l.unlock ();
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Big-endian handling */
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline uint16_t hb_be_uint16 (const uint16_t v)
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const uint8_t *V = (const uint8_t *) &v;
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (V[0] << 8) | V[1];
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline uint16_t hb_uint16_swap (const uint16_t v)
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (v >> 8) | (v << 8);
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline uint32_t hb_uint32_swap (const uint32_t v)
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (hb_uint16_swap (v) << 16) | hb_uint16_swap (v >> 16);
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Note, of the following macros, uint16_get is the one called many many times.
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * If there is any optimizations to be done, it's in that macro.  However, I
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * already confirmed that on my T400 ThinkPad at least, using bswap_16(), which
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * results in a single ror instruction, does NOT speed this up.  In fact, it
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * resulted in a minor slowdown.  At any rate, note that v may not be correctly
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * aligned, so I think the current implementation is optimal.
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define hb_be_uint16_put(v,V)	HB_STMT_START { v[0] = (V>>8); v[1] = (V); } HB_STMT_END
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define hb_be_uint16_get(v)	(uint16_t) ((v[0] << 8) + v[1])
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define hb_be_uint16_eq(a,b)	(a[0] == b[0] && a[1] == b[1])
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (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
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define hb_be_uint32_get(v)	(uint32_t) ((v[0] << 24) + (v[1] << 16) + (v[2] << 8) + v[3])
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (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])
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (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
5132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define hb_be_uint24_get(v)	(uint32_t) ((v[0] << 16) + (v[1] << 8) + v[2])
5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define hb_be_uint24_eq(a,b)	(a[0] == b[0] && a[1] == b[1] && a[2] == b[2])
5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* ASCII tag/character handling */
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline unsigned char ISALPHA (unsigned char c)
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); }
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline unsigned char ISALNUM (unsigned char c)
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'); }
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline unsigned char TOUPPER (unsigned char c)
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ return (c >= 'a' && c <= 'z') ? c - 'a' + 'A' : c; }
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline unsigned char TOLOWER (unsigned char c)
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ return (c >= 'A' && c <= 'Z') ? c - 'A' + 'a' : c; }
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define HB_TAG_CHAR4(s)   (HB_TAG(((const char *) s)[0], \
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				  ((const char *) s)[1], \
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				  ((const char *) s)[2], \
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				  ((const char *) s)[3]))
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* C++ helpers */
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Makes class uncopyable.  Use in private: section. */
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define NO_COPY(T) \
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  T (const T &o); \
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  T &operator = (const T &o)
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Debug */
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef HB_DEBUG
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define HB_DEBUG 0
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline bool
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_hb_debug (unsigned int level,
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	   unsigned int max_level)
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return level < max_level;
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define DEBUG_LEVEL(WHAT, LEVEL) (_hb_debug ((LEVEL), HB_DEBUG_##WHAT))
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define DEBUG(WHAT) (DEBUG_LEVEL (WHAT, 0))
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <int max_level> static inline void
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_hb_debug_msg_va (const char *what,
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		  const void *obj,
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		  const char *func,
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		  bool indented,
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		  unsigned int level,
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		  int level_dir,
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		  const char *message,
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		  va_list ap)
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!_hb_debug (level, max_level))
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fprintf (stderr, "%-10s", what ? what : "");
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (obj)
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fprintf (stderr, "(%0*lx) ", (unsigned int) (2 * sizeof (void *)), (unsigned long) obj);
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fprintf (stderr, " %*s  ", (unsigned int) (2 * sizeof (void *)), "");
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (indented) {
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* One may want to add ASCII version of these.  See:
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * https://bugs.freedesktop.org/show_bug.cgi?id=50970 */
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define VBAR	"\342\224\202"	/* U+2502 BOX DRAWINGS LIGHT VERTICAL */
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define VRBAR	"\342\224\234"	/* U+251C BOX DRAWINGS LIGHT VERTICAL AND RIGHT */
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define DLBAR	"\342\225\256"	/* U+256E BOX DRAWINGS LIGHT ARC DOWN AND LEFT */
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define ULBAR	"\342\225\257"	/* U+256F BOX DRAWINGS LIGHT ARC UP AND LEFT */
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define LBAR	"\342\225\264"	/* U+2574 BOX DRAWINGS LIGHT LEFT */
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (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;
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fprintf (stderr, "%2d %s" VRBAR "%s",
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	     level,
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	     bars + sizeof (bars) - 1 - MIN ((unsigned int) sizeof (bars), (unsigned int) (sizeof (VBAR) - 1) * level),
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	     level_dir ? (level_dir > 0 ? DLBAR : ULBAR) : LBAR);
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fprintf (stderr, "   " VRBAR LBAR);
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (func)
5962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
5972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    /* Skip "typename" */
5982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (0 == strncmp (func, "typename ", 9))
5992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      func += 9;
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Skip return type */
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char *space = strchr (func, ' ');
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (space)
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      func = space + 1;
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Skip parameter list */
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char *paren = strchr (func, '(');
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int func_len = paren ? paren - func : strlen (func);
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fprintf (stderr, "%.*s: ", func_len, func);
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (message)
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    vfprintf (stderr, message, ap);
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fprintf (stderr, "\n");
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <> inline void
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_hb_debug_msg_va<0> (const char *what HB_UNUSED,
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     const void *obj HB_UNUSED,
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     const char *func HB_UNUSED,
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     bool indented HB_UNUSED,
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     unsigned int level HB_UNUSED,
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     int level_dir HB_UNUSED,
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     const char *message HB_UNUSED,
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     va_list ap HB_UNUSED) {}
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <int max_level> static inline void
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_hb_debug_msg (const char *what,
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	       const void *obj,
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	       const char *func,
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	       bool indented,
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	       unsigned int level,
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	       int level_dir,
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	       const char *message,
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	       ...) HB_PRINTF_FUNC(7, 8);
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <int max_level> static inline void
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_hb_debug_msg (const char *what,
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	       const void *obj,
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	       const char *func,
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	       bool indented,
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	       unsigned int level,
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	       int level_dir,
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	       const char *message,
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	       ...)
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  va_list ap;
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  va_start (ap, message);
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  _hb_debug_msg_va<max_level> (what, obj, func, indented, level, level_dir, message, ap);
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  va_end (ap);
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <> inline void
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_hb_debug_msg<0> (const char *what HB_UNUSED,
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		  const void *obj HB_UNUSED,
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		  const char *func HB_UNUSED,
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		  bool indented HB_UNUSED,
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		  unsigned int level HB_UNUSED,
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		  int level_dir HB_UNUSED,
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		  const char *message HB_UNUSED,
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		  ...) HB_PRINTF_FUNC(7, 8);
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <> inline void
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_hb_debug_msg<0> (const char *what HB_UNUSED,
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		  const void *obj HB_UNUSED,
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		  const char *func HB_UNUSED,
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		  bool indented HB_UNUSED,
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		  unsigned int level HB_UNUSED,
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		  int level_dir HB_UNUSED,
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		  const char *message HB_UNUSED,
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		  ...) {}
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (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__)
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define DEBUG_MSG(WHAT, OBJ, ...) 				_hb_debug_msg<HB_DEBUG_##WHAT> (#WHAT, (OBJ), NULL,    false, 0, 0, __VA_ARGS__)
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define DEBUG_MSG_FUNC(WHAT, OBJ, ...)				_hb_debug_msg<HB_DEBUG_##WHAT> (#WHAT, (OBJ), HB_FUNC, false, 0, 0, __VA_ARGS__)
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
6742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Printer
6752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */
6762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)template <typename T>
6782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct hb_printer_t {};
6792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)template <>
6812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct hb_printer_t<bool> {
6822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const char *print (bool v) { return v ? "true" : "false"; }
6832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
6842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)template <>
6862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct hb_printer_t<hb_void_t> {
6872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const char *print (hb_void_t) { return ""; }
6882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
6892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/*
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Trace
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)template <typename T>
6962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static inline void _hb_warn_no_return (bool returned)
6972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
6982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (unlikely (!returned)) {
6992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    fprintf (stderr, "OUCH, returned with no call to TRACE_RETURN.  This is a bug, please report.\n");
7002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)template <>
7032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)inline void _hb_warn_no_return<hb_void_t> (bool returned HB_UNUSED)
7042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){}
7052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)template <int max_level, typename ret_t>
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct hb_auto_trace_t {
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit inline hb_auto_trace_t (unsigned int *plevel_,
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   const char *what_,
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   const void *obj_,
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   const char *func,
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   const char *message,
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   ...) : plevel (plevel_), what (what_), obj (obj_), returned (false)
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (plevel) ++*plevel;
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    va_list ap;
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    va_start (ap, message);
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    _hb_debug_msg_va<max_level> (what, obj, func, true, plevel ? *plevel : 0, +1, message, ap);
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    va_end (ap);
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline ~hb_auto_trace_t (void)
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
7242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    _hb_warn_no_return<ret_t> (returned);
7252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!returned) {
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      _hb_debug_msg<max_level> (what, obj, NULL, true, plevel ? *plevel : 1, -1, " ");
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (plevel) --*plevel;
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline ret_t ret (ret_t v, unsigned int line = 0)
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (returned)) {
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      fprintf (stderr, "OUCH, double calls to TRACE_RETURN.  This is a bug, please report.\n");
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return v;
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    _hb_debug_msg<max_level> (what, obj, NULL, true, plevel ? *plevel : 1, -1,
7392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			      "return %s (line %d)",
7402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			      hb_printer_t<ret_t>().print (v), line);
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (plevel) --*plevel;
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    plevel = NULL;
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    returned = true;
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return v;
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  private:
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int *plevel;
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char *what;
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const void *obj;
7512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool returned;
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
7532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)template <typename ret_t> /* Optimize when tracing is disabled */
7542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct hb_auto_trace_t<0, ret_t> {
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit inline hb_auto_trace_t (unsigned int *plevel_ HB_UNUSED,
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   const char *what HB_UNUSED,
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   const void *obj HB_UNUSED,
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   const char *func HB_UNUSED,
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   const char *message HB_UNUSED,
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   ...) {}
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline ret_t ret (ret_t v, unsigned int line HB_UNUSED = 0) { return v; }
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TRACE_RETURN(RET) trace.ret (RET, __LINE__)
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Misc */
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Pre-mature optimization:
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Checks for lo <= u <= hi but with an optimization if lo and hi
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * are only different in a contiguous set of lower-most bits.
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename T> static inline bool
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_in_range (T u, T lo, T hi)
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ( ((lo^hi) & lo) == 0 &&
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ((lo^hi) & hi) == (lo^hi) &&
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ((lo^hi) & ((lo^hi) + 1)) == 0 )
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return (u & ~(lo^hi)) == lo;
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return lo <= u && u <= hi;
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename T> static inline bool
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3)
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2) || hb_in_range (u, lo3, hi3);
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Useful for set-operations on small enums.
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * For example, for testing "x ∈ {x1, x2, x3}" use:
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * (FLAG(x) & (FLAG(x1) | FLAG(x2) | FLAG(x3)))
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define FLAG(x) (1<<(x))
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define FLAG_RANGE(x,y) (ASSERT_STATIC_EXPR_ZERO ((x) < (y)) + FLAG(y+1) - FLAG(x))
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename T, typename T2> inline void
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_bubble_sort (T *array, unsigned int len, int(*compar)(const T *, const T *), T2 *array2)
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (unlikely (!len))
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int k = len - 1;
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int new_k = 0;
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int j = 0; j < k; j++)
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (compar (&array[j], &array[j+1]) > 0)
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	  T t;
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	  t = array[j];
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	  array[j] = array[j + 1];
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	  array[j + 1] = t;
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (array2)
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	  T2 t;
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	  t = array2[j];
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	  array2[j] = array2[j + 1];
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	  array2[j + 1] = t;
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	new_k = j;
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    k = new_k;
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (k);
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename T> inline void
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_bubble_sort (T *array, unsigned int len, int(*compar)(const T *, const T *))
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hb_bubble_sort (array, len, compar, (int *) NULL);
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline hb_bool_t
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_codepoint_parse (const char *s, unsigned int len, int base, hb_codepoint_t *out)
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Pain because we don't know whether s is nul-terminated. */
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char buf[64];
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  strncpy (buf, s, MIN (ARRAY_LENGTH (buf) - 1, len));
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  buf[MIN (ARRAY_LENGTH (buf) - 1, len)] = '\0';
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char *end;
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  errno = 0;
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned long v = strtoul (buf, &end, base);
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (errno) return false;
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (*end) return false;
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *out = v;
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* HB_PRIVATE_HH */
858