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)
63extern "C" void* hb_malloc_impl(size_t size);
64extern "C" void* hb_calloc_impl(size_t nmemb, size_t size);
65extern "C" void* hb_realloc_impl(void *ptr, size_t size);
66extern "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"
176static 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
223template <typename Type>
224static inline Type MIN (const Type &a, const Type &b) { return a < b ? a : b; }
225
226#undef MAX
227template <typename Type>
228static inline Type MAX (const Type &a, const Type &b) { return a > b ? a : b; }
229
230static inline unsigned int DIV_CEIL (const unsigned int a, unsigned int b)
231{ return (a + (b - 1)) / b; }
232
233
234#undef  ARRAY_LENGTH
235template <typename Type, unsigned int n>
236static 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
247template <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
256ASSERT_STATIC (sizeof (int8_t) == 1);
257ASSERT_STATIC (sizeof (uint8_t) == 1);
258ASSERT_STATIC (sizeof (int16_t) == 2);
259ASSERT_STATIC (sizeof (uint16_t) == 2);
260ASSERT_STATIC (sizeof (int32_t) == 4);
261ASSERT_STATIC (sizeof (uint32_t) == 4);
262ASSERT_STATIC (sizeof (int64_t) == 8);
263ASSERT_STATIC (sizeof (uint64_t) == 8);
264
265ASSERT_STATIC (sizeof (hb_codepoint_t) == 4);
266ASSERT_STATIC (sizeof (hb_position_t) == 4);
267ASSERT_STATIC (sizeof (hb_mask_t) == 4);
268ASSERT_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! */
301struct _hb_void_t {};
302typedef 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. */
306static 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 */
321static 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 */
337static 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
353static 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 */
361typedef 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}
370template <typename Type, unsigned int StaticSize=16>
371struct 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
481template <typename Type>
482struct 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}
490template <typename item_t, typename lock_t>
491struct 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
587static inline bool ISALPHA (unsigned char c)
588{ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); }
589static inline bool ISALNUM (unsigned char c)
590{ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'); }
591static inline bool ISSPACE (unsigned char c)
592{ return c == ' ' || c =='\f'|| c =='\n'|| c =='\r'|| c =='\t'|| c =='\v'; }
593static inline unsigned char TOUPPER (unsigned char c)
594{ return (c >= 'a' && c <= 'z') ? c - 'a' + 'A' : c; }
595static 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
628static 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
638static 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
662template <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);
671template <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}
720template <> 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
730template <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);
739template <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}
754template <> 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);
763template <> 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
782template <typename T>
783struct hb_printer_t {
784  const char *print (const T&) { return "something"; }
785};
786
787template <>
788struct hb_printer_t<bool> {
789  const char *print (bool v) { return v ? "true" : "false"; }
790};
791
792template <>
793struct hb_printer_t<hb_void_t> {
794  const char *print (hb_void_t) { return ""; }
795};
796
797
798/*
799 * Trace
800 */
801
802template <typename T>
803static 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}
809template <>
810/*static*/ inline void _hb_warn_no_return<hb_void_t> (bool returned HB_UNUSED)
811{}
812
813template <int max_level, typename ret_t>
814struct 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};
860template <typename ret_t> /* Optimize when tracing is disabled */
861struct 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
876template <typename T> class hb_assert_unsigned_t;
877template <> class hb_assert_unsigned_t<unsigned char> {};
878template <> class hb_assert_unsigned_t<unsigned short> {};
879template <> class hb_assert_unsigned_t<unsigned int> {};
880template <> class hb_assert_unsigned_t<unsigned long> {};
881
882template <typename T> static inline bool
883hb_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
897template <typename T> static inline bool
898hb_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
903template <typename T> static inline bool
904hb_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
943template <typename T, typename T2> static inline void
944hb_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
968template <typename T> static inline void
969hb_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
974static inline hb_bool_t
975hb_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
995struct hb_options_t
996{
997  unsigned int initialized : 1;
998  unsigned int uniscribe_bug_compatible : 1;
999};
1000
1001union hb_options_union_t {
1002  unsigned int i;
1003  hb_options_t opts;
1004};
1005ASSERT_STATIC (sizeof (int) == sizeof (hb_options_union_t));
1006
1007HB_INTERNAL void
1008_hb_options_init (void);
1009
1010extern HB_INTERNAL hb_options_union_t _hb_options;
1011
1012static inline hb_options_t
1013hb_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