Home | History | Annotate | Download | only in src
      1 /*
      2  * Copyright  2007,2008,2009  Red Hat, Inc.
      3  * Copyright  2011,2012  Google, Inc.
      4  *
      5  *  This is part of HarfBuzz, a text shaping library.
      6  *
      7  * Permission is hereby granted, without written agreement and without
      8  * license or royalty fees, to use, copy, modify, and distribute this
      9  * software and its documentation for any purpose, provided that the
     10  * above copyright notice and the following two paragraphs appear in
     11  * all copies of this software.
     12  *
     13  * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
     14  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
     15  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
     16  * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
     17  * DAMAGE.
     18  *
     19  * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
     20  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
     21  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
     22  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
     23  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
     24  *
     25  * Red Hat Author(s): Behdad Esfahbod
     26  * Google Author(s): Behdad Esfahbod
     27  */
     28 
     29 #ifndef HB_PRIVATE_HH
     30 #define HB_PRIVATE_HH
     31 
     32 #ifdef HAVE_CONFIG_H
     33 #include "config.h"
     34 #endif
     35 
     36 #include "hb.h"
     37 #define HB_H_IN
     38 #ifdef HAVE_OT
     39 #include "hb-ot.h"
     40 #define HB_OT_H_IN
     41 #endif
     42 
     43 #include <stdlib.h>
     44 #include <stddef.h>
     45 #include <string.h>
     46 #include <assert.h>
     47 
     48 /* We only use these two for debug output.  However, the debug code is
     49  * always seen by the compiler (and optimized out in non-debug builds.
     50  * If including these becomes a problem, we can start thinking about
     51  * someway around that. */
     52 #include <stdio.h>
     53 #include <errno.h>
     54 #include <stdarg.h>
     55 
     56 
     57 /* Compile-time custom allocator support. */
     58 
     59 #if defined(hb_malloc_impl) \
     60  && defined(hb_calloc_impl) \
     61  && defined(hb_realloc_impl) \
     62  && defined(hb_free_impl)
     63 extern "C" void* hb_malloc_impl(size_t size);
     64 extern "C" void* hb_calloc_impl(size_t nmemb, size_t size);
     65 extern "C" void* hb_realloc_impl(void *ptr, size_t size);
     66 extern "C" void  hb_free_impl(void *ptr);
     67 #define malloc hb_malloc_impl
     68 #define calloc hb_calloc_impl
     69 #define realloc hb_realloc_impl
     70 #define free hb_free_impl
     71 #endif
     72 
     73 
     74 /* Compiler attributes */
     75 
     76 
     77 #if defined(__GNUC__) && (__GNUC__ > 2) && defined(__OPTIMIZE__)
     78 #define _HB_BOOLEAN_EXPR(expr) ((expr) ? 1 : 0)
     79 #define likely(expr) (__builtin_expect (_HB_BOOLEAN_EXPR(expr), 1))
     80 #define unlikely(expr) (__builtin_expect (_HB_BOOLEAN_EXPR(expr), 0))
     81 #else
     82 #define likely(expr) (expr)
     83 #define unlikely(expr) (expr)
     84 #endif
     85 
     86 #ifndef __GNUC__
     87 #undef __attribute__
     88 #define __attribute__(x)
     89 #endif
     90 
     91 #if __GNUC__ >= 3
     92 #define HB_PURE_FUNC	__attribute__((pure))
     93 #define HB_CONST_FUNC	__attribute__((const))
     94 #define HB_PRINTF_FUNC(format_idx, arg_idx) __attribute__((__format__ (__printf__, format_idx, arg_idx)))
     95 #else
     96 #define HB_PURE_FUNC
     97 #define HB_CONST_FUNC
     98 #define HB_PRINTF_FUNC(format_idx, arg_idx)
     99 #endif
    100 #if __GNUC__ >= 4
    101 #define HB_UNUSED	__attribute__((unused))
    102 #else
    103 #define HB_UNUSED
    104 #endif
    105 
    106 #ifndef HB_INTERNAL
    107 # if !defined(__MINGW32__) && !defined(__CYGWIN__)
    108 #  define HB_INTERNAL __attribute__((__visibility__("hidden")))
    109 # else
    110 #  define HB_INTERNAL
    111 # endif
    112 #endif
    113 
    114 #if __GNUC__ >= 3
    115 #define HB_FUNC __PRETTY_FUNCTION__
    116 #elif defined(_MSC_VER)
    117 #define HB_FUNC __FUNCSIG__
    118 #else
    119 #define HB_FUNC __func__
    120 #endif
    121 
    122 /*
    123  * Borrowed from https://bugzilla.mozilla.org/show_bug.cgi?id=1215411
    124  * HB_FALLTHROUGH is an annotation to suppress compiler warnings about switch
    125  * cases that fall through without a break or return statement. HB_FALLTHROUGH
    126  * is only needed on cases that have code:
    127  *
    128  * switch (foo) {
    129  *   case 1: // These cases have no code. No fallthrough annotations are needed.
    130  *   case 2:
    131  *   case 3:
    132  *     foo = 4; // This case has code, so a fallthrough annotation is needed:
    133  *     HB_FALLTHROUGH;
    134  *   default:
    135  *     return foo;
    136  * }
    137  */
    138 #if defined(__clang__) && __cplusplus >= 201103L
    139    /* clang's fallthrough annotations are only available starting in C++11. */
    140 #  define HB_FALLTHROUGH [[clang::fallthrough]]
    141 #elif defined(_MSC_VER)
    142    /*
    143     * MSVC's __fallthrough annotations are checked by /analyze (Code Analysis):
    144     * https://msdn.microsoft.com/en-us/library/ms235402%28VS.80%29.aspx
    145     */
    146 #  include <sal.h>
    147 #  define HB_FALLTHROUGH __fallthrough
    148 #else
    149 #  define HB_FALLTHROUGH /* FALLTHROUGH */
    150 #endif
    151 
    152 #if defined(_WIN32) || defined(__CYGWIN__)
    153    /* We need Windows Vista for both Uniscribe backend and for
    154     * MemoryBarrier.  We don't support compiling on Windows XP,
    155     * though we run on it fine. */
    156 #  if defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0600
    157 #    undef _WIN32_WINNT
    158 #  endif
    159 #  ifndef _WIN32_WINNT
    160 #    define _WIN32_WINNT 0x0600
    161 #  endif
    162 #  ifndef WIN32_LEAN_AND_MEAN
    163 #    define WIN32_LEAN_AND_MEAN 1
    164 #  endif
    165 #  ifndef STRICT
    166 #    define STRICT 1
    167 #  endif
    168 
    169 #  if defined(_WIN32_WCE)
    170      /* Some things not defined on Windows CE. */
    171 #    define strdup _strdup
    172 #    define getenv(Name) NULL
    173 #    if _WIN32_WCE < 0x800
    174 #      define setlocale(Category, Locale) "C"
    175 static int errno = 0; /* Use something better? */
    176 #    endif
    177 #  elif defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP)
    178 #    define getenv(Name) NULL
    179 #  endif
    180 #  if defined(_MSC_VER) && _MSC_VER < 1900
    181 #    define snprintf _snprintf
    182 #  elif defined(_MSC_VER) && _MSC_VER >= 1900
    183 #    /* Covers VC++ Error for strdup being a deprecated POSIX name and to instead use _strdup instead */
    184 #    define strdup _strdup
    185 #  endif
    186 #endif
    187 
    188 #if HAVE_ATEXIT
    189 /* atexit() is only safe to be called from shared libraries on certain
    190  * platforms.  Whitelist.
    191  * https://bugs.freedesktop.org/show_bug.cgi?id=82246 */
    192 #  if defined(__linux) && defined(__GLIBC_PREREQ)
    193 #    if __GLIBC_PREREQ(2,3)
    194 /* From atexit() manpage, it's safe with glibc 2.2.3 on Linux. */
    195 #      define HB_USE_ATEXIT 1
    196 #    endif
    197 #  elif defined(_MSC_VER) || defined(__MINGW32__)
    198 /* For MSVC:
    199  * http://msdn.microsoft.com/en-ca/library/tze57ck3.aspx
    200  * http://msdn.microsoft.com/en-ca/library/zk17ww08.aspx
    201  * mingw32 headers say atexit is safe to use in shared libraries.
    202  */
    203 #    define HB_USE_ATEXIT 1
    204 #  elif defined(__ANDROID__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
    205 /* This was fixed in Android NKD r8 or r8b:
    206  * https://code.google.com/p/android/issues/detail?id=6455
    207  * which introduced GCC 4.6:
    208  * https://developer.android.com/tools/sdk/ndk/index.html
    209  */
    210 #    define HB_USE_ATEXIT 1
    211 #  endif
    212 #endif
    213 
    214 /* Basics */
    215 
    216 
    217 #ifndef NULL
    218 # define NULL ((void *) 0)
    219 #endif
    220 
    221 #undef MIN
    222 template <typename Type>
    223 static inline Type MIN (const Type &a, const Type &b) { return a < b ? a : b; }
    224 
    225 #undef MAX
    226 template <typename Type>
    227 static inline Type MAX (const Type &a, const Type &b) { return a > b ? a : b; }
    228 
    229 static inline unsigned int DIV_CEIL (const unsigned int a, unsigned int b)
    230 { return (a + (b - 1)) / b; }
    231 
    232 
    233 #undef  ARRAY_LENGTH
    234 template <typename Type, unsigned int n>
    235 static inline unsigned int ARRAY_LENGTH (const Type (&)[n]) { return n; }
    236 /* A const version, but does not detect erratically being called on pointers. */
    237 #define ARRAY_LENGTH_CONST(__array) ((signed int) (sizeof (__array) / sizeof (__array[0])))
    238 
    239 #define HB_STMT_START do
    240 #define HB_STMT_END   while (0)
    241 
    242 #define _ASSERT_STATIC1(_line, _cond)	HB_UNUSED typedef int _static_assert_on_line_##_line##_failed[(_cond)?1:-1]
    243 #define _ASSERT_STATIC0(_line, _cond)	_ASSERT_STATIC1 (_line, (_cond))
    244 #define ASSERT_STATIC(_cond)		_ASSERT_STATIC0 (__LINE__, (_cond))
    245 
    246 template <unsigned int cond> class hb_assert_constant_t {};
    247 
    248 #define ASSERT_STATIC_EXPR_ZERO(_cond) (0 * (unsigned int) sizeof (hb_assert_constant_t<_cond>))
    249 
    250 #define _PASTE1(a,b) a##b
    251 #define PASTE(a,b) _PASTE1(a,b)
    252 
    253 /* Lets assert int types.  Saves trouble down the road. */
    254 
    255 ASSERT_STATIC (sizeof (int8_t) == 1);
    256 ASSERT_STATIC (sizeof (uint8_t) == 1);
    257 ASSERT_STATIC (sizeof (int16_t) == 2);
    258 ASSERT_STATIC (sizeof (uint16_t) == 2);
    259 ASSERT_STATIC (sizeof (int32_t) == 4);
    260 ASSERT_STATIC (sizeof (uint32_t) == 4);
    261 ASSERT_STATIC (sizeof (int64_t) == 8);
    262 ASSERT_STATIC (sizeof (uint64_t) == 8);
    263 
    264 ASSERT_STATIC (sizeof (hb_codepoint_t) == 4);
    265 ASSERT_STATIC (sizeof (hb_position_t) == 4);
    266 ASSERT_STATIC (sizeof (hb_mask_t) == 4);
    267 ASSERT_STATIC (sizeof (hb_var_int_t) == 4);
    268 
    269 
    270 /* We like our types POD */
    271 
    272 #define _ASSERT_TYPE_POD1(_line, _type)	union _type_##_type##_on_line_##_line##_is_not_POD { _type instance; }
    273 #define _ASSERT_TYPE_POD0(_line, _type)	_ASSERT_TYPE_POD1 (_line, _type)
    274 #define ASSERT_TYPE_POD(_type)		_ASSERT_TYPE_POD0 (__LINE__, _type)
    275 
    276 #ifdef __GNUC__
    277 # define _ASSERT_INSTANCE_POD1(_line, _instance) \
    278 	HB_STMT_START { \
    279 		typedef __typeof__(_instance) _type_##_line; \
    280 		_ASSERT_TYPE_POD1 (_line, _type_##_line); \
    281 	} HB_STMT_END
    282 #else
    283 # define _ASSERT_INSTANCE_POD1(_line, _instance)	typedef int _assertion_on_line_##_line##_not_tested
    284 #endif
    285 # define _ASSERT_INSTANCE_POD0(_line, _instance)	_ASSERT_INSTANCE_POD1 (_line, _instance)
    286 # define ASSERT_INSTANCE_POD(_instance)			_ASSERT_INSTANCE_POD0 (__LINE__, _instance)
    287 
    288 /* Check _assertion in a method environment */
    289 #define _ASSERT_POD1(_line) \
    290 	HB_UNUSED inline void _static_assertion_on_line_##_line (void) const \
    291 	{ _ASSERT_INSTANCE_POD1 (_line, *this); /* Make sure it's POD. */ }
    292 # define _ASSERT_POD0(_line)	_ASSERT_POD1 (_line)
    293 # define ASSERT_POD()		_ASSERT_POD0 (__LINE__)
    294 
    295 
    296 
    297 /* Misc */
    298 
    299 /* Void! */
    300 struct _hb_void_t {};
    301 typedef const _hb_void_t *hb_void_t;
    302 #define HB_VOID ((const _hb_void_t *) NULL)
    303 
    304 /* Return the number of 1 bits in mask. */
    305 static inline HB_CONST_FUNC unsigned int
    306 _hb_popcount32 (uint32_t mask)
    307 {
    308 #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
    309   return __builtin_popcount (mask);
    310 #else
    311   /* "HACKMEM 169" */
    312   uint32_t y;
    313   y = (mask >> 1) &033333333333;
    314   y = mask - y - ((y >>1) & 033333333333);
    315   return (((y + (y >> 3)) & 030707070707) % 077);
    316 #endif
    317 }
    318 
    319 /* Returns the number of bits needed to store number */
    320 static inline HB_CONST_FUNC unsigned int
    321 _hb_bit_storage (unsigned int number)
    322 {
    323 #if defined(__GNUC__) && (__GNUC__ >= 4) && defined(__OPTIMIZE__)
    324   return likely (number) ? (sizeof (unsigned int) * 8 - __builtin_clz (number)) : 0;
    325 #else
    326   unsigned int n_bits = 0;
    327   while (number) {
    328     n_bits++;
    329     number >>= 1;
    330   }
    331   return n_bits;
    332 #endif
    333 }
    334 
    335 /* Returns the number of zero bits in the least significant side of number */
    336 static inline HB_CONST_FUNC unsigned int
    337 _hb_ctz (unsigned int number)
    338 {
    339 #if defined(__GNUC__) && (__GNUC__ >= 4) && defined(__OPTIMIZE__)
    340   return likely (number) ? __builtin_ctz (number) : 0;
    341 #else
    342   unsigned int n_bits = 0;
    343   if (unlikely (!number)) return 0;
    344   while (!(number & 1)) {
    345     n_bits++;
    346     number >>= 1;
    347   }
    348   return n_bits;
    349 #endif
    350 }
    351 
    352 static inline bool
    353 _hb_unsigned_int_mul_overflows (unsigned int count, unsigned int size)
    354 {
    355   return (size > 0) && (count >= ((unsigned int) -1) / size);
    356 }
    357 
    358 
    359 /* Type of bsearch() / qsort() compare function */
    360 typedef int (*hb_compare_func_t) (const void *, const void *);
    361 
    362 
    363 
    364 
    365 /* arrays and maps */
    366 
    367 
    368 #define HB_PREALLOCED_ARRAY_INIT {0, 0, NULL}
    369 template <typename Type, unsigned int StaticSize=16>
    370 struct hb_prealloced_array_t
    371 {
    372   unsigned int len;
    373   unsigned int allocated;
    374   Type *array;
    375   Type static_array[StaticSize];
    376 
    377   void init (void) { memset (this, 0, sizeof (*this)); }
    378 
    379   inline Type& operator [] (unsigned int i) { return array[i]; }
    380   inline const Type& operator [] (unsigned int i) const { return array[i]; }
    381 
    382   inline Type *push (void)
    383   {
    384     if (!array) {
    385       array = static_array;
    386       allocated = ARRAY_LENGTH (static_array);
    387     }
    388     if (likely (len < allocated))
    389       return &array[len++];
    390 
    391     /* Need to reallocate */
    392     unsigned int new_allocated = allocated + (allocated >> 1) + 8;
    393     Type *new_array = NULL;
    394 
    395     if (array == static_array) {
    396       new_array = (Type *) calloc (new_allocated, sizeof (Type));
    397       if (new_array)
    398         memcpy (new_array, array, len * sizeof (Type));
    399     } else {
    400       bool overflows = (new_allocated < allocated) || _hb_unsigned_int_mul_overflows (new_allocated, sizeof (Type));
    401       if (likely (!overflows)) {
    402 	new_array = (Type *) realloc (array, new_allocated * sizeof (Type));
    403       }
    404     }
    405 
    406     if (unlikely (!new_array))
    407       return NULL;
    408 
    409     array = new_array;
    410     allocated = new_allocated;
    411     return &array[len++];
    412   }
    413 
    414   inline void pop (void)
    415   {
    416     len--;
    417   }
    418 
    419   inline void remove (unsigned int i)
    420   {
    421      if (unlikely (i >= len))
    422        return;
    423      memmove (static_cast<void *> (&array[i]),
    424 	      static_cast<void *> (&array[i + 1]),
    425 	      (len - i - 1) * sizeof (Type));
    426      len--;
    427   }
    428 
    429   inline void shrink (unsigned int l)
    430   {
    431      if (l < len)
    432        len = l;
    433   }
    434 
    435   template <typename T>
    436   inline Type *find (T v) {
    437     for (unsigned int i = 0; i < len; i++)
    438       if (array[i] == v)
    439 	return &array[i];
    440     return NULL;
    441   }
    442   template <typename T>
    443   inline const Type *find (T v) const {
    444     for (unsigned int i = 0; i < len; i++)
    445       if (array[i] == v)
    446 	return &array[i];
    447     return NULL;
    448   }
    449 
    450   inline void qsort (void)
    451   {
    452     ::qsort (array, len, sizeof (Type), (hb_compare_func_t) Type::cmp);
    453   }
    454 
    455   inline void qsort (unsigned int start, unsigned int end)
    456   {
    457     ::qsort (array + start, end - start, sizeof (Type), (hb_compare_func_t) Type::cmp);
    458   }
    459 
    460   template <typename T>
    461   inline Type *bsearch (T *key)
    462   {
    463     return (Type *) ::bsearch (key, array, len, sizeof (Type), (hb_compare_func_t) Type::cmp);
    464   }
    465   template <typename T>
    466   inline const Type *bsearch (T *key) const
    467   {
    468     return (const Type *) ::bsearch (key, array, len, sizeof (Type), (hb_compare_func_t) Type::cmp);
    469   }
    470 
    471   inline void finish (void)
    472   {
    473     if (array != static_array)
    474       free (array);
    475     array = NULL;
    476     allocated = len = 0;
    477   }
    478 };
    479 
    480 template <typename Type>
    481 struct hb_auto_array_t : hb_prealloced_array_t <Type>
    482 {
    483   hb_auto_array_t (void) { hb_prealloced_array_t<Type>::init (); }
    484   ~hb_auto_array_t (void) { hb_prealloced_array_t<Type>::finish (); }
    485 };
    486 
    487 
    488 #define HB_LOCKABLE_SET_INIT {HB_PREALLOCED_ARRAY_INIT}
    489 template <typename item_t, typename lock_t>
    490 struct hb_lockable_set_t
    491 {
    492   hb_prealloced_array_t <item_t, 2> items;
    493 
    494   inline void init (void) { items.init (); }
    495 
    496   template <typename T>
    497   inline item_t *replace_or_insert (T v, lock_t &l, bool replace)
    498   {
    499     l.lock ();
    500     item_t *item = items.find (v);
    501     if (item) {
    502       if (replace) {
    503 	item_t old = *item;
    504 	*item = v;
    505 	l.unlock ();
    506 	old.finish ();
    507       }
    508       else {
    509         item = NULL;
    510 	l.unlock ();
    511       }
    512     } else {
    513       item = items.push ();
    514       if (likely (item))
    515 	*item = v;
    516       l.unlock ();
    517     }
    518     return item;
    519   }
    520 
    521   template <typename T>
    522   inline void remove (T v, lock_t &l)
    523   {
    524     l.lock ();
    525     item_t *item = items.find (v);
    526     if (item) {
    527       item_t old = *item;
    528       *item = items[items.len - 1];
    529       items.pop ();
    530       l.unlock ();
    531       old.finish ();
    532     } else {
    533       l.unlock ();
    534     }
    535   }
    536 
    537   template <typename T>
    538   inline bool find (T v, item_t *i, lock_t &l)
    539   {
    540     l.lock ();
    541     item_t *item = items.find (v);
    542     if (item)
    543       *i = *item;
    544     l.unlock ();
    545     return !!item;
    546   }
    547 
    548   template <typename T>
    549   inline item_t *find_or_insert (T v, lock_t &l)
    550   {
    551     l.lock ();
    552     item_t *item = items.find (v);
    553     if (!item) {
    554       item = items.push ();
    555       if (likely (item))
    556         *item = v;
    557     }
    558     l.unlock ();
    559     return item;
    560   }
    561 
    562   inline void finish (lock_t &l)
    563   {
    564     if (!items.len) {
    565       /* No need for locking. */
    566       items.finish ();
    567       return;
    568     }
    569     l.lock ();
    570     while (items.len) {
    571       item_t old = items[items.len - 1];
    572 	items.pop ();
    573 	l.unlock ();
    574 	old.finish ();
    575 	l.lock ();
    576     }
    577     items.finish ();
    578     l.unlock ();
    579   }
    580 
    581 };
    582 
    583 
    584 /* ASCII tag/character handling */
    585 
    586 static inline bool ISALPHA (unsigned char c)
    587 { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); }
    588 static inline bool ISALNUM (unsigned char c)
    589 { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'); }
    590 static inline bool ISSPACE (unsigned char c)
    591 { return c == ' ' || c =='\f'|| c =='\n'|| c =='\r'|| c =='\t'|| c =='\v'; }
    592 static inline unsigned char TOUPPER (unsigned char c)
    593 { return (c >= 'a' && c <= 'z') ? c - 'a' + 'A' : c; }
    594 static inline unsigned char TOLOWER (unsigned char c)
    595 { return (c >= 'A' && c <= 'Z') ? c - 'A' + 'a' : c; }
    596 
    597 #define HB_TAG_CHAR4(s)   (HB_TAG(((const char *) s)[0], \
    598 				  ((const char *) s)[1], \
    599 				  ((const char *) s)[2], \
    600 				  ((const char *) s)[3]))
    601 
    602 
    603 /* C++ helpers */
    604 
    605 /* Makes class uncopyable.  Use in private: section. */
    606 #define NO_COPY(T) \
    607   T (const T &o); \
    608   T &operator = (const T &o)
    609 
    610 
    611 /* Debug */
    612 
    613 
    614 /* HB_NDEBUG disables some sanity checks that are very safe to disable and
    615  * should be disabled in production systems.  If NDEBUG is defined, enable
    616  * HB_NDEBUG; but if it's desirable that normal assert()s (which are very
    617  * light-weight) to be enabled, then HB_DEBUG can be defined to disable
    618  * the costlier checks. */
    619 #ifdef NDEBUG
    620 #define HB_NDEBUG
    621 #endif
    622 
    623 #ifndef HB_DEBUG
    624 #define HB_DEBUG 0
    625 #endif
    626 
    627 static inline bool
    628 _hb_debug (unsigned int level,
    629 	   unsigned int max_level)
    630 {
    631   return level < max_level;
    632 }
    633 
    634 #define DEBUG_LEVEL_ENABLED(WHAT, LEVEL) (_hb_debug ((LEVEL), HB_DEBUG_##WHAT))
    635 #define DEBUG_ENABLED(WHAT) (DEBUG_LEVEL_ENABLED (WHAT, 0))
    636 
    637 static inline void
    638 _hb_print_func (const char *func)
    639 {
    640   if (func)
    641   {
    642     unsigned int func_len = strlen (func);
    643     /* Skip "static" */
    644     if (0 == strncmp (func, "static ", 7))
    645       func += 7;
    646     /* Skip "typename" */
    647     if (0 == strncmp (func, "typename ", 9))
    648       func += 9;
    649     /* Skip return type */
    650     const char *space = strchr (func, ' ');
    651     if (space)
    652       func = space + 1;
    653     /* Skip parameter list */
    654     const char *paren = strchr (func, '(');
    655     if (paren)
    656       func_len = paren - func;
    657     fprintf (stderr, "%.*s", func_len, func);
    658   }
    659 }
    660 
    661 template <int max_level> static inline void
    662 _hb_debug_msg_va (const char *what,
    663 		  const void *obj,
    664 		  const char *func,
    665 		  bool indented,
    666 		  unsigned int level,
    667 		  int level_dir,
    668 		  const char *message,
    669 		  va_list ap) HB_PRINTF_FUNC(7, 0);
    670 template <int max_level> static inline void
    671 _hb_debug_msg_va (const char *what,
    672 		  const void *obj,
    673 		  const char *func,
    674 		  bool indented,
    675 		  unsigned int level,
    676 		  int level_dir,
    677 		  const char *message,
    678 		  va_list ap)
    679 {
    680   if (!_hb_debug (level, max_level))
    681     return;
    682 
    683   fprintf (stderr, "%-10s", what ? what : "");
    684 
    685   if (obj)
    686     fprintf (stderr, "(%0*lx) ", (unsigned int) (2 * sizeof (void *)), (unsigned long) obj);
    687   else
    688     fprintf (stderr, " %*s  ", (unsigned int) (2 * sizeof (void *)), "");
    689 
    690   if (indented) {
    691 /* One may want to add ASCII version of these.  See:
    692  * https://bugs.freedesktop.org/show_bug.cgi?id=50970 */
    693 #define VBAR	"\342\224\202"	/* U+2502 BOX DRAWINGS LIGHT VERTICAL */
    694 #define VRBAR	"\342\224\234"	/* U+251C BOX DRAWINGS LIGHT VERTICAL AND RIGHT */
    695 #define DLBAR	"\342\225\256"	/* U+256E BOX DRAWINGS LIGHT ARC DOWN AND LEFT */
    696 #define ULBAR	"\342\225\257"	/* U+256F BOX DRAWINGS LIGHT ARC UP AND LEFT */
    697 #define LBAR	"\342\225\264"	/* U+2574 BOX DRAWINGS LIGHT LEFT */
    698     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;
    699     fprintf (stderr, "%2u %s" VRBAR "%s",
    700 	     level,
    701 	     bars + sizeof (bars) - 1 - MIN ((unsigned int) sizeof (bars), (unsigned int) (sizeof (VBAR) - 1) * level),
    702 	     level_dir ? (level_dir > 0 ? DLBAR : ULBAR) : LBAR);
    703   } else
    704     fprintf (stderr, "   " VRBAR LBAR);
    705 
    706   _hb_print_func (func);
    707 
    708   if (message)
    709   {
    710     fprintf (stderr, ": ");
    711     vfprintf (stderr, message, ap);
    712   }
    713 
    714   fprintf (stderr, "\n");
    715 }
    716 template <> inline void
    717 _hb_debug_msg_va<0> (const char *what HB_UNUSED,
    718 		     const void *obj HB_UNUSED,
    719 		     const char *func HB_UNUSED,
    720 		     bool indented HB_UNUSED,
    721 		     unsigned int level HB_UNUSED,
    722 		     int level_dir HB_UNUSED,
    723 		     const char *message HB_UNUSED,
    724 		     va_list ap HB_UNUSED) {}
    725 
    726 template <int max_level> static inline void
    727 _hb_debug_msg (const char *what,
    728 	       const void *obj,
    729 	       const char *func,
    730 	       bool indented,
    731 	       unsigned int level,
    732 	       int level_dir,
    733 	       const char *message,
    734 	       ...) HB_PRINTF_FUNC(7, 8);
    735 template <int max_level> static inline void
    736 _hb_debug_msg (const char *what,
    737 	       const void *obj,
    738 	       const char *func,
    739 	       bool indented,
    740 	       unsigned int level,
    741 	       int level_dir,
    742 	       const char *message,
    743 	       ...)
    744 {
    745   va_list ap;
    746   va_start (ap, message);
    747   _hb_debug_msg_va<max_level> (what, obj, func, indented, level, level_dir, message, ap);
    748   va_end (ap);
    749 }
    750 template <> inline void
    751 _hb_debug_msg<0> (const char *what HB_UNUSED,
    752 		  const void *obj HB_UNUSED,
    753 		  const char *func HB_UNUSED,
    754 		  bool indented HB_UNUSED,
    755 		  unsigned int level HB_UNUSED,
    756 		  int level_dir HB_UNUSED,
    757 		  const char *message HB_UNUSED,
    758 		  ...) HB_PRINTF_FUNC(7, 8);
    759 template <> inline void
    760 _hb_debug_msg<0> (const char *what HB_UNUSED,
    761 		  const void *obj HB_UNUSED,
    762 		  const char *func HB_UNUSED,
    763 		  bool indented HB_UNUSED,
    764 		  unsigned int level HB_UNUSED,
    765 		  int level_dir HB_UNUSED,
    766 		  const char *message HB_UNUSED,
    767 		  ...) {}
    768 
    769 #define DEBUG_MSG_LEVEL(WHAT, OBJ, LEVEL, LEVEL_DIR, ...)	_hb_debug_msg<HB_DEBUG_##WHAT> (#WHAT, (OBJ), NULL,    true, (LEVEL), (LEVEL_DIR), __VA_ARGS__)
    770 #define DEBUG_MSG(WHAT, OBJ, ...) 				_hb_debug_msg<HB_DEBUG_##WHAT> (#WHAT, (OBJ), NULL,    false, 0, 0, __VA_ARGS__)
    771 #define DEBUG_MSG_FUNC(WHAT, OBJ, ...)				_hb_debug_msg<HB_DEBUG_##WHAT> (#WHAT, (OBJ), HB_FUNC, false, 0, 0, __VA_ARGS__)
    772 
    773 
    774 /*
    775  * Printer
    776  */
    777 
    778 template <typename T>
    779 struct hb_printer_t {
    780   const char *print (const T&) { return "something"; }
    781 };
    782 
    783 template <>
    784 struct hb_printer_t<bool> {
    785   const char *print (bool v) { return v ? "true" : "false"; }
    786 };
    787 
    788 template <>
    789 struct hb_printer_t<hb_void_t> {
    790   const char *print (hb_void_t) { return ""; }
    791 };
    792 
    793 
    794 /*
    795  * Trace
    796  */
    797 
    798 template <typename T>
    799 static inline void _hb_warn_no_return (bool returned)
    800 {
    801   if (unlikely (!returned)) {
    802     fprintf (stderr, "OUCH, returned with no call to return_trace().  This is a bug, please report.\n");
    803   }
    804 }
    805 template <>
    806 /*static*/ inline void _hb_warn_no_return<hb_void_t> (bool returned HB_UNUSED)
    807 {}
    808 
    809 template <int max_level, typename ret_t>
    810 struct hb_auto_trace_t {
    811   explicit inline hb_auto_trace_t (unsigned int *plevel_,
    812 				   const char *what_,
    813 				   const void *obj_,
    814 				   const char *func,
    815 				   const char *message,
    816 				   ...) : plevel (plevel_), what (what_), obj (obj_), returned (false)
    817   {
    818     if (plevel) ++*plevel;
    819 
    820     va_list ap;
    821     va_start (ap, message);
    822     _hb_debug_msg_va<max_level> (what, obj, func, true, plevel ? *plevel : 0, +1, message, ap);
    823     va_end (ap);
    824   }
    825   inline ~hb_auto_trace_t (void)
    826   {
    827     _hb_warn_no_return<ret_t> (returned);
    828     if (!returned) {
    829       _hb_debug_msg<max_level> (what, obj, NULL, true, plevel ? *plevel : 1, -1, " ");
    830     }
    831     if (plevel) --*plevel;
    832   }
    833 
    834   inline ret_t ret (ret_t v, unsigned int line = 0)
    835   {
    836     if (unlikely (returned)) {
    837       fprintf (stderr, "OUCH, double calls to return_trace().  This is a bug, please report.\n");
    838       return v;
    839     }
    840 
    841     _hb_debug_msg<max_level> (what, obj, NULL, true, plevel ? *plevel : 1, -1,
    842 			      "return %s (line %d)",
    843 			      hb_printer_t<ret_t>().print (v), line);
    844     if (plevel) --*plevel;
    845     plevel = NULL;
    846     returned = true;
    847     return v;
    848   }
    849 
    850   private:
    851   unsigned int *plevel;
    852   const char *what;
    853   const void *obj;
    854   bool returned;
    855 };
    856 template <typename ret_t> /* Optimize when tracing is disabled */
    857 struct hb_auto_trace_t<0, ret_t> {
    858   explicit inline hb_auto_trace_t (unsigned int *plevel_ HB_UNUSED,
    859 				   const char *what HB_UNUSED,
    860 				   const void *obj HB_UNUSED,
    861 				   const char *func HB_UNUSED,
    862 				   const char *message HB_UNUSED,
    863 				   ...) {}
    864 
    865   inline ret_t ret (ret_t v, unsigned int line HB_UNUSED = 0) { return v; }
    866 };
    867 
    868 #define return_trace(RET) return trace.ret (RET, __LINE__)
    869 
    870 /* Misc */
    871 
    872 template <typename T> class hb_assert_unsigned_t;
    873 template <> class hb_assert_unsigned_t<unsigned char> {};
    874 template <> class hb_assert_unsigned_t<unsigned short> {};
    875 template <> class hb_assert_unsigned_t<unsigned int> {};
    876 template <> class hb_assert_unsigned_t<unsigned long> {};
    877 
    878 template <typename T> static inline bool
    879 hb_in_range (T u, T lo, T hi)
    880 {
    881   /* The sizeof() is here to force template instantiation.
    882    * I'm sure there are better ways to do this but can't think of
    883    * one right now.  Declaring a variable won't work as HB_UNUSED
    884    * is unusable on some platforms and unused types are less likely
    885    * to generate a warning than unused variables. */
    886   ASSERT_STATIC (sizeof (hb_assert_unsigned_t<T>) >= 0);
    887 
    888   /* The casts below are important as if T is smaller than int,
    889    * the subtract results will become a signed int! */
    890   return (T)(u - lo) <= (T)(hi - lo);
    891 }
    892 
    893 template <typename T> static inline bool
    894 hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2)
    895 {
    896   return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2);
    897 }
    898 
    899 template <typename T> static inline bool
    900 hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3)
    901 {
    902   return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2) || hb_in_range (u, lo3, hi3);
    903 }
    904 
    905 
    906 /* Enable bitwise ops on enums marked as flags_t */
    907 /* To my surprise, looks like the function resolver is happy to silently cast
    908  * one enum to another...  So this doesn't provide the type-checking that I
    909  * originally had in mind... :(.
    910  *
    911  * For MSVC warnings, see: https://github.com/behdad/harfbuzz/pull/163
    912  */
    913 #ifdef _MSC_VER
    914 # pragma warning(disable:4200)
    915 # pragma warning(disable:4800)
    916 #endif
    917 #define HB_MARK_AS_FLAG_T(T) \
    918 	extern "C++" { \
    919 	  static inline T operator | (T l, T r) { return T ((unsigned) l | (unsigned) r); } \
    920 	  static inline T operator & (T l, T r) { return T ((unsigned) l & (unsigned) r); } \
    921 	  static inline T operator ^ (T l, T r) { return T ((unsigned) l ^ (unsigned) r); } \
    922 	  static inline T operator ~ (T r) { return T (~(unsigned int) r); } \
    923 	  static inline T& operator |= (T &l, T r) { l = l | r; return l; } \
    924 	  static inline T& operator &= (T& l, T r) { l = l & r; return l; } \
    925 	  static inline T& operator ^= (T& l, T r) { l = l ^ r; return l; } \
    926 	}
    927 
    928 
    929 /* Useful for set-operations on small enums.
    930  * For example, for testing "x  {x1, x2, x3}" use:
    931  * (FLAG_SAFE(x) & (FLAG(x1) | FLAG(x2) | FLAG(x3)))
    932  */
    933 #define FLAG(x) (ASSERT_STATIC_EXPR_ZERO ((x) < 32) + (1U << (x)))
    934 #define FLAG_SAFE(x) (1U << (x))
    935 #define FLAG_UNSAFE(x) ((x) < 32 ? FLAG_SAFE(x) : 0)
    936 #define FLAG_RANGE(x,y) (ASSERT_STATIC_EXPR_ZERO ((x) < (y)) + FLAG(y+1) - FLAG(x))
    937 
    938 
    939 template <typename T, typename T2> static inline void
    940 hb_stable_sort (T *array, unsigned int len, int(*compar)(const T *, const T *), T2 *array2)
    941 {
    942   for (unsigned int i = 1; i < len; i++)
    943   {
    944     unsigned int j = i;
    945     while (j && compar (&array[j - 1], &array[i]) > 0)
    946       j--;
    947     if (i == j)
    948       continue;
    949     /* Move item i to occupy place for item j, shift what's in between. */
    950     {
    951       T t = array[i];
    952       memmove (&array[j + 1], &array[j], (i - j) * sizeof (T));
    953       array[j] = t;
    954     }
    955     if (array2)
    956     {
    957       T2 t = array2[i];
    958       memmove (&array2[j + 1], &array2[j], (i - j) * sizeof (T2));
    959       array2[j] = t;
    960     }
    961   }
    962 }
    963 
    964 template <typename T> static inline void
    965 hb_stable_sort (T *array, unsigned int len, int(*compar)(const T *, const T *))
    966 {
    967   hb_stable_sort (array, len, compar, (int *) NULL);
    968 }
    969 
    970 static inline hb_bool_t
    971 hb_codepoint_parse (const char *s, unsigned int len, int base, hb_codepoint_t *out)
    972 {
    973   /* Pain because we don't know whether s is nul-terminated. */
    974   char buf[64];
    975   len = MIN (ARRAY_LENGTH (buf) - 1, len);
    976   strncpy (buf, s, len);
    977   buf[len] = '\0';
    978 
    979   char *end;
    980   errno = 0;
    981   unsigned long v = strtoul (buf, &end, base);
    982   if (errno) return false;
    983   if (*end) return false;
    984   *out = v;
    985   return true;
    986 }
    987 
    988 
    989 /* Global runtime options. */
    990 
    991 struct hb_options_t
    992 {
    993   unsigned int initialized : 1;
    994   unsigned int uniscribe_bug_compatible : 1;
    995 };
    996 
    997 union hb_options_union_t {
    998   unsigned int i;
    999   hb_options_t opts;
   1000 };
   1001 ASSERT_STATIC (sizeof (int) == sizeof (hb_options_union_t));
   1002 
   1003 HB_INTERNAL void
   1004 _hb_options_init (void);
   1005 
   1006 extern HB_INTERNAL hb_options_union_t _hb_options;
   1007 
   1008 static inline hb_options_t
   1009 hb_options (void)
   1010 {
   1011   if (unlikely (!_hb_options.i))
   1012     _hb_options_init ();
   1013 
   1014   return _hb_options.opts;
   1015 }
   1016 
   1017 /* Size signifying variable-sized array */
   1018 #define VAR 1
   1019 
   1020 #endif /* HB_PRIVATE_HH */
   1021