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 #include <errno.h>
  48 #include <stdio.h>
  49 #include <stdarg.h>
  50 
  51 
  52 #define HB_PASTE1(a,b) a##b
  53 #define HB_PASTE(a,b) HB_PASTE1(a,b)
  54 
  55 /* Compile-time custom allocator support. */
  56 
  57 #if defined(hb_malloc_impl) \
  58  && defined(hb_calloc_impl) \
  59  && defined(hb_realloc_impl) \
  60  && defined(hb_free_impl)
  61 extern "C" void* hb_malloc_impl(size_t size);
  62 extern "C" void* hb_calloc_impl(size_t nmemb, size_t size);
  63 extern "C" void* hb_realloc_impl(void *ptr, size_t size);
  64 extern "C" void  hb_free_impl(void *ptr);
  65 #define malloc hb_malloc_impl
  66 #define calloc hb_calloc_impl
  67 #define realloc hb_realloc_impl
  68 #define free hb_free_impl
  69 #endif
  70 
  71 
  72 /* Compiler attributes */
  73 
  74 
  75 #if __cplusplus < 201103L
  76 
  77 #ifndef nullptr
  78 #define nullptr NULL
  79 #endif
  80 
  81 // Static assertions
  82 #ifndef static_assert
  83 #define static_assert(e, msg) \
  84         HB_UNUSED typedef int HB_PASTE(static_assertion_failed_at_line_, __LINE__) [(e) ? 1 : -1]
  85 #endif // static_assert
  86 
  87 #endif // __cplusplus < 201103L
  88 
  89 #define _GNU_SOURCE 1
  90 
  91 #if (defined(__GNUC__) || defined(__clang__)) && defined(__OPTIMIZE__)
  92 #define likely(expr) (__builtin_expect (!!(expr), 1))
  93 #define unlikely(expr) (__builtin_expect (!!(expr), 0))
  94 #else
  95 #define likely(expr) (expr)
  96 #define unlikely(expr) (expr)
  97 #endif
  98 
  99 #if !defined(__GNUC__) && !defined(__clang__)
 100 #undef __attribute__
 101 #define __attribute__(x)
 102 #endif
 103 
 104 #if __GNUC__ >= 3
 105 #define HB_PURE_FUNC    __attribute__((pure))
 106 #define HB_CONST_FUNC   __attribute__((const))
 107 #define HB_PRINTF_FUNC(format_idx, arg_idx) __attribute__((__format__ (__printf__, format_idx, arg_idx)))
 108 #else
 109 #define HB_PURE_FUNC
 110 #define HB_CONST_FUNC
 111 #define HB_PRINTF_FUNC(format_idx, arg_idx)
 112 #endif
 113 #if __GNUC__ >= 4
 114 #define HB_UNUSED       __attribute__((unused))
 115 #else
 116 #define HB_UNUSED
 117 #endif
 118 
 119 #ifndef HB_INTERNAL
 120 # if !defined(__MINGW32__) && !defined(__CYGWIN__)
 121 #  define HB_INTERNAL __attribute__((__visibility__("hidden")))
 122 # else
 123 #  define HB_INTERNAL
 124 # endif
 125 #endif
 126 
 127 #if __GNUC__ >= 3
 128 #define HB_FUNC __PRETTY_FUNCTION__
 129 #elif defined(_MSC_VER)
 130 #define HB_FUNC __FUNCSIG__
 131 #else
 132 #define HB_FUNC __func__
 133 #endif
 134 
 135 /*
 136  * Borrowed from https://bugzilla.mozilla.org/show_bug.cgi?id=1215411
 137  * HB_FALLTHROUGH is an annotation to suppress compiler warnings about switch
 138  * cases that fall through without a break or return statement. HB_FALLTHROUGH
 139  * is only needed on cases that have code:
 140  *
 141  * switch (foo) {
 142  *   case 1: // These cases have no code. No fallthrough annotations are needed.
 143  *   case 2:
 144  *   case 3:
 145  *     foo = 4; // This case has code, so a fallthrough annotation is needed:
 146  *     HB_FALLTHROUGH;
 147  *   default:
 148  *     return foo;
 149  * }
 150  */
 151 #if defined(__clang__) && __cplusplus >= 201103L
 152    /* clang's fallthrough annotations are only available starting in C++11. */
 153 #  define HB_FALLTHROUGH [[clang::fallthrough]]
 154 #elif defined(_MSC_VER)
 155    /*
 156     * MSVC's __fallthrough annotations are checked by /analyze (Code Analysis):
 157     * https://msdn.microsoft.com/en-us/library/ms235402%28VS.80%29.aspx
 158     */
 159 #  include <sal.h>
 160 #  define HB_FALLTHROUGH __fallthrough
 161 #else
 162 #  define HB_FALLTHROUGH /* FALLTHROUGH */
 163 #endif
 164 
 165 #if defined(_WIN32) || defined(__CYGWIN__)
 166    /* We need Windows Vista for both Uniscribe backend and for
 167     * MemoryBarrier.  We don't support compiling on Windows XP,
 168     * though we run on it fine. */
 169 #  if defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0600
 170 #    undef _WIN32_WINNT
 171 #  endif
 172 #  ifndef _WIN32_WINNT
 173 #    define _WIN32_WINNT 0x0600
 174 #  endif
 175 #  ifndef WIN32_LEAN_AND_MEAN
 176 #    define WIN32_LEAN_AND_MEAN 1
 177 #  endif
 178 #  ifndef STRICT
 179 #    define STRICT 1
 180 #  endif
 181 
 182 #  if defined(_WIN32_WCE)
 183      /* Some things not defined on Windows CE. */
 184 #    define vsnprintf _vsnprintf
 185 #    define getenv(Name) nullptr
 186 #    if _WIN32_WCE < 0x800
 187 #      define setlocale(Category, Locale) "C"
 188 static int errno = 0; /* Use something better? */
 189 #    endif
 190 #  elif defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP)
 191 #    define getenv(Name) nullptr
 192 #  endif
 193 #  if defined(_MSC_VER) && _MSC_VER < 1900
 194 #    define snprintf _snprintf
 195 #  endif
 196 #endif
 197 
 198 #if HAVE_ATEXIT
 199 /* atexit() is only safe to be called from shared libraries on certain
 200  * platforms.  Whitelist.
 201  * https://bugs.freedesktop.org/show_bug.cgi?id=82246 */
 202 #  if defined(__linux) && defined(__GLIBC_PREREQ)
 203 #    if __GLIBC_PREREQ(2,3)
 204 /* From atexit() manpage, it's safe with glibc 2.2.3 on Linux. */
 205 #      define HB_USE_ATEXIT 1
 206 #    endif
 207 #  elif defined(_MSC_VER) || defined(__MINGW32__)
 208 /* For MSVC:
 209  * http://msdn.microsoft.com/en-ca/library/tze57ck3.aspx
 210  * http://msdn.microsoft.com/en-ca/library/zk17ww08.aspx
 211  * mingw32 headers say atexit is safe to use in shared libraries.
 212  */
 213 #    define HB_USE_ATEXIT 1
 214 #  elif defined(__ANDROID__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
 215 /* This was fixed in Android NKD r8 or r8b:
 216  * https://code.google.com/p/android/issues/detail?id=6455
 217  * which introduced GCC 4.6:
 218  * https://developer.android.com/tools/sdk/ndk/index.html
 219  */
 220 #    define HB_USE_ATEXIT 1
 221 #  endif
 222 #endif
 223 
 224 /* Basics */
 225 
 226 #undef MIN
 227 template <typename Type>
 228 static inline Type MIN (const Type &a, const Type &b) { return a < b ? a : b; }
 229 
 230 #undef MAX
 231 template <typename Type>
 232 static inline Type MAX (const Type &a, const Type &b) { return a > b ? a : b; }
 233 
 234 static inline unsigned int DIV_CEIL (const unsigned int a, unsigned int b)
 235 { return (a + (b - 1)) / b; }
 236 
 237 
 238 #undef  ARRAY_LENGTH
 239 template <typename Type, unsigned int n>
 240 static inline unsigned int ARRAY_LENGTH (const Type (&)[n]) { return n; }
 241 /* A const version, but does not detect erratically being called on pointers. */
 242 #define ARRAY_LENGTH_CONST(__array) ((signed int) (sizeof (__array) / sizeof (__array[0])))
 243 
 244 #define HB_STMT_START do
 245 #define HB_STMT_END   while (0)
 246 
 247 template <unsigned int cond> class hb_assert_constant_t;
 248 template <> class hb_assert_constant_t<1> {};
 249 
 250 #define ASSERT_STATIC_EXPR_ZERO(_cond) (0 * (unsigned int) sizeof (hb_assert_constant_t<_cond>))
 251 
 252 /* Lets assert int types.  Saves trouble down the road. */
 253 
 254 static_assert ((sizeof (int8_t) == 1), "");
 255 static_assert ((sizeof (uint8_t) == 1), "");
 256 static_assert ((sizeof (int16_t) == 2), "");
 257 static_assert ((sizeof (uint16_t) == 2), "");
 258 static_assert ((sizeof (int32_t) == 4), "");
 259 static_assert ((sizeof (uint32_t) == 4), "");
 260 static_assert ((sizeof (int64_t) == 8), "");
 261 static_assert ((sizeof (uint64_t) == 8), "");
 262 
 263 static_assert ((sizeof (hb_codepoint_t) == 4), "");
 264 static_assert ((sizeof (hb_position_t) == 4), "");
 265 static_assert ((sizeof (hb_mask_t) == 4), "");
 266 static_assert ((sizeof (hb_var_int_t) == 4), "");
 267 
 268 
 269 /* We like our types POD */
 270 
 271 #define _ASSERT_TYPE_POD1(_line, _type) union _type_##_type##_on_line_##_line##_is_not_POD { _type instance; }
 272 #define _ASSERT_TYPE_POD0(_line, _type) _ASSERT_TYPE_POD1 (_line, _type)
 273 #define ASSERT_TYPE_POD(_type)          _ASSERT_TYPE_POD0 (__LINE__, _type)
 274 
 275 #ifdef __GNUC__
 276 # define _ASSERT_INSTANCE_POD1(_line, _instance) \
 277         HB_STMT_START { \
 278                 typedef __typeof__(_instance) _type_##_line; \
 279                 _ASSERT_TYPE_POD1 (_line, _type_##_line); \
 280         } HB_STMT_END
 281 #else
 282 # define _ASSERT_INSTANCE_POD1(_line, _instance)        typedef int _assertion_on_line_##_line##_not_tested
 283 #endif
 284 # define _ASSERT_INSTANCE_POD0(_line, _instance)        _ASSERT_INSTANCE_POD1 (_line, _instance)
 285 # define ASSERT_INSTANCE_POD(_instance)                 _ASSERT_INSTANCE_POD0 (__LINE__, _instance)
 286 
 287 /* Check _assertion in a method environment */
 288 #define _ASSERT_POD1(_line) \
 289         HB_UNUSED inline void _static_assertion_on_line_##_line (void) const \
 290         { _ASSERT_INSTANCE_POD1 (_line, *this); /* Make sure it's POD. */ }
 291 # define _ASSERT_POD0(_line)    _ASSERT_POD1 (_line)
 292 # define ASSERT_POD()           _ASSERT_POD0 (__LINE__)
 293 
 294 
 295 
 296 /* Misc */
 297 
 298 /* Void! */
 299 struct _hb_void_t {};
 300 typedef const _hb_void_t *hb_void_t;
 301 #define HB_VOID ((const _hb_void_t *) nullptr)
 302 
 303 /* Return the number of 1 bits in mask. */
 304 static inline HB_CONST_FUNC unsigned int
 305 _hb_popcount32 (uint32_t mask)
 306 {
 307 #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
 308   return __builtin_popcount (mask);
 309 #else
 310   /* "HACKMEM 169" */
 311   uint32_t y;
 312   y = (mask >> 1) &033333333333;
 313   y = mask - y - ((y >>1) & 033333333333);
 314   return (((y + (y >> 3)) & 030707070707) % 077);
 315 #endif
 316 }
 317 static inline HB_CONST_FUNC unsigned int
 318 _hb_popcount64 (uint64_t mask)
 319 {
 320 #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
 321   if (sizeof (long) >= sizeof (mask))
 322     return __builtin_popcountl (mask);
 323 #endif
 324   return _hb_popcount32 (mask & 0xFFFFFFFF) + _hb_popcount32 (mask >> 32);
 325 }
 326 template <typename T> static inline unsigned int _hb_popcount (T mask);
 327 template <> inline unsigned int _hb_popcount<uint32_t> (uint32_t mask) { return _hb_popcount32 (mask); }
 328 template <> inline unsigned int _hb_popcount<uint64_t> (uint64_t mask) { return _hb_popcount64 (mask); }
 329 
 330 /* Returns the number of bits needed to store number */
 331 static inline HB_CONST_FUNC unsigned int
 332 _hb_bit_storage (unsigned int number)
 333 {
 334 #if defined(__GNUC__) && (__GNUC__ >= 4) && defined(__OPTIMIZE__)
 335   return likely (number) ? (sizeof (unsigned int) * 8 - __builtin_clz (number)) : 0;
 336 #else
 337   unsigned int n_bits = 0;
 338   while (number) {
 339     n_bits++;
 340     number >>= 1;
 341   }
 342   return n_bits;
 343 #endif
 344 }
 345 
 346 /* Returns the number of zero bits in the least significant side of number */
 347 static inline HB_CONST_FUNC unsigned int
 348 _hb_ctz (unsigned int number)
 349 {
 350 #if defined(__GNUC__) && (__GNUC__ >= 4) && defined(__OPTIMIZE__)
 351   return likely (number) ? __builtin_ctz (number) : 0;
 352 #else
 353   unsigned int n_bits = 0;
 354   if (unlikely (!number)) return 0;
 355   while (!(number & 1)) {
 356     n_bits++;
 357     number >>= 1;
 358   }
 359   return n_bits;
 360 #endif
 361 }
 362 
 363 static inline bool
 364 _hb_unsigned_int_mul_overflows (unsigned int count, unsigned int size)
 365 {
 366   return (size > 0) && (count >= ((unsigned int) -1) / size);
 367 }
 368 
 369 
 370 
 371 /* arrays and maps */
 372 
 373 
 374 #define HB_PREALLOCED_ARRAY_INIT {0, 0, nullptr}
 375 template <typename Type, unsigned int StaticSize=16>
 376 struct hb_prealloced_array_t
 377 {
 378   unsigned int len;
 379   unsigned int allocated;
 380   Type *array;
 381   Type static_array[StaticSize];
 382 
 383   void init (void)
 384   {
 385     len = 0;
 386     allocated = ARRAY_LENGTH (static_array);
 387     array = static_array;
 388   }
 389 
 390   inline Type& operator [] (unsigned int i) { return array[i]; }
 391   inline const Type& operator [] (unsigned int i) const { return array[i]; }
 392 
 393   inline Type *push (void)
 394   {
 395     if (unlikely (!resize (len + 1)))
 396       return nullptr;
 397 
 398     return &array[len - 1];
 399   }
 400 
 401   inline bool resize (unsigned int size)
 402   {
 403     if (unlikely (size > allocated))
 404     {
 405       /* Need to reallocate */
 406 
 407       unsigned int new_allocated = allocated;
 408       while (size >= new_allocated)
 409         new_allocated += (new_allocated >> 1) + 8;
 410 
 411       Type *new_array = nullptr;
 412 
 413       if (array == static_array) {
 414         new_array = (Type *) calloc (new_allocated, sizeof (Type));
 415         if (new_array)
 416           memcpy (new_array, array, len * sizeof (Type));
 417       } else {
 418         bool overflows = (new_allocated < allocated) || _hb_unsigned_int_mul_overflows (new_allocated, sizeof (Type));
 419         if (likely (!overflows)) {
 420           new_array = (Type *) realloc (array, new_allocated * sizeof (Type));
 421         }
 422       }
 423 
 424       if (unlikely (!new_array))
 425         return false;
 426 
 427       array = new_array;
 428       allocated = new_allocated;
 429     }
 430 
 431     len = size;
 432     return true;
 433   }
 434 
 435   inline void pop (void)
 436   {
 437     len--;
 438   }
 439 
 440   inline void remove (unsigned int i)
 441   {
 442      if (unlikely (i >= len))
 443        return;
 444      memmove (static_cast<void *> (&array[i]),
 445               static_cast<void *> (&array[i + 1]),
 446               (len - i - 1) * sizeof (Type));
 447      len--;
 448   }
 449 
 450   inline void shrink (unsigned int l)
 451   {
 452      if (l < len)
 453        len = l;
 454   }
 455 
 456   template <typename T>
 457   inline Type *find (T v) {
 458     for (unsigned int i = 0; i < len; i++)
 459       if (array[i] == v)
 460         return &array[i];
 461     return nullptr;
 462   }
 463   template <typename T>
 464   inline const Type *find (T v) const {
 465     for (unsigned int i = 0; i < len; i++)
 466       if (array[i] == v)
 467         return &array[i];
 468     return nullptr;
 469   }
 470 
 471   inline void qsort (void)
 472   {
 473     ::qsort (array, len, sizeof (Type), Type::cmp);
 474   }
 475 
 476   inline void qsort (unsigned int start, unsigned int end)
 477   {
 478     ::qsort (array + start, end - start, sizeof (Type), Type::cmp);
 479   }
 480 
 481   template <typename T>
 482   inline Type *bsearch (T *x)
 483   {
 484     unsigned int i;
 485     return bfind (x, &i) ? &array[i] : nullptr;
 486   }
 487   template <typename T>
 488   inline const Type *bsearch (T *x) const
 489   {
 490     unsigned int i;
 491     return bfind (x, &i) ? &array[i] : nullptr;
 492   }
 493   template <typename T>
 494   inline bool bfind (T *x, unsigned int *i) const
 495   {
 496     int min = 0, max = (int) this->len - 1;
 497     while (min <= max)
 498     {
 499       int mid = (min + max) / 2;
 500       int c = this->array[mid].cmp (x);
 501       if (c < 0)
 502         max = mid - 1;
 503       else if (c > 0)
 504         min = mid + 1;
 505       else
 506       {
 507         *i = mid;
 508         return true;
 509       }
 510     }
 511     if (max < 0 || (max < (int) this->len && this->array[max].cmp (x) > 0))
 512       max++;
 513     *i = max;
 514     return false;
 515   }
 516 
 517   inline void finish (void)
 518   {
 519     if (array != static_array)
 520       free (array);
 521     array = nullptr;
 522     allocated = len = 0;
 523   }
 524 };
 525 
 526 template <typename Type>
 527 struct hb_auto_array_t : hb_prealloced_array_t <Type>
 528 {
 529   hb_auto_array_t (void) { hb_prealloced_array_t<Type>::init (); }
 530   ~hb_auto_array_t (void) { hb_prealloced_array_t<Type>::finish (); }
 531 };
 532 
 533 
 534 #define HB_LOCKABLE_SET_INIT {HB_PREALLOCED_ARRAY_INIT}
 535 template <typename item_t, typename lock_t>
 536 struct hb_lockable_set_t
 537 {
 538   hb_prealloced_array_t <item_t, 1> items;
 539 
 540   inline void init (void) { items.init (); }
 541 
 542   template <typename T>
 543   inline item_t *replace_or_insert (T v, lock_t &l, bool replace)
 544   {
 545     l.lock ();
 546     item_t *item = items.find (v);
 547     if (item) {
 548       if (replace) {
 549         item_t old = *item;
 550         *item = v;
 551         l.unlock ();
 552         old.finish ();
 553       }
 554       else {
 555         item = nullptr;
 556         l.unlock ();
 557       }
 558     } else {
 559       item = items.push ();
 560       if (likely (item))
 561         *item = v;
 562       l.unlock ();
 563     }
 564     return item;
 565   }
 566 
 567   template <typename T>
 568   inline void remove (T v, lock_t &l)
 569   {
 570     l.lock ();
 571     item_t *item = items.find (v);
 572     if (item) {
 573       item_t old = *item;
 574       *item = items[items.len - 1];
 575       items.pop ();
 576       l.unlock ();
 577       old.finish ();
 578     } else {
 579       l.unlock ();
 580     }
 581   }
 582 
 583   template <typename T>
 584   inline bool find (T v, item_t *i, lock_t &l)
 585   {
 586     l.lock ();
 587     item_t *item = items.find (v);
 588     if (item)
 589       *i = *item;
 590     l.unlock ();
 591     return !!item;
 592   }
 593 
 594   template <typename T>
 595   inline item_t *find_or_insert (T v, lock_t &l)
 596   {
 597     l.lock ();
 598     item_t *item = items.find (v);
 599     if (!item) {
 600       item = items.push ();
 601       if (likely (item))
 602         *item = v;
 603     }
 604     l.unlock ();
 605     return item;
 606   }
 607 
 608   inline void finish (lock_t &l)
 609   {
 610     if (!items.len) {
 611       /* No need for locking. */
 612       items.finish ();
 613       return;
 614     }
 615     l.lock ();
 616     while (items.len) {
 617       item_t old = items[items.len - 1];
 618         items.pop ();
 619         l.unlock ();
 620         old.finish ();
 621         l.lock ();
 622     }
 623     items.finish ();
 624     l.unlock ();
 625   }
 626 
 627 };
 628 
 629 
 630 /* ASCII tag/character handling */
 631 
 632 static inline bool ISALPHA (unsigned char c)
 633 { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); }
 634 static inline bool ISALNUM (unsigned char c)
 635 { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'); }
 636 static inline bool ISSPACE (unsigned char c)
 637 { return c == ' ' || c =='\f'|| c =='\n'|| c =='\r'|| c =='\t'|| c =='\v'; }
 638 static inline unsigned char TOUPPER (unsigned char c)
 639 { return (c >= 'a' && c <= 'z') ? c - 'a' + 'A' : c; }
 640 static inline unsigned char TOLOWER (unsigned char c)
 641 { return (c >= 'A' && c <= 'Z') ? c - 'A' + 'a' : c; }
 642 
 643 
 644 /* HB_NDEBUG disables some sanity checks that are very safe to disable and
 645  * should be disabled in production systems.  If NDEBUG is defined, enable
 646  * HB_NDEBUG; but if it's desirable that normal assert()s (which are very
 647  * light-weight) to be enabled, then HB_DEBUG can be defined to disable
 648  * the costlier checks. */
 649 #ifdef NDEBUG
 650 #define HB_NDEBUG
 651 #endif
 652 
 653 
 654 /* Misc */
 655 
 656 template <typename T> class hb_assert_unsigned_t;
 657 template <> class hb_assert_unsigned_t<unsigned char> {};
 658 template <> class hb_assert_unsigned_t<unsigned short> {};
 659 template <> class hb_assert_unsigned_t<unsigned int> {};
 660 template <> class hb_assert_unsigned_t<unsigned long> {};
 661 
 662 template <typename T> static inline bool
 663 hb_in_range (T u, T lo, T hi)
 664 {
 665   /* The sizeof() is here to force template instantiation.
 666    * I'm sure there are better ways to do this but can't think of
 667    * one right now.  Declaring a variable won't work as HB_UNUSED
 668    * is unusable on some platforms and unused types are less likely
 669    * to generate a warning than unused variables. */
 670   static_assert ((sizeof (hb_assert_unsigned_t<T>) >= 0), "");
 671 
 672   /* The casts below are important as if T is smaller than int,
 673    * the subtract results will become a signed int! */
 674   return (T)(u - lo) <= (T)(hi - lo);
 675 }
 676 
 677 template <typename T> static inline bool
 678 hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2)
 679 {
 680   return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2);
 681 }
 682 
 683 template <typename T> static inline bool
 684 hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3)
 685 {
 686   return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2) || hb_in_range (u, lo3, hi3);
 687 }
 688 
 689 
 690 /* Enable bitwise ops on enums marked as flags_t */
 691 /* To my surprise, looks like the function resolver is happy to silently cast
 692  * one enum to another...  So this doesn't provide the type-checking that I
 693  * originally had in mind... :(.
 694  *
 695  * For MSVC warnings, see: https://github.com/behdad/harfbuzz/pull/163
 696  */
 697 #ifdef _MSC_VER
 698 # pragma warning(disable:4200)
 699 # pragma warning(disable:4800)
 700 #endif
 701 #define HB_MARK_AS_FLAG_T(T) \
 702         extern "C++" { \
 703           static inline T operator | (T l, T r) { return T ((unsigned) l | (unsigned) r); } \
 704           static inline T operator & (T l, T r) { return T ((unsigned) l & (unsigned) r); } \
 705           static inline T operator ^ (T l, T r) { return T ((unsigned) l ^ (unsigned) r); } \
 706           static inline T operator ~ (T r) { return T (~(unsigned int) r); } \
 707           static inline T& operator |= (T &l, T r) { l = l | r; return l; } \
 708           static inline T& operator &= (T& l, T r) { l = l & r; return l; } \
 709           static inline T& operator ^= (T& l, T r) { l = l ^ r; return l; } \
 710         }
 711 
 712 
 713 /* Useful for set-operations on small enums.
 714  * For example, for testing "x ∈ {x1, x2, x3}" use:
 715  * (FLAG_UNSAFE(x) & (FLAG(x1) | FLAG(x2) | FLAG(x3)))
 716  */
 717 #define FLAG(x) (ASSERT_STATIC_EXPR_ZERO ((unsigned int)(x) < 32) + (1U << (unsigned int)(x)))
 718 #define FLAG_UNSAFE(x) ((unsigned int)(x) < 32 ? (1U << (unsigned int)(x)) : 0)
 719 #define FLAG_RANGE(x,y) (ASSERT_STATIC_EXPR_ZERO ((x) < (y)) + FLAG(y+1) - FLAG(x))
 720 
 721 
 722 template <typename T, typename T2> static inline void
 723 hb_stable_sort (T *array, unsigned int len, int(*compar)(const T *, const T *), T2 *array2)
 724 {
 725   for (unsigned int i = 1; i < len; i++)
 726   {
 727     unsigned int j = i;
 728     while (j && compar (&array[j - 1], &array[i]) > 0)
 729       j--;
 730     if (i == j)
 731       continue;
 732     /* Move item i to occupy place for item j, shift what's in between. */
 733     {
 734       T t = array[i];
 735       memmove (&array[j + 1], &array[j], (i - j) * sizeof (T));
 736       array[j] = t;
 737     }
 738     if (array2)
 739     {
 740       T2 t = array2[i];
 741       memmove (&array2[j + 1], &array2[j], (i - j) * sizeof (T2));
 742       array2[j] = t;
 743     }
 744   }
 745 }
 746 
 747 template <typename T> static inline void
 748 hb_stable_sort (T *array, unsigned int len, int(*compar)(const T *, const T *))
 749 {
 750   hb_stable_sort (array, len, compar, (int *) nullptr);
 751 }
 752 
 753 static inline hb_bool_t
 754 hb_codepoint_parse (const char *s, unsigned int len, int base, hb_codepoint_t *out)
 755 {
 756   /* Pain because we don't know whether s is nul-terminated. */
 757   char buf[64];
 758   len = MIN (ARRAY_LENGTH (buf) - 1, len);
 759   strncpy (buf, s, len);
 760   buf[len] = '\0';
 761 
 762   char *end;
 763   errno = 0;
 764   unsigned long v = strtoul (buf, &end, base);
 765   if (errno) return false;
 766   if (*end) return false;
 767   *out = v;
 768   return true;
 769 }
 770 
 771 
 772 /* Vectorization */
 773 
 774 struct HbOpOr
 775 {
 776   static const bool passthru_left = true;
 777   static const bool passthru_right = true;
 778   template <typename T> static void process (T &o, const T &a, const T &b) { o = a | b; }
 779 };
 780 struct HbOpAnd
 781 {
 782   static const bool passthru_left = false;
 783   static const bool passthru_right = false;
 784   template <typename T> static void process (T &o, const T &a, const T &b) { o = a & b; }
 785 };
 786 struct HbOpMinus
 787 {
 788   static const bool passthru_left = true;
 789   static const bool passthru_right = false;
 790   template <typename T> static void process (T &o, const T &a, const T &b) { o = a & ~b; }
 791 };
 792 struct HbOpXor
 793 {
 794   static const bool passthru_left = true;
 795   static const bool passthru_right = true;
 796   template <typename T> static void process (T &o, const T &a, const T &b) { o = a ^ b; }
 797 };
 798 
 799 /* Type behaving similar to vectorized vars defined using __attribute__((vector_size(...))). */
 800 template <typename elt_t, unsigned int byte_size>
 801 struct hb_vector_size_t
 802 {
 803   elt_t& operator [] (unsigned int i) { return v[i]; }
 804   const elt_t& operator [] (unsigned int i) const { return v[i]; }
 805 
 806   template <class Op>
 807   inline hb_vector_size_t process (const hb_vector_size_t &o) const
 808   {
 809     hb_vector_size_t r;
 810     for (unsigned int i = 0; i < ARRAY_LENGTH (v); i++)
 811       Op::process (r.v[i], v[i], o.v[i]);
 812     return r;
 813   }
 814   inline hb_vector_size_t operator | (const hb_vector_size_t &o) const
 815   { return process<HbOpOr> (o); }
 816   inline hb_vector_size_t operator & (const hb_vector_size_t &o) const
 817   { return process<HbOpAnd> (o); }
 818   inline hb_vector_size_t operator ^ (const hb_vector_size_t &o) const
 819   { return process<HbOpXor> (o); }
 820   inline hb_vector_size_t operator ~ () const
 821   {
 822     hb_vector_size_t r;
 823     for (unsigned int i = 0; i < ARRAY_LENGTH (v); i++)
 824       r.v[i] = ~v[i];
 825     return r;
 826   }
 827 
 828   private:
 829   static_assert (byte_size / sizeof (elt_t) * sizeof (elt_t) == byte_size, "");
 830   elt_t v[byte_size / sizeof (elt_t)];
 831 };
 832 
 833 /* The `vector_size' attribute was introduced in gcc 3.1. */
 834 #if defined( __GNUC__ ) && ( __GNUC__ >= 4 )
 835 #define HAVE_VECTOR_SIZE 1
 836 #endif
 837 
 838 
 839 /* Global runtime options. */
 840 
 841 struct hb_options_t
 842 {
 843   unsigned int initialized : 1;
 844   unsigned int uniscribe_bug_compatible : 1;
 845 };
 846 
 847 union hb_options_union_t {
 848   unsigned int i;
 849   hb_options_t opts;
 850 };
 851 static_assert ((sizeof (int) == sizeof (hb_options_union_t)), "");
 852 
 853 HB_INTERNAL void
 854 _hb_options_init (void);
 855 
 856 extern HB_INTERNAL hb_options_union_t _hb_options;
 857 
 858 static inline hb_options_t
 859 hb_options (void)
 860 {
 861   if (unlikely (!_hb_options.i))
 862     _hb_options_init ();
 863 
 864   return _hb_options.opts;
 865 }
 866 
 867 /* Size signifying variable-sized array */
 868 #define VAR 1
 869 
 870 
 871 /* String type. */
 872 
 873 struct hb_string_t
 874 {
 875   inline hb_string_t (void) : bytes (nullptr), len (0) {}
 876   inline hb_string_t (const char *bytes_, unsigned int len_) : bytes (bytes_), len (len_) {}
 877 
 878   inline int cmp (const hb_string_t &a) const
 879   {
 880     if (len != a.len)
 881       return (int) a.len - (int) len;
 882 
 883     return memcmp (a.bytes, bytes, len);
 884   }
 885   static inline int cmp (const void *pa, const void *pb)
 886   {
 887     hb_string_t *a = (hb_string_t *) pa;
 888     hb_string_t *b = (hb_string_t *) pb;
 889     return b->cmp (*a);
 890   }
 891 
 892   const char *bytes;
 893   unsigned int len;
 894 };
 895 
 896 
 897 #endif /* HB_PRIVATE_HH */