238 #define ARRAY_LENGTH_CONST(__array) ((signed int) (sizeof (__array) / sizeof (__array[0]))) |
242 #define ARRAY_LENGTH_CONST(__array) ((signed int) (sizeof (__array) / sizeof (__array[0]))) |
239 |
243 |
240 #define HB_STMT_START do |
244 #define HB_STMT_START do |
241 #define HB_STMT_END while (0) |
245 #define HB_STMT_END while (0) |
242 |
246 |
243 #define _ASSERT_STATIC1(_line, _cond) HB_UNUSED typedef int _static_assert_on_line_##_line##_failed[(_cond)?1:-1] |
247 template <unsigned int cond> class hb_assert_constant_t; |
244 #define _ASSERT_STATIC0(_line, _cond) _ASSERT_STATIC1 (_line, (_cond)) |
248 template <> class hb_assert_constant_t<1> {}; |
245 #define ASSERT_STATIC(_cond) _ASSERT_STATIC0 (__LINE__, (_cond)) |
|
246 |
|
247 template <unsigned int cond> class hb_assert_constant_t {}; |
|
248 |
249 |
249 #define ASSERT_STATIC_EXPR_ZERO(_cond) (0 * (unsigned int) sizeof (hb_assert_constant_t<_cond>)) |
250 #define ASSERT_STATIC_EXPR_ZERO(_cond) (0 * (unsigned int) sizeof (hb_assert_constant_t<_cond>)) |
250 |
251 |
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. */ |
252 /* Lets assert int types. Saves trouble down the road. */ |
255 |
253 |
256 ASSERT_STATIC (sizeof (int8_t) == 1); |
254 static_assert ((sizeof (int8_t) == 1), ""); |
257 ASSERT_STATIC (sizeof (uint8_t) == 1); |
255 static_assert ((sizeof (uint8_t) == 1), ""); |
258 ASSERT_STATIC (sizeof (int16_t) == 2); |
256 static_assert ((sizeof (int16_t) == 2), ""); |
259 ASSERT_STATIC (sizeof (uint16_t) == 2); |
257 static_assert ((sizeof (uint16_t) == 2), ""); |
260 ASSERT_STATIC (sizeof (int32_t) == 4); |
258 static_assert ((sizeof (int32_t) == 4), ""); |
261 ASSERT_STATIC (sizeof (uint32_t) == 4); |
259 static_assert ((sizeof (uint32_t) == 4), ""); |
262 ASSERT_STATIC (sizeof (int64_t) == 8); |
260 static_assert ((sizeof (int64_t) == 8), ""); |
263 ASSERT_STATIC (sizeof (uint64_t) == 8); |
261 static_assert ((sizeof (uint64_t) == 8), ""); |
264 |
262 |
265 ASSERT_STATIC (sizeof (hb_codepoint_t) == 4); |
263 static_assert ((sizeof (hb_codepoint_t) == 4), ""); |
266 ASSERT_STATIC (sizeof (hb_position_t) == 4); |
264 static_assert ((sizeof (hb_position_t) == 4), ""); |
267 ASSERT_STATIC (sizeof (hb_mask_t) == 4); |
265 static_assert ((sizeof (hb_mask_t) == 4), ""); |
268 ASSERT_STATIC (sizeof (hb_var_int_t) == 4); |
266 static_assert ((sizeof (hb_var_int_t) == 4), ""); |
269 |
267 |
270 |
268 |
271 /* We like our types POD */ |
269 /* We like our types POD */ |
272 |
270 |
273 #define _ASSERT_TYPE_POD1(_line, _type) union _type_##_type##_on_line_##_line##_is_not_POD { _type instance; } |
271 #define _ASSERT_TYPE_POD1(_line, _type) union _type_##_type##_on_line_##_line##_is_not_POD { _type instance; } |
355 { |
365 { |
356 return (size > 0) && (count >= ((unsigned int) -1) / size); |
366 return (size > 0) && (count >= ((unsigned int) -1) / size); |
357 } |
367 } |
358 |
368 |
359 |
369 |
360 /* Type of bsearch() / qsort() compare function */ |
|
361 typedef int (*hb_compare_func_t) (const void *, const void *); |
|
362 |
|
363 |
|
364 |
|
365 |
370 |
366 /* arrays and maps */ |
371 /* arrays and maps */ |
367 |
372 |
368 |
373 |
369 #define HB_PREALLOCED_ARRAY_INIT {0, 0, NULL} |
374 #define HB_PREALLOCED_ARRAY_INIT {0, 0, nullptr} |
370 template <typename Type, unsigned int StaticSize=16> |
375 template <typename Type, unsigned int StaticSize=16> |
371 struct hb_prealloced_array_t |
376 struct hb_prealloced_array_t |
372 { |
377 { |
373 unsigned int len; |
378 unsigned int len; |
374 unsigned int allocated; |
379 unsigned int allocated; |
375 Type *array; |
380 Type *array; |
376 Type static_array[StaticSize]; |
381 Type static_array[StaticSize]; |
377 |
382 |
378 void init (void) { memset (this, 0, sizeof (*this)); } |
383 void init (void) |
|
384 { |
|
385 len = 0; |
|
386 allocated = ARRAY_LENGTH (static_array); |
|
387 array = static_array; |
|
388 } |
379 |
389 |
380 inline Type& operator [] (unsigned int i) { return array[i]; } |
390 inline Type& operator [] (unsigned int i) { return array[i]; } |
381 inline const Type& operator [] (unsigned int i) const { return array[i]; } |
391 inline const Type& operator [] (unsigned int i) const { return array[i]; } |
382 |
392 |
383 inline Type *push (void) |
393 inline Type *push (void) |
384 { |
394 { |
385 if (!array) { |
395 if (unlikely (!resize (len + 1))) |
386 array = static_array; |
396 return nullptr; |
387 allocated = ARRAY_LENGTH (static_array); |
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; |
388 } |
429 } |
389 if (likely (len < allocated)) |
430 |
390 return &array[len++]; |
431 len = size; |
391 |
432 return true; |
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 } |
433 } |
414 |
434 |
415 inline void pop (void) |
435 inline void pop (void) |
416 { |
436 { |
417 len--; |
437 len--; |
436 template <typename T> |
456 template <typename T> |
437 inline Type *find (T v) { |
457 inline Type *find (T v) { |
438 for (unsigned int i = 0; i < len; i++) |
458 for (unsigned int i = 0; i < len; i++) |
439 if (array[i] == v) |
459 if (array[i] == v) |
440 return &array[i]; |
460 return &array[i]; |
441 return NULL; |
461 return nullptr; |
442 } |
462 } |
443 template <typename T> |
463 template <typename T> |
444 inline const Type *find (T v) const { |
464 inline const Type *find (T v) const { |
445 for (unsigned int i = 0; i < len; i++) |
465 for (unsigned int i = 0; i < len; i++) |
446 if (array[i] == v) |
466 if (array[i] == v) |
447 return &array[i]; |
467 return &array[i]; |
448 return NULL; |
468 return nullptr; |
449 } |
469 } |
450 |
470 |
451 inline void qsort (void) |
471 inline void qsort (void) |
452 { |
472 { |
453 ::qsort (array, len, sizeof (Type), (hb_compare_func_t) Type::cmp); |
473 ::qsort (array, len, sizeof (Type), Type::cmp); |
454 } |
474 } |
455 |
475 |
456 inline void qsort (unsigned int start, unsigned int end) |
476 inline void qsort (unsigned int start, unsigned int end) |
457 { |
477 { |
458 ::qsort (array + start, end - start, sizeof (Type), (hb_compare_func_t) Type::cmp); |
478 ::qsort (array + start, end - start, sizeof (Type), Type::cmp); |
459 } |
479 } |
460 |
480 |
461 template <typename T> |
481 template <typename T> |
462 inline Type *bsearch (T *key) |
482 inline Type *bsearch (T *x) |
463 { |
483 { |
464 return (Type *) ::bsearch (key, array, len, sizeof (Type), (hb_compare_func_t) Type::cmp); |
484 unsigned int i; |
|
485 return bfind (x, &i) ? &array[i] : nullptr; |
465 } |
486 } |
466 template <typename T> |
487 template <typename T> |
467 inline const Type *bsearch (T *key) const |
488 inline const Type *bsearch (T *x) const |
468 { |
489 { |
469 return (const Type *) ::bsearch (key, array, len, sizeof (Type), (hb_compare_func_t) Type::cmp); |
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; |
470 } |
515 } |
471 |
516 |
472 inline void finish (void) |
517 inline void finish (void) |
473 { |
518 { |
474 if (array != static_array) |
519 if (array != static_array) |
475 free (array); |
520 free (array); |
476 array = NULL; |
521 array = nullptr; |
477 allocated = len = 0; |
522 allocated = len = 0; |
478 } |
523 } |
479 }; |
524 }; |
480 |
525 |
481 template <typename Type> |
526 template <typename Type> |
593 static inline unsigned char TOUPPER (unsigned char c) |
638 static inline unsigned char TOUPPER (unsigned char c) |
594 { return (c >= 'a' && c <= 'z') ? c - 'a' + 'A' : c; } |
639 { return (c >= 'a' && c <= 'z') ? c - 'a' + 'A' : c; } |
595 static inline unsigned char TOLOWER (unsigned char c) |
640 static inline unsigned char TOLOWER (unsigned char c) |
596 { return (c >= 'A' && c <= 'Z') ? c - 'A' + 'a' : c; } |
641 { return (c >= 'A' && c <= 'Z') ? c - 'A' + 'a' : c; } |
597 |
642 |
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 |
643 |
615 /* HB_NDEBUG disables some sanity checks that are very safe to disable and |
644 /* 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 |
645 * 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 |
646 * 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 |
647 * light-weight) to be enabled, then HB_DEBUG can be defined to disable |
619 * the costlier checks. */ |
648 * the costlier checks. */ |
620 #ifdef NDEBUG |
649 #ifdef NDEBUG |
621 #define HB_NDEBUG |
650 #define HB_NDEBUG |
622 #endif |
651 #endif |
623 |
652 |
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 |
653 |
874 /* Misc */ |
654 /* Misc */ |
875 |
655 |
876 template <typename T> class hb_assert_unsigned_t; |
656 template <typename T> class hb_assert_unsigned_t; |
877 template <> class hb_assert_unsigned_t<unsigned char> {}; |
657 template <> class hb_assert_unsigned_t<unsigned char> {}; |
988 *out = v; |
767 *out = v; |
989 return true; |
768 return true; |
990 } |
769 } |
991 |
770 |
992 |
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 |
993 /* Global runtime options. */ |
839 /* Global runtime options. */ |
994 |
840 |
995 struct hb_options_t |
841 struct hb_options_t |
996 { |
842 { |
997 unsigned int initialized : 1; |
843 unsigned int initialized : 1; |