2 * Copyright © 2007,2008,2009 Red Hat, Inc.
3 * Copyright © 2011,2012 Google, Inc.
5 * This is part of HarfBuzz, a text shaping library.
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.
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
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.
25 * Red Hat Author(s): Behdad Esfahbod
26 * Google Author(s): Behdad Esfahbod
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. */
57 /* Compile-time custom allocator support. */
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
74 /* Compiler attributes */
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))
82 #define likely(expr) (expr)
83 #define unlikely(expr) (expr)
86 #if !defined(__GNUC__) && !defined(__clang__)
88 #define __attribute__(x)
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)))
98 #define HB_PRINTF_FUNC(format_idx, arg_idx)
101 #define HB_UNUSED __attribute__((unused))
107 # if !defined(__MINGW32__) && !defined(__CYGWIN__)
108 # define HB_INTERNAL __attribute__((__visibility__("hidden")))
115 #define HB_FUNC __PRETTY_FUNCTION__
116 #elif defined(_MSC_VER)
117 #define HB_FUNC __FUNCSIG__
119 #define HB_FUNC __func__
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:
129 * case 1: // These cases have no code. No fallthrough annotations are needed.
132 * foo = 4; // This case has code, so a fallthrough annotation is needed:
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)
143 * MSVC's __fallthrough annotations are checked by /analyze (Code Analysis):
144 * https://msdn.microsoft.com/en-us/library/ms235402%28VS.80%29.aspx
147 # define HB_FALLTHROUGH __fallthrough
149 # define HB_FALLTHROUGH /* FALLTHROUGH */
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
159 # ifndef _WIN32_WINNT
160 # define _WIN32_WINNT 0x0600
162 # ifndef WIN32_LEAN_AND_MEAN
163 # define WIN32_LEAN_AND_MEAN 1
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? */
178 # elif defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP)
179 # define getenv(Name) NULL
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
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
198 # elif defined(_MSC_VER) || defined(__MINGW32__)
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.
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
211 # define HB_USE_ATEXIT 1
219 # define NULL ((void *) 0)
223 template <typename Type>
224 static inline Type MIN (const Type &a, const Type &b) { return a < b ? a : b; }
227 template <typename Type>
228 static inline Type MAX (const Type &a, const Type &b) { return a > b ? a : b; }
230 static inline unsigned int DIV_CEIL (const unsigned int a, unsigned int b)
231 { return (a + (b - 1)) / b; }
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])))
240 #define HB_STMT_START do
241 #define HB_STMT_END while (0)
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))
247 template <unsigned int cond> class hb_assert_constant_t {};
249 #define ASSERT_STATIC_EXPR_ZERO(_cond) (0 * (unsigned int) sizeof (hb_assert_constant_t<_cond>))
251 #define _PASTE1(a,b) a##b
252 #define PASTE(a,b) _PASTE1(a,b)
254 /* Lets assert int types. Saves trouble down the road. */
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);
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);
271 /* We like our types POD */
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)
278 # define _ASSERT_INSTANCE_POD1(_line, _instance) \
280 typedef __typeof__(_instance) _type_##_line; \
281 _ASSERT_TYPE_POD1 (_line, _type_##_line); \
284 # define _ASSERT_INSTANCE_POD1(_line, _instance) typedef int _assertion_on_line_##_line##_not_tested
286 # define _ASSERT_INSTANCE_POD0(_line, _instance) _ASSERT_INSTANCE_POD1 (_line, _instance)
287 # define ASSERT_INSTANCE_POD(_instance) _ASSERT_INSTANCE_POD0 (__LINE__, _instance)
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__)
301 struct _hb_void_t {};
302 typedef const _hb_void_t *hb_void_t;
303 #define HB_VOID ((const _hb_void_t *) NULL)
305 /* Return the number of 1 bits in mask. */
306 static inline HB_CONST_FUNC unsigned int
307 _hb_popcount32 (uint32_t mask)
309 #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
310 return __builtin_popcount (mask);
314 y = (mask >> 1) &033333333333;
315 y = mask - y - ((y >>1) & 033333333333);
316 return (((y + (y >> 3)) & 030707070707) % 077);
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)
324 #if defined(__GNUC__) && (__GNUC__ >= 4) && defined(__OPTIMIZE__)
325 return likely (number) ? (sizeof (unsigned int) * 8 - __builtin_clz (number)) : 0;
327 unsigned int n_bits = 0;
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)
340 #if defined(__GNUC__) && (__GNUC__ >= 4) && defined(__OPTIMIZE__)
341 return likely (number) ? __builtin_ctz (number) : 0;
343 unsigned int n_bits = 0;
344 if (unlikely (!number)) return 0;
345 while (!(number & 1)) {
354 _hb_unsigned_int_mul_overflows (unsigned int count, unsigned int size)
356 return (size > 0) && (count >= ((unsigned int) -1) / size);
360 /* Type of bsearch() / qsort() compare function */
361 typedef int (*hb_compare_func_t) (const void *, const void *);
366 /* arrays and maps */
369 #define HB_PREALLOCED_ARRAY_INIT {0, 0, NULL}
370 template <typename Type, unsigned int StaticSize=16>
371 struct hb_prealloced_array_t
374 unsigned int allocated;
376 Type static_array[StaticSize];
378 void init (void) { memset (this, 0, sizeof (*this)); }
380 inline Type& operator [] (unsigned int i) { return array[i]; }
381 inline const Type& operator [] (unsigned int i) const { return array[i]; }
383 inline Type *push (void)
386 array = static_array;
387 allocated = ARRAY_LENGTH (static_array);
389 if (likely (len < allocated))
390 return &array[len++];
392 /* Need to reallocate */
393 unsigned int new_allocated = allocated + (allocated >> 1) + 8;
394 Type *new_array = NULL;
396 if (array == static_array) {
397 new_array = (Type *) calloc (new_allocated, sizeof (Type));
399 memcpy (new_array, array, len * sizeof (Type));
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));
407 if (unlikely (!new_array))
411 allocated = new_allocated;
412 return &array[len++];
415 inline void pop (void)
420 inline void remove (unsigned int i)
422 if (unlikely (i >= len))
424 memmove (static_cast<void *> (&array[i]),
425 static_cast<void *> (&array[i + 1]),
426 (len - i - 1) * sizeof (Type));
430 inline void shrink (unsigned int l)
436 template <typename T>
437 inline Type *find (T v) {
438 for (unsigned int i = 0; i < len; i++)
443 template <typename T>
444 inline const Type *find (T v) const {
445 for (unsigned int i = 0; i < len; i++)
451 inline void qsort (void)
453 ::qsort (array, len, sizeof (Type), (hb_compare_func_t) Type::cmp);
456 inline void qsort (unsigned int start, unsigned int end)
458 ::qsort (array + start, end - start, sizeof (Type), (hb_compare_func_t) Type::cmp);
461 template <typename T>
462 inline Type *bsearch (T *key)
464 return (Type *) ::bsearch (key, array, len, sizeof (Type), (hb_compare_func_t) Type::cmp);
466 template <typename T>
467 inline const Type *bsearch (T *key) const
469 return (const Type *) ::bsearch (key, array, len, sizeof (Type), (hb_compare_func_t) Type::cmp);
472 inline void finish (void)
474 if (array != static_array)
481 template <typename Type>
482 struct hb_auto_array_t : hb_prealloced_array_t <Type>
484 hb_auto_array_t (void) { hb_prealloced_array_t<Type>::init (); }
485 ~hb_auto_array_t (void) { hb_prealloced_array_t<Type>::finish (); }
489 #define HB_LOCKABLE_SET_INIT {HB_PREALLOCED_ARRAY_INIT}
490 template <typename item_t, typename lock_t>
491 struct hb_lockable_set_t
493 hb_prealloced_array_t <item_t, 2> items;
495 inline void init (void) { items.init (); }
497 template <typename T>
498 inline item_t *replace_or_insert (T v, lock_t &l, bool replace)
501 item_t *item = items.find (v);
514 item = items.push ();
522 template <typename T>
523 inline void remove (T v, lock_t &l)
526 item_t *item = items.find (v);
529 *item = items[items.len - 1];
538 template <typename T>
539 inline bool find (T v, item_t *i, lock_t &l)
542 item_t *item = items.find (v);
549 template <typename T>
550 inline item_t *find_or_insert (T v, lock_t &l)
553 item_t *item = items.find (v);
555 item = items.push ();
563 inline void finish (lock_t &l)
566 /* No need for locking. */
572 item_t old = items[items.len - 1];
585 /* ASCII tag/character handling */
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; }
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]))
606 /* Makes class uncopyable. Use in private: section. */
609 T &operator = (const T &o)
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. */
629 _hb_debug (unsigned int level,
630 unsigned int max_level)
632 return level < max_level;
635 #define DEBUG_LEVEL_ENABLED(WHAT, LEVEL) (_hb_debug ((LEVEL), HB_DEBUG_##WHAT))
636 #define DEBUG_ENABLED(WHAT) (DEBUG_LEVEL_ENABLED (WHAT, 0))
639 _hb_print_func (const char *func)
643 unsigned int func_len = strlen (func);
645 if (0 == strncmp (func, "static ", 7))
647 /* Skip "typename" */
648 if (0 == strncmp (func, "typename ", 9))
650 /* Skip return type */
651 const char *space = strchr (func, ' ');
654 /* Skip parameter list */
655 const char *paren = strchr (func, '(');
657 func_len = paren - func;
658 fprintf (stderr, "%.*s", func_len, func);
662 template <int max_level> static inline void
663 _hb_debug_msg_va (const char *what,
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,
681 if (!_hb_debug (level, max_level))
684 fprintf (stderr, "%-10s", what ? what : "");
687 fprintf (stderr, "(%0*lx) ", (unsigned int) (2 * sizeof (void *)), (unsigned long) obj);
689 fprintf (stderr, " %*s ", (unsigned int) (2 * sizeof (void *)), "");
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",
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);
708 fprintf (stderr, " " VRBAR LBAR);
710 _hb_print_func (func);
714 fprintf (stderr, ": ");
715 vfprintf (stderr, message, ap);
718 fprintf (stderr, "\n");
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) {}
730 template <int max_level> static inline void
731 _hb_debug_msg (const char *what,
738 ...) HB_PRINTF_FUNC(7, 8);
739 template <int max_level> static inline void
740 _hb_debug_msg (const char *what,
750 va_start (ap, message);
751 _hb_debug_msg_va<max_level> (what, obj, func, indented, level, level_dir, message, ap);
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,
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__)
782 template <typename T>
783 struct hb_printer_t {
784 const char *print (const T&) { return "something"; }
788 struct hb_printer_t<bool> {
789 const char *print (bool v) { return v ? "true" : "false"; }
793 struct hb_printer_t<hb_void_t> {
794 const char *print (hb_void_t) { return ""; }
802 template <typename T>
803 static inline void _hb_warn_no_return (bool returned)
805 if (unlikely (!returned)) {
806 fprintf (stderr, "OUCH, returned with no call to return_trace(). This is a bug, please report.\n");
810 /*static*/ inline void _hb_warn_no_return<hb_void_t> (bool returned HB_UNUSED)
813 template <int max_level, typename ret_t>
814 struct hb_auto_trace_t {
815 explicit inline hb_auto_trace_t (unsigned int *plevel_,
820 ...) : plevel (plevel_), what (what_), obj (obj_), returned (false)
822 if (plevel) ++*plevel;
825 va_start (ap, message);
826 _hb_debug_msg_va<max_level> (what, obj, func, true, plevel ? *plevel : 0, +1, message, ap);
829 inline ~hb_auto_trace_t (void)
831 _hb_warn_no_return<ret_t> (returned);
833 _hb_debug_msg<max_level> (what, obj, NULL, true, plevel ? *plevel : 1, -1, " ");
835 if (plevel) --*plevel;
838 inline ret_t ret (ret_t v, unsigned int line = 0)
840 if (unlikely (returned)) {
841 fprintf (stderr, "OUCH, double calls to return_trace(). This is a bug, please report.\n");
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;
855 unsigned int *plevel;
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,
869 inline ret_t ret (ret_t v, unsigned int line HB_UNUSED = 0) { return v; }
872 #define return_trace(RET) return trace.ret (RET, __LINE__)
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> {};
882 template <typename T> static inline bool
883 hb_in_range (T u, T lo, T hi)
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);
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);
897 template <typename T> static inline bool
898 hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2)
900 return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2);
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)
906 return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2) || hb_in_range (u, lo3, hi3);
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... :(.
915 * For MSVC warnings, see: https://github.com/behdad/harfbuzz/pull/163
918 # pragma warning(disable:4200)
919 # pragma warning(disable:4800)
921 #define HB_MARK_AS_FLAG_T(T) \
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; } \
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)))
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))
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)
946 for (unsigned int i = 1; i < len; i++)
949 while (j && compar (&array[j - 1], &array[i]) > 0)
953 /* Move item i to occupy place for item j, shift what's in between. */
956 memmove (&array[j + 1], &array[j], (i - j) * sizeof (T));
962 memmove (&array2[j + 1], &array2[j], (i - j) * sizeof (T2));
968 template <typename T> static inline void
969 hb_stable_sort (T *array, unsigned int len, int(*compar)(const T *, const T *))
971 hb_stable_sort (array, len, compar, (int *) NULL);
974 static inline hb_bool_t
975 hb_codepoint_parse (const char *s, unsigned int len, int base, hb_codepoint_t *out)
977 /* Pain because we don't know whether s is nul-terminated. */
979 len = MIN (ARRAY_LENGTH (buf) - 1, len);
980 strncpy (buf, s, len);
985 unsigned long v = strtoul (buf, &end, base);
986 if (errno) return false;
987 if (*end) return false;
993 /* Global runtime options. */
997 unsigned int initialized : 1;
998 unsigned int uniscribe_bug_compatible : 1;
1001 union hb_options_union_t {
1005 ASSERT_STATIC (sizeof (int) == sizeof (hb_options_union_t));
1008 _hb_options_init (void);
1010 extern HB_INTERNAL hb_options_union_t _hb_options;
1012 static inline hb_options_t
1015 if (unlikely (!_hb_options.i))
1016 _hb_options_init ();
1018 return _hb_options.opts;
1021 /* Size signifying variable-sized array */
1024 #endif /* HB_PRIVATE_HH */