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 #if !defined(__GNUC__) && !defined(__clang__)
     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 vsnprintf _vsnprintf
    173 #    define getenv(Name) NULL
    174 #    if _WIN32_WCE < 0x800
    175 #      define setlocale(Category, Locale) "C"
    176 static int errno = 0; /* Use something better? */
    177 #    endif
    178 #  elif defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP)
    179 #    define getenv(Name) NULL
    180 #  endif
    181 #  if defined(_MSC_VER) && _MSC_VER < 1900
    182 #    define snprintf _snprintf
    183 #  elif defined(_MSC_VER) && _MSC_VER >= 1900
    184 #    /* Covers VC++ Error for strdup being a deprecated POSIX name and to instead use _strdup instead */
    185 #    define strdup _strdup
    186 #  endif
    187 #endif
    188 
    189 #if HAVE_ATEXIT
    190 /* atexit() is only safe to be called from shared libraries on certain
    191  * platforms.  Whitelist.
    192  * https://bugs.freedesktop.org/show_bug.cgi?id=82246 */
    193 #  if defined(__linux) && defined(__GLIBC_PREREQ)
    194 #    if __GLIBC_PREREQ(2,3)
    195 /* From atexit() manpage, it's safe with glibc 2.2.3 on Linux. */
    196 #      define HB_USE_ATEXIT 1
    197 #    endif
    198 #  elif defined(_MSC_VER) || defined(__MINGW32__)
    199 /* For MSVC:
    200  * http://msdn.microsoft.com/en-ca/library/tze57ck3.aspx
    201  * http://msdn.microsoft.com/en-ca/library/zk17ww08.aspx
    202  * mingw32 headers say atexit is safe to use in shared libraries.
    203  */
    204 #    define HB_USE_ATEXIT 1
    205 #  elif defined(__ANDROID__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
    206 /* This was fixed in Android NKD r8 or r8b:
    207  * https://code.google.com/p/android/issues/detail?id=6455
    208  * which introduced GCC 4.6:
    209  * https://developer.android.com/tools/sdk/ndk/index.html
    210  */
    211 #    define HB_USE_ATEXIT 1
    212 #  endif
    213 #endif
    214 
    215 /* Basics */
    216 
    217 
    218 #ifndef NULL
    219 # define NULL ((void *) 0)
    220 #endif
    221 
    222 #undef MIN
    223 template <typename Type>
    224 static inline Type MIN (const Type &a, const Type &b) { return a < b ? a : b; }
    225 
    226 #undef MAX
    227 template <typename Type>
    228 static inline Type MAX (const Type &a, const Type &b) { return a > b ? a : b; }
    229 
    230 static inline unsigned int DIV_CEIL (const unsigned int a, unsigned int b)
    231 { return (a + (b - 1)) / b; }
    232 
    233 
    234 #undef  ARRAY_LENGTH
    235 template <typename Type, unsigned int n>
    236 static inline unsigned int ARRAY_LENGTH (const Type (&)[n]) { return n; }
    237 /* A const version, but does not detect erratically being called on pointers. */
    238 #define ARRAY_LENGTH_CONST(__array) ((signed int) (sizeof (__array) / sizeof (__array[0])))
    239 
    240 #define HB_STMT_START do
    241 #define HB_STMT_END   while (0)
    242 
    243 #define _ASSERT_STATIC1(_line, _cond)	HB_UNUSED typedef int _static_assert_on_line_##_line##_failed[(_cond)?1:-1]
    244 #define _ASSERT_STATIC0(_line, _cond)	_ASSERT_STATIC1 (_line, (_cond))
    245 #define ASSERT_STATIC(_cond)		_ASSERT_STATIC0 (__LINE__, (_cond))
    246 
    247 template <unsigned int cond> class hb_assert_constant_t {};
    248 
    249 #define ASSERT_STATIC_EXPR_ZERO(_cond) (0 * (unsigned int) sizeof (hb_assert_constant_t<_cond>))
    250 
    251 #define _PASTE1(a,b) a##b
    252 #define PASTE(a,b) _PASTE1(a,b)
    253 
    254 /* Lets assert int types.  Saves trouble down the road. */
    255 
    256 ASSERT_STATIC (sizeof (int8_t) == 1);
    257 ASSERT_STATIC (sizeof (uint8_t) == 1);
    258 ASSERT_STATIC (sizeof (int16_t) == 2);
    259 ASSERT_STATIC (sizeof (uint16_t) == 2);
    260 ASSERT_STATIC (sizeof (int32_t) == 4);
    261 ASSERT_STATIC (sizeof (uint32_t) == 4);
    262 ASSERT_STATIC (sizeof (int64_t) == 8);
    263 ASSERT_STATIC (sizeof (uint64_t) == 8);
    264 
    265 ASSERT_STATIC (sizeof (hb_codepoint_t) == 4);
    266 ASSERT_STATIC (sizeof (hb_position_t) == 4);
    267 ASSERT_STATIC (sizeof (hb_mask_t) == 4);
    268 ASSERT_STATIC (sizeof (hb_var_int_t) == 4);
    269 
    270 
    271 /* We like our types POD */
    272 
    273 #define _ASSERT_TYPE_POD1(_line, _type)	union _type_##_type##_on_line_##_line##_is_not_POD { _type instance; }
    274 #define _ASSERT_TYPE_POD0(_line, _type)	_ASSERT_TYPE_POD1 (_line, _type)
    275 #define ASSERT_TYPE_POD(_type)		_ASSERT_TYPE_POD0 (__LINE__, _type)
    276 
    277 #ifdef __GNUC__
    278 # define _ASSERT_INSTANCE_POD1(_line, _instance) \
    279 	HB_STMT_START { \
    280 		typedef __typeof__(_instance) _type_##_line; \
    281 		_ASSERT_TYPE_POD1 (_line, _type_##_line); \
    282 	} HB_STMT_END
    283 #else
    284 # define _ASSERT_INSTANCE_POD1(_line, _instance)	typedef int _assertion_on_line_##_line##_not_tested
    285 #endif
    286 # define _ASSERT_INSTANCE_POD0(_line, _instance)	_ASSERT_INSTANCE_POD1 (_line, _instance)
    287 # define ASSERT_INSTANCE_POD(_instance)			_ASSERT_INSTANCE_POD0 (__LINE__, _instance)
    288 
    289 /* Check _assertion in a method environment */
    290 #define _ASSERT_POD1(_line) \
    291 	HB_UNUSED inline void _static_assertion_on_line_##_line (void) const \
    292 	{ _ASSERT_INSTANCE_POD1 (_line, *this); /* Make sure it's POD. */ }
    293 # define _ASSERT_POD0(_line)	_ASSERT_POD1 (_line)
    294 # define ASSERT_POD()		_ASSERT_POD0 (__LINE__)
    295 
    296 
    297 
    298 /* Misc */
    299 
    300 /* Void! */
    301 struct _hb_void_t {};
    302 typedef const _hb_void_t *hb_void_t;
    303 #define HB_VOID ((const _hb_void_t *) NULL)
    304 
    305 /* Return the number of 1 bits in mask. */
    306 static inline HB_CONST_FUNC unsigned int
    307 _hb_popcount32 (uint32_t mask)
    308 {
    309 #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
    310   return __builtin_popcount (mask);
    311 #else
    312   /* "HACKMEM 169" */
    313   uint32_t y;
    314   y = (mask >> 1) &033333333333;
    315   y = mask - y - ((y >>1) & 033333333333);
    316   return (((y + (y >> 3)) & 030707070707) % 077);
    317 #endif
    318 }
    319 
    320 /* Returns the number of bits needed to store number */
    321 static inline HB_CONST_FUNC unsigned int
    322 _hb_bit_storage (unsigned int number)
    323 {
    324 #if defined(__GNUC__) && (__GNUC__ >= 4) && defined(__OPTIMIZE__)
    325   return likely (number) ? (sizeof (unsigned int) * 8 - __builtin_clz (number)) : 0;
    326 #else
    327   unsigned int n_bits = 0;
    328   while (number) {
    329     n_bits++;
    330     number >>= 1;
    331   }
    332   return n_bits;
    333 #endif
    334 }
    335 
    336 /* Returns the number of zero bits in the least significant side of number */
    337 static inline HB_CONST_FUNC unsigned int
    338 _hb_ctz (unsigned int number)
    339 {
    340 #if defined(__GNUC__) && (__GNUC__ >= 4) && defined(__OPTIMIZE__)
    341   return likely (number) ? __builtin_ctz (number) : 0;
    342 #else
    343   unsigned int n_bits = 0;
    344   if (unlikely (!number)) return 0;
    345   while (!(number & 1)) {
    346     n_bits++;
    347     number >>= 1;
    348   }
    349   return n_bits;
    350 #endif
    351 }
    352 
    353 static inline bool
    354 _hb_unsigned_int_mul_overflows (unsigned int count, unsigned int size)
    355 {
    356   return (size > 0) && (count >= ((unsigned int) -1) / size);
    357 }
    358 
    359 
    360 /* Type of bsearch() / qsort() compare function */
    361 typedef int (*hb_compare_func_t) (const void *, const void *);
    362 
    363 
    364 
    365 
    366 /* arrays and maps */
    367 
    368 
    369 #define HB_PREALLOCED_ARRAY_INIT {0, 0, NULL}
    370 template <typename Type, unsigned int StaticSize=16>
    371 struct hb_prealloced_array_t
    372 {
    373   unsigned int len;
    374   unsigned int allocated;
    375   Type *array;
    376   Type static_array[StaticSize];
    377 
    378   void init (void) { memset (this, 0, sizeof (*this)); }
    379 
    380   inline Type& operator [] (unsigned int i) { return array[i]; }
    381   inline const Type& operator [] (unsigned int i) const { return array[i]; }
    382 
    383   inline Type *push (void)
    384   {
    385     if (!array) {
    386       array = static_array;
    387       allocated = ARRAY_LENGTH (static_array);
    388     }
    389     if (likely (len < allocated))
    390       return &array[len++];
    391 
    392     /* Need to reallocate */
    393     unsigned int new_allocated = allocated + (allocated >> 1) + 8;
    394     Type *new_array = NULL;
    395 
    396     if (array == static_array) {
    397       new_array = (Type *) calloc (new_allocated, sizeof (Type));
    398       if (new_array)
    399         memcpy (new_array, array, len * sizeof (Type));
    400     } else {
    401       bool overflows = (new_allocated < allocated) || _hb_unsigned_int_mul_overflows (new_allocated, sizeof (Type));
    402       if (likely (!overflows)) {
    403 	new_array = (Type *) realloc (array, new_allocated * sizeof (Type));
    404       }
    405     }
    406 
    407     if (unlikely (!new_array))
    408       return NULL;
    409 
    410     array = new_array;
    411     allocated = new_allocated;
    412     return &array[len++];
    413   }
    414 
    415   inline void pop (void)
    416   {
    417     len--;
    418   }
    419 
    420   inline void remove (unsigned int i)
    421   {
    422      if (unlikely (i >= len))
    423        return;
    424      memmove (static_cast<void *> (&array[i]),
    425 	      static_cast<void *> (&array[i + 1]),
    426 	      (len - i - 1) * sizeof (Type));
    427      len--;
    428   }
    429 
    430   inline void shrink (unsigned int l)
    431   {
    432      if (l < len)
    433        len = l;
    434   }
    435 
    436   template <typename T>
    437   inline Type *find (T v) {
    438     for (unsigned int i = 0; i < len; i++)
    439       if (array[i] == v)
    440 	return &array[i];
    441     return NULL;
    442   }
    443   template <typename T>
    444   inline const Type *find (T v) const {
    445     for (unsigned int i = 0; i < len; i++)
    446       if (array[i] == v)
    447 	return &array[i];
    448     return NULL;
    449   }
    450 
    451   inline void qsort (void)
    452   {
    453     ::qsort (array, len, sizeof (Type), (hb_compare_func_t) Type::cmp);
    454   }
    455 
    456   inline void qsort (unsigned int start, unsigned int end)
    457   {
    458     ::qsort (array + start, end - start, sizeof (Type), (hb_compare_func_t) Type::cmp);
    459   }
    460 
    461   template <typename T>
    462   inline Type *bsearch (T *key)
    463   {
    464     return (Type *) ::bsearch (key, array, len, sizeof (Type), (hb_compare_func_t) Type::cmp);
    465   }
    466   template <typename T>
    467   inline const Type *bsearch (T *key) const
    468   {
    469     return (const Type *) ::bsearch (key, array, len, sizeof (Type), (hb_compare_func_t) Type::cmp);
    470   }
    471 
    472   inline void finish (void)
    473   {
    474     if (array != static_array)
    475       free (array);
    476     array = NULL;
    477     allocated = len = 0;
    478   }
    479 };
    480 
    481 template <typename Type>
    482 struct hb_auto_array_t : hb_prealloced_array_t <Type>
    483 {
    484   hb_auto_array_t (void) { hb_prealloced_array_t<Type>::init (); }
    485   ~hb_auto_array_t (void) { hb_prealloced_array_t<Type>::finish (); }
    486 };
    487 
    488 
    489 #define HB_LOCKABLE_SET_INIT {HB_PREALLOCED_ARRAY_INIT}
    490 template <typename item_t, typename lock_t>
    491 struct hb_lockable_set_t
    492 {
    493   hb_prealloced_array_t <item_t, 2> items;
    494 
    495   inline void init (void) { items.init (); }
    496 
    497   template <typename T>
    498   inline item_t *replace_or_insert (T v, lock_t &l, bool replace)
    499   {
    500     l.lock ();
    501     item_t *item = items.find (v);
    502     if (item) {
    503       if (replace) {
    504 	item_t old = *item;
    505 	*item = v;
    506 	l.unlock ();
    507 	old.finish ();
    508       }
    509       else {
    510         item = NULL;
    511 	l.unlock ();
    512       }
    513     } else {
    514       item = items.push ();
    515       if (likely (item))
    516 	*item = v;
    517       l.unlock ();
    518     }
    519     return item;
    520   }
    521 
    522   template <typename T>
    523   inline void remove (T v, lock_t &l)
    524   {
    525     l.lock ();
    526     item_t *item = items.find (v);
    527     if (item) {
    528       item_t old = *item;
    529       *item = items[items.len - 1];
    530       items.pop ();
    531       l.unlock ();
    532       old.finish ();
    533     } else {
    534       l.unlock ();
    535     }
    536   }
    537 
    538   template <typename T>
    539   inline bool find (T v, item_t *i, lock_t &l)
    540   {
    541     l.lock ();
    542     item_t *item = items.find (v);
    543     if (item)
    544       *i = *item;
    545     l.unlock ();
    546     return !!item;
    547   }
    548 
    549   template <typename T>
    550   inline item_t *find_or_insert (T v, lock_t &l)
    551   {
    552     l.lock ();
    553     item_t *item = items.find (v);
    554     if (!item) {
    555       item = items.push ();
    556       if (likely (item))
    557         *item = v;
    558     }
    559     l.unlock ();
    560     return item;
    561   }
    562 
    563   inline void finish (lock_t &l)
    564   {
    565     if (!items.len) {
    566       /* No need for locking. */
    567       items.finish ();
    568       return;
    569     }
    570     l.lock ();
    571     while (items.len) {
    572       item_t old = items[items.len - 1];
    573 	items.pop ();
    574 	l.unlock ();
    575 	old.finish ();
    576 	l.lock ();
    577     }
    578     items.finish ();
    579     l.unlock ();
    580   }
    581 
    582 };
    583 
    584 
    585 /* ASCII tag/character handling */
    586 
    587 static inline bool ISALPHA (unsigned char c)
    588 { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); }
    589 static inline bool ISALNUM (unsigned char c)
    590 { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'); }
    591 static inline bool ISSPACE (unsigned char c)
    592 { return c == ' ' || c =='\f'|| c =='\n'|| c =='\r'|| c =='\t'|| c =='\v'; }
    593 static inline unsigned char TOUPPER (unsigned char c)
    594 { return (c >= 'a' && c <= 'z') ? c - 'a' + 'A' : c; }
    595 static inline unsigned char TOLOWER (unsigned char c)
    596 { return (c >= 'A' && c <= 'Z') ? c - 'A' + 'a' : c; }
    597 
    598 #define HB_TAG_CHAR4(s)   (HB_TAG(((const char *) s)[0], \
    599 				  ((const char *) s)[1], \
    600 				  ((const char *) s)[2], \
    601 				  ((const char *) s)[3]))
    602 
    603 
    604 /* C++ helpers */
    605 
    606 /* Makes class uncopyable.  Use in private: section. */
    607 #define NO_COPY(T) \
    608   T (const T &o); \
    609   T &operator = (const T &o)
    610 
    611 
    612 /* Debug */
    613 
    614 
    615 /* HB_NDEBUG disables some sanity checks that are very safe to disable and
    616  * should be disabled in production systems.  If NDEBUG is defined, enable
    617  * HB_NDEBUG; but if it's desirable that normal assert()s (which are very
    618  * light-weight) to be enabled, then HB_DEBUG can be defined to disable
    619  * the costlier checks. */
    620 #ifdef NDEBUG
    621 #define HB_NDEBUG
    622 #endif
    623 
    624 #ifndef HB_DEBUG
    625 #define HB_DEBUG 0
    626 #endif
    627 
    628 static inline bool
    629 _hb_debug (unsigned int level,
    630 	   unsigned int max_level)
    631 {
    632   return level < max_level;
    633 }
    634 
    635 #define DEBUG_LEVEL_ENABLED(WHAT, LEVEL) (_hb_debug ((LEVEL), HB_DEBUG_##WHAT))
    636 #define DEBUG_ENABLED(WHAT) (DEBUG_LEVEL_ENABLED (WHAT, 0))
    637 
    638 static inline void
    639 _hb_print_func (const char *func)
    640 {
    641   if (func)
    642   {
    643     unsigned int func_len = strlen (func);
    644     /* Skip "static" */
    645     if (0 == strncmp (func, "static ", 7))
    646       func += 7;
    647     /* Skip "typename" */
    648     if (0 == strncmp (func, "typename ", 9))
    649       func += 9;
    650     /* Skip return type */
    651     const char *space = strchr (func, ' ');
    652     if (space)
    653       func = space + 1;
    654     /* Skip parameter list */
    655     const char *paren = strchr (func, '(');
    656     if (paren)
    657       func_len = paren - func;
    658     fprintf (stderr, "%.*s", func_len, func);
    659   }
    660 }
    661 
    662 template <int max_level> static inline void
    663 _hb_debug_msg_va (const char *what,
    664 		  const void *obj,
    665 		  const char *func,
    666 		  bool indented,
    667 		  unsigned int level,
    668 		  int level_dir,
    669 		  const char *message,
    670 		  va_list ap) HB_PRINTF_FUNC(7, 0);
    671 template <int max_level> static inline void
    672 _hb_debug_msg_va (const char *what,
    673 		  const void *obj,
    674 		  const char *func,
    675 		  bool indented,
    676 		  unsigned int level,
    677 		  int level_dir,
    678 		  const char *message,
    679 		  va_list ap)
    680 {
    681   if (!_hb_debug (level, max_level))
    682     return;
    683 
    684   fprintf (stderr, "%-10s", what ? what : "");
    685 
    686   if (obj)
    687     fprintf (stderr, "(%0*lx) ", (unsigned int) (2 * sizeof (void *)), (unsigned long) obj);
    688   else
    689     fprintf (stderr, " %*s  ", (unsigned int) (2 * sizeof (void *)), "");
    690 
    691   if (indented) {
    692 #define VBAR	"\342\224\202"	/* U+2502 BOX DRAWINGS LIGHT VERTICAL */
    693 #define VRBAR	"\342\224\234"	/* U+251C BOX DRAWINGS LIGHT VERTICAL AND RIGHT */
    694 #define DLBAR	"\342\225\256"	/* U+256E BOX DRAWINGS LIGHT ARC DOWN AND LEFT */
    695 #define ULBAR	"\342\225\257"	/* U+256F BOX DRAWINGS LIGHT ARC UP AND LEFT */
    696 #define LBAR	"\342\225\264"	/* U+2574 BOX DRAWINGS LIGHT LEFT */
    697     static const char bars[] =
    698       VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR
    699       VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR
    700       VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR
    701       VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR
    702       VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR;
    703     fprintf (stderr, "%2u %s" VRBAR "%s",
    704 	     level,
    705 	     bars + sizeof (bars) - 1 - MIN ((unsigned int) sizeof (bars) - 1, (unsigned int) (sizeof (VBAR) - 1) * level),
    706 	     level_dir ? (level_dir > 0 ? DLBAR : ULBAR) : LBAR);
    707   } else
    708     fprintf (stderr, "   " VRBAR LBAR);
    709 
    710   _hb_print_func (func);
    711 
    712   if (message)
    713   {
    714     fprintf (stderr, ": ");
    715     vfprintf (stderr, message, ap);
    716   }
    717 
    718   fprintf (stderr, "\n");
    719 }
    720 template <> inline void
    721 _hb_debug_msg_va<0> (const char *what HB_UNUSED,
    722 		     const void *obj HB_UNUSED,
    723 		     const char *func HB_UNUSED,
    724 		     bool indented HB_UNUSED,
    725 		     unsigned int level HB_UNUSED,
    726 		     int level_dir HB_UNUSED,
    727 		     const char *message HB_UNUSED,
    728 		     va_list ap HB_UNUSED) {}
    729 
    730 template <int max_level> static inline void
    731 _hb_debug_msg (const char *what,
    732 	       const void *obj,
    733 	       const char *func,
    734 	       bool indented,
    735 	       unsigned int level,
    736 	       int level_dir,
    737 	       const char *message,
    738 	       ...) HB_PRINTF_FUNC(7, 8);
    739 template <int max_level> static inline void
    740 _hb_debug_msg (const char *what,
    741 	       const void *obj,
    742 	       const char *func,
    743 	       bool indented,
    744 	       unsigned int level,
    745 	       int level_dir,
    746 	       const char *message,
    747 	       ...)
    748 {
    749   va_list ap;
    750   va_start (ap, message);
    751   _hb_debug_msg_va<max_level> (what, obj, func, indented, level, level_dir, message, ap);
    752   va_end (ap);
    753 }
    754 template <> inline void
    755 _hb_debug_msg<0> (const char *what HB_UNUSED,
    756 		  const void *obj HB_UNUSED,
    757 		  const char *func HB_UNUSED,
    758 		  bool indented HB_UNUSED,
    759 		  unsigned int level HB_UNUSED,
    760 		  int level_dir HB_UNUSED,
    761 		  const char *message HB_UNUSED,
    762 		  ...) HB_PRINTF_FUNC(7, 8);
    763 template <> inline void
    764 _hb_debug_msg<0> (const char *what HB_UNUSED,
    765 		  const void *obj HB_UNUSED,
    766 		  const char *func HB_UNUSED,
    767 		  bool indented HB_UNUSED,
    768 		  unsigned int level HB_UNUSED,
    769 		  int level_dir HB_UNUSED,
    770 		  const char *message HB_UNUSED,
    771 		  ...) {}
    772 
    773 #define DEBUG_MSG_LEVEL(WHAT, OBJ, LEVEL, LEVEL_DIR, ...)	_hb_debug_msg<HB_DEBUG_##WHAT> (#WHAT, (OBJ), NULL,    true, (LEVEL), (LEVEL_DIR), __VA_ARGS__)
    774 #define DEBUG_MSG(WHAT, OBJ, ...) 				_hb_debug_msg<HB_DEBUG_##WHAT> (#WHAT, (OBJ), NULL,    false, 0, 0, __VA_ARGS__)
    775 #define DEBUG_MSG_FUNC(WHAT, OBJ, ...)				_hb_debug_msg<HB_DEBUG_##WHAT> (#WHAT, (OBJ), HB_FUNC, false, 0, 0, __VA_ARGS__)
    776 
    777 
    778 /*
    779  * Printer
    780  */
    781 
    782 template <typename T>
    783 struct hb_printer_t {
    784   const char *print (const T&) { return "something"; }
    785 };
    786 
    787 template <>
    788 struct hb_printer_t<bool> {
    789   const char *print (bool v) { return v ? "true" : "false"; }
    790 };
    791 
    792 template <>
    793 struct hb_printer_t<hb_void_t> {
    794   const char *print (hb_void_t) { return ""; }
    795 };
    796 
    797 
    798 /*
    799  * Trace
    800  */
    801 
    802 template <typename T>
    803 static inline void _hb_warn_no_return (bool returned)
    804 {
    805   if (unlikely (!returned)) {
    806     fprintf (stderr, "OUCH, returned with no call to return_trace().  This is a bug, please report.\n");
    807   }
    808 }
    809 template <>
    810 /*static*/ inline void _hb_warn_no_return<hb_void_t> (bool returned HB_UNUSED)
    811 {}
    812 
    813 template <int max_level, typename ret_t>
    814 struct hb_auto_trace_t {
    815   explicit inline hb_auto_trace_t (unsigned int *plevel_,
    816 				   const char *what_,
    817 				   const void *obj_,
    818 				   const char *func,
    819 				   const char *message,
    820 				   ...) : plevel (plevel_), what (what_), obj (obj_), returned (false)
    821   {
    822     if (plevel) ++*plevel;
    823 
    824     va_list ap;
    825     va_start (ap, message);
    826     _hb_debug_msg_va<max_level> (what, obj, func, true, plevel ? *plevel : 0, +1, message, ap);
    827     va_end (ap);
    828   }
    829   inline ~hb_auto_trace_t (void)
    830   {
    831     _hb_warn_no_return<ret_t> (returned);
    832     if (!returned) {
    833       _hb_debug_msg<max_level> (what, obj, NULL, true, plevel ? *plevel : 1, -1, " ");
    834     }
    835     if (plevel) --*plevel;
    836   }
    837 
    838   inline ret_t ret (ret_t v, unsigned int line = 0)
    839   {
    840     if (unlikely (returned)) {
    841       fprintf (stderr, "OUCH, double calls to return_trace().  This is a bug, please report.\n");
    842       return v;
    843     }
    844 
    845     _hb_debug_msg<max_level> (what, obj, NULL, true, plevel ? *plevel : 1, -1,
    846 			      "return %s (line %d)",
    847 			      hb_printer_t<ret_t>().print (v), line);
    848     if (plevel) --*plevel;
    849     plevel = NULL;
    850     returned = true;
    851     return v;
    852   }
    853 
    854   private:
    855   unsigned int *plevel;
    856   const char *what;
    857   const void *obj;
    858   bool returned;
    859 };
    860 template <typename ret_t> /* Optimize when tracing is disabled */
    861 struct hb_auto_trace_t<0, ret_t> {
    862   explicit inline hb_auto_trace_t (unsigned int *plevel_ HB_UNUSED,
    863 				   const char *what HB_UNUSED,
    864 				   const void *obj HB_UNUSED,
    865 				   const char *func HB_UNUSED,
    866 				   const char *message HB_UNUSED,
    867 				   ...) {}
    868 
    869   inline ret_t ret (ret_t v, unsigned int line HB_UNUSED = 0) { return v; }
    870 };
    871 
    872 #define return_trace(RET) return trace.ret (RET, __LINE__)
    873 
    874 /* Misc */
    875 
    876 template <typename T> class hb_assert_unsigned_t;
    877 template <> class hb_assert_unsigned_t<unsigned char> {};
    878 template <> class hb_assert_unsigned_t<unsigned short> {};
    879 template <> class hb_assert_unsigned_t<unsigned int> {};
    880 template <> class hb_assert_unsigned_t<unsigned long> {};
    881 
    882 template <typename T> static inline bool
    883 hb_in_range (T u, T lo, T hi)
    884 {
    885   /* The sizeof() is here to force template instantiation.
    886    * I'm sure there are better ways to do this but can't think of
    887    * one right now.  Declaring a variable won't work as HB_UNUSED
    888    * is unusable on some platforms and unused types are less likely
    889    * to generate a warning than unused variables. */
    890   ASSERT_STATIC (sizeof (hb_assert_unsigned_t<T>) >= 0);
    891 
    892   /* The casts below are important as if T is smaller than int,
    893    * the subtract results will become a signed int! */
    894   return (T)(u - lo) <= (T)(hi - lo);
    895 }
    896 
    897 template <typename T> static inline bool
    898 hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2)
    899 {
    900   return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2);
    901 }
    902 
    903 template <typename T> static inline bool
    904 hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3)
    905 {
    906   return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2) || hb_in_range (u, lo3, hi3);
    907 }
    908 
    909 
    910 /* Enable bitwise ops on enums marked as flags_t */
    911 /* To my surprise, looks like the function resolver is happy to silently cast
    912  * one enum to another...  So this doesn't provide the type-checking that I
    913  * originally had in mind... :(.
    914  *
    915  * For MSVC warnings, see: https://github.com/behdad/harfbuzz/pull/163
    916  */
    917 #ifdef _MSC_VER
    918 # pragma warning(disable:4200)
    919 # pragma warning(disable:4800)
    920 #endif
    921 #define HB_MARK_AS_FLAG_T(T) \
    922 	extern "C++" { \
    923 	  static inline T operator | (T l, T r) { return T ((unsigned) l | (unsigned) r); } \
    924 	  static inline T operator & (T l, T r) { return T ((unsigned) l & (unsigned) r); } \
    925 	  static inline T operator ^ (T l, T r) { return T ((unsigned) l ^ (unsigned) r); } \
    926 	  static inline T operator ~ (T r) { return T (~(unsigned int) r); } \
    927 	  static inline T& operator |= (T &l, T r) { l = l | r; return l; } \
    928 	  static inline T& operator &= (T& l, T r) { l = l & r; return l; } \
    929 	  static inline T& operator ^= (T& l, T r) { l = l ^ r; return l; } \
    930 	}
    931 
    932 
    933 /* Useful for set-operations on small enums.
    934  * For example, for testing "x  {x1, x2, x3}" use:
    935  * (FLAG_SAFE(x) & (FLAG(x1) | FLAG(x2) | FLAG(x3)))
    936  */
    937 #define FLAG(x) (ASSERT_STATIC_EXPR_ZERO ((x) < 32) + (1U << (x)))
    938 #define FLAG_SAFE(x) (1U << (x))
    939 #define FLAG_UNSAFE(x) ((x) < 32 ? FLAG_SAFE(x) : 0)
    940 #define FLAG_RANGE(x,y) (ASSERT_STATIC_EXPR_ZERO ((x) < (y)) + FLAG(y+1) - FLAG(x))
    941 
    942 
    943 template <typename T, typename T2> static inline void
    944 hb_stable_sort (T *array, unsigned int len, int(*compar)(const T *, const T *), T2 *array2)
    945 {
    946   for (unsigned int i = 1; i < len; i++)
    947   {
    948     unsigned int j = i;
    949     while (j && compar (&array[j - 1], &array[i]) > 0)
    950       j--;
    951     if (i == j)
    952       continue;
    953     /* Move item i to occupy place for item j, shift what's in between. */
    954     {
    955       T t = array[i];
    956       memmove (&array[j + 1], &array[j], (i - j) * sizeof (T));
    957       array[j] = t;
    958     }
    959     if (array2)
    960     {
    961       T2 t = array2[i];
    962       memmove (&array2[j + 1], &array2[j], (i - j) * sizeof (T2));
    963       array2[j] = t;
    964     }
    965   }
    966 }
    967 
    968 template <typename T> static inline void
    969 hb_stable_sort (T *array, unsigned int len, int(*compar)(const T *, const T *))
    970 {
    971   hb_stable_sort (array, len, compar, (int *) NULL);
    972 }
    973 
    974 static inline hb_bool_t
    975 hb_codepoint_parse (const char *s, unsigned int len, int base, hb_codepoint_t *out)
    976 {
    977   /* Pain because we don't know whether s is nul-terminated. */
    978   char buf[64];
    979   len = MIN (ARRAY_LENGTH (buf) - 1, len);
    980   strncpy (buf, s, len);
    981   buf[len] = '\0';
    982 
    983   char *end;
    984   errno = 0;
    985   unsigned long v = strtoul (buf, &end, base);
    986   if (errno) return false;
    987   if (*end) return false;
    988   *out = v;
    989   return true;
    990 }
    991 
    992 
    993 /* Global runtime options. */
    994 
    995 struct hb_options_t
    996 {
    997   unsigned int initialized : 1;
    998   unsigned int uniscribe_bug_compatible : 1;
    999 };
   1000 
   1001 union hb_options_union_t {
   1002   unsigned int i;
   1003   hb_options_t opts;
   1004 };
   1005 ASSERT_STATIC (sizeof (int) == sizeof (hb_options_union_t));
   1006 
   1007 HB_INTERNAL void
   1008 _hb_options_init (void);
   1009 
   1010 extern HB_INTERNAL hb_options_union_t _hb_options;
   1011 
   1012 static inline hb_options_t
   1013 hb_options (void)
   1014 {
   1015   if (unlikely (!_hb_options.i))
   1016     _hb_options_init ();
   1017 
   1018   return _hb_options.opts;
   1019 }
   1020 
   1021 /* Size signifying variable-sized array */
   1022 #define VAR 1
   1023 
   1024 #endif /* HB_PRIVATE_HH */
   1025