LCOV - code coverage report
Current view: top level - gfx/harfbuzz/src - hb-private.hh (source / functions) Hit Total Coverage
Test: output.info Lines: 57 173 32.9 %
Date: 2017-07-14 16:53:18 Functions: 52 102 51.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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         685 : static inline Type MIN (const Type &a, const Type &b) { return a < b ? a : b; }
     225             : 
     226             : #undef MAX
     227             : template <typename Type>
     228          34 : 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         576 : 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         672 : _hb_popcount32 (uint32_t mask)
     308             : {
     309             : #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
     310         672 :   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           6 : _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           6 :   unsigned int n_bits = 0;
     328          18 :   while (number) {
     329           6 :     n_bits++;
     330           6 :     number >>= 1;
     331             :   }
     332           6 :   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           0 : _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           0 :   unsigned int n_bits = 0;
     344           0 :   if (unlikely (!number)) return 0;
     345           0 :   while (!(number & 1)) {
     346           0 :     n_bits++;
     347           0 :     number >>= 1;
     348             :   }
     349           0 :   return n_bits;
     350             : #endif
     351             : }
     352             : 
     353             : static inline bool
     354        3312 : _hb_unsigned_int_mul_overflows (unsigned int count, unsigned int size)
     355             : {
     356        3312 :   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         494 : struct hb_prealloced_array_t
     372             : {
     373             :   unsigned int len;
     374             :   unsigned int allocated;
     375             :   Type *array;
     376             :   Type static_array[StaticSize];
     377             : 
     378         648 :   void init (void) { memset (this, 0, sizeof (*this)); }
     379             : 
     380         336 :   inline Type& operator [] (unsigned int i) { return array[i]; }
     381        2555 :   inline const Type& operator [] (unsigned int i) const { return array[i]; }
     382             : 
     383         572 :   inline Type *push (void)
     384             :   {
     385         572 :     if (!array) {
     386         510 :       array = static_array;
     387         510 :       allocated = ARRAY_LENGTH (static_array);
     388             :     }
     389         572 :     if (likely (len < allocated))
     390         572 :       return &array[len++];
     391             : 
     392             :     /* Need to reallocate */
     393           0 :     unsigned int new_allocated = allocated + (allocated >> 1) + 8;
     394           0 :     Type *new_array = NULL;
     395             : 
     396           0 :     if (array == static_array) {
     397           0 :       new_array = (Type *) calloc (new_allocated, sizeof (Type));
     398           0 :       if (new_array)
     399           0 :         memcpy (new_array, array, len * sizeof (Type));
     400             :     } else {
     401           0 :       bool overflows = (new_allocated < allocated) || _hb_unsigned_int_mul_overflows (new_allocated, sizeof (Type));
     402           0 :       if (likely (!overflows)) {
     403           0 :         new_array = (Type *) realloc (array, new_allocated * sizeof (Type));
     404             :       }
     405             :     }
     406             : 
     407           0 :     if (unlikely (!new_array))
     408           0 :       return NULL;
     409             : 
     410           0 :     array = new_array;
     411           0 :     allocated = new_allocated;
     412           0 :     return &array[len++];
     413             :   }
     414             : 
     415           0 :   inline void pop (void)
     416             :   {
     417           0 :     len--;
     418           0 :   }
     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           8 :   inline void shrink (unsigned int l)
     431             :   {
     432           8 :      if (l < len)
     433           2 :        len = l;
     434           8 :   }
     435             : 
     436             :   template <typename T>
     437           0 :   inline Type *find (T v) {
     438           0 :     for (unsigned int i = 0; i < len; i++)
     439           0 :       if (array[i] == v)
     440           0 :         return &array[i];
     441           0 :     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           2 :   inline void qsort (void)
     452             :   {
     453           2 :     ::qsort (array, len, sizeof (Type), (hb_compare_func_t) Type::cmp);
     454           2 :   }
     455             : 
     456           4 :   inline void qsort (unsigned int start, unsigned int end)
     457             :   {
     458           4 :     ::qsort (array + start, end - start, sizeof (Type), (hb_compare_func_t) Type::cmp);
     459           4 :   }
     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          12 :   inline const Type *bsearch (T *key) const
     468             :   {
     469          12 :     return (const Type *) ::bsearch (key, array, len, sizeof (Type), (hb_compare_func_t) Type::cmp);
     470             :   }
     471             : 
     472         541 :   inline void finish (void)
     473             :   {
     474         541 :     if (array != static_array)
     475          41 :       free (array);
     476         541 :     array = NULL;
     477         541 :     allocated = len = 0;
     478         541 :   }
     479             : };
     480             : 
     481             : template <typename Type>
     482             : struct hb_auto_array_t : hb_prealloced_array_t <Type>
     483             : {
     484         494 :   hb_auto_array_t (void) { hb_prealloced_array_t<Type>::init (); }
     485         494 :   ~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         154 :   inline void init (void) { items.init (); }
     496             : 
     497             :   template <typename T>
     498           0 :   inline item_t *replace_or_insert (T v, lock_t &l, bool replace)
     499             :   {
     500           0 :     l.lock ();
     501           0 :     item_t *item = items.find (v);
     502           0 :     if (item) {
     503           0 :       if (replace) {
     504           0 :         item_t old = *item;
     505           0 :         *item = v;
     506           0 :         l.unlock ();
     507           0 :         old.finish ();
     508             :       }
     509             :       else {
     510           0 :         item = NULL;
     511           0 :         l.unlock ();
     512             :       }
     513             :     } else {
     514           0 :       item = items.push ();
     515           0 :       if (likely (item))
     516           0 :         *item = v;
     517           0 :       l.unlock ();
     518             :     }
     519           0 :     return item;
     520             :   }
     521             : 
     522             :   template <typename T>
     523           0 :   inline void remove (T v, lock_t &l)
     524             :   {
     525           0 :     l.lock ();
     526           0 :     item_t *item = items.find (v);
     527           0 :     if (item) {
     528           0 :       item_t old = *item;
     529           0 :       *item = items[items.len - 1];
     530           0 :       items.pop ();
     531           0 :       l.unlock ();
     532           0 :       old.finish ();
     533             :     } else {
     534           0 :       l.unlock ();
     535             :     }
     536           0 :   }
     537             : 
     538             :   template <typename T>
     539           0 :   inline bool find (T v, item_t *i, lock_t &l)
     540             :   {
     541           0 :     l.lock ();
     542           0 :     item_t *item = items.find (v);
     543           0 :     if (item)
     544           0 :       *i = *item;
     545           0 :     l.unlock ();
     546           0 :     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          41 :   inline void finish (lock_t &l)
     564             :   {
     565          41 :     if (!items.len) {
     566             :       /* No need for locking. */
     567          41 :       items.finish ();
     568          41 :       return;
     569             :     }
     570           0 :     l.lock ();
     571           0 :     while (items.len) {
     572           0 :       item_t old = items[items.len - 1];
     573           0 :         items.pop ();
     574           0 :         l.unlock ();
     575           0 :         old.finish ();
     576           0 :         l.lock ();
     577             :     }
     578           0 :     items.finish ();
     579           0 :     l.unlock ();
     580             :   }
     581             : 
     582             : };
     583             : 
     584             : 
     585             : /* ASCII tag/character handling */
     586             : 
     587           0 : static inline bool ISALPHA (unsigned char c)
     588           0 : { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); }
     589           0 : static inline bool ISALNUM (unsigned char c)
     590           0 : { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'); }
     591           0 : static inline bool ISSPACE (unsigned char c)
     592           0 : { return c == ' ' || c =='\f'|| c =='\n'|| c =='\r'|| c =='\t'|| c =='\v'; }
     593           0 : static inline unsigned char TOUPPER (unsigned char c)
     594           0 : { return (c >= 'a' && c <= 'z') ? c - 'a' + 'A' : c; }
     595           0 : static inline unsigned char TOLOWER (unsigned char c)
     596           0 : { 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       29279 : _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       29279 :                   ...) {}
     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       30199 :   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       30199 :                                    ...) {}
     868             : 
     869       26852 :   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         271 : 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         271 :   return (T)(u - lo) <= (T)(hi - lo);
     895             : }
     896             : 
     897             : template <typename T> static inline bool
     898           0 : hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2)
     899             : {
     900           0 :   return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2);
     901             : }
     902             : 
     903             : template <typename T> static inline bool
     904           2 : hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3)
     905             : {
     906           2 :   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           0 : hb_stable_sort (T *array, unsigned int len, int(*compar)(const T *, const T *), T2 *array2)
     945             : {
     946           0 :   for (unsigned int i = 1; i < len; i++)
     947             :   {
     948           0 :     unsigned int j = i;
     949           0 :     while (j && compar (&array[j - 1], &array[i]) > 0)
     950           0 :       j--;
     951           0 :     if (i == j)
     952           0 :       continue;
     953             :     /* Move item i to occupy place for item j, shift what's in between. */
     954             :     {
     955           0 :       T t = array[i];
     956           0 :       memmove (&array[j + 1], &array[j], (i - j) * sizeof (T));
     957           0 :       array[j] = t;
     958             :     }
     959           0 :     if (array2)
     960             :     {
     961           0 :       T2 t = array2[i];
     962           0 :       memmove (&array2[j + 1], &array2[j], (i - j) * sizeof (T2));
     963           0 :       array2[j] = t;
     964             :     }
     965             :   }
     966           0 : }
     967             : 
     968             : template <typename T> static inline void
     969           0 : hb_stable_sort (T *array, unsigned int len, int(*compar)(const T *, const T *))
     970             : {
     971           0 :   hb_stable_sort (array, len, compar, (int *) NULL);
     972           0 : }
     973             : 
     974             : static inline hb_bool_t
     975           0 : 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           0 :   len = MIN (ARRAY_LENGTH (buf) - 1, len);
     980           0 :   strncpy (buf, s, len);
     981           0 :   buf[len] = '\0';
     982             : 
     983             :   char *end;
     984           0 :   errno = 0;
     985           0 :   unsigned long v = strtoul (buf, &end, base);
     986           0 :   if (errno) return false;
     987           0 :   if (*end) return false;
     988           0 :   *out = v;
     989           0 :   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           0 : hb_options (void)
    1014             : {
    1015           0 :   if (unlikely (!_hb_options.i))
    1016           0 :     _hb_options_init ();
    1017             : 
    1018           0 :   return _hb_options.opts;
    1019             : }
    1020             : 
    1021             : /* Size signifying variable-sized array */
    1022             : #define VAR 1
    1023             : 
    1024             : #endif /* HB_PRIVATE_HH */

Generated by: LCOV version 1.13