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
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)
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 ();
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 */
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 */
|
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
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)
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 ();
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 */
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 */
|