OLD | NEW |
1 /* | 1 /* |
2 * Copyright © 2007,2008,2009 Red Hat, Inc. | 2 * Copyright © 2007,2008,2009 Red Hat, Inc. |
3 * Copyright © 2011,2012 Google, Inc. | 3 * Copyright © 2011,2012 Google, Inc. |
4 * | 4 * |
5 * This is part of HarfBuzz, a text shaping library. | 5 * This is part of HarfBuzz, a text shaping library. |
6 * | 6 * |
7 * Permission is hereby granted, without written agreement and without | 7 * Permission is hereby granted, without written agreement and without |
8 * license or royalty fees, to use, copy, modify, and distribute this | 8 * license or royalty fees, to use, copy, modify, and distribute this |
9 * software and its documentation for any purpose, provided that the | 9 * software and its documentation for any purpose, provided that the |
10 * above copyright notice and the following two paragraphs appear in | 10 * above copyright notice and the following two paragraphs appear in |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
59 | 59 |
60 #ifndef NULL | 60 #ifndef NULL |
61 # define NULL ((void *) 0) | 61 # define NULL ((void *) 0) |
62 #endif | 62 #endif |
63 | 63 |
64 | 64 |
65 /* Basics */ | 65 /* Basics */ |
66 | 66 |
67 | 67 |
68 #undef MIN | 68 #undef MIN |
69 template <typename Type> static inline Type MIN (const Type &a, const Type &b) {
return a < b ? a : b; } | 69 template <typename Type> |
| 70 static inline Type MIN (const Type &a, const Type &b) { return a < b ? a : b; } |
70 | 71 |
71 #undef MAX | 72 #undef MAX |
72 template <typename Type> static inline Type MAX (const Type &a, const Type &b) {
return a > b ? a : b; } | 73 template <typename Type> |
| 74 static inline Type MAX (const Type &a, const Type &b) { return a > b ? a : b; } |
73 | 75 |
74 | 76 |
75 #undef ARRAY_LENGTH | 77 #undef ARRAY_LENGTH |
76 #define ARRAY_LENGTH(__array) ((signed int) (sizeof (__array) / sizeof (__array[
0]))) | 78 template <typename Type, unsigned int n> |
| 79 static inline unsigned int ARRAY_LENGTH (const Type (&a)[n]) { return n; } |
| 80 /* A const version, but does not detect erratically being called on pointers. */ |
| 81 #define ARRAY_LENGTH_CONST(__array) ((signed int) (sizeof (__array) / sizeof (__
array[0]))) |
77 | 82 |
78 #define HB_STMT_START do | 83 #define HB_STMT_START do |
79 #define HB_STMT_END while (0) | 84 #define HB_STMT_END while (0) |
80 | 85 |
81 #define _ASSERT_STATIC1(_line, _cond) typedef int _static_assert_on_line_##_li
ne##_failed[(_cond)?1:-1] | 86 #define _ASSERT_STATIC1(_line, _cond) typedef int _static_assert_on_line_##_li
ne##_failed[(_cond)?1:-1] |
82 #define _ASSERT_STATIC0(_line, _cond) _ASSERT_STATIC1 (_line, (_cond)) | 87 #define _ASSERT_STATIC0(_line, _cond) _ASSERT_STATIC1 (_line, (_cond)) |
83 #define ASSERT_STATIC(_cond) _ASSERT_STATIC0 (__LINE__, (_cond)) | 88 #define ASSERT_STATIC(_cond) _ASSERT_STATIC0 (__LINE__, (_cond)) |
84 | 89 |
85 #define ASSERT_STATIC_EXPR(_cond)((void) sizeof (char[(_cond) ? 1 : -1])) | 90 #define ASSERT_STATIC_EXPR(_cond)((void) sizeof (char[(_cond) ? 1 : -1])) |
86 #define ASSERT_STATIC_EXPR_ZERO(_cond) (0 * sizeof (char[(_cond) ? 1 : -1])) | 91 #define ASSERT_STATIC_EXPR_ZERO(_cond) (0 * sizeof (char[(_cond) ? 1 : -1])) |
(...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
435 item = items.push (); | 440 item = items.push (); |
436 if (likely (item)) | 441 if (likely (item)) |
437 *item = v; | 442 *item = v; |
438 } | 443 } |
439 l.unlock (); | 444 l.unlock (); |
440 return item; | 445 return item; |
441 } | 446 } |
442 | 447 |
443 inline void finish (lock_t &l) | 448 inline void finish (lock_t &l) |
444 { | 449 { |
| 450 if (!items.len) { |
| 451 /* No need for locking. */ |
| 452 items.finish (); |
| 453 return; |
| 454 } |
445 l.lock (); | 455 l.lock (); |
446 while (items.len) { | 456 while (items.len) { |
447 item_t old = items[items.len - 1]; | 457 item_t old = items[items.len - 1]; |
448 items.pop (); | 458 items.pop (); |
449 l.unlock (); | 459 l.unlock (); |
450 old.finish (); | 460 old.finish (); |
451 l.lock (); | 461 l.lock (); |
452 } | 462 } |
453 items.finish (); | 463 items.finish (); |
454 l.unlock (); | 464 l.unlock (); |
455 } | 465 } |
456 | 466 |
457 }; | 467 }; |
458 | 468 |
459 | 469 |
460 | 470 |
461 | 471 |
462 /* Big-endian handling */ | 472 /* Big-endian handling */ |
463 | 473 |
464 static inline uint16_t hb_be_uint16 (const uint16_t v) | 474 static inline uint16_t hb_be_uint16 (const uint16_t v) |
465 { | 475 { |
466 const uint8_t *V = (const uint8_t *) &v; | 476 const uint8_t *V = (const uint8_t *) &v; |
467 return (uint16_t) (V[0] << 8) + V[1]; | 477 return (V[0] << 8) | V[1]; |
| 478 } |
| 479 |
| 480 static inline uint16_t hb_uint16_swap (const uint16_t v) |
| 481 { |
| 482 return (v >> 8) | (v << 8); |
| 483 } |
| 484 |
| 485 static inline uint32_t hb_uint32_swap (const uint32_t v) |
| 486 { |
| 487 return (hb_uint16_swap (v) << 16) | hb_uint16_swap (v >> 16); |
468 } | 488 } |
469 | 489 |
470 /* Note, of the following macros, uint16_get is the one called many many times. | 490 /* Note, of the following macros, uint16_get is the one called many many times. |
471 * If there is any optimizations to be done, it's in that macro. However, I | 491 * If there is any optimizations to be done, it's in that macro. However, I |
472 * already confirmed that on my T400 ThinkPad at least, using bswap_16(), which | 492 * already confirmed that on my T400 ThinkPad at least, using bswap_16(), which |
473 * results in a single ror instruction, does NOT speed this up. In fact, it | 493 * results in a single ror instruction, does NOT speed this up. In fact, it |
474 * resulted in a minor slowdown. At any rate, note that v may not be correctly | 494 * resulted in a minor slowdown. At any rate, note that v may not be correctly |
475 * aligned, so I think the current implementation is optimal. | 495 * aligned, so I think the current implementation is optimal. |
476 */ | 496 */ |
477 | 497 |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
540 return; | 560 return; |
541 | 561 |
542 fprintf (stderr, "%-10s", what ? what : ""); | 562 fprintf (stderr, "%-10s", what ? what : ""); |
543 | 563 |
544 if (obj) | 564 if (obj) |
545 fprintf (stderr, "(%0*lx) ", (unsigned int) (2 * sizeof (void *)), (unsigned
long) obj); | 565 fprintf (stderr, "(%0*lx) ", (unsigned int) (2 * sizeof (void *)), (unsigned
long) obj); |
546 else | 566 else |
547 fprintf (stderr, " %*s ", (unsigned int) (2 * sizeof (void *)), ""); | 567 fprintf (stderr, " %*s ", (unsigned int) (2 * sizeof (void *)), ""); |
548 | 568 |
549 if (indented) { | 569 if (indented) { |
550 static const char bars[] = "││││││││││││││││││││││││││││││││││││││││"; | 570 /* One may want to add ASCII version of these. See: |
551 fprintf (stderr, "%2d %s├%s", | 571 * https://bugs.freedesktop.org/show_bug.cgi?id=50970 */ |
| 572 #define VBAR» "\342\224\202"» /* U+2502 BOX DRAWINGS LIGHT VERTICAL */ |
| 573 #define VRBAR» "\342\224\234"» /* U+251C BOX DRAWINGS LIGHT VERTICAL AND RIGHT
*/ |
| 574 #define DLBAR» "\342\225\256"» /* U+256E BOX DRAWINGS LIGHT ARC DOWN AND LEFT *
/ |
| 575 #define ULBAR» "\342\225\257"» /* U+256F BOX DRAWINGS LIGHT ARC UP AND LEFT */ |
| 576 #define LBAR» "\342\225\264"» /* U+2574 BOX DRAWINGS LIGHT LEFT */ |
| 577 static const char bars[] = VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR
VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR
VBAR VBAR VBAR VBAR; |
| 578 fprintf (stderr, "%2d %s" VRBAR "%s", |
552 level, | 579 level, |
553 » bars + sizeof (bars) - 1 - MIN ((unsigned int) sizeof (bars), 3 * l
evel), | 580 » bars + sizeof (bars) - 1 - MIN ((unsigned int) sizeof (bars), (unsi
gned int) (sizeof (VBAR) - 1) * level), |
554 » level_dir ? (level_dir > 0 ? "╮" : "╯") : "╴"); | 581 » level_dir ? (level_dir > 0 ? DLBAR : ULBAR) : LBAR); |
555 } else | 582 } else |
556 fprintf (stderr, " ├╴"); | 583 fprintf (stderr, " " VRBAR LBAR); |
557 | 584 |
558 if (func) { | 585 if (func) { |
559 /* If there's a class name, just write that. */ | 586 /* Skip return type */ |
560 const char *dotdot = strstr (func, "::"); | |
561 const char *space = strchr (func, ' '); | 587 const char *space = strchr (func, ' '); |
562 if (space && dotdot && space < dotdot) | 588 if (space) |
563 func = space + 1; | 589 func = space + 1; |
564 unsigned int func_len = dotdot ? dotdot - func : strlen (func); | 590 /* Skip parameter list */ |
| 591 const char *paren = strchr (func, '('); |
| 592 unsigned int func_len = paren ? paren - func : strlen (func); |
565 fprintf (stderr, "%.*s: ", func_len, func); | 593 fprintf (stderr, "%.*s: ", func_len, func); |
566 } | 594 } |
567 | 595 |
568 if (message) | 596 if (message) |
569 vfprintf (stderr, message, ap); | 597 vfprintf (stderr, message, ap); |
570 | 598 |
571 fprintf (stderr, "\n"); | 599 fprintf (stderr, "\n"); |
572 } | 600 } |
573 template <> inline void | 601 template <> inline void |
574 _hb_debug_msg_va<0> (const char *what HB_UNUSED, | 602 _hb_debug_msg_va<0> (const char *what HB_UNUSED, |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
652 { | 680 { |
653 if (unlikely (!returned)) { | 681 if (unlikely (!returned)) { |
654 fprintf (stderr, "OUCH, returned with no call to TRACE_RETURN. This is a
bug, please report. Level was %d.\n", plevel ? *plevel : -1); | 682 fprintf (stderr, "OUCH, returned with no call to TRACE_RETURN. This is a
bug, please report. Level was %d.\n", plevel ? *plevel : -1); |
655 _hb_debug_msg<max_level> (what, obj, NULL, true, plevel ? *plevel : 1, -1,
" "); | 683 _hb_debug_msg<max_level> (what, obj, NULL, true, plevel ? *plevel : 1, -1,
" "); |
656 return; | 684 return; |
657 } | 685 } |
658 | 686 |
659 if (plevel) --*plevel; | 687 if (plevel) --*plevel; |
660 } | 688 } |
661 | 689 |
662 inline bool ret (bool v) | 690 inline bool ret (bool v, unsigned int line = 0) |
663 { | 691 { |
664 if (unlikely (returned)) { | 692 if (unlikely (returned)) { |
665 fprintf (stderr, "OUCH, double calls to TRACE_RETURN. This is a bug, plea
se report.\n"); | 693 fprintf (stderr, "OUCH, double calls to TRACE_RETURN. This is a bug, plea
se report.\n"); |
666 return v; | 694 return v; |
667 } | 695 } |
668 | 696 |
669 _hb_debug_msg<max_level> (what, obj, NULL, true, plevel ? *plevel : 1, -1, "
return %s", v ? "true" : "false"); | 697 _hb_debug_msg<max_level> (what, obj, NULL, true, plevel ? *plevel : 1, -1, "
return %s (line %d)", v ? "true" : "false", line); |
670 if (plevel) --*plevel; | 698 if (plevel) --*plevel; |
671 plevel = NULL; | 699 plevel = NULL; |
672 returned = true; | 700 returned = true; |
673 return v; | 701 return v; |
674 } | 702 } |
675 | 703 |
676 private: | 704 private: |
677 unsigned int *plevel; | 705 unsigned int *plevel; |
678 bool returned; | 706 bool returned; |
679 const char *what; | 707 const char *what; |
680 const void *obj; | 708 const void *obj; |
681 }; | 709 }; |
682 template <> /* Optimize when tracing is disabled */ | 710 template <> /* Optimize when tracing is disabled */ |
683 struct hb_auto_trace_t<0> { | 711 struct hb_auto_trace_t<0> { |
684 explicit inline hb_auto_trace_t (unsigned int *plevel_ HB_UNUSED, | 712 explicit inline hb_auto_trace_t (unsigned int *plevel_ HB_UNUSED, |
685 const char *what HB_UNUSED, | 713 const char *what HB_UNUSED, |
686 const void *obj HB_UNUSED, | 714 const void *obj HB_UNUSED, |
687 const char *func HB_UNUSED, | 715 const char *func HB_UNUSED, |
688 const char *message HB_UNUSED, | 716 const char *message HB_UNUSED, |
689 ...) {} | 717 ...) {} |
690 | 718 |
691 template <typename T> | 719 template <typename T> |
692 inline T ret (T v) { return v; } | 720 inline T ret (T v, unsigned int line = 0) { return v; } |
693 }; | 721 }; |
694 | 722 |
695 #define TRACE_RETURN(RET) trace.ret (RET) | 723 #define TRACE_RETURN(RET) trace.ret (RET, __LINE__) |
696 | 724 |
697 /* Misc */ | 725 /* Misc */ |
698 | 726 |
699 | 727 |
700 /* Pre-mature optimization: | 728 /* Pre-mature optimization: |
701 * Checks for lo <= u <= hi but with an optimization if lo and hi | 729 * Checks for lo <= u <= hi but with an optimization if lo and hi |
702 * are only different in a contiguous set of lower-most bits. | 730 * are only different in a contiguous set of lower-most bits. |
703 */ | 731 */ |
704 template <typename T> inline bool | 732 template <typename T> static inline bool |
705 hb_in_range (T u, T lo, T hi) | 733 hb_in_range (T u, T lo, T hi) |
706 { | 734 { |
707 if ( ((lo^hi) & lo) == 0 && | 735 if ( ((lo^hi) & lo) == 0 && |
708 ((lo^hi) & hi) == (lo^hi) && | 736 ((lo^hi) & hi) == (lo^hi) && |
709 ((lo^hi) & ((lo^hi) + 1)) == 0 ) | 737 ((lo^hi) & ((lo^hi) + 1)) == 0 ) |
710 return (u & ~(lo^hi)) == lo; | 738 return (u & ~(lo^hi)) == lo; |
711 else | 739 else |
712 return lo <= u && u <= hi; | 740 return lo <= u && u <= hi; |
713 } | 741 } |
714 | 742 |
| 743 template <typename T> static inline bool |
| 744 hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3) |
| 745 { |
| 746 return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2) || hb_in_range (
u, lo3, hi3); |
| 747 } |
| 748 |
715 | 749 |
716 /* Useful for set-operations on small enums. | 750 /* Useful for set-operations on small enums. |
717 * For example, for testing "x ∈ {x1, x2, x3}" use: | 751 * For example, for testing "x ∈ {x1, x2, x3}" use: |
718 * (FLAG(x) & (FLAG(x1) | FLAG(x2) | FLAG(x3))) | 752 * (FLAG(x) & (FLAG(x1) | FLAG(x2) | FLAG(x3))) |
719 */ | 753 */ |
720 #define FLAG(x) (1<<(x)) | 754 #define FLAG(x) (1<<(x)) |
| 755 #define FLAG_RANGE(x,y) (ASSERT_STATIC_EXPR_ZERO ((x) < (y)) + FLAG(y+1) - FLAG(
x)) |
721 | 756 |
722 | 757 |
723 template <typename T> inline void | 758 template <typename T, typename T2> inline void |
724 hb_bubble_sort (T *array, unsigned int len, int(*compar)(const T *, const T *)) | 759 hb_bubble_sort (T *array, unsigned int len, int(*compar)(const T *, const T *),
T2 *array2) |
725 { | 760 { |
726 if (unlikely (!len)) | 761 if (unlikely (!len)) |
727 return; | 762 return; |
728 | 763 |
729 unsigned int k = len - 1; | 764 unsigned int k = len - 1; |
730 do { | 765 do { |
731 unsigned int new_k = 0; | 766 unsigned int new_k = 0; |
732 | 767 |
733 for (unsigned int j = 0; j < k; j++) | 768 for (unsigned int j = 0; j < k; j++) |
734 if (compar (&array[j], &array[j+1]) > 0) { | 769 if (compar (&array[j], &array[j+1]) > 0) |
735 T t; | 770 { |
736 » t = array[j]; | 771 { |
737 » array[j] = array[j + 1]; | 772 » T t; |
738 » array[j + 1] = t; | 773 » t = array[j]; |
| 774 » array[j] = array[j + 1]; |
| 775 » array[j + 1] = t; |
| 776 » } |
| 777 if (array2) |
| 778 { |
| 779 » T2 t; |
| 780 » t = array2[j]; |
| 781 » array2[j] = array2[j + 1]; |
| 782 » array2[j + 1] = t; |
| 783 » } |
739 | 784 |
740 new_k = j; | 785 new_k = j; |
741 } | 786 } |
742 k = new_k; | 787 k = new_k; |
743 } while (k); | 788 } while (k); |
744 } | 789 } |
745 | 790 |
| 791 template <typename T> inline void |
| 792 hb_bubble_sort (T *array, unsigned int len, int(*compar)(const T *, const T *)) |
| 793 { |
| 794 hb_bubble_sort (array, len, compar, (int *) NULL); |
| 795 } |
746 | 796 |
| 797 static inline hb_bool_t |
| 798 hb_codepoint_parse (const char *s, unsigned int len, int base, hb_codepoint_t *o
ut) |
| 799 { |
| 800 /* Pain because we don't know whether s is nul-terminated. */ |
| 801 char buf[64]; |
| 802 strncpy (buf, s, MIN (ARRAY_LENGTH (buf) - 1, len)); |
| 803 buf[MIN (ARRAY_LENGTH (buf) - 1, len)] = '\0'; |
| 804 |
| 805 char *end; |
| 806 errno = 0; |
| 807 unsigned long v = strtoul (buf, &end, base); |
| 808 if (errno) return false; |
| 809 if (*end) return false; |
| 810 *out = v; |
| 811 return true; |
| 812 } |
747 | 813 |
748 | 814 |
749 #endif /* HB_PRIVATE_HH */ | 815 #endif /* HB_PRIVATE_HH */ |
OLD | NEW |