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