164aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod/* 22409d5f8d7dd8b535ce5ea29e933f7db27d33793Behdad Esfahbod * Copyright © 2007,2008,2009 Red Hat, Inc. 30ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod * Copyright © 2011,2012 Google, Inc. 464aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * 5c755cb3e3ac55156d0d2ec05adea7a650b97cc41Behdad Esfahbod * This is part of HarfBuzz, a text shaping library. 664aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * 764aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * Permission is hereby granted, without written agreement and without 864aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * license or royalty fees, to use, copy, modify, and distribute this 964aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * software and its documentation for any purpose, provided that the 1064aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * above copyright notice and the following two paragraphs appear in 1164aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * all copies of this software. 1264aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * 1364aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR 1464aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 1564aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN 1664aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 1764aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * DAMAGE. 1864aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * 1964aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, 2064aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 2164aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS 2264aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO 2364aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 2464aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * 2564aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * Red Hat Author(s): Behdad Esfahbod 262409d5f8d7dd8b535ce5ea29e933f7db27d33793Behdad Esfahbod * Google Author(s): Behdad Esfahbod 2764aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod */ 2864aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod 29c57d454accff66e5f2c58006e8fb40bc020b6182Behdad Esfahbod#ifndef HB_PRIVATE_HH 30c57d454accff66e5f2c58006e8fb40bc020b6182Behdad Esfahbod#define HB_PRIVATE_HH 315b3f7702a64fe0513d08a67bdb72704e46fd7cd4Behdad Esfahbod 325ddd9cc499f2470eca239ae357a5c8a3626c0809Behdad Esfahbod#ifdef HAVE_CONFIG_H 33df66028781a7609a515980e64396e6f1044d764aBehdad Esfahbod#include "config.h" 34df66028781a7609a515980e64396e6f1044d764aBehdad Esfahbod#endif 35c7d457aa3ae7138630f52ca7263f663a3ea284c0Behdad Esfahbod 36d1c9eb458c843215da8df84b596bfae51fee135bBehdad Esfahbod#include "hb.h" 37d1c9eb458c843215da8df84b596bfae51fee135bBehdad Esfahbod#define HB_H_IN 383e32cd9570fd8b09901fb790b80365ae425f681aBehdad Esfahbod#ifdef HAVE_OT 393e32cd9570fd8b09901fb790b80365ae425f681aBehdad Esfahbod#include "hb-ot.h" 40d1c9eb458c843215da8df84b596bfae51fee135bBehdad Esfahbod#define HB_OT_H_IN 413e32cd9570fd8b09901fb790b80365ae425f681aBehdad Esfahbod#endif 42b28815c1f6e46d38471cacbc31248ca6fda8c4d1Behdad Esfahbod 43c7d457aa3ae7138630f52ca7263f663a3ea284c0Behdad Esfahbod#include <stdlib.h> 44b65c06025d2b54a44f716e030d4b10072c65bea8Behdad Esfahbod#include <stddef.h> 45f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod#include <string.h> 46f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod#include <assert.h> 471d52151a19ed8ec776276aac5cc6ce3769e0d947Behdad Esfahbod 481d52151a19ed8ec776276aac5cc6ce3769e0d947Behdad Esfahbod/* We only use these two for debug output. However, the debug code is 491d52151a19ed8ec776276aac5cc6ce3769e0d947Behdad Esfahbod * always seen by the compiler (and optimized out in non-debug builds. 501d52151a19ed8ec776276aac5cc6ce3769e0d947Behdad Esfahbod * If including these becomes a problem, we can start thinking about 511d52151a19ed8ec776276aac5cc6ce3769e0d947Behdad Esfahbod * someway around that. */ 527acb389569cf99c6bae9db31a8ed7c7007fbb566Behdad Esfahbod#include <stdio.h> 537acb389569cf99c6bae9db31a8ed7c7007fbb566Behdad Esfahbod#include <errno.h> 54cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod#include <stdarg.h> 55c7d457aa3ae7138630f52ca7263f663a3ea284c0Behdad Esfahbod 56acdba3f90b232fc12fcb200dca2584481b339118Behdad Esfahbod 57ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod/* Compiler attributes */ 58bc200457430c083914a64bf4b056153506749610Behdad Esfahbod 59bc200457430c083914a64bf4b056153506749610Behdad Esfahbod 60ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#if defined(__GNUC__) && (__GNUC__ > 2) && defined(__OPTIMIZE__) 61ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#define _HB_BOOLEAN_EXPR(expr) ((expr) ? 1 : 0) 62ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#define likely(expr) (__builtin_expect (_HB_BOOLEAN_EXPR(expr), 1)) 63ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#define unlikely(expr) (__builtin_expect (_HB_BOOLEAN_EXPR(expr), 0)) 64ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#else 65ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#define likely(expr) (expr) 66ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#define unlikely(expr) (expr) 67bc200457430c083914a64bf4b056153506749610Behdad Esfahbod#endif 68bc200457430c083914a64bf4b056153506749610Behdad Esfahbod 69ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#ifndef __GNUC__ 70ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#undef __attribute__ 71ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#define __attribute__(x) 72ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#endif 73ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod 74ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#if __GNUC__ >= 3 75ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#define HB_PURE_FUNC __attribute__((pure)) 76ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#define HB_CONST_FUNC __attribute__((const)) 77ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#define HB_PRINTF_FUNC(format_idx, arg_idx) __attribute__((__format__ (__printf__, format_idx, arg_idx))) 78ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#else 79ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#define HB_PURE_FUNC 80ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#define HB_CONST_FUNC 81ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#define HB_PRINTF_FUNC(format_idx, arg_idx) 82ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#endif 83ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#if __GNUC__ >= 4 84ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#define HB_UNUSED __attribute__((unused)) 85ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#else 86ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#define HB_UNUSED 87ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#endif 88ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod 89ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#ifndef HB_INTERNAL 90f1a8d50a87edfb8147aa1bec732ed7ccbfef2877Behdad Esfahbod# if !defined(__MINGW32__) && !defined(__CYGWIN__) 91ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod# define HB_INTERNAL __attribute__((__visibility__("hidden"))) 92ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod# else 93ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod# define HB_INTERNAL 94ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod# endif 95ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#endif 96ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod 97ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#if (defined(__WIN32__) && !defined(__WINE__)) || defined(_MSC_VER) 98ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#define snprintf _snprintf 99ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#endif 100ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod 101ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#ifdef _MSC_VER 102ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#undef inline 103ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#define inline __inline 104ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#endif 105ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod 106ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#ifdef __STRICT_ANSI__ 107ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#undef inline 108ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#define inline __inline__ 109ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#endif 110ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod 111ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#if __GNUC__ >= 3 112ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#define HB_FUNC __PRETTY_FUNCTION__ 113ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#elif defined(_MSC_VER) 114ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#define HB_FUNC __FUNCSIG__ 115ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#else 116ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#define HB_FUNC __func__ 117ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#endif 118a794ebf4be9896393f4badf02905a4007981a588Behdad Esfahbod 1190fc0a1022854324261fea8893678a3e9fd9443ebBehdad Esfahbod#if defined(_WIN32) || defined(__CYGWIN__) 120db308280488c2ee11ba865a9922eb6a0c1abeef3Behdad Esfahbod /* We need Windows Vista for both Uniscribe backend and for 121db308280488c2ee11ba865a9922eb6a0c1abeef3Behdad Esfahbod * MemoryBarrier. We don't support compiling on Windows XP, 122db308280488c2ee11ba865a9922eb6a0c1abeef3Behdad Esfahbod * though we run on it fine. */ 123db308280488c2ee11ba865a9922eb6a0c1abeef3Behdad Esfahbod# if defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0600 124db308280488c2ee11ba865a9922eb6a0c1abeef3Behdad Esfahbod# undef _WIN32_WINNT 125db308280488c2ee11ba865a9922eb6a0c1abeef3Behdad Esfahbod# endif 126db308280488c2ee11ba865a9922eb6a0c1abeef3Behdad Esfahbod# ifndef _WIN32_WINNT 127db308280488c2ee11ba865a9922eb6a0c1abeef3Behdad Esfahbod# define _WIN32_WINNT 0x0600 128db308280488c2ee11ba865a9922eb6a0c1abeef3Behdad Esfahbod# endif 129db308280488c2ee11ba865a9922eb6a0c1abeef3Behdad Esfahbod# define WIN32_LEAN_AND_MEAN 1309c77027d645142794c3ff1590a96bb151c3f2e91Behdad Esfahbod# define STRICT 131db308280488c2ee11ba865a9922eb6a0c1abeef3Behdad Esfahbod#endif 132dabe698fcbeb02911128b17aa8e3b2d864795960Behdad Esfahbod 133dabe698fcbeb02911128b17aa8e3b2d864795960Behdad Esfahbod 134c7d457aa3ae7138630f52ca7263f663a3ea284c0Behdad Esfahbod/* Basics */ 135c7d457aa3ae7138630f52ca7263f663a3ea284c0Behdad Esfahbod 136153142dac8dd9abaf164bb88af07c600c17fc3a1Behdad Esfahbod 137ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#ifndef NULL 138ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod# define NULL ((void *) 0) 139ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#endif 140ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod 141c7d457aa3ae7138630f52ca7263f663a3ea284c0Behdad Esfahbod#undef MIN 14225326c2359b0a3e25222b94acd142bc36eff78a4Behdad Esfahbodtemplate <typename Type> 14325326c2359b0a3e25222b94acd142bc36eff78a4Behdad Esfahbodstatic inline Type MIN (const Type &a, const Type &b) { return a < b ? a : b; } 1447586089c6fa8185cad8387869d3703c637e5cbb1Behdad Esfahbod 1458a3511ac6c795226699c2b36e03401ecdf88f5f8Behdad Esfahbod#undef MAX 14625326c2359b0a3e25222b94acd142bc36eff78a4Behdad Esfahbodtemplate <typename Type> 14725326c2359b0a3e25222b94acd142bc36eff78a4Behdad Esfahbodstatic inline Type MAX (const Type &a, const Type &b) { return a > b ? a : b; } 148153142dac8dd9abaf164bb88af07c600c17fc3a1Behdad Esfahbod 14916f175cb2e081e605fe7f9cd01bbe8c24380278aBehdad Esfahbodstatic inline unsigned int DIV_CEIL (const unsigned int a, unsigned int b) 15016f175cb2e081e605fe7f9cd01bbe8c24380278aBehdad Esfahbod{ return (a + (b - 1)) / b; } 15116f175cb2e081e605fe7f9cd01bbe8c24380278aBehdad Esfahbod 1528a3511ac6c795226699c2b36e03401ecdf88f5f8Behdad Esfahbod 1534591753ad4b5ec0224e3f1befdfe4fc5f6075562Behdad Esfahbod#undef ARRAY_LENGTH 15425326c2359b0a3e25222b94acd142bc36eff78a4Behdad Esfahbodtemplate <typename Type, unsigned int n> 1550beb66e3a61ae8bb1fa66e54b1ff1abb2f8711e9Behdad Esfahbodstatic inline unsigned int ARRAY_LENGTH (const Type (&)[n]) { return n; } 156fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod/* A const version, but does not detect erratically being called on pointers. */ 157fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod#define ARRAY_LENGTH_CONST(__array) ((signed int) (sizeof (__array) / sizeof (__array[0]))) 15812360f7c159826ae72271b34486dee59d96aa8caBehdad Esfahbod 15935a7383c6138fd705560f0d4bb30659cbd1ab64cBehdad Esfahbod#define HB_STMT_START do 16035a7383c6138fd705560f0d4bb30659cbd1ab64cBehdad Esfahbod#define HB_STMT_END while (0) 1615b3f7702a64fe0513d08a67bdb72704e46fd7cd4Behdad Esfahbod 162c306410cab368a27c1941a2625d3b475edeaac04Behdad Esfahbod#define _ASSERT_STATIC1(_line, _cond) HB_UNUSED typedef int _static_assert_on_line_##_line##_failed[(_cond)?1:-1] 16373cb02de2dd28b09d4aa76230132248215cfe83dBehdad Esfahbod#define _ASSERT_STATIC0(_line, _cond) _ASSERT_STATIC1 (_line, (_cond)) 16473cb02de2dd28b09d4aa76230132248215cfe83dBehdad Esfahbod#define ASSERT_STATIC(_cond) _ASSERT_STATIC0 (__LINE__, (_cond)) 165303fe62824d4e99df554b6bfaacba05d068522fbBehdad Esfahbod 16679e2b4791fe95ede9a1e6b1c71ccc6e36c4fc0e5Behdad Esfahbod#define ASSERT_STATIC_EXPR(_cond)((void) sizeof (char[(_cond) ? 1 : -1])) 1674ec30aec3014be6effc09cbbc88dcd075f3826dfBehdad Esfahbod#define ASSERT_STATIC_EXPR_ZERO(_cond) (0 * sizeof (char[(_cond) ? 1 : -1])) 168dcb7026f33cbcdf60e9b7fcdd44c64cc08702c74Behdad Esfahbod 1694be46bade26faf13f7b4d447e9cc608e183955dcBehdad Esfahbod#define _PASTE1(a,b) a##b 1704be46bade26faf13f7b4d447e9cc608e183955dcBehdad Esfahbod#define PASTE(a,b) _PASTE1(a,b) 171bc200457430c083914a64bf4b056153506749610Behdad Esfahbod 1726fd5364bdc3a2b459175377e9e16c86cff054232Behdad Esfahbod/* Lets assert int types. Saves trouble down the road. */ 1736fd5364bdc3a2b459175377e9e16c86cff054232Behdad Esfahbod 1746fd5364bdc3a2b459175377e9e16c86cff054232Behdad EsfahbodASSERT_STATIC (sizeof (int8_t) == 1); 1756fd5364bdc3a2b459175377e9e16c86cff054232Behdad EsfahbodASSERT_STATIC (sizeof (uint8_t) == 1); 1766fd5364bdc3a2b459175377e9e16c86cff054232Behdad EsfahbodASSERT_STATIC (sizeof (int16_t) == 2); 1776fd5364bdc3a2b459175377e9e16c86cff054232Behdad EsfahbodASSERT_STATIC (sizeof (uint16_t) == 2); 1786fd5364bdc3a2b459175377e9e16c86cff054232Behdad EsfahbodASSERT_STATIC (sizeof (int32_t) == 4); 1796fd5364bdc3a2b459175377e9e16c86cff054232Behdad EsfahbodASSERT_STATIC (sizeof (uint32_t) == 4); 1806fd5364bdc3a2b459175377e9e16c86cff054232Behdad EsfahbodASSERT_STATIC (sizeof (int64_t) == 8); 1816fd5364bdc3a2b459175377e9e16c86cff054232Behdad EsfahbodASSERT_STATIC (sizeof (uint64_t) == 8); 1826fd5364bdc3a2b459175377e9e16c86cff054232Behdad Esfahbod 183b13640de6992de9ee9d07e3581c33b8181b70ff9Behdad EsfahbodASSERT_STATIC (sizeof (hb_codepoint_t) == 4); 184b13640de6992de9ee9d07e3581c33b8181b70ff9Behdad EsfahbodASSERT_STATIC (sizeof (hb_position_t) == 4); 185b13640de6992de9ee9d07e3581c33b8181b70ff9Behdad EsfahbodASSERT_STATIC (sizeof (hb_mask_t) == 4); 186ae9eeaff9300f3bb7bed588c5478e8e5461b3df0Behdad EsfahbodASSERT_STATIC (sizeof (hb_var_int_t) == 4); 1876fd5364bdc3a2b459175377e9e16c86cff054232Behdad Esfahbod 188a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod 189a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod/* We like our types POD */ 190a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod 19173cb02de2dd28b09d4aa76230132248215cfe83dBehdad Esfahbod#define _ASSERT_TYPE_POD1(_line, _type) union _type_##_type##_on_line_##_line##_is_not_POD { _type instance; } 19273cb02de2dd28b09d4aa76230132248215cfe83dBehdad Esfahbod#define _ASSERT_TYPE_POD0(_line, _type) _ASSERT_TYPE_POD1 (_line, _type) 19373cb02de2dd28b09d4aa76230132248215cfe83dBehdad Esfahbod#define ASSERT_TYPE_POD(_type) _ASSERT_TYPE_POD0 (__LINE__, _type) 194a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod 195a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod#ifdef __GNUC__ 19679e2b4791fe95ede9a1e6b1c71ccc6e36c4fc0e5Behdad Esfahbod# define _ASSERT_INSTANCE_POD1(_line, _instance) \ 19779e2b4791fe95ede9a1e6b1c71ccc6e36c4fc0e5Behdad Esfahbod HB_STMT_START { \ 19879e2b4791fe95ede9a1e6b1c71ccc6e36c4fc0e5Behdad Esfahbod typedef __typeof__(_instance) _type_##_line; \ 19979e2b4791fe95ede9a1e6b1c71ccc6e36c4fc0e5Behdad Esfahbod _ASSERT_TYPE_POD1 (_line, _type_##_line); \ 20079e2b4791fe95ede9a1e6b1c71ccc6e36c4fc0e5Behdad Esfahbod } HB_STMT_END 201a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod#else 20273cb02de2dd28b09d4aa76230132248215cfe83dBehdad Esfahbod# define _ASSERT_INSTANCE_POD1(_line, _instance) typedef int _assertion_on_line_##_line##_not_tested 203a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod#endif 20473cb02de2dd28b09d4aa76230132248215cfe83dBehdad Esfahbod# define _ASSERT_INSTANCE_POD0(_line, _instance) _ASSERT_INSTANCE_POD1 (_line, _instance) 20573cb02de2dd28b09d4aa76230132248215cfe83dBehdad Esfahbod# define ASSERT_INSTANCE_POD(_instance) _ASSERT_INSTANCE_POD0 (__LINE__, _instance) 206a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod 207a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod/* Check _assertion in a method environment */ 208a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod#define _ASSERT_POD1(_line) \ 209dac86026a6bae5a8a03cfe885bf93f32e5f48614Behdad Esfahbod HB_UNUSED inline void _static_assertion_on_line_##_line (void) const \ 21073cb02de2dd28b09d4aa76230132248215cfe83dBehdad Esfahbod { _ASSERT_INSTANCE_POD1 (_line, *this); /* Make sure it's POD. */ } 21173cb02de2dd28b09d4aa76230132248215cfe83dBehdad Esfahbod# define _ASSERT_POD0(_line) _ASSERT_POD1 (_line) 21273cb02de2dd28b09d4aa76230132248215cfe83dBehdad Esfahbod# define ASSERT_POD() _ASSERT_POD0 (__LINE__) 213a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod 214a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod 215a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod 216bc200457430c083914a64bf4b056153506749610Behdad Esfahbod/* Misc */ 217bc200457430c083914a64bf4b056153506749610Behdad Esfahbod 218ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod/* Void! */ 219ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbodstruct _hb_void_t {}; 220ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbodtypedef const _hb_void_t &hb_void_t; 221ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#define HB_VOID (* (const _hb_void_t *) NULL) 2227d3a126334f8e6f6441561c1bb592bd3fa7a2c5cBehdad Esfahbod 2239b6023338530a2dbb8214eb4391ef3e8372f3892Behdad Esfahbod/* Return the number of 1 bits in mask. */ 22497e7f8f305c47caf2968a9da3b8407825547286dBehdad Esfahbodstatic inline HB_CONST_FUNC unsigned int 225c7d457aa3ae7138630f52ca7263f663a3ea284c0Behdad Esfahbod_hb_popcount32 (uint32_t mask) 226c7d457aa3ae7138630f52ca7263f663a3ea284c0Behdad Esfahbod{ 227c7d457aa3ae7138630f52ca7263f663a3ea284c0Behdad Esfahbod#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) 2289b6023338530a2dbb8214eb4391ef3e8372f3892Behdad Esfahbod return __builtin_popcount (mask); 229c7d457aa3ae7138630f52ca7263f663a3ea284c0Behdad Esfahbod#else 2309b6023338530a2dbb8214eb4391ef3e8372f3892Behdad Esfahbod /* "HACKMEM 169" */ 231a949cd329e49d2c0ad6f1e023f324790d886dafeBehdad Esfahbod uint32_t y; 2329b6023338530a2dbb8214eb4391ef3e8372f3892Behdad Esfahbod y = (mask >> 1) &033333333333; 2339b6023338530a2dbb8214eb4391ef3e8372f3892Behdad Esfahbod y = mask - y - ((y >>1) & 033333333333); 2349b6023338530a2dbb8214eb4391ef3e8372f3892Behdad Esfahbod return (((y + (y >> 3)) & 030707070707) % 077); 235c7d457aa3ae7138630f52ca7263f663a3ea284c0Behdad Esfahbod#endif 236c7d457aa3ae7138630f52ca7263f663a3ea284c0Behdad Esfahbod} 237c7d457aa3ae7138630f52ca7263f663a3ea284c0Behdad Esfahbod 2389b6023338530a2dbb8214eb4391ef3e8372f3892Behdad Esfahbod/* Returns the number of bits needed to store number */ 2399b6023338530a2dbb8214eb4391ef3e8372f3892Behdad Esfahbodstatic inline HB_CONST_FUNC unsigned int 2409b6023338530a2dbb8214eb4391ef3e8372f3892Behdad Esfahbod_hb_bit_storage (unsigned int number) 2419b6023338530a2dbb8214eb4391ef3e8372f3892Behdad Esfahbod{ 2429b6023338530a2dbb8214eb4391ef3e8372f3892Behdad Esfahbod#if defined(__GNUC__) && (__GNUC__ >= 4) && defined(__OPTIMIZE__) 243f7acd8df5146155b51d6f50aeb04f54f3030c1c3Behdad Esfahbod return likely (number) ? (sizeof (unsigned int) * 8 - __builtin_clz (number)) : 0; 2449b6023338530a2dbb8214eb4391ef3e8372f3892Behdad Esfahbod#else 245a949cd329e49d2c0ad6f1e023f324790d886dafeBehdad Esfahbod unsigned int n_bits = 0; 2469b6023338530a2dbb8214eb4391ef3e8372f3892Behdad Esfahbod while (number) { 2479b6023338530a2dbb8214eb4391ef3e8372f3892Behdad Esfahbod n_bits++; 2489b6023338530a2dbb8214eb4391ef3e8372f3892Behdad Esfahbod number >>= 1; 2499b6023338530a2dbb8214eb4391ef3e8372f3892Behdad Esfahbod } 2509b6023338530a2dbb8214eb4391ef3e8372f3892Behdad Esfahbod return n_bits; 2519b6023338530a2dbb8214eb4391ef3e8372f3892Behdad Esfahbod#endif 2529b6023338530a2dbb8214eb4391ef3e8372f3892Behdad Esfahbod} 253df66028781a7609a515980e64396e6f1044d764aBehdad Esfahbod 254f7acd8df5146155b51d6f50aeb04f54f3030c1c3Behdad Esfahbod/* Returns the number of zero bits in the least significant side of number */ 255f7acd8df5146155b51d6f50aeb04f54f3030c1c3Behdad Esfahbodstatic inline HB_CONST_FUNC unsigned int 256f7acd8df5146155b51d6f50aeb04f54f3030c1c3Behdad Esfahbod_hb_ctz (unsigned int number) 257f7acd8df5146155b51d6f50aeb04f54f3030c1c3Behdad Esfahbod{ 258f7acd8df5146155b51d6f50aeb04f54f3030c1c3Behdad Esfahbod#if defined(__GNUC__) && (__GNUC__ >= 4) && defined(__OPTIMIZE__) 259f7acd8df5146155b51d6f50aeb04f54f3030c1c3Behdad Esfahbod return likely (number) ? __builtin_ctz (number) : 0; 260f7acd8df5146155b51d6f50aeb04f54f3030c1c3Behdad Esfahbod#else 261a949cd329e49d2c0ad6f1e023f324790d886dafeBehdad Esfahbod unsigned int n_bits = 0; 262f7acd8df5146155b51d6f50aeb04f54f3030c1c3Behdad Esfahbod if (unlikely (!number)) return 0; 263f7acd8df5146155b51d6f50aeb04f54f3030c1c3Behdad Esfahbod while (!(number & 1)) { 264f7acd8df5146155b51d6f50aeb04f54f3030c1c3Behdad Esfahbod n_bits++; 265f7acd8df5146155b51d6f50aeb04f54f3030c1c3Behdad Esfahbod number >>= 1; 266f7acd8df5146155b51d6f50aeb04f54f3030c1c3Behdad Esfahbod } 267f7acd8df5146155b51d6f50aeb04f54f3030c1c3Behdad Esfahbod return n_bits; 268f7acd8df5146155b51d6f50aeb04f54f3030c1c3Behdad Esfahbod#endif 269f7acd8df5146155b51d6f50aeb04f54f3030c1c3Behdad Esfahbod} 270f7acd8df5146155b51d6f50aeb04f54f3030c1c3Behdad Esfahbod 271080a0eb7d82d7195be72c16ece6e0a3ffed636b6Behdad Esfahbodstatic inline bool 272080a0eb7d82d7195be72c16ece6e0a3ffed636b6Behdad Esfahbod_hb_unsigned_int_mul_overflows (unsigned int count, unsigned int size) 273080a0eb7d82d7195be72c16ece6e0a3ffed636b6Behdad Esfahbod{ 274080a0eb7d82d7195be72c16ece6e0a3ffed636b6Behdad Esfahbod return (size > 0) && (count >= ((unsigned int) -1) / size); 275080a0eb7d82d7195be72c16ece6e0a3ffed636b6Behdad Esfahbod} 276080a0eb7d82d7195be72c16ece6e0a3ffed636b6Behdad Esfahbod 277080a0eb7d82d7195be72c16ece6e0a3ffed636b6Behdad Esfahbod 2788f08c3275040870a645ef034a38d30c05c619f21Behdad Esfahbod/* Type of bsearch() / qsort() compare function */ 2798f08c3275040870a645ef034a38d30c05c619f21Behdad Esfahbodtypedef int (*hb_compare_func_t) (const void *, const void *); 2808f08c3275040870a645ef034a38d30c05c619f21Behdad Esfahbod 2818f08c3275040870a645ef034a38d30c05c619f21Behdad Esfahbod 282852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod 283852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod 284852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod/* arrays and maps */ 285852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod 286852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod 2877e8c38954649c0bf2e6051d84ca08dce090ec169Behdad Esfahbod#define HB_PREALLOCED_ARRAY_INIT {0, 0, NULL} 288546b1adcdce2d3592843938b0b81ff32e67b0b83Behdad Esfahbodtemplate <typename Type, unsigned int StaticSize=16> 2890e253e97af71e2a7ead153589f61fd579a247502Behdad Esfahbodstruct hb_prealloced_array_t 2900e253e97af71e2a7ead153589f61fd579a247502Behdad Esfahbod{ 291852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod unsigned int len; 292852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod unsigned int allocated; 293852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod Type *array; 294852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod Type static_array[StaticSize]; 295852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod 296bf93b636c4963cbc32d5fba7ace1053db6719192Behdad Esfahbod void init (void) { memset (this, 0, sizeof (*this)); } 297efde8113258b117ec0a7fbffe6d681442d045c41Behdad Esfahbod 298265ac614ea6d26041c7d64739098b76a82bbc4f4Behdad Esfahbod inline Type& operator [] (unsigned int i) { return array[i]; } 299265ac614ea6d26041c7d64739098b76a82bbc4f4Behdad Esfahbod inline const Type& operator [] (unsigned int i) const { return array[i]; } 300852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod 301852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod inline Type *push (void) 302852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod { 303852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod if (!array) { 304852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod array = static_array; 305852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod allocated = ARRAY_LENGTH (static_array); 306852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod } 307852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod if (likely (len < allocated)) 308852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod return &array[len++]; 3095a5030366e40baa8d96ca67b47a52ad5af143157Behdad Esfahbod 310852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod /* Need to reallocate */ 311852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod unsigned int new_allocated = allocated + (allocated >> 1) + 8; 3125a5030366e40baa8d96ca67b47a52ad5af143157Behdad Esfahbod Type *new_array = NULL; 3135a5030366e40baa8d96ca67b47a52ad5af143157Behdad Esfahbod 314852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod if (array == static_array) { 315852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod new_array = (Type *) calloc (new_allocated, sizeof (Type)); 3165a5030366e40baa8d96ca67b47a52ad5af143157Behdad Esfahbod if (new_array) 317852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod memcpy (new_array, array, len * sizeof (Type)); 318852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod } else { 319080a0eb7d82d7195be72c16ece6e0a3ffed636b6Behdad Esfahbod bool overflows = (new_allocated < allocated) || _hb_unsigned_int_mul_overflows (new_allocated, sizeof (Type)); 3205a5030366e40baa8d96ca67b47a52ad5af143157Behdad Esfahbod if (likely (!overflows)) { 321852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod new_array = (Type *) realloc (array, new_allocated * sizeof (Type)); 322852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod } 323852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod } 3245a5030366e40baa8d96ca67b47a52ad5af143157Behdad Esfahbod 3255a5030366e40baa8d96ca67b47a52ad5af143157Behdad Esfahbod if (unlikely (!new_array)) 326852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod return NULL; 3275a5030366e40baa8d96ca67b47a52ad5af143157Behdad Esfahbod 3285a5030366e40baa8d96ca67b47a52ad5af143157Behdad Esfahbod array = new_array; 3295a5030366e40baa8d96ca67b47a52ad5af143157Behdad Esfahbod allocated = new_allocated; 3305a5030366e40baa8d96ca67b47a52ad5af143157Behdad Esfahbod return &array[len++]; 331852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod } 332852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod 333852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod inline void pop (void) 334852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod { 335852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod len--; 336639afdc690c681a302080239a1967ce735ba5be5Behdad Esfahbod } 337639afdc690c681a302080239a1967ce735ba5be5Behdad Esfahbod 338639afdc690c681a302080239a1967ce735ba5be5Behdad Esfahbod inline void remove (unsigned int i) 339639afdc690c681a302080239a1967ce735ba5be5Behdad Esfahbod { 340639afdc690c681a302080239a1967ce735ba5be5Behdad Esfahbod if (unlikely (i >= len)) 341639afdc690c681a302080239a1967ce735ba5be5Behdad Esfahbod return; 342639afdc690c681a302080239a1967ce735ba5be5Behdad Esfahbod memmove (static_cast<void *> (&array[i]), 343639afdc690c681a302080239a1967ce735ba5be5Behdad Esfahbod static_cast<void *> (&array[i + 1]), 344639afdc690c681a302080239a1967ce735ba5be5Behdad Esfahbod (len - i - 1) * sizeof (Type)); 345639afdc690c681a302080239a1967ce735ba5be5Behdad Esfahbod len--; 346852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod } 34744b0a4d2fc62689fc56ef57f412b4bb1e439a614Behdad Esfahbod 34844b0a4d2fc62689fc56ef57f412b4bb1e439a614Behdad Esfahbod inline void shrink (unsigned int l) 34944b0a4d2fc62689fc56ef57f412b4bb1e439a614Behdad Esfahbod { 35044b0a4d2fc62689fc56ef57f412b4bb1e439a614Behdad Esfahbod if (l < len) 35144b0a4d2fc62689fc56ef57f412b4bb1e439a614Behdad Esfahbod len = l; 35244b0a4d2fc62689fc56ef57f412b4bb1e439a614Behdad Esfahbod } 35344b0a4d2fc62689fc56ef57f412b4bb1e439a614Behdad Esfahbod 3546843569d2c70c1771ce964e3d1a4cf91e14e7687Behdad Esfahbod template <typename T> 3556843569d2c70c1771ce964e3d1a4cf91e14e7687Behdad Esfahbod inline Type *find (T v) { 3566843569d2c70c1771ce964e3d1a4cf91e14e7687Behdad Esfahbod for (unsigned int i = 0; i < len; i++) 3576843569d2c70c1771ce964e3d1a4cf91e14e7687Behdad Esfahbod if (array[i] == v) 3586843569d2c70c1771ce964e3d1a4cf91e14e7687Behdad Esfahbod return &array[i]; 3596843569d2c70c1771ce964e3d1a4cf91e14e7687Behdad Esfahbod return NULL; 3606843569d2c70c1771ce964e3d1a4cf91e14e7687Behdad Esfahbod } 3616843569d2c70c1771ce964e3d1a4cf91e14e7687Behdad Esfahbod template <typename T> 3626843569d2c70c1771ce964e3d1a4cf91e14e7687Behdad Esfahbod inline const Type *find (T v) const { 3636843569d2c70c1771ce964e3d1a4cf91e14e7687Behdad Esfahbod for (unsigned int i = 0; i < len; i++) 3646843569d2c70c1771ce964e3d1a4cf91e14e7687Behdad Esfahbod if (array[i] == v) 3656843569d2c70c1771ce964e3d1a4cf91e14e7687Behdad Esfahbod return &array[i]; 3666843569d2c70c1771ce964e3d1a4cf91e14e7687Behdad Esfahbod return NULL; 3676843569d2c70c1771ce964e3d1a4cf91e14e7687Behdad Esfahbod } 3686843569d2c70c1771ce964e3d1a4cf91e14e7687Behdad Esfahbod 369fb8cc86ff99c08064ac58a559bb66cc340693b92Behdad Esfahbod inline void qsort (void) 37044b0a4d2fc62689fc56ef57f412b4bb1e439a614Behdad Esfahbod { 371fb8cc86ff99c08064ac58a559bb66cc340693b92Behdad Esfahbod ::qsort (array, len, sizeof (Type), (hb_compare_func_t) Type::cmp); 37244b0a4d2fc62689fc56ef57f412b4bb1e439a614Behdad Esfahbod } 3736843569d2c70c1771ce964e3d1a4cf91e14e7687Behdad Esfahbod 374fb8cc86ff99c08064ac58a559bb66cc340693b92Behdad Esfahbod inline void qsort (unsigned int start, unsigned int end) 375b70c96dbe41d6512b80fe3d966a1942e1ef64a4bBehdad Esfahbod { 376fb8cc86ff99c08064ac58a559bb66cc340693b92Behdad Esfahbod ::qsort (array + start, end - start, sizeof (Type), (hb_compare_func_t) Type::cmp); 377b70c96dbe41d6512b80fe3d966a1942e1ef64a4bBehdad Esfahbod } 378b70c96dbe41d6512b80fe3d966a1942e1ef64a4bBehdad Esfahbod 3796843569d2c70c1771ce964e3d1a4cf91e14e7687Behdad Esfahbod template <typename T> 3806843569d2c70c1771ce964e3d1a4cf91e14e7687Behdad Esfahbod inline Type *bsearch (T *key) 3816843569d2c70c1771ce964e3d1a4cf91e14e7687Behdad Esfahbod { 3826843569d2c70c1771ce964e3d1a4cf91e14e7687Behdad Esfahbod return (Type *) ::bsearch (key, array, len, sizeof (Type), (hb_compare_func_t) Type::cmp); 3836843569d2c70c1771ce964e3d1a4cf91e14e7687Behdad Esfahbod } 3846843569d2c70c1771ce964e3d1a4cf91e14e7687Behdad Esfahbod template <typename T> 3856843569d2c70c1771ce964e3d1a4cf91e14e7687Behdad Esfahbod inline const Type *bsearch (T *key) const 3866843569d2c70c1771ce964e3d1a4cf91e14e7687Behdad Esfahbod { 3876843569d2c70c1771ce964e3d1a4cf91e14e7687Behdad Esfahbod return (const Type *) ::bsearch (key, array, len, sizeof (Type), (hb_compare_func_t) Type::cmp); 3886843569d2c70c1771ce964e3d1a4cf91e14e7687Behdad Esfahbod } 3896a7ac79e26e85f6781186cf708a12825c0857324Behdad Esfahbod 3906a7ac79e26e85f6781186cf708a12825c0857324Behdad Esfahbod inline void finish (void) 3916a7ac79e26e85f6781186cf708a12825c0857324Behdad Esfahbod { 3926a7ac79e26e85f6781186cf708a12825c0857324Behdad Esfahbod if (array != static_array) 3936a7ac79e26e85f6781186cf708a12825c0857324Behdad Esfahbod free (array); 3946a7ac79e26e85f6781186cf708a12825c0857324Behdad Esfahbod array = NULL; 3956a7ac79e26e85f6781186cf708a12825c0857324Behdad Esfahbod allocated = len = 0; 3966a7ac79e26e85f6781186cf708a12825c0857324Behdad Esfahbod } 397852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod}; 398852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod 399c5d91f39802078fc6f6de71940739ec4d04eca07Behdad Esfahbodtemplate <typename Type> 400546b1adcdce2d3592843938b0b81ff32e67b0b83Behdad Esfahbodstruct hb_auto_array_t : hb_prealloced_array_t <Type> 401c5d91f39802078fc6f6de71940739ec4d04eca07Behdad Esfahbod{ 402546b1adcdce2d3592843938b0b81ff32e67b0b83Behdad Esfahbod hb_auto_array_t (void) { hb_prealloced_array_t<Type>::init (); } 403546b1adcdce2d3592843938b0b81ff32e67b0b83Behdad Esfahbod ~hb_auto_array_t (void) { hb_prealloced_array_t<Type>::finish (); } 404c5d91f39802078fc6f6de71940739ec4d04eca07Behdad Esfahbod}; 405c5d91f39802078fc6f6de71940739ec4d04eca07Behdad Esfahbod 406a9f24c802956d57180d71b83e96a0fb81197df4aBehdad Esfahbod 4070e253e97af71e2a7ead153589f61fd579a247502Behdad Esfahbod#define HB_LOCKABLE_SET_INIT {HB_PREALLOCED_ARRAY_INIT} 40845bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbodtemplate <typename item_t, typename lock_t> 40945bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbodstruct hb_lockable_set_t 410852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod{ 4110e253e97af71e2a7ead153589f61fd579a247502Behdad Esfahbod hb_prealloced_array_t <item_t, 2> items; 412852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod 413bf93b636c4963cbc32d5fba7ace1053db6719192Behdad Esfahbod inline void init (void) { items.init (); } 414bf93b636c4963cbc32d5fba7ace1053db6719192Behdad Esfahbod 415478a42536ff7ab777a7774fbfdb9c5e51334a14eBehdad Esfahbod template <typename T> 41633ccc77902660ed4b49184e5ec99f4fd0ef63175Behdad Esfahbod inline item_t *replace_or_insert (T v, lock_t &l, bool replace) 417852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod { 41845bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod l.lock (); 4196843569d2c70c1771ce964e3d1a4cf91e14e7687Behdad Esfahbod item_t *item = items.find (v); 42045bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod if (item) { 42133ccc77902660ed4b49184e5ec99f4fd0ef63175Behdad Esfahbod if (replace) { 42233ccc77902660ed4b49184e5ec99f4fd0ef63175Behdad Esfahbod item_t old = *item; 42333ccc77902660ed4b49184e5ec99f4fd0ef63175Behdad Esfahbod *item = v; 42433ccc77902660ed4b49184e5ec99f4fd0ef63175Behdad Esfahbod l.unlock (); 42533ccc77902660ed4b49184e5ec99f4fd0ef63175Behdad Esfahbod old.finish (); 42633ccc77902660ed4b49184e5ec99f4fd0ef63175Behdad Esfahbod } 42733ccc77902660ed4b49184e5ec99f4fd0ef63175Behdad Esfahbod else { 42833ccc77902660ed4b49184e5ec99f4fd0ef63175Behdad Esfahbod item = NULL; 42933ccc77902660ed4b49184e5ec99f4fd0ef63175Behdad Esfahbod l.unlock (); 43033ccc77902660ed4b49184e5ec99f4fd0ef63175Behdad Esfahbod } 43145bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod } else { 432852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod item = items.push (); 43345bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod if (likely (item)) 43445bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod *item = v; 43545bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod l.unlock (); 43645bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod } 437b45f32ee4e599c515ce93e44315283d236b073bbBehdad Esfahbod return item; 438852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod } 439852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod 440811482bd650fb5652a9835471ae8ecf0fb185611Behdad Esfahbod template <typename T> 44145bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod inline void remove (T v, lock_t &l) 442852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod { 44345bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod l.lock (); 4446843569d2c70c1771ce964e3d1a4cf91e14e7687Behdad Esfahbod item_t *item = items.find (v); 44545bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod if (item) { 44645bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod item_t old = *item; 44745bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod *item = items[items.len - 1]; 44845bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod items.pop (); 44945bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod l.unlock (); 45045bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod old.finish (); 45145bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod } else { 45245bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod l.unlock (); 45345bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod } 454852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod } 455a9f24c802956d57180d71b83e96a0fb81197df4aBehdad Esfahbod 456478a42536ff7ab777a7774fbfdb9c5e51334a14eBehdad Esfahbod template <typename T> 45745bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod inline bool find (T v, item_t *i, lock_t &l) 458852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod { 45945bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod l.lock (); 46045bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod item_t *item = items.find (v); 46145bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod if (item) 46245bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod *i = *item; 46345bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod l.unlock (); 46445bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod return !!item; 465811482bd650fb5652a9835471ae8ecf0fb185611Behdad Esfahbod } 466811482bd650fb5652a9835471ae8ecf0fb185611Behdad Esfahbod 467b45f32ee4e599c515ce93e44315283d236b073bbBehdad Esfahbod template <typename T> 46845bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod inline item_t *find_or_insert (T v, lock_t &l) 46945bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod { 47045bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod l.lock (); 47145bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod item_t *item = items.find (v); 472b45f32ee4e599c515ce93e44315283d236b073bbBehdad Esfahbod if (!item) { 473b45f32ee4e599c515ce93e44315283d236b073bbBehdad Esfahbod item = items.push (); 474b45f32ee4e599c515ce93e44315283d236b073bbBehdad Esfahbod if (likely (item)) 475b45f32ee4e599c515ce93e44315283d236b073bbBehdad Esfahbod *item = v; 476b45f32ee4e599c515ce93e44315283d236b073bbBehdad Esfahbod } 47745bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod l.unlock (); 478b45f32ee4e599c515ce93e44315283d236b073bbBehdad Esfahbod return item; 479b45f32ee4e599c515ce93e44315283d236b073bbBehdad Esfahbod } 480b45f32ee4e599c515ce93e44315283d236b073bbBehdad Esfahbod 48145bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod inline void finish (lock_t &l) 48245bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod { 4833f4764bb56bb7e42ba8859f1905810bd2f998838Behdad Esfahbod if (!items.len) { 4843f4764bb56bb7e42ba8859f1905810bd2f998838Behdad Esfahbod /* No need for locking. */ 4853f4764bb56bb7e42ba8859f1905810bd2f998838Behdad Esfahbod items.finish (); 4863f4764bb56bb7e42ba8859f1905810bd2f998838Behdad Esfahbod return; 4873f4764bb56bb7e42ba8859f1905810bd2f998838Behdad Esfahbod } 48845bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod l.lock (); 48945bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod while (items.len) { 49045bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod item_t old = items[items.len - 1]; 49145bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod items.pop (); 49245bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod l.unlock (); 49345bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod old.finish (); 49445bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod l.lock (); 49545bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod } 4966a7ac79e26e85f6781186cf708a12825c0857324Behdad Esfahbod items.finish (); 49745bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod l.unlock (); 49845bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod } 49945bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod 50045bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod}; 50145bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod 502852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod 503a9f24c802956d57180d71b83e96a0fb81197df4aBehdad Esfahbod 504a9f24c802956d57180d71b83e96a0fb81197df4aBehdad Esfahbod 505f60f2166c48d07f556ff83f04e95181946eb03dfBehdad Esfahbod/* Big-endian handling */ 506f60f2166c48d07f556ff83f04e95181946eb03dfBehdad Esfahbod 507153142dac8dd9abaf164bb88af07c600c17fc3a1Behdad Esfahbodstatic inline uint16_t hb_be_uint16 (const uint16_t v) 508153142dac8dd9abaf164bb88af07c600c17fc3a1Behdad Esfahbod{ 509153142dac8dd9abaf164bb88af07c600c17fc3a1Behdad Esfahbod const uint8_t *V = (const uint8_t *) &v; 510fcd6f5326166e993b8f5222efbaffe916da98f0aBehdad Esfahbod return (V[0] << 8) | V[1]; 511fcd6f5326166e993b8f5222efbaffe916da98f0aBehdad Esfahbod} 512fcd6f5326166e993b8f5222efbaffe916da98f0aBehdad Esfahbod 513fcd6f5326166e993b8f5222efbaffe916da98f0aBehdad Esfahbodstatic inline uint16_t hb_uint16_swap (const uint16_t v) 514fcd6f5326166e993b8f5222efbaffe916da98f0aBehdad Esfahbod{ 515fcd6f5326166e993b8f5222efbaffe916da98f0aBehdad Esfahbod return (v >> 8) | (v << 8); 516fcd6f5326166e993b8f5222efbaffe916da98f0aBehdad Esfahbod} 517fcd6f5326166e993b8f5222efbaffe916da98f0aBehdad Esfahbod 518fcd6f5326166e993b8f5222efbaffe916da98f0aBehdad Esfahbodstatic inline uint32_t hb_uint32_swap (const uint32_t v) 519fcd6f5326166e993b8f5222efbaffe916da98f0aBehdad Esfahbod{ 520fcd6f5326166e993b8f5222efbaffe916da98f0aBehdad Esfahbod return (hb_uint16_swap (v) << 16) | hb_uint16_swap (v >> 16); 521153142dac8dd9abaf164bb88af07c600c17fc3a1Behdad Esfahbod} 5227a52f281178867379adb6e6c6fb0022102f75d17Behdad Esfahbod 523e74616b8898b5f18d9bf82b9e81aefad056c1e36Behdad Esfahbod/* Note, of the following macros, uint16_get is the one called many many times. 524e74616b8898b5f18d9bf82b9e81aefad056c1e36Behdad Esfahbod * If there is any optimizations to be done, it's in that macro. However, I 525e74616b8898b5f18d9bf82b9e81aefad056c1e36Behdad Esfahbod * already confirmed that on my T400 ThinkPad at least, using bswap_16(), which 526e74616b8898b5f18d9bf82b9e81aefad056c1e36Behdad Esfahbod * results in a single ror instruction, does NOT speed this up. In fact, it 527e74616b8898b5f18d9bf82b9e81aefad056c1e36Behdad Esfahbod * resulted in a minor slowdown. At any rate, note that v may not be correctly 528e74616b8898b5f18d9bf82b9e81aefad056c1e36Behdad Esfahbod * aligned, so I think the current implementation is optimal. 529e74616b8898b5f18d9bf82b9e81aefad056c1e36Behdad Esfahbod */ 530e74616b8898b5f18d9bf82b9e81aefad056c1e36Behdad Esfahbod 531e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod#define hb_be_uint16_put(v,V) HB_STMT_START { v[0] = (V>>8); v[1] = (V); } HB_STMT_END 5327a52f281178867379adb6e6c6fb0022102f75d17Behdad Esfahbod#define hb_be_uint16_get(v) (uint16_t) ((v[0] << 8) + v[1]) 533153142dac8dd9abaf164bb88af07c600c17fc3a1Behdad Esfahbod#define hb_be_uint16_eq(a,b) (a[0] == b[0] && a[1] == b[1]) 5347a52f281178867379adb6e6c6fb0022102f75d17Behdad Esfahbod 535e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod#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 5367a52f281178867379adb6e6c6fb0022102f75d17Behdad Esfahbod#define hb_be_uint32_get(v) (uint32_t) ((v[0] << 24) + (v[1] << 16) + (v[2] << 8) + v[3]) 537153142dac8dd9abaf164bb88af07c600c17fc3a1Behdad Esfahbod#define hb_be_uint32_eq(a,b) (a[0] == b[0] && a[1] == b[1] && a[2] == b[2] && a[3] == b[3]) 538f60f2166c48d07f556ff83f04e95181946eb03dfBehdad Esfahbod 5392b712bba3f7c459653737dfa2f7d26f17f3b9f64Behdad Esfahbod#define hb_be_uint24_put(v,V) HB_STMT_START { v[0] = (V>>16); v[1] = (V>>8); v[2] = (V); } HB_STMT_END 540bd61bc13ea8ff350ada5449b2cfeb612e66ecafaBehdad Esfahbod#define hb_be_uint24_get(v) (uint32_t) ((v[0] << 16) + (v[1] << 8) + v[2]) 541bd61bc13ea8ff350ada5449b2cfeb612e66ecafaBehdad Esfahbod#define hb_be_uint24_eq(a,b) (a[0] == b[0] && a[1] == b[1] && a[2] == b[2]) 542bd61bc13ea8ff350ada5449b2cfeb612e66ecafaBehdad Esfahbod 543f60f2166c48d07f556ff83f04e95181946eb03dfBehdad Esfahbod 5444188096a7722f09ffa9319986c0286071da10a27Behdad Esfahbod/* ASCII tag/character handling */ 545db5227c40e5c35fe2ffb750f32b639cb44424a1dBehdad Esfahbod 54620b817ac21147e0a8edbf23ef071c2f4ce6c2b95Behdad Esfahbodstatic inline bool ISALPHA (unsigned char c) 547153142dac8dd9abaf164bb88af07c600c17fc3a1Behdad Esfahbod{ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); } 54820b817ac21147e0a8edbf23ef071c2f4ce6c2b95Behdad Esfahbodstatic inline bool ISALNUM (unsigned char c) 549153142dac8dd9abaf164bb88af07c600c17fc3a1Behdad Esfahbod{ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'); } 55020b817ac21147e0a8edbf23ef071c2f4ce6c2b95Behdad Esfahbodstatic inline bool ISSPACE (unsigned char c) 55120b817ac21147e0a8edbf23ef071c2f4ce6c2b95Behdad Esfahbod{ return c == ' ' || c =='\f'|| c =='\n'|| c =='\r'|| c =='\t'|| c =='\v'; } 552153142dac8dd9abaf164bb88af07c600c17fc3a1Behdad Esfahbodstatic inline unsigned char TOUPPER (unsigned char c) 553153142dac8dd9abaf164bb88af07c600c17fc3a1Behdad Esfahbod{ return (c >= 'a' && c <= 'z') ? c - 'a' + 'A' : c; } 554153142dac8dd9abaf164bb88af07c600c17fc3a1Behdad Esfahbodstatic inline unsigned char TOLOWER (unsigned char c) 555153142dac8dd9abaf164bb88af07c600c17fc3a1Behdad Esfahbod{ return (c >= 'A' && c <= 'Z') ? c - 'A' + 'a' : c; } 556db5227c40e5c35fe2ffb750f32b639cb44424a1dBehdad Esfahbod 5574188096a7722f09ffa9319986c0286071da10a27Behdad Esfahbod#define HB_TAG_CHAR4(s) (HB_TAG(((const char *) s)[0], \ 5584188096a7722f09ffa9319986c0286071da10a27Behdad Esfahbod ((const char *) s)[1], \ 5594188096a7722f09ffa9319986c0286071da10a27Behdad Esfahbod ((const char *) s)[2], \ 5604188096a7722f09ffa9319986c0286071da10a27Behdad Esfahbod ((const char *) s)[3])) 5614188096a7722f09ffa9319986c0286071da10a27Behdad Esfahbod 562db5227c40e5c35fe2ffb750f32b639cb44424a1dBehdad Esfahbod 563831886a9b4073cfe27f7e1db0e957cbd5913fd31Behdad Esfahbod/* C++ helpers */ 564831886a9b4073cfe27f7e1db0e957cbd5913fd31Behdad Esfahbod 565831886a9b4073cfe27f7e1db0e957cbd5913fd31Behdad Esfahbod/* Makes class uncopyable. Use in private: section. */ 566831886a9b4073cfe27f7e1db0e957cbd5913fd31Behdad Esfahbod#define NO_COPY(T) \ 567831886a9b4073cfe27f7e1db0e957cbd5913fd31Behdad Esfahbod T (const T &o); \ 568970e092dc23cbeb7897d4c7bb58c042209f518fbBehdad Esfahbod T &operator = (const T &o) 569831886a9b4073cfe27f7e1db0e957cbd5913fd31Behdad Esfahbod 570831886a9b4073cfe27f7e1db0e957cbd5913fd31Behdad Esfahbod 571bc200457430c083914a64bf4b056153506749610Behdad Esfahbod/* Debug */ 572bc200457430c083914a64bf4b056153506749610Behdad Esfahbod 573cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod 574bc200457430c083914a64bf4b056153506749610Behdad Esfahbod#ifndef HB_DEBUG 575bc200457430c083914a64bf4b056153506749610Behdad Esfahbod#define HB_DEBUG 0 576bc200457430c083914a64bf4b056153506749610Behdad Esfahbod#endif 577bc200457430c083914a64bf4b056153506749610Behdad Esfahbod 578cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbodstatic inline bool 579cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod_hb_debug (unsigned int level, 580cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod unsigned int max_level) 581cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod{ 582cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod return level < max_level; 583cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod} 584cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod 5856c15ddfe2b45383824b64058ae69939d002183a6Behdad Esfahbod#define DEBUG_LEVEL_ENABLED(WHAT, LEVEL) (_hb_debug ((LEVEL), HB_DEBUG_##WHAT)) 5866c15ddfe2b45383824b64058ae69939d002183a6Behdad Esfahbod#define DEBUG_ENABLED(WHAT) (DEBUG_LEVEL_ENABLED (WHAT, 0)) 58743ff203d8ea3e1b09e316e3aae1a4e5ec15bfdd2Behdad Esfahbod 5882d1dcb3ce3354c2d5e2b4d1d291beb8d23cdea22Behdad Esfahbodtemplate <int max_level> static inline void 589208109703c929428c684ddcf9310b8ba780c4c31Behdad Esfahbod_hb_debug_msg_va (const char *what, 5901e08830b4fac3a60ae52349cab6e101d389d30cdBehdad Esfahbod const void *obj, 5911e08830b4fac3a60ae52349cab6e101d389d30cdBehdad Esfahbod const char *func, 5921e08830b4fac3a60ae52349cab6e101d389d30cdBehdad Esfahbod bool indented, 5931e08830b4fac3a60ae52349cab6e101d389d30cdBehdad Esfahbod unsigned int level, 5941e08830b4fac3a60ae52349cab6e101d389d30cdBehdad Esfahbod int level_dir, 5951e08830b4fac3a60ae52349cab6e101d389d30cdBehdad Esfahbod const char *message, 5961e08830b4fac3a60ae52349cab6e101d389d30cdBehdad Esfahbod va_list ap) 597208109703c929428c684ddcf9310b8ba780c4c31Behdad Esfahbod{ 5986eec6f406d2cc13dbca422e88492d3d498af02bfBehdad Esfahbod if (!_hb_debug (level, max_level)) 599829e814ff358c5e700ba4df54932696801aa9f65Behdad Esfahbod return; 6006eec6f406d2cc13dbca422e88492d3d498af02bfBehdad Esfahbod 6016eec6f406d2cc13dbca422e88492d3d498af02bfBehdad Esfahbod fprintf (stderr, "%-10s", what ? what : ""); 6026eec6f406d2cc13dbca422e88492d3d498af02bfBehdad Esfahbod 6036eec6f406d2cc13dbca422e88492d3d498af02bfBehdad Esfahbod if (obj) 6045ccfe8e2154ad0b58dabcc236bbe9478c17b02abBehdad Esfahbod fprintf (stderr, "(%0*lx) ", (unsigned int) (2 * sizeof (void *)), (unsigned long) obj); 6056eec6f406d2cc13dbca422e88492d3d498af02bfBehdad Esfahbod else 6066eec6f406d2cc13dbca422e88492d3d498af02bfBehdad Esfahbod fprintf (stderr, " %*s ", (unsigned int) (2 * sizeof (void *)), ""); 6076eec6f406d2cc13dbca422e88492d3d498af02bfBehdad Esfahbod 608d7bba01a353efc7432c474dd8755a02db4abd2aeBehdad Esfahbod if (indented) { 6096932a41fb61ffc2901c260587b1e98ed9c2a7ea1Behdad Esfahbod/* One may want to add ASCII version of these. See: 6106932a41fb61ffc2901c260587b1e98ed9c2a7ea1Behdad Esfahbod * https://bugs.freedesktop.org/show_bug.cgi?id=50970 */ 6116932a41fb61ffc2901c260587b1e98ed9c2a7ea1Behdad Esfahbod#define VBAR "\342\224\202" /* U+2502 BOX DRAWINGS LIGHT VERTICAL */ 6126932a41fb61ffc2901c260587b1e98ed9c2a7ea1Behdad Esfahbod#define VRBAR "\342\224\234" /* U+251C BOX DRAWINGS LIGHT VERTICAL AND RIGHT */ 6136932a41fb61ffc2901c260587b1e98ed9c2a7ea1Behdad Esfahbod#define DLBAR "\342\225\256" /* U+256E BOX DRAWINGS LIGHT ARC DOWN AND LEFT */ 6146932a41fb61ffc2901c260587b1e98ed9c2a7ea1Behdad Esfahbod#define ULBAR "\342\225\257" /* U+256F BOX DRAWINGS LIGHT ARC UP AND LEFT */ 6156932a41fb61ffc2901c260587b1e98ed9c2a7ea1Behdad Esfahbod#define LBAR "\342\225\264" /* U+2574 BOX DRAWINGS LIGHT LEFT */ 6166932a41fb61ffc2901c260587b1e98ed9c2a7ea1Behdad Esfahbod 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; 6177235f33f9e5e031622a00a84f4b2e98f16803579Behdad Esfahbod fprintf (stderr, "%2u %s" VRBAR "%s", 6186eec6f406d2cc13dbca422e88492d3d498af02bfBehdad Esfahbod level, 6196932a41fb61ffc2901c260587b1e98ed9c2a7ea1Behdad Esfahbod bars + sizeof (bars) - 1 - MIN ((unsigned int) sizeof (bars), (unsigned int) (sizeof (VBAR) - 1) * level), 6206932a41fb61ffc2901c260587b1e98ed9c2a7ea1Behdad Esfahbod level_dir ? (level_dir > 0 ? DLBAR : ULBAR) : LBAR); 621d7bba01a353efc7432c474dd8755a02db4abd2aeBehdad Esfahbod } else 6226932a41fb61ffc2901c260587b1e98ed9c2a7ea1Behdad Esfahbod fprintf (stderr, " " VRBAR LBAR); 6236eec6f406d2cc13dbca422e88492d3d498af02bfBehdad Esfahbod 624adf7758a27a11fb1a8a14a2673867589437d22a3Behdad Esfahbod if (func) 625adf7758a27a11fb1a8a14a2673867589437d22a3Behdad Esfahbod { 62629ff25481584e20a2fa39195f295c8eb4bf3bad0Behdad Esfahbod unsigned int func_len = strlen (func); 62729ff25481584e20a2fa39195f295c8eb4bf3bad0Behdad Esfahbod#ifndef HB_DEBUG_VERBOSE 628adf7758a27a11fb1a8a14a2673867589437d22a3Behdad Esfahbod /* Skip "typename" */ 629adf7758a27a11fb1a8a14a2673867589437d22a3Behdad Esfahbod if (0 == strncmp (func, "typename ", 9)) 630adf7758a27a11fb1a8a14a2673867589437d22a3Behdad Esfahbod func += 9; 631fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod /* Skip return type */ 632d7bba01a353efc7432c474dd8755a02db4abd2aeBehdad Esfahbod const char *space = strchr (func, ' '); 633fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod if (space) 634d7bba01a353efc7432c474dd8755a02db4abd2aeBehdad Esfahbod func = space + 1; 635fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod /* Skip parameter list */ 636fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod const char *paren = strchr (func, '('); 63729ff25481584e20a2fa39195f295c8eb4bf3bad0Behdad Esfahbod if (paren) 63829ff25481584e20a2fa39195f295c8eb4bf3bad0Behdad Esfahbod func_len = paren - func; 63929ff25481584e20a2fa39195f295c8eb4bf3bad0Behdad Esfahbod#endif 640d7bba01a353efc7432c474dd8755a02db4abd2aeBehdad Esfahbod fprintf (stderr, "%.*s: ", func_len, func); 64185f73fa8da1fbb864aef0f3a592b1d65e24d593dBehdad Esfahbod } 6426eec6f406d2cc13dbca422e88492d3d498af02bfBehdad Esfahbod 6436eec6f406d2cc13dbca422e88492d3d498af02bfBehdad Esfahbod if (message) 6446eec6f406d2cc13dbca422e88492d3d498af02bfBehdad Esfahbod vfprintf (stderr, message, ap); 6456eec6f406d2cc13dbca422e88492d3d498af02bfBehdad Esfahbod 6466eec6f406d2cc13dbca422e88492d3d498af02bfBehdad Esfahbod fprintf (stderr, "\n"); 647208109703c929428c684ddcf9310b8ba780c4c31Behdad Esfahbod} 648829e814ff358c5e700ba4df54932696801aa9f65Behdad Esfahbodtemplate <> inline void 64993345edcbea49bdf0e22f26b5b74a23e601dfab4Behdad Esfahbod_hb_debug_msg_va<0> (const char *what HB_UNUSED, 65093345edcbea49bdf0e22f26b5b74a23e601dfab4Behdad Esfahbod const void *obj HB_UNUSED, 65193345edcbea49bdf0e22f26b5b74a23e601dfab4Behdad Esfahbod const char *func HB_UNUSED, 65293345edcbea49bdf0e22f26b5b74a23e601dfab4Behdad Esfahbod bool indented HB_UNUSED, 65393345edcbea49bdf0e22f26b5b74a23e601dfab4Behdad Esfahbod unsigned int level HB_UNUSED, 65493345edcbea49bdf0e22f26b5b74a23e601dfab4Behdad Esfahbod int level_dir HB_UNUSED, 65593345edcbea49bdf0e22f26b5b74a23e601dfab4Behdad Esfahbod const char *message HB_UNUSED, 65693345edcbea49bdf0e22f26b5b74a23e601dfab4Behdad Esfahbod va_list ap HB_UNUSED) {} 657208109703c929428c684ddcf9310b8ba780c4c31Behdad Esfahbod 6582d1dcb3ce3354c2d5e2b4d1d291beb8d23cdea22Behdad Esfahbodtemplate <int max_level> static inline void 659cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod_hb_debug_msg (const char *what, 660cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod const void *obj, 661cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod const char *func, 662cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod bool indented, 6631e08830b4fac3a60ae52349cab6e101d389d30cdBehdad Esfahbod unsigned int level, 6641e08830b4fac3a60ae52349cab6e101d389d30cdBehdad Esfahbod int level_dir, 665cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod const char *message, 6661e08830b4fac3a60ae52349cab6e101d389d30cdBehdad Esfahbod ...) HB_PRINTF_FUNC(7, 8); 6672d1dcb3ce3354c2d5e2b4d1d291beb8d23cdea22Behdad Esfahbodtemplate <int max_level> static inline void 668cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod_hb_debug_msg (const char *what, 669cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod const void *obj, 670cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod const char *func, 671cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod bool indented, 6721e08830b4fac3a60ae52349cab6e101d389d30cdBehdad Esfahbod unsigned int level, 6731e08830b4fac3a60ae52349cab6e101d389d30cdBehdad Esfahbod int level_dir, 674cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod const char *message, 675cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod ...) 676cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod{ 677cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod va_list ap; 678cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod va_start (ap, message); 679829e814ff358c5e700ba4df54932696801aa9f65Behdad Esfahbod _hb_debug_msg_va<max_level> (what, obj, func, indented, level, level_dir, message, ap); 680cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod va_end (ap); 681cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod} 682829e814ff358c5e700ba4df54932696801aa9f65Behdad Esfahbodtemplate <> inline void 68393345edcbea49bdf0e22f26b5b74a23e601dfab4Behdad Esfahbod_hb_debug_msg<0> (const char *what HB_UNUSED, 68493345edcbea49bdf0e22f26b5b74a23e601dfab4Behdad Esfahbod const void *obj HB_UNUSED, 68593345edcbea49bdf0e22f26b5b74a23e601dfab4Behdad Esfahbod const char *func HB_UNUSED, 68693345edcbea49bdf0e22f26b5b74a23e601dfab4Behdad Esfahbod bool indented HB_UNUSED, 68793345edcbea49bdf0e22f26b5b74a23e601dfab4Behdad Esfahbod unsigned int level HB_UNUSED, 68893345edcbea49bdf0e22f26b5b74a23e601dfab4Behdad Esfahbod int level_dir HB_UNUSED, 68993345edcbea49bdf0e22f26b5b74a23e601dfab4Behdad Esfahbod const char *message HB_UNUSED, 6901e08830b4fac3a60ae52349cab6e101d389d30cdBehdad Esfahbod ...) HB_PRINTF_FUNC(7, 8); 691829e814ff358c5e700ba4df54932696801aa9f65Behdad Esfahbodtemplate <> inline void 69293345edcbea49bdf0e22f26b5b74a23e601dfab4Behdad Esfahbod_hb_debug_msg<0> (const char *what HB_UNUSED, 69393345edcbea49bdf0e22f26b5b74a23e601dfab4Behdad Esfahbod const void *obj HB_UNUSED, 69493345edcbea49bdf0e22f26b5b74a23e601dfab4Behdad Esfahbod const char *func HB_UNUSED, 69593345edcbea49bdf0e22f26b5b74a23e601dfab4Behdad Esfahbod bool indented HB_UNUSED, 69693345edcbea49bdf0e22f26b5b74a23e601dfab4Behdad Esfahbod unsigned int level HB_UNUSED, 69793345edcbea49bdf0e22f26b5b74a23e601dfab4Behdad Esfahbod int level_dir HB_UNUSED, 69893345edcbea49bdf0e22f26b5b74a23e601dfab4Behdad Esfahbod const char *message HB_UNUSED, 699829e814ff358c5e700ba4df54932696801aa9f65Behdad Esfahbod ...) {} 700bc200457430c083914a64bf4b056153506749610Behdad Esfahbod 7010594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod#define DEBUG_MSG_LEVEL(WHAT, OBJ, LEVEL, LEVEL_DIR, ...) _hb_debug_msg<HB_DEBUG_##WHAT> (#WHAT, (OBJ), NULL, true, (LEVEL), (LEVEL_DIR), __VA_ARGS__) 7020594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod#define DEBUG_MSG(WHAT, OBJ, ...) _hb_debug_msg<HB_DEBUG_##WHAT> (#WHAT, (OBJ), NULL, false, 0, 0, __VA_ARGS__) 7030594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod#define DEBUG_MSG_FUNC(WHAT, OBJ, ...) _hb_debug_msg<HB_DEBUG_##WHAT> (#WHAT, (OBJ), HB_FUNC, false, 0, 0, __VA_ARGS__) 704cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod 705cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod 706cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod/* 707dabe698fcbeb02911128b17aa8e3b2d864795960Behdad Esfahbod * Printer 708dabe698fcbeb02911128b17aa8e3b2d864795960Behdad Esfahbod */ 709dabe698fcbeb02911128b17aa8e3b2d864795960Behdad Esfahbod 710dabe698fcbeb02911128b17aa8e3b2d864795960Behdad Esfahbodtemplate <typename T> 711dabe698fcbeb02911128b17aa8e3b2d864795960Behdad Esfahbodstruct hb_printer_t {}; 712dabe698fcbeb02911128b17aa8e3b2d864795960Behdad Esfahbod 713dabe698fcbeb02911128b17aa8e3b2d864795960Behdad Esfahbodtemplate <> 714dabe698fcbeb02911128b17aa8e3b2d864795960Behdad Esfahbodstruct hb_printer_t<bool> { 715dabe698fcbeb02911128b17aa8e3b2d864795960Behdad Esfahbod const char *print (bool v) { return v ? "true" : "false"; } 716dabe698fcbeb02911128b17aa8e3b2d864795960Behdad Esfahbod}; 717dabe698fcbeb02911128b17aa8e3b2d864795960Behdad Esfahbod 718dabe698fcbeb02911128b17aa8e3b2d864795960Behdad Esfahbodtemplate <> 719130bb3f6144afe5c88bb5b4e4c98e7cba03b1e26Behdad Esfahbodstruct hb_printer_t<hb_void_t> { 7200beb66e3a61ae8bb1fa66e54b1ff1abb2f8711e9Behdad Esfahbod const char *print (hb_void_t) { return ""; } 721dabe698fcbeb02911128b17aa8e3b2d864795960Behdad Esfahbod}; 722dabe698fcbeb02911128b17aa8e3b2d864795960Behdad Esfahbod 723dabe698fcbeb02911128b17aa8e3b2d864795960Behdad Esfahbod 724dabe698fcbeb02911128b17aa8e3b2d864795960Behdad Esfahbod/* 725cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod * Trace 726cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod */ 727cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod 728902cc8aca0b3ff25eeee50b3a84d729e31731ef3Behdad Esfahbodtemplate <typename T> 729902cc8aca0b3ff25eeee50b3a84d729e31731ef3Behdad Esfahbodstatic inline void _hb_warn_no_return (bool returned) 730902cc8aca0b3ff25eeee50b3a84d729e31731ef3Behdad Esfahbod{ 731902cc8aca0b3ff25eeee50b3a84d729e31731ef3Behdad Esfahbod if (unlikely (!returned)) { 732902cc8aca0b3ff25eeee50b3a84d729e31731ef3Behdad Esfahbod fprintf (stderr, "OUCH, returned with no call to TRACE_RETURN. This is a bug, please report.\n"); 733902cc8aca0b3ff25eeee50b3a84d729e31731ef3Behdad Esfahbod } 734902cc8aca0b3ff25eeee50b3a84d729e31731ef3Behdad Esfahbod} 735902cc8aca0b3ff25eeee50b3a84d729e31731ef3Behdad Esfahbodtemplate <> 7366faff8e4132197ba06f0e685b82efe35b546cf64Behdad Esfahbod/*static*/ inline void _hb_warn_no_return<hb_void_t> (bool returned HB_UNUSED) 737902cc8aca0b3ff25eeee50b3a84d729e31731ef3Behdad Esfahbod{} 738902cc8aca0b3ff25eeee50b3a84d729e31731ef3Behdad Esfahbod 739902cc8aca0b3ff25eeee50b3a84d729e31731ef3Behdad Esfahbodtemplate <int max_level, typename ret_t> 740cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbodstruct hb_auto_trace_t { 741cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod explicit inline hb_auto_trace_t (unsigned int *plevel_, 7429659523ca32b0e254d0e5fe387d817208d9cb6bfBehdad Esfahbod const char *what_, 7439659523ca32b0e254d0e5fe387d817208d9cb6bfBehdad Esfahbod const void *obj_, 744cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod const char *func, 745208109703c929428c684ddcf9310b8ba780c4c31Behdad Esfahbod const char *message, 7469659523ca32b0e254d0e5fe387d817208d9cb6bfBehdad Esfahbod ...) : plevel (plevel_), what (what_), obj (obj_), returned (false) 747cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod { 7481e08830b4fac3a60ae52349cab6e101d389d30cdBehdad Esfahbod if (plevel) ++*plevel; 749208109703c929428c684ddcf9310b8ba780c4c31Behdad Esfahbod 750208109703c929428c684ddcf9310b8ba780c4c31Behdad Esfahbod va_list ap; 751208109703c929428c684ddcf9310b8ba780c4c31Behdad Esfahbod va_start (ap, message); 7520594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod _hb_debug_msg_va<max_level> (what, obj, func, true, plevel ? *plevel : 0, +1, message, ap); 753208109703c929428c684ddcf9310b8ba780c4c31Behdad Esfahbod va_end (ap); 754cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod } 7550ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod inline ~hb_auto_trace_t (void) 7561e08830b4fac3a60ae52349cab6e101d389d30cdBehdad Esfahbod { 757902cc8aca0b3ff25eeee50b3a84d729e31731ef3Behdad Esfahbod _hb_warn_no_return<ret_t> (returned); 758902cc8aca0b3ff25eeee50b3a84d729e31731ef3Behdad Esfahbod if (!returned) { 7590594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod _hb_debug_msg<max_level> (what, obj, NULL, true, plevel ? *plevel : 1, -1, " "); 7600ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod } 7611e08830b4fac3a60ae52349cab6e101d389d30cdBehdad Esfahbod if (plevel) --*plevel; 7621e08830b4fac3a60ae52349cab6e101d389d30cdBehdad Esfahbod } 763cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod 7642c9d6485a1f89c11f84e720d3c7978dc11a5039aBehdad Esfahbod inline ret_t ret (ret_t v, unsigned int line = 0) 7650ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod { 7660ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod if (unlikely (returned)) { 7670ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod fprintf (stderr, "OUCH, double calls to TRACE_RETURN. This is a bug, please report.\n"); 7680ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod return v; 7690ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod } 7700ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod 771902cc8aca0b3ff25eeee50b3a84d729e31731ef3Behdad Esfahbod _hb_debug_msg<max_level> (what, obj, NULL, true, plevel ? *plevel : 1, -1, 772902cc8aca0b3ff25eeee50b3a84d729e31731ef3Behdad Esfahbod "return %s (line %d)", 773902cc8aca0b3ff25eeee50b3a84d729e31731ef3Behdad Esfahbod hb_printer_t<ret_t>().print (v), line); 7740ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod if (plevel) --*plevel; 7750ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod plevel = NULL; 7760ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod returned = true; 7770ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod return v; 7780ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod } 7790ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod 780cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod private: 781cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod unsigned int *plevel; 7829659523ca32b0e254d0e5fe387d817208d9cb6bfBehdad Esfahbod const char *what; 7839659523ca32b0e254d0e5fe387d817208d9cb6bfBehdad Esfahbod const void *obj; 784c779d82b2fc801eec0d349a106c0e860448fcf4eBehdad Esfahbod bool returned; 785cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod}; 786902cc8aca0b3ff25eeee50b3a84d729e31731ef3Behdad Esfahbodtemplate <typename ret_t> /* Optimize when tracing is disabled */ 787902cc8aca0b3ff25eeee50b3a84d729e31731ef3Behdad Esfahbodstruct hb_auto_trace_t<0, ret_t> { 78893345edcbea49bdf0e22f26b5b74a23e601dfab4Behdad Esfahbod explicit inline hb_auto_trace_t (unsigned int *plevel_ HB_UNUSED, 78993345edcbea49bdf0e22f26b5b74a23e601dfab4Behdad Esfahbod const char *what HB_UNUSED, 79093345edcbea49bdf0e22f26b5b74a23e601dfab4Behdad Esfahbod const void *obj HB_UNUSED, 79193345edcbea49bdf0e22f26b5b74a23e601dfab4Behdad Esfahbod const char *func HB_UNUSED, 79293345edcbea49bdf0e22f26b5b74a23e601dfab4Behdad Esfahbod const char *message HB_UNUSED, 793208109703c929428c684ddcf9310b8ba780c4c31Behdad Esfahbod ...) {} 7940ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod 7950beb66e3a61ae8bb1fa66e54b1ff1abb2f8711e9Behdad Esfahbod inline ret_t ret (ret_t v, unsigned int line HB_UNUSED = 0) { return v; } 796cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod}; 797cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod 798ae63cf206291befe3920adfe015e6cd0961580e5Behdad Esfahbod#define TRACE_RETURN(RET) trace.ret (RET, __LINE__) 799cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod 800cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod/* Misc */ 801cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod 802a8b89a09f6d3a3466282aae07fd65e143f9f8f83Behdad Esfahbodtemplate <typename T> class hb_assert_unsigned_t; 803a8b89a09f6d3a3466282aae07fd65e143f9f8f83Behdad Esfahbodtemplate <> class hb_assert_unsigned_t<unsigned char> {}; 8049e7c720100e432b43564ed5ff12f3175ca2ed74aDominik Röttschestemplate <> class hb_assert_unsigned_t<unsigned short> {}; 805a8b89a09f6d3a3466282aae07fd65e143f9f8f83Behdad Esfahbodtemplate <> class hb_assert_unsigned_t<unsigned int> {}; 806a8b89a09f6d3a3466282aae07fd65e143f9f8f83Behdad Esfahbodtemplate <> class hb_assert_unsigned_t<unsigned long> {}; 807f60f2166c48d07f556ff83f04e95181946eb03dfBehdad Esfahbod 808b5aeb95afeb13a66177caada9f5d5ad4cddbd35fBehdad Esfahbodtemplate <typename T> static inline bool 8098f0b64fb6988f9502d2c5e39768a9af133d9a83fBehdad Esfahbodhb_in_range (T u, T lo, T hi) 8107b08b0a7f2057937dfc3ab2ec191656bf2386463Behdad Esfahbod{ 811385cf37cf084198e3aedb4354a7b025938a9f11bBehdad Esfahbod /* The sizeof() is here to force template instantiation. 812385cf37cf084198e3aedb4354a7b025938a9f11bBehdad Esfahbod * I'm sure there are better ways to do this but can't think of 813385cf37cf084198e3aedb4354a7b025938a9f11bBehdad Esfahbod * one right now. Declaring a variable won't work as HB_UNUSED 814385cf37cf084198e3aedb4354a7b025938a9f11bBehdad Esfahbod * is unsable on some platforms and unused types are less likely 815385cf37cf084198e3aedb4354a7b025938a9f11bBehdad Esfahbod * to generate a warning than unused variables. */ 816385cf37cf084198e3aedb4354a7b025938a9f11bBehdad Esfahbod ASSERT_STATIC (sizeof (hb_assert_unsigned_t<T>) >= 0); 817385cf37cf084198e3aedb4354a7b025938a9f11bBehdad Esfahbod 818a8b89a09f6d3a3466282aae07fd65e143f9f8f83Behdad Esfahbod return (u - lo) <= (hi - lo); 8197b08b0a7f2057937dfc3ab2ec191656bf2386463Behdad Esfahbod} 8207b08b0a7f2057937dfc3ab2ec191656bf2386463Behdad Esfahbod 8214a7f4f3e56f8f7640ae7337aa1b3324f31e0d4abBehdad Esfahbodtemplate <typename T> static inline bool 822c98b7183f7dc453d5bac1f2503017cded317a495Behdad Esfahbodhb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2) 823c98b7183f7dc453d5bac1f2503017cded317a495Behdad Esfahbod{ 824c98b7183f7dc453d5bac1f2503017cded317a495Behdad Esfahbod return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2); 825c98b7183f7dc453d5bac1f2503017cded317a495Behdad Esfahbod} 826c98b7183f7dc453d5bac1f2503017cded317a495Behdad Esfahbod 827c98b7183f7dc453d5bac1f2503017cded317a495Behdad Esfahbodtemplate <typename T> static inline bool 828093cd583263a5d427e3377b31585043fb55d2557Behdad Esfahbodhb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3) 8294a7f4f3e56f8f7640ae7337aa1b3324f31e0d4abBehdad Esfahbod{ 830093cd583263a5d427e3377b31585043fb55d2557Behdad Esfahbod return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2) || hb_in_range (u, lo3, hi3); 8314a7f4f3e56f8f7640ae7337aa1b3324f31e0d4abBehdad Esfahbod} 8324a7f4f3e56f8f7640ae7337aa1b3324f31e0d4abBehdad Esfahbod 8337b08b0a7f2057937dfc3ab2ec191656bf2386463Behdad Esfahbod 83445d6f29f15f1d2323bcaa2498aed23ff0c8a1567Behdad Esfahbod/* Useful for set-operations on small enums. 83545d6f29f15f1d2323bcaa2498aed23ff0c8a1567Behdad Esfahbod * For example, for testing "x ∈ {x1, x2, x3}" use: 83645d6f29f15f1d2323bcaa2498aed23ff0c8a1567Behdad Esfahbod * (FLAG(x) & (FLAG(x1) | FLAG(x2) | FLAG(x3))) 83745d6f29f15f1d2323bcaa2498aed23ff0c8a1567Behdad Esfahbod */ 838efb4ad735691837a52447bedc1a66a87d0d9af51Behdad Esfahbod#define FLAG(x) (1<<(x)) 8392c372b80f6befad69e216e3f218b38640b8cc044Behdad Esfahbod#define FLAG_RANGE(x,y) (ASSERT_STATIC_EXPR_ZERO ((x) < (y)) + FLAG(y+1) - FLAG(x)) 8407b08b0a7f2057937dfc3ab2ec191656bf2386463Behdad Esfahbod 8418f0b64fb6988f9502d2c5e39768a9af133d9a83fBehdad Esfahbod 84239b17837b4064d59c18cebb49c1c0b5b8cc0c117Behdad Esfahbodtemplate <typename T, typename T2> inline void 84339b17837b4064d59c18cebb49c1c0b5b8cc0c117Behdad Esfahbodhb_bubble_sort (T *array, unsigned int len, int(*compar)(const T *, const T *), T2 *array2) 84445d6f29f15f1d2323bcaa2498aed23ff0c8a1567Behdad Esfahbod{ 84545d6f29f15f1d2323bcaa2498aed23ff0c8a1567Behdad Esfahbod if (unlikely (!len)) 84645d6f29f15f1d2323bcaa2498aed23ff0c8a1567Behdad Esfahbod return; 84745d6f29f15f1d2323bcaa2498aed23ff0c8a1567Behdad Esfahbod 84845d6f29f15f1d2323bcaa2498aed23ff0c8a1567Behdad Esfahbod unsigned int k = len - 1; 84945d6f29f15f1d2323bcaa2498aed23ff0c8a1567Behdad Esfahbod do { 85045d6f29f15f1d2323bcaa2498aed23ff0c8a1567Behdad Esfahbod unsigned int new_k = 0; 85145d6f29f15f1d2323bcaa2498aed23ff0c8a1567Behdad Esfahbod 85245d6f29f15f1d2323bcaa2498aed23ff0c8a1567Behdad Esfahbod for (unsigned int j = 0; j < k; j++) 85339b17837b4064d59c18cebb49c1c0b5b8cc0c117Behdad Esfahbod if (compar (&array[j], &array[j+1]) > 0) 85439b17837b4064d59c18cebb49c1c0b5b8cc0c117Behdad Esfahbod { 85539b17837b4064d59c18cebb49c1c0b5b8cc0c117Behdad Esfahbod { 85639b17837b4064d59c18cebb49c1c0b5b8cc0c117Behdad Esfahbod T t; 85739b17837b4064d59c18cebb49c1c0b5b8cc0c117Behdad Esfahbod t = array[j]; 85839b17837b4064d59c18cebb49c1c0b5b8cc0c117Behdad Esfahbod array[j] = array[j + 1]; 85939b17837b4064d59c18cebb49c1c0b5b8cc0c117Behdad Esfahbod array[j + 1] = t; 86039b17837b4064d59c18cebb49c1c0b5b8cc0c117Behdad Esfahbod } 86139b17837b4064d59c18cebb49c1c0b5b8cc0c117Behdad Esfahbod if (array2) 86239b17837b4064d59c18cebb49c1c0b5b8cc0c117Behdad Esfahbod { 86339b17837b4064d59c18cebb49c1c0b5b8cc0c117Behdad Esfahbod T2 t; 86439b17837b4064d59c18cebb49c1c0b5b8cc0c117Behdad Esfahbod t = array2[j]; 86539b17837b4064d59c18cebb49c1c0b5b8cc0c117Behdad Esfahbod array2[j] = array2[j + 1]; 86639b17837b4064d59c18cebb49c1c0b5b8cc0c117Behdad Esfahbod array2[j + 1] = t; 86739b17837b4064d59c18cebb49c1c0b5b8cc0c117Behdad Esfahbod } 86845d6f29f15f1d2323bcaa2498aed23ff0c8a1567Behdad Esfahbod 86945d6f29f15f1d2323bcaa2498aed23ff0c8a1567Behdad Esfahbod new_k = j; 87045d6f29f15f1d2323bcaa2498aed23ff0c8a1567Behdad Esfahbod } 87145d6f29f15f1d2323bcaa2498aed23ff0c8a1567Behdad Esfahbod k = new_k; 87245d6f29f15f1d2323bcaa2498aed23ff0c8a1567Behdad Esfahbod } while (k); 87345d6f29f15f1d2323bcaa2498aed23ff0c8a1567Behdad Esfahbod} 87445d6f29f15f1d2323bcaa2498aed23ff0c8a1567Behdad Esfahbod 87539b17837b4064d59c18cebb49c1c0b5b8cc0c117Behdad Esfahbodtemplate <typename T> inline void 87639b17837b4064d59c18cebb49c1c0b5b8cc0c117Behdad Esfahbodhb_bubble_sort (T *array, unsigned int len, int(*compar)(const T *, const T *)) 87739b17837b4064d59c18cebb49c1c0b5b8cc0c117Behdad Esfahbod{ 87839b17837b4064d59c18cebb49c1c0b5b8cc0c117Behdad Esfahbod hb_bubble_sort (array, len, compar, (int *) NULL); 87939b17837b4064d59c18cebb49c1c0b5b8cc0c117Behdad Esfahbod} 88045d6f29f15f1d2323bcaa2498aed23ff0c8a1567Behdad Esfahbod 8816f3a300138f659020c21c3e08b7981c78df5f332Behdad Esfahbodstatic inline hb_bool_t 8826f3a300138f659020c21c3e08b7981c78df5f332Behdad Esfahbodhb_codepoint_parse (const char *s, unsigned int len, int base, hb_codepoint_t *out) 8836f3a300138f659020c21c3e08b7981c78df5f332Behdad Esfahbod{ 8846f3a300138f659020c21c3e08b7981c78df5f332Behdad Esfahbod /* Pain because we don't know whether s is nul-terminated. */ 8856f3a300138f659020c21c3e08b7981c78df5f332Behdad Esfahbod char buf[64]; 886847794e929831750e97525137ab5e285ccd1064eBehdad Esfahbod len = MIN (ARRAY_LENGTH (buf) - 1, len); 887847794e929831750e97525137ab5e285ccd1064eBehdad Esfahbod strncpy (buf, s, len); 888847794e929831750e97525137ab5e285ccd1064eBehdad Esfahbod buf[len] = '\0'; 8896f3a300138f659020c21c3e08b7981c78df5f332Behdad Esfahbod 8906f3a300138f659020c21c3e08b7981c78df5f332Behdad Esfahbod char *end; 8916f3a300138f659020c21c3e08b7981c78df5f332Behdad Esfahbod errno = 0; 8926f3a300138f659020c21c3e08b7981c78df5f332Behdad Esfahbod unsigned long v = strtoul (buf, &end, base); 8936f3a300138f659020c21c3e08b7981c78df5f332Behdad Esfahbod if (errno) return false; 8946f3a300138f659020c21c3e08b7981c78df5f332Behdad Esfahbod if (*end) return false; 8956f3a300138f659020c21c3e08b7981c78df5f332Behdad Esfahbod *out = v; 8966f3a300138f659020c21c3e08b7981c78df5f332Behdad Esfahbod return true; 8976f3a300138f659020c21c3e08b7981c78df5f332Behdad Esfahbod} 89845d6f29f15f1d2323bcaa2498aed23ff0c8a1567Behdad Esfahbod 899acdba3f90b232fc12fcb200dca2584481b339118Behdad Esfahbod 900bab02d339f39ed5168daaef9461227f78e596a2fBehdad Esfahbod/* Global runtime options. */ 901bab02d339f39ed5168daaef9461227f78e596a2fBehdad Esfahbod 902bab02d339f39ed5168daaef9461227f78e596a2fBehdad Esfahbodstruct hb_options_t 903bab02d339f39ed5168daaef9461227f78e596a2fBehdad Esfahbod{ 904bab02d339f39ed5168daaef9461227f78e596a2fBehdad Esfahbod int initialized : 1; 905bab02d339f39ed5168daaef9461227f78e596a2fBehdad Esfahbod int uniscribe_bug_compatible : 1; 906bab02d339f39ed5168daaef9461227f78e596a2fBehdad Esfahbod}; 907bab02d339f39ed5168daaef9461227f78e596a2fBehdad Esfahbod 908bab02d339f39ed5168daaef9461227f78e596a2fBehdad Esfahbodunion hb_options_union_t { 909bab02d339f39ed5168daaef9461227f78e596a2fBehdad Esfahbod int i; 910bab02d339f39ed5168daaef9461227f78e596a2fBehdad Esfahbod hb_options_t opts; 911bab02d339f39ed5168daaef9461227f78e596a2fBehdad Esfahbod}; 912bab02d339f39ed5168daaef9461227f78e596a2fBehdad EsfahbodASSERT_STATIC (sizeof (int) == sizeof (hb_options_union_t)); 913bab02d339f39ed5168daaef9461227f78e596a2fBehdad Esfahbod 914bab02d339f39ed5168daaef9461227f78e596a2fBehdad EsfahbodHB_INTERNAL void 915bab02d339f39ed5168daaef9461227f78e596a2fBehdad Esfahbod_hb_options_init (void); 916bab02d339f39ed5168daaef9461227f78e596a2fBehdad Esfahbod 917bab02d339f39ed5168daaef9461227f78e596a2fBehdad Esfahbodextern HB_INTERNAL hb_options_union_t _hb_options; 918bab02d339f39ed5168daaef9461227f78e596a2fBehdad Esfahbod 919bab02d339f39ed5168daaef9461227f78e596a2fBehdad Esfahbodstatic inline hb_options_t 920bab02d339f39ed5168daaef9461227f78e596a2fBehdad Esfahbodhb_options (void) 921bab02d339f39ed5168daaef9461227f78e596a2fBehdad Esfahbod{ 922bab02d339f39ed5168daaef9461227f78e596a2fBehdad Esfahbod if (unlikely (!_hb_options.i)) 923bab02d339f39ed5168daaef9461227f78e596a2fBehdad Esfahbod _hb_options_init (); 924bab02d339f39ed5168daaef9461227f78e596a2fBehdad Esfahbod 925bab02d339f39ed5168daaef9461227f78e596a2fBehdad Esfahbod return _hb_options.opts; 926bab02d339f39ed5168daaef9461227f78e596a2fBehdad Esfahbod} 927bab02d339f39ed5168daaef9461227f78e596a2fBehdad Esfahbod 928bab02d339f39ed5168daaef9461227f78e596a2fBehdad Esfahbod 929c57d454accff66e5f2c58006e8fb40bc020b6182Behdad Esfahbod#endif /* HB_PRIVATE_HH */ 930