OLD | NEW |
1 /* | 1 /* |
2 * Copyright © 2007,2008,2009 Red Hat, Inc. | 2 * Copyright © 2007,2008,2009 Red Hat, Inc. |
3 * Copyright © 2011 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 |
11 * all copies of this software. | 11 * all copies of this software. |
12 * | 12 * |
13 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR | 13 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR |
(...skipping 12 matching lines...) Expand all Loading... |
26 * Google Author(s): Behdad Esfahbod | 26 * Google Author(s): Behdad Esfahbod |
27 */ | 27 */ |
28 | 28 |
29 #ifndef HB_PRIVATE_HH | 29 #ifndef HB_PRIVATE_HH |
30 #define HB_PRIVATE_HH | 30 #define HB_PRIVATE_HH |
31 | 31 |
32 #ifdef HAVE_CONFIG_H | 32 #ifdef HAVE_CONFIG_H |
33 #include "config.h" | 33 #include "config.h" |
34 #endif | 34 #endif |
35 | 35 |
36 #include "hb-common.h" | 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 |
37 | 42 |
38 #include <stdlib.h> | 43 #include <stdlib.h> |
39 #include <stddef.h> | 44 #include <stddef.h> |
40 #include <string.h> | 45 #include <string.h> |
41 #include <assert.h> | 46 #include <assert.h> |
42 | 47 |
43 /* We only use these two for debug output. However, the debug code is | 48 /* We only use these two for debug output. However, the debug code is |
44 * always seen by the compiler (and optimized out in non-debug builds. | 49 * always seen by the compiler (and optimized out in non-debug builds. |
45 * If including these becomes a problem, we can start thinking about | 50 * If including these becomes a problem, we can start thinking about |
46 * someway around that. */ | 51 * someway around that. */ |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
79 #define HB_STMT_START do | 84 #define HB_STMT_START do |
80 #define HB_STMT_END while (0) | 85 #define HB_STMT_END while (0) |
81 | 86 |
82 #define _ASSERT_STATIC1(_line, _cond) typedef int _static_assert_on_line_##_line
##_failed[(_cond)?1:-1] | 87 #define _ASSERT_STATIC1(_line, _cond) typedef int _static_assert_on_line_##_line
##_failed[(_cond)?1:-1] |
83 #define _ASSERT_STATIC0(_line, _cond) _ASSERT_STATIC1 (_line, (_cond)) | 88 #define _ASSERT_STATIC0(_line, _cond) _ASSERT_STATIC1 (_line, (_cond)) |
84 #define ASSERT_STATIC(_cond) _ASSERT_STATIC0 (__LINE__, (_cond)) | 89 #define ASSERT_STATIC(_cond) _ASSERT_STATIC0 (__LINE__, (_cond)) |
85 | 90 |
86 #define ASSERT_STATIC_EXPR(_cond) ((void) sizeof (char[(_cond) ? 1 : -1])) | 91 #define ASSERT_STATIC_EXPR(_cond) ((void) sizeof (char[(_cond) ? 1 : -1])) |
87 #define ASSERT_STATIC_EXPR_ZERO(_cond) (0 * sizeof (char[(_cond) ? 1 : -1])) | 92 #define ASSERT_STATIC_EXPR_ZERO(_cond) (0 * sizeof (char[(_cond) ? 1 : -1])) |
88 | 93 |
| 94 #define _PASTE1(a,b) a##b |
| 95 #define PASTE(a,b) _PASTE1(a,b) |
89 | 96 |
90 /* Lets assert int types. Saves trouble down the road. */ | 97 /* Lets assert int types. Saves trouble down the road. */ |
91 | 98 |
92 ASSERT_STATIC (sizeof (int8_t) == 1); | 99 ASSERT_STATIC (sizeof (int8_t) == 1); |
93 ASSERT_STATIC (sizeof (uint8_t) == 1); | 100 ASSERT_STATIC (sizeof (uint8_t) == 1); |
94 ASSERT_STATIC (sizeof (int16_t) == 2); | 101 ASSERT_STATIC (sizeof (int16_t) == 2); |
95 ASSERT_STATIC (sizeof (uint16_t) == 2); | 102 ASSERT_STATIC (sizeof (uint16_t) == 2); |
96 ASSERT_STATIC (sizeof (int32_t) == 4); | 103 ASSERT_STATIC (sizeof (int32_t) == 4); |
97 ASSERT_STATIC (sizeof (uint32_t) == 4); | 104 ASSERT_STATIC (sizeof (uint32_t) == 4); |
98 ASSERT_STATIC (sizeof (int64_t) == 8); | 105 ASSERT_STATIC (sizeof (int64_t) == 8); |
(...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
430 | 437 |
431 | 438 |
432 /* Big-endian handling */ | 439 /* Big-endian handling */ |
433 | 440 |
434 static inline uint16_t hb_be_uint16 (const uint16_t v) | 441 static inline uint16_t hb_be_uint16 (const uint16_t v) |
435 { | 442 { |
436 const uint8_t *V = (const uint8_t *) &v; | 443 const uint8_t *V = (const uint8_t *) &v; |
437 return (uint16_t) (V[0] << 8) + V[1]; | 444 return (uint16_t) (V[0] << 8) + V[1]; |
438 } | 445 } |
439 | 446 |
| 447 /* Note, of the following macros, uint16_get is the one called many many times. |
| 448 * If there is any optimizations to be done, it's in that macro. However, I |
| 449 * already confirmed that on my T400 ThinkPad at least, using bswap_16(), which |
| 450 * results in a single ror instruction, does NOT speed this up. In fact, it |
| 451 * resulted in a minor slowdown. At any rate, note that v may not be correctly |
| 452 * aligned, so I think the current implementation is optimal. |
| 453 */ |
| 454 |
440 #define hb_be_uint16_put(v,V) HB_STMT_START { v[0] = (V>>8); v[1] = (V); } HB_
STMT_END | 455 #define hb_be_uint16_put(v,V) HB_STMT_START { v[0] = (V>>8); v[1] = (V); } HB_
STMT_END |
441 #define hb_be_uint16_get(v) (uint16_t) ((v[0] << 8) + v[1]) | 456 #define hb_be_uint16_get(v) (uint16_t) ((v[0] << 8) + v[1]) |
442 #define hb_be_uint16_eq(a,b) (a[0] == b[0] && a[1] == b[1]) | 457 #define hb_be_uint16_eq(a,b) (a[0] == b[0] && a[1] == b[1]) |
443 | 458 |
444 #define hb_be_uint32_put(v,V) HB_STMT_START { v[0] = (V>>24); v[1] = (V>>16);
v[2] = (V>>8); v[3] = (V); } HB_STMT_END | 459 #define hb_be_uint32_put(v,V) HB_STMT_START { v[0] = (V>>24); v[1] = (V>>16);
v[2] = (V>>8); v[3] = (V); } HB_STMT_END |
445 #define hb_be_uint32_get(v) (uint32_t) ((v[0] << 24) + (v[1] << 16) + (v[2]
<< 8) + v[3]) | 460 #define hb_be_uint32_get(v) (uint32_t) ((v[0] << 24) + (v[1] << 16) + (v[2]
<< 8) + v[3]) |
446 #define hb_be_uint32_eq(a,b) (a[0] == b[0] && a[1] == b[1] && a[2] == b[2] &&
a[3] == b[3]) | 461 #define hb_be_uint32_eq(a,b) (a[0] == b[0] && a[1] == b[1] && a[2] == b[2] &&
a[3] == b[3]) |
447 | 462 |
448 | 463 |
449 /* ASCII tag/character handling */ | 464 /* ASCII tag/character handling */ |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
481 static inline bool | 496 static inline bool |
482 _hb_debug (unsigned int level, | 497 _hb_debug (unsigned int level, |
483 unsigned int max_level) | 498 unsigned int max_level) |
484 { | 499 { |
485 return level < max_level; | 500 return level < max_level; |
486 } | 501 } |
487 | 502 |
488 #define DEBUG_LEVEL(WHAT, LEVEL) (_hb_debug ((LEVEL), HB_DEBUG_##WHAT)) | 503 #define DEBUG_LEVEL(WHAT, LEVEL) (_hb_debug ((LEVEL), HB_DEBUG_##WHAT)) |
489 #define DEBUG(WHAT) (DEBUG_LEVEL (WHAT, 0)) | 504 #define DEBUG(WHAT) (DEBUG_LEVEL (WHAT, 0)) |
490 | 505 |
491 template <int max_level> inline bool /* always returns TRUE */ | 506 template <int max_level> inline void |
| 507 _hb_debug_msg_va (const char *what, |
| 508 » » const void *obj, |
| 509 » » const char *func, |
| 510 » » bool indented, |
| 511 » » unsigned int level, |
| 512 » » int level_dir, |
| 513 » » const char *message, |
| 514 » » va_list ap) |
| 515 { |
| 516 if (!_hb_debug (level, max_level)) |
| 517 return; |
| 518 |
| 519 fprintf (stderr, "%-10s", what ? what : ""); |
| 520 |
| 521 if (obj) |
| 522 fprintf (stderr, "(%0*lx) ", (unsigned int) (2 * sizeof (void *)), (unsigned
long) obj); |
| 523 else |
| 524 fprintf (stderr, " %*s ", (unsigned int) (2 * sizeof (void *)), ""); |
| 525 |
| 526 if (indented) { |
| 527 static const char bars[] = "││││││││││││││││││││││││││││││││││││││││"; |
| 528 fprintf (stderr, "%2d %s├%s", |
| 529 » level, |
| 530 » bars + sizeof (bars) - 1 - MIN ((unsigned int) sizeof (bars), 3 * l
evel), |
| 531 » level_dir ? (level_dir > 0 ? "╮" : "╯") : "╴"); |
| 532 } else |
| 533 fprintf (stderr, " ├╴"); |
| 534 |
| 535 if (func) { |
| 536 /* If there's a class name, just write that. */ |
| 537 const char *dotdot = strstr (func, "::"); |
| 538 const char *space = strchr (func, ' '); |
| 539 if (space && dotdot && space < dotdot) |
| 540 func = space + 1; |
| 541 unsigned int func_len = dotdot ? dotdot - func : strlen (func); |
| 542 fprintf (stderr, "%.*s: ", func_len, func); |
| 543 } |
| 544 |
| 545 if (message) |
| 546 vfprintf (stderr, message, ap); |
| 547 |
| 548 fprintf (stderr, "\n"); |
| 549 } |
| 550 template <> inline void |
| 551 _hb_debug_msg_va<0> (const char *what HB_UNUSED, |
| 552 » » const void *obj HB_UNUSED, |
| 553 » » const char *func HB_UNUSED, |
| 554 » » bool indented HB_UNUSED, |
| 555 » » unsigned int level HB_UNUSED, |
| 556 » » int level_dir HB_UNUSED, |
| 557 » » const char *message HB_UNUSED, |
| 558 » » va_list ap HB_UNUSED) {} |
| 559 |
| 560 template <int max_level> inline void |
492 _hb_debug_msg (const char *what, | 561 _hb_debug_msg (const char *what, |
493 const void *obj, | 562 const void *obj, |
494 const char *func, | 563 const char *func, |
495 bool indented, | 564 bool indented, |
496 » int level, | 565 » unsigned int level, |
| 566 » int level_dir, |
497 const char *message, | 567 const char *message, |
498 » ...) HB_PRINTF_FUNC(6, 7); | 568 » ...) HB_PRINTF_FUNC(7, 8); |
499 template <int max_level> inline bool /* always returns TRUE */ | 569 template <int max_level> inline void |
500 _hb_debug_msg (const char *what, | 570 _hb_debug_msg (const char *what, |
501 const void *obj, | 571 const void *obj, |
502 const char *func, | 572 const char *func, |
503 bool indented, | 573 bool indented, |
504 » int level, | 574 » unsigned int level, |
| 575 » int level_dir, |
505 const char *message, | 576 const char *message, |
506 ...) | 577 ...) |
507 { | 578 { |
508 va_list ap; | 579 va_list ap; |
509 va_start (ap, message); | 580 va_start (ap, message); |
| 581 _hb_debug_msg_va<max_level> (what, obj, func, indented, level, level_dir, mess
age, ap); |
| 582 va_end (ap); |
| 583 } |
| 584 template <> inline void |
| 585 _hb_debug_msg<0> (const char *what HB_UNUSED, |
| 586 const void *obj HB_UNUSED, |
| 587 const char *func HB_UNUSED, |
| 588 bool indented HB_UNUSED, |
| 589 unsigned int level HB_UNUSED, |
| 590 int level_dir HB_UNUSED, |
| 591 const char *message HB_UNUSED, |
| 592 ...) HB_PRINTF_FUNC(7, 8); |
| 593 template <> inline void |
| 594 _hb_debug_msg<0> (const char *what HB_UNUSED, |
| 595 const void *obj HB_UNUSED, |
| 596 const char *func HB_UNUSED, |
| 597 bool indented HB_UNUSED, |
| 598 unsigned int level HB_UNUSED, |
| 599 int level_dir HB_UNUSED, |
| 600 const char *message HB_UNUSED, |
| 601 ...) {} |
510 | 602 |
511 (void) (_hb_debug (level, max_level) && | 603 #define DEBUG_MSG_LEVEL(WHAT, OBJ, LEVEL, LEVEL_DIR, ...)» _hb_debug_msg<HB
_DEBUG_##WHAT> (#WHAT, (OBJ), NULL, TRUE, (LEVEL), (LEVEL_DIR), __VA_ARGS__) |
512 » fprintf (stderr, "%s", what) && | 604 #define DEBUG_MSG(WHAT, OBJ, ...) » » » » _hb_debug_msg<HB
_DEBUG_##WHAT> (#WHAT, (OBJ), NULL, FALSE, 0, 0, __VA_ARGS__) |
513 » (obj && fprintf (stderr, "(%p)", obj), TRUE) && | 605 #define DEBUG_MSG_FUNC(WHAT, OBJ, ...)» » » » _hb_debug_msg<HB
_DEBUG_##WHAT> (#WHAT, (OBJ), HB_FUNC, FALSE, 0, 0, __VA_ARGS__) |
514 » fprintf (stderr, ": ") && | |
515 » (func && fprintf (stderr, "%s: ", func), TRUE) && | |
516 » (indented && fprintf (stderr, "%-*d-> ", level + 1, level), TRUE) && | |
517 » vfprintf (stderr, message, ap) && | |
518 » fprintf (stderr, "\n")); | |
519 | |
520 va_end (ap); | |
521 | |
522 return TRUE; | |
523 } | |
524 template <> inline bool /* always returns TRUE */ | |
525 _hb_debug_msg<0> (const char *what, | |
526 » » const void *obj, | |
527 » » const char *func, | |
528 » » bool indented, | |
529 » » int level, | |
530 » » const char *message, | |
531 » » ...) HB_PRINTF_FUNC(6, 7); | |
532 template <> inline bool /* always returns TRUE */ | |
533 _hb_debug_msg<0> (const char *what, | |
534 » » const void *obj, | |
535 » » const char *func, | |
536 » » bool indented, | |
537 » » int level, | |
538 » » const char *message, | |
539 » » ...) | |
540 { | |
541 return TRUE; | |
542 } | |
543 | |
544 #define DEBUG_MSG_LEVEL(WHAT, OBJ, LEVEL, ...) _hb_debug_msg<HB_DEBUG_##WHAT> (#
WHAT, (OBJ), NULL, FALSE, (LEVEL), __VA_ARGS__) | |
545 #define DEBUG_MSG(WHAT, OBJ, ...) DEBUG_MSG_LEVEL (WHAT, OBJ, 0, __VA_ARGS__) | |
546 #define DEBUG_MSG_FUNC(WHAT, OBJ, ...) _hb_debug_msg<HB_DEBUG_##WHAT> (#WHAT, (O
BJ), HB_FUNC, FALSE, 0, __VA_ARGS__) | |
547 | 606 |
548 | 607 |
549 /* | 608 /* |
550 * Trace | 609 * Trace |
551 */ | 610 */ |
552 | 611 |
553 template <int max_level> | 612 template <int max_level> |
554 struct hb_auto_trace_t { | 613 struct hb_auto_trace_t { |
555 explicit inline hb_auto_trace_t (unsigned int *plevel_, | 614 explicit inline hb_auto_trace_t (unsigned int *plevel_, |
556 » » » » const char *what, | 615 » » » » const char *what_, |
557 » » » » const void *obj, | 616 » » » » const void *obj_, |
558 const char *func, | 617 const char *func, |
559 » » » » const char *message) : plevel(plevel_) | 618 » » » » const char *message, |
| 619 » » » » ...) : plevel (plevel_), what (what_), obj (o
bj_), returned (false) |
560 { | 620 { |
561 if (max_level) ++*plevel; | 621 if (plevel) ++*plevel; |
562 /* TODO support variadic args here */ | 622 |
563 _hb_debug_msg<max_level> (what, obj, func, TRUE, *plevel, "%s", message); | 623 va_list ap; |
| 624 va_start (ap, message); |
| 625 _hb_debug_msg_va<max_level> (what, obj, func, TRUE, plevel ? *plevel : 0, +1
, message, ap); |
| 626 va_end (ap); |
564 } | 627 } |
565 ~hb_auto_trace_t (void) { if (max_level) --*plevel; } | 628 inline ~hb_auto_trace_t (void) |
| 629 { |
| 630 if (unlikely (!returned)) { |
| 631 fprintf (stderr, "OUCH, returned with no call to TRACE_RETURN. This is a
bug, please report. Level was %d.\n", plevel ? *plevel : -1); |
| 632 _hb_debug_msg<max_level> (what, obj, NULL, TRUE, plevel ? *plevel : 1, -1,
" "); |
| 633 return; |
| 634 } |
| 635 |
| 636 if (plevel) --*plevel; |
| 637 } |
| 638 |
| 639 inline bool ret (bool v) |
| 640 { |
| 641 if (unlikely (returned)) { |
| 642 fprintf (stderr, "OUCH, double calls to TRACE_RETURN. This is a bug, plea
se report.\n"); |
| 643 return v; |
| 644 } |
| 645 |
| 646 _hb_debug_msg<max_level> (what, obj, NULL, TRUE, plevel ? *plevel : 1, -1, "
return %s", v ? "true" : "false"); |
| 647 if (plevel) --*plevel; |
| 648 plevel = NULL; |
| 649 returned = true; |
| 650 return v; |
| 651 } |
566 | 652 |
567 private: | 653 private: |
568 unsigned int *plevel; | 654 unsigned int *plevel; |
| 655 bool returned; |
| 656 const char *what; |
| 657 const void *obj; |
569 }; | 658 }; |
570 template <> /* Optimize when tracing is disabled */ | 659 template <> /* Optimize when tracing is disabled */ |
571 struct hb_auto_trace_t<0> { | 660 struct hb_auto_trace_t<0> { |
572 explicit inline hb_auto_trace_t (unsigned int *plevel_, | 661 explicit inline hb_auto_trace_t (unsigned int *plevel_ HB_UNUSED, |
573 » » » » const char *what, | 662 » » » » const char *what HB_UNUSED, |
574 » » » » const void *obj, | 663 » » » » const void *obj HB_UNUSED, |
575 » » » » const char *func, | 664 » » » » const char *func HB_UNUSED, |
576 » » » » const char *message) {} | 665 » » » » const char *message HB_UNUSED, |
| 666 » » » » ...) {} |
| 667 |
| 668 template <typename T> |
| 669 inline T ret (T v) { return v; } |
577 }; | 670 }; |
578 | 671 |
| 672 #define TRACE_RETURN(RET) trace.ret (RET) |
579 | 673 |
580 /* Misc */ | 674 /* Misc */ |
581 | 675 |
582 | 676 |
583 /* Pre-mature optimization: | 677 /* Pre-mature optimization: |
584 * Checks for lo <= u <= hi but with an optimization if lo and hi | 678 * Checks for lo <= u <= hi but with an optimization if lo and hi |
585 * are only different in a contiguous set of lower-most bits. | 679 * are only different in a contiguous set of lower-most bits. |
586 */ | 680 */ |
587 template <typename T> inline bool | 681 template <typename T> inline bool |
588 hb_in_range (T u, T lo, T hi) | 682 hb_in_range (T u, T lo, T hi) |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
623 new_k = j; | 717 new_k = j; |
624 } | 718 } |
625 k = new_k; | 719 k = new_k; |
626 } while (k); | 720 } while (k); |
627 } | 721 } |
628 | 722 |
629 | 723 |
630 | 724 |
631 | 725 |
632 #endif /* HB_PRIVATE_HH */ | 726 #endif /* HB_PRIVATE_HH */ |
OLD | NEW |