OLD | NEW |
1 /* | 1 /* |
2 * Copyright © 2007,2008,2009,2010 Red Hat, Inc. | 2 * Copyright © 2007,2008,2009,2010 Red Hat, Inc. |
3 * Copyright © 2012 Google, Inc. | 3 * Copyright © 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 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
172 /* This limits sanitizing time on really broken fonts. */ | 172 /* This limits sanitizing time on really broken fonts. */ |
173 #ifndef HB_SANITIZE_MAX_EDITS | 173 #ifndef HB_SANITIZE_MAX_EDITS |
174 #define HB_SANITIZE_MAX_EDITS 100 | 174 #define HB_SANITIZE_MAX_EDITS 100 |
175 #endif | 175 #endif |
176 | 176 |
177 struct hb_sanitize_context_t | 177 struct hb_sanitize_context_t |
178 { | 178 { |
179 inline const char *get_name (void) { return "SANITIZE"; } | 179 inline const char *get_name (void) { return "SANITIZE"; } |
180 static const unsigned int max_debug_depth = HB_DEBUG_SANITIZE; | 180 static const unsigned int max_debug_depth = HB_DEBUG_SANITIZE; |
181 typedef bool return_t; | 181 typedef bool return_t; |
| 182 template <typename T, typename F> |
| 183 inline bool may_dispatch (const T *obj, const F *format) |
| 184 { return format->sanitize (this); } |
182 template <typename T> | 185 template <typename T> |
183 inline return_t dispatch (const T &obj) { return obj.sanitize (this); } | 186 inline return_t dispatch (const T &obj) { return obj.sanitize (this); } |
184 static return_t default_return_value (void) { return true; } | 187 static return_t default_return_value (void) { return true; } |
185 bool stop_sublookup_iteration (const return_t r HB_UNUSED) const { return fals
e; } | 188 bool stop_sublookup_iteration (const return_t r) const { return !r; } |
186 | 189 |
187 inline void init (hb_blob_t *b) | 190 inline void init (hb_blob_t *b) |
188 { | 191 { |
189 this->blob = hb_blob_reference (b); | 192 this->blob = hb_blob_reference (b); |
190 this->writable = false; | 193 this->writable = false; |
191 } | 194 } |
192 | 195 |
193 inline void start_processing (void) | 196 inline void start_processing (void) |
194 { | 197 { |
195 this->start = hb_blob_get_data (this->blob, NULL); | 198 this->start = hb_blob_get_data (this->blob, NULL); |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
263 "may_edit(%u) [%p..%p] (%d bytes) in [%p..%p] -> %s", | 266 "may_edit(%u) [%p..%p] (%d bytes) in [%p..%p] -> %s", |
264 this->edit_count, | 267 this->edit_count, |
265 p, p + len, len, | 268 p, p + len, len, |
266 this->start, this->end, | 269 this->start, this->end, |
267 this->writable ? "GRANTED" : "DENIED"); | 270 this->writable ? "GRANTED" : "DENIED"); |
268 | 271 |
269 return this->writable; | 272 return this->writable; |
270 } | 273 } |
271 | 274 |
272 template <typename Type, typename ValueType> | 275 template <typename Type, typename ValueType> |
273 inline bool try_set (Type *obj, const ValueType &v) { | 276 inline bool try_set (const Type *obj, const ValueType &v) { |
274 if (this->may_edit (obj, obj->static_size)) { | 277 if (this->may_edit (obj, obj->static_size)) { |
275 obj->set (v); | 278 const_cast<Type *> (obj)->set (v); |
276 return true; | 279 return true; |
277 } | 280 } |
278 return false; | 281 return false; |
279 } | 282 } |
280 | 283 |
281 mutable unsigned int debug_depth; | 284 mutable unsigned int debug_depth; |
282 const char *start, *end; | 285 const char *start, *end; |
283 bool writable; | 286 bool writable; |
284 unsigned int edit_count; | 287 unsigned int edit_count; |
285 hb_blob_t *blob; | 288 hb_blob_t *blob; |
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
539 inline void set (Type V) | 542 inline void set (Type V) |
540 { | 543 { |
541 v[0] = (V >> 8) & 0xFF; | 544 v[0] = (V >> 8) & 0xFF; |
542 v[1] = (V ) & 0xFF; | 545 v[1] = (V ) & 0xFF; |
543 } | 546 } |
544 inline operator Type (void) const | 547 inline operator Type (void) const |
545 { | 548 { |
546 return (v[0] << 8) | 549 return (v[0] << 8) |
547 + (v[1] ); | 550 + (v[1] ); |
548 } | 551 } |
549 inline bool operator == (const BEInt<Type, 2>& o) const | |
550 { | |
551 return v[0] == o.v[0] | |
552 && v[1] == o.v[1]; | |
553 } | |
554 inline bool operator != (const BEInt<Type, 2>& o) const { return !(*this == o)
; } | |
555 private: uint8_t v[2]; | 552 private: uint8_t v[2]; |
556 }; | 553 }; |
557 template <typename Type> | 554 template <typename Type> |
558 struct BEInt<Type, 3> | 555 struct BEInt<Type, 3> |
559 { | 556 { |
560 public: | 557 public: |
561 inline void set (Type V) | 558 inline void set (Type V) |
562 { | 559 { |
563 v[0] = (V >> 16) & 0xFF; | 560 v[0] = (V >> 16) & 0xFF; |
564 v[1] = (V >> 8) & 0xFF; | 561 v[1] = (V >> 8) & 0xFF; |
565 v[2] = (V ) & 0xFF; | 562 v[2] = (V ) & 0xFF; |
566 } | 563 } |
567 inline operator Type (void) const | 564 inline operator Type (void) const |
568 { | 565 { |
569 return (v[0] << 16) | 566 return (v[0] << 16) |
570 + (v[1] << 8) | 567 + (v[1] << 8) |
571 + (v[2] ); | 568 + (v[2] ); |
572 } | 569 } |
573 inline bool operator == (const BEInt<Type, 3>& o) const | |
574 { | |
575 return v[0] == o.v[0] | |
576 && v[1] == o.v[1] | |
577 && v[2] == o.v[2]; | |
578 } | |
579 inline bool operator != (const BEInt<Type, 3>& o) const { return !(*this == o)
; } | |
580 private: uint8_t v[3]; | 570 private: uint8_t v[3]; |
581 }; | 571 }; |
582 template <typename Type> | 572 template <typename Type> |
583 struct BEInt<Type, 4> | 573 struct BEInt<Type, 4> |
584 { | 574 { |
585 public: | 575 public: |
586 inline void set (Type V) | 576 inline void set (Type V) |
587 { | 577 { |
588 v[0] = (V >> 24) & 0xFF; | 578 v[0] = (V >> 24) & 0xFF; |
589 v[1] = (V >> 16) & 0xFF; | 579 v[1] = (V >> 16) & 0xFF; |
590 v[2] = (V >> 8) & 0xFF; | 580 v[2] = (V >> 8) & 0xFF; |
591 v[3] = (V ) & 0xFF; | 581 v[3] = (V ) & 0xFF; |
592 } | 582 } |
593 inline operator Type (void) const | 583 inline operator Type (void) const |
594 { | 584 { |
595 return (v[0] << 24) | 585 return (v[0] << 24) |
596 + (v[1] << 16) | 586 + (v[1] << 16) |
597 + (v[2] << 8) | 587 + (v[2] << 8) |
598 + (v[3] ); | 588 + (v[3] ); |
599 } | 589 } |
600 inline bool operator == (const BEInt<Type, 4>& o) const | |
601 { | |
602 return v[0] == o.v[0] | |
603 && v[1] == o.v[1] | |
604 && v[2] == o.v[2] | |
605 && v[3] == o.v[3]; | |
606 } | |
607 inline bool operator != (const BEInt<Type, 4>& o) const { return !(*this == o)
; } | |
608 private: uint8_t v[4]; | 590 private: uint8_t v[4]; |
609 }; | 591 }; |
610 | 592 |
611 /* Integer types in big-endian order and no alignment requirement */ | 593 /* Integer types in big-endian order and no alignment requirement */ |
612 template <typename Type, unsigned int Size> | 594 template <typename Type, unsigned int Size> |
613 struct IntType | 595 struct IntType |
614 { | 596 { |
615 inline void set (Type i) { v.set (i); } | 597 inline void set (Type i) { v.set (i); } |
616 inline operator Type(void) const { return v; } | 598 inline operator Type(void) const { return v; } |
617 inline bool operator == (const IntType<Type,Size> &o) const { return v == o.v;
} | 599 inline bool operator == (const IntType<Type,Size> &o) const { return (Type) v
== (Type) o.v; } |
618 inline bool operator != (const IntType<Type,Size> &o) const { return v != o.v;
} | 600 inline bool operator != (const IntType<Type,Size> &o) const { return !(*this =
= o); } |
619 static inline int cmp (const IntType<Type,Size> *a, const IntType<Type,Size> *
b) { return b->cmp (*a); } | 601 static inline int cmp (const IntType<Type,Size> *a, const IntType<Type,Size> *
b) { return b->cmp (*a); } |
620 inline int cmp (IntType<Type,Size> va) const { Type a = va; Type b = v; return
a < b ? -1 : a == b ? 0 : +1; } | 602 inline int cmp (Type a) const |
621 inline int cmp (Type a) const { Type b = v; return a < b ? -1 : a == b ? 0 : +
1; } | 603 { |
622 inline bool sanitize (hb_sanitize_context_t *c) { | 604 Type b = v; |
| 605 if (sizeof (Type) < sizeof (int)) |
| 606 return (int) a - (int) b; |
| 607 else |
| 608 return a < b ? -1 : a == b ? 0 : +1; |
| 609 } |
| 610 inline bool sanitize (hb_sanitize_context_t *c) const |
| 611 { |
623 TRACE_SANITIZE (this); | 612 TRACE_SANITIZE (this); |
624 return TRACE_RETURN (likely (c->check_struct (this))); | 613 return TRACE_RETURN (likely (c->check_struct (this))); |
625 } | 614 } |
626 protected: | 615 protected: |
627 BEInt<Type, Size> v; | 616 BEInt<Type, Size> v; |
628 public: | 617 public: |
629 DEFINE_SIZE_STATIC (Size); | 618 DEFINE_SIZE_STATIC (Size); |
630 }; | 619 }; |
631 | 620 |
632 typedef uint8_t BYTE; /* 8-bit unsigned integer. */ | 621 typedef uint8_t BYTE; /* 8-bit unsigned integer. */ |
633 typedef IntType<uint16_t, 2> USHORT; /* 16-bit unsigned integer. */ | 622 typedef IntType<uint16_t, 2> USHORT; /* 16-bit unsigned integer. */ |
634 typedef IntType<int16_t, 2> SHORT; /* 16-bit signed integer. */ | 623 typedef IntType<int16_t, 2> SHORT; /* 16-bit signed integer. */ |
635 typedef IntType<uint32_t, 4> ULONG; /* 32-bit unsigned integer. */ | 624 typedef IntType<uint32_t, 4> ULONG; /* 32-bit unsigned integer. */ |
636 typedef IntType<int32_t, 4> LONG; /* 32-bit signed integer. */ | 625 typedef IntType<int32_t, 4> LONG; /* 32-bit signed integer. */ |
637 typedef IntType<uint32_t, 3> UINT24; /* 24-bit unsigned integer. */ | 626 typedef IntType<uint32_t, 3> UINT24; /* 24-bit unsigned integer. */ |
638 | 627 |
639 /* 16-bit signed integer (SHORT) that describes a quantity in FUnits. */ | 628 /* 16-bit signed integer (SHORT) that describes a quantity in FUnits. */ |
640 typedef SHORT FWORD; | 629 typedef SHORT FWORD; |
641 | 630 |
642 /* 16-bit unsigned integer (USHORT) that describes a quantity in FUnits. */ | 631 /* 16-bit unsigned integer (USHORT) that describes a quantity in FUnits. */ |
643 typedef USHORT UFWORD; | 632 typedef USHORT UFWORD; |
644 | 633 |
645 /* Date represented in number of seconds since 12:00 midnight, January 1, | 634 /* Date represented in number of seconds since 12:00 midnight, January 1, |
646 * 1904. The value is represented as a signed 64-bit integer. */ | 635 * 1904. The value is represented as a signed 64-bit integer. */ |
647 struct LONGDATETIME | 636 struct LONGDATETIME |
648 { | 637 { |
649 inline bool sanitize (hb_sanitize_context_t *c) { | 638 inline bool sanitize (hb_sanitize_context_t *c) const |
| 639 { |
650 TRACE_SANITIZE (this); | 640 TRACE_SANITIZE (this); |
651 return TRACE_RETURN (likely (c->check_struct (this))); | 641 return TRACE_RETURN (likely (c->check_struct (this))); |
652 } | 642 } |
653 protected: | 643 protected: |
654 LONG major; | 644 LONG major; |
655 ULONG minor; | 645 ULONG minor; |
656 public: | 646 public: |
657 DEFINE_SIZE_STATIC (8); | 647 DEFINE_SIZE_STATIC (8); |
658 }; | 648 }; |
659 | 649 |
660 /* Array of four uint8s (length = 32 bits) used to identify a script, language | 650 /* Array of four uint8s (length = 32 bits) used to identify a script, language |
661 * system, feature, or baseline */ | 651 * system, feature, or baseline */ |
662 struct Tag : ULONG | 652 struct Tag : ULONG |
663 { | 653 { |
664 /* What the char* converters return is NOT nul-terminated. Print using "%.4s"
*/ | 654 /* What the char* converters return is NOT nul-terminated. Print using "%.4s"
*/ |
665 inline operator const char* (void) const { return reinterpret_cast<const char
*> (&this->v); } | 655 inline operator const char* (void) const { return reinterpret_cast<const char
*> (&this->v); } |
666 inline operator char* (void) { return reinterpret_cast<char *> (&this->v); } | 656 inline operator char* (void) { return reinterpret_cast<char *> (&this->v); } |
667 public: | 657 public: |
668 DEFINE_SIZE_STATIC (4); | 658 DEFINE_SIZE_STATIC (4); |
669 }; | 659 }; |
670 DEFINE_NULL_DATA (Tag, " "); | 660 DEFINE_NULL_DATA (Tag, " "); |
671 | 661 |
672 /* Glyph index number, same as uint16 (length = 16 bits) */ | 662 /* Glyph index number, same as uint16 (length = 16 bits) */ |
673 typedef USHORT GlyphID; | 663 struct GlyphID : USHORT { |
| 664 static inline int cmp (const GlyphID *a, const GlyphID *b) { return b->USHORT:
:cmp (*a); } |
| 665 inline int cmp (hb_codepoint_t a) const { return (int) a - (int) *this; } |
| 666 }; |
674 | 667 |
675 /* Script/language-system/feature index */ | 668 /* Script/language-system/feature index */ |
676 struct Index : USHORT { | 669 struct Index : USHORT { |
677 static const unsigned int NOT_FOUND_INDEX = 0xFFFFu; | 670 static const unsigned int NOT_FOUND_INDEX = 0xFFFFu; |
678 }; | 671 }; |
679 DEFINE_NULL_DATA (Index, "\xff\xff"); | 672 DEFINE_NULL_DATA (Index, "\xff\xff"); |
680 | 673 |
681 /* Offset, Null offset = 0 */ | 674 /* Offset, Null offset = 0 */ |
682 template <typename Type=USHORT> | 675 template <typename Type=USHORT> |
683 struct Offset : Type | 676 struct Offset : Type |
(...skipping 28 matching lines...) Expand all Loading... |
712 | 705 |
713 | 706 |
714 /* | 707 /* |
715 * Version Numbers | 708 * Version Numbers |
716 */ | 709 */ |
717 | 710 |
718 struct FixedVersion | 711 struct FixedVersion |
719 { | 712 { |
720 inline uint32_t to_int (void) const { return (major << 16) + minor; } | 713 inline uint32_t to_int (void) const { return (major << 16) + minor; } |
721 | 714 |
722 inline bool sanitize (hb_sanitize_context_t *c) { | 715 inline bool sanitize (hb_sanitize_context_t *c) const |
| 716 { |
723 TRACE_SANITIZE (this); | 717 TRACE_SANITIZE (this); |
724 return TRACE_RETURN (c->check_struct (this)); | 718 return TRACE_RETURN (c->check_struct (this)); |
725 } | 719 } |
726 | 720 |
727 USHORT major; | 721 USHORT major; |
728 USHORT minor; | 722 USHORT minor; |
729 public: | 723 public: |
730 DEFINE_SIZE_STATIC (4); | 724 DEFINE_SIZE_STATIC (4); |
731 }; | 725 }; |
732 | 726 |
733 | 727 |
734 | 728 |
735 /* | 729 /* |
736 * Template subclasses of Offset that do the dereferencing. | 730 * Template subclasses of Offset that do the dereferencing. |
737 * Use: (base+offset) | 731 * Use: (base+offset) |
738 */ | 732 */ |
739 | 733 |
740 template <typename Type, typename OffsetType=USHORT> | 734 template <typename Type, typename OffsetType=USHORT> |
741 struct OffsetTo : Offset<OffsetType> | 735 struct OffsetTo : Offset<OffsetType> |
742 { | 736 { |
743 inline const Type& operator () (const void *base) const | 737 inline const Type& operator () (const void *base) const |
744 { | 738 { |
745 unsigned int offset = *this; | 739 unsigned int offset = *this; |
746 if (unlikely (!offset)) return Null(Type); | 740 if (unlikely (!offset)) return Null(Type); |
747 return StructAtOffset<Type> (base, offset); | 741 return StructAtOffset<Type> (base, offset); |
748 } | 742 } |
749 | 743 |
750 inline Type& serialize (hb_serialize_context_t *c, void *base) | 744 inline Type& serialize (hb_serialize_context_t *c, const void *base) |
751 { | 745 { |
752 Type *t = c->start_embed<Type> (); | 746 Type *t = c->start_embed<Type> (); |
753 this->set ((char *) t - (char *) base); /* TODO(serialize) Overflow? */ | 747 this->set ((char *) t - (char *) base); /* TODO(serialize) Overflow? */ |
754 return *t; | 748 return *t; |
755 } | 749 } |
756 | 750 |
757 inline bool sanitize (hb_sanitize_context_t *c, void *base) { | 751 inline bool sanitize (hb_sanitize_context_t *c, const void *base) const |
| 752 { |
758 TRACE_SANITIZE (this); | 753 TRACE_SANITIZE (this); |
759 if (unlikely (!c->check_struct (this))) return TRACE_RETURN (false); | 754 if (unlikely (!c->check_struct (this))) return TRACE_RETURN (false); |
760 unsigned int offset = *this; | 755 unsigned int offset = *this; |
761 if (unlikely (!offset)) return TRACE_RETURN (true); | 756 if (unlikely (!offset)) return TRACE_RETURN (true); |
762 Type &obj = StructAtOffset<Type> (base, offset); | 757 const Type &obj = StructAtOffset<Type> (base, offset); |
763 return TRACE_RETURN (likely (obj.sanitize (c)) || neuter (c)); | 758 return TRACE_RETURN (likely (obj.sanitize (c)) || neuter (c)); |
764 } | 759 } |
765 template <typename T> | 760 template <typename T> |
766 inline bool sanitize (hb_sanitize_context_t *c, void *base, T user_data) { | 761 inline bool sanitize (hb_sanitize_context_t *c, const void *base, T user_data)
const |
| 762 { |
767 TRACE_SANITIZE (this); | 763 TRACE_SANITIZE (this); |
768 if (unlikely (!c->check_struct (this))) return TRACE_RETURN (false); | 764 if (unlikely (!c->check_struct (this))) return TRACE_RETURN (false); |
769 unsigned int offset = *this; | 765 unsigned int offset = *this; |
770 if (unlikely (!offset)) return TRACE_RETURN (true); | 766 if (unlikely (!offset)) return TRACE_RETURN (true); |
771 Type &obj = StructAtOffset<Type> (base, offset); | 767 const Type &obj = StructAtOffset<Type> (base, offset); |
772 return TRACE_RETURN (likely (obj.sanitize (c, user_data)) || neuter (c)); | 768 return TRACE_RETURN (likely (obj.sanitize (c, user_data)) || neuter (c)); |
773 } | 769 } |
774 | 770 |
775 /* Set the offset to Null */ | 771 /* Set the offset to Null */ |
776 inline bool neuter (hb_sanitize_context_t *c) { | 772 inline bool neuter (hb_sanitize_context_t *c) const { |
777 return c->try_set (this, 0); | 773 return c->try_set (this, 0); |
778 } | 774 } |
779 DEFINE_SIZE_STATIC (sizeof(OffsetType)); | 775 DEFINE_SIZE_STATIC (sizeof(OffsetType)); |
780 }; | 776 }; |
781 template <typename Base, typename OffsetType, typename Type> | 777 template <typename Base, typename OffsetType, typename Type> |
782 static inline const Type& operator + (const Base &base, const OffsetTo<Type, Off
setType> &offset) { return offset (base); } | 778 static inline const Type& operator + (const Base &base, const OffsetTo<Type, Off
setType> &offset) { return offset (base); } |
783 template <typename Base, typename OffsetType, typename Type> | 779 template <typename Base, typename OffsetType, typename Type> |
784 static inline Type& operator + (Base &base, OffsetTo<Type, OffsetType> &offset)
{ return offset (base); } | 780 static inline Type& operator + (Base &base, OffsetTo<Type, OffsetType> &offset)
{ return offset (base); } |
785 | 781 |
786 | 782 |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
831 unsigned int items_len) | 827 unsigned int items_len) |
832 { | 828 { |
833 TRACE_SERIALIZE (this); | 829 TRACE_SERIALIZE (this); |
834 if (unlikely (!serialize (c, items_len))) return TRACE_RETURN (false); | 830 if (unlikely (!serialize (c, items_len))) return TRACE_RETURN (false); |
835 for (unsigned int i = 0; i < items_len; i++) | 831 for (unsigned int i = 0; i < items_len; i++) |
836 array[i] = items[i]; | 832 array[i] = items[i]; |
837 items.advance (items_len); | 833 items.advance (items_len); |
838 return TRACE_RETURN (true); | 834 return TRACE_RETURN (true); |
839 } | 835 } |
840 | 836 |
841 inline bool sanitize (hb_sanitize_context_t *c) { | 837 inline bool sanitize (hb_sanitize_context_t *c) const |
| 838 { |
842 TRACE_SANITIZE (this); | 839 TRACE_SANITIZE (this); |
843 if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false); | 840 if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false); |
844 | 841 |
845 /* Note: for structs that do not reference other structs, | 842 /* Note: for structs that do not reference other structs, |
846 * we do not need to call their sanitize() as we already did | 843 * we do not need to call their sanitize() as we already did |
847 * a bound check on the aggregate array size. We just include | 844 * a bound check on the aggregate array size. We just include |
848 * a small unreachable expression to make sure the structs | 845 * a small unreachable expression to make sure the structs |
849 * pointed to do have a simple sanitize(), ie. they do not | 846 * pointed to do have a simple sanitize(), ie. they do not |
850 * reference other structs via offsets. | 847 * reference other structs via offsets. |
851 */ | 848 */ |
852 (void) (false && array[0].sanitize (c)); | 849 (void) (false && array[0].sanitize (c)); |
853 | 850 |
854 return TRACE_RETURN (true); | 851 return TRACE_RETURN (true); |
855 } | 852 } |
856 inline bool sanitize (hb_sanitize_context_t *c, void *base) { | 853 inline bool sanitize (hb_sanitize_context_t *c, const void *base) const |
| 854 { |
857 TRACE_SANITIZE (this); | 855 TRACE_SANITIZE (this); |
858 if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false); | 856 if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false); |
859 unsigned int count = len; | 857 unsigned int count = len; |
860 for (unsigned int i = 0; i < count; i++) | 858 for (unsigned int i = 0; i < count; i++) |
861 if (unlikely (!array[i].sanitize (c, base))) | 859 if (unlikely (!array[i].sanitize (c, base))) |
862 return TRACE_RETURN (false); | 860 return TRACE_RETURN (false); |
863 return TRACE_RETURN (true); | 861 return TRACE_RETURN (true); |
864 } | 862 } |
865 template <typename T> | 863 template <typename T> |
866 inline bool sanitize (hb_sanitize_context_t *c, void *base, T user_data) { | 864 inline bool sanitize (hb_sanitize_context_t *c, const void *base, T user_data)
const |
| 865 { |
867 TRACE_SANITIZE (this); | 866 TRACE_SANITIZE (this); |
868 if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false); | 867 if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false); |
869 unsigned int count = len; | 868 unsigned int count = len; |
870 for (unsigned int i = 0; i < count; i++) | 869 for (unsigned int i = 0; i < count; i++) |
871 if (unlikely (!array[i].sanitize (c, base, user_data))) | 870 if (unlikely (!array[i].sanitize (c, base, user_data))) |
872 return TRACE_RETURN (false); | 871 return TRACE_RETURN (false); |
873 return TRACE_RETURN (true); | 872 return TRACE_RETURN (true); |
874 } | 873 } |
875 | 874 |
876 template <typename SearchType> | 875 template <typename SearchType> |
877 inline int lsearch (const SearchType &x) const | 876 inline int lsearch (const SearchType &x) const |
878 { | 877 { |
879 unsigned int count = len; | 878 unsigned int count = len; |
880 for (unsigned int i = 0; i < count; i++) | 879 for (unsigned int i = 0; i < count; i++) |
881 if (!this->array[i].cmp (x)) | 880 if (!this->array[i].cmp (x)) |
882 return i; | 881 return i; |
883 return -1; | 882 return -1; |
884 } | 883 } |
885 | 884 |
886 private: | 885 private: |
887 inline bool sanitize_shallow (hb_sanitize_context_t *c) { | 886 inline bool sanitize_shallow (hb_sanitize_context_t *c) const |
| 887 { |
888 TRACE_SANITIZE (this); | 888 TRACE_SANITIZE (this); |
889 return TRACE_RETURN (c->check_struct (this) && c->check_array (this, Type::s
tatic_size, len)); | 889 return TRACE_RETURN (c->check_struct (this) && c->check_array (this, Type::s
tatic_size, len)); |
890 } | 890 } |
891 | 891 |
892 public: | 892 public: |
893 LenType len; | 893 LenType len; |
894 Type array[VAR]; | 894 Type array[VAR]; |
895 public: | 895 public: |
896 DEFINE_SIZE_ARRAY (sizeof (LenType), array); | 896 DEFINE_SIZE_ARRAY (sizeof (LenType), array); |
897 }; | 897 }; |
898 | 898 |
899 /* Array of Offset's */ | 899 /* Array of Offset's */ |
900 template <typename Type> | 900 template <typename Type> |
901 struct OffsetArrayOf : ArrayOf<OffsetTo<Type> > {}; | 901 struct OffsetArrayOf : ArrayOf<OffsetTo<Type> > {}; |
902 | 902 |
903 /* Array of offsets relative to the beginning of the array itself. */ | 903 /* Array of offsets relative to the beginning of the array itself. */ |
904 template <typename Type> | 904 template <typename Type> |
905 struct OffsetListOf : OffsetArrayOf<Type> | 905 struct OffsetListOf : OffsetArrayOf<Type> |
906 { | 906 { |
907 inline const Type& operator [] (unsigned int i) const | 907 inline const Type& operator [] (unsigned int i) const |
908 { | 908 { |
909 if (unlikely (i >= this->len)) return Null(Type); | 909 if (unlikely (i >= this->len)) return Null(Type); |
910 return this+this->array[i]; | 910 return this+this->array[i]; |
911 } | 911 } |
912 | 912 |
913 inline bool sanitize (hb_sanitize_context_t *c) { | 913 inline bool sanitize (hb_sanitize_context_t *c) const |
| 914 { |
914 TRACE_SANITIZE (this); | 915 TRACE_SANITIZE (this); |
915 return TRACE_RETURN (OffsetArrayOf<Type>::sanitize (c, this)); | 916 return TRACE_RETURN (OffsetArrayOf<Type>::sanitize (c, this)); |
916 } | 917 } |
917 template <typename T> | 918 template <typename T> |
918 inline bool sanitize (hb_sanitize_context_t *c, T user_data) { | 919 inline bool sanitize (hb_sanitize_context_t *c, T user_data) const |
| 920 { |
919 TRACE_SANITIZE (this); | 921 TRACE_SANITIZE (this); |
920 return TRACE_RETURN (OffsetArrayOf<Type>::sanitize (c, this, user_data)); | 922 return TRACE_RETURN (OffsetArrayOf<Type>::sanitize (c, this, user_data)); |
921 } | 923 } |
922 }; | 924 }; |
923 | 925 |
924 | 926 |
925 /* An array starting at second element. */ | 927 /* An array starting at second element. */ |
926 template <typename Type, typename LenType=USHORT> | 928 template <typename Type, typename LenType=USHORT> |
927 struct HeadlessArrayOf | 929 struct HeadlessArrayOf |
928 { | 930 { |
(...skipping 13 matching lines...) Expand all Loading... |
942 if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); | 944 if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); |
943 len.set (items_len); /* TODO(serialize) Overflow? */ | 945 len.set (items_len); /* TODO(serialize) Overflow? */ |
944 if (unlikely (!items_len)) return TRACE_RETURN (true); | 946 if (unlikely (!items_len)) return TRACE_RETURN (true); |
945 if (unlikely (!c->extend (*this))) return TRACE_RETURN (false); | 947 if (unlikely (!c->extend (*this))) return TRACE_RETURN (false); |
946 for (unsigned int i = 0; i < items_len - 1; i++) | 948 for (unsigned int i = 0; i < items_len - 1; i++) |
947 array[i] = items[i]; | 949 array[i] = items[i]; |
948 items.advance (items_len - 1); | 950 items.advance (items_len - 1); |
949 return TRACE_RETURN (true); | 951 return TRACE_RETURN (true); |
950 } | 952 } |
951 | 953 |
952 inline bool sanitize_shallow (hb_sanitize_context_t *c) { | 954 inline bool sanitize_shallow (hb_sanitize_context_t *c) const |
| 955 { |
953 return c->check_struct (this) | 956 return c->check_struct (this) |
954 && c->check_array (this, Type::static_size, len); | 957 && c->check_array (this, Type::static_size, len); |
955 } | 958 } |
956 | 959 |
957 inline bool sanitize (hb_sanitize_context_t *c) { | 960 inline bool sanitize (hb_sanitize_context_t *c) const |
| 961 { |
958 TRACE_SANITIZE (this); | 962 TRACE_SANITIZE (this); |
959 if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false); | 963 if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false); |
960 | 964 |
961 /* Note: for structs that do not reference other structs, | 965 /* Note: for structs that do not reference other structs, |
962 * we do not need to call their sanitize() as we already did | 966 * we do not need to call their sanitize() as we already did |
963 * a bound check on the aggregate array size. We just include | 967 * a bound check on the aggregate array size. We just include |
964 * a small unreachable expression to make sure the structs | 968 * a small unreachable expression to make sure the structs |
965 * pointed to do have a simple sanitize(), ie. they do not | 969 * pointed to do have a simple sanitize(), ie. they do not |
966 * reference other structs via offsets. | 970 * reference other structs via offsets. |
967 */ | 971 */ |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
999 } | 1003 } |
1000 return -1; | 1004 return -1; |
1001 } | 1005 } |
1002 }; | 1006 }; |
1003 | 1007 |
1004 | 1008 |
1005 } /* namespace OT */ | 1009 } /* namespace OT */ |
1006 | 1010 |
1007 | 1011 |
1008 #endif /* HB_OPEN_TYPE_PRIVATE_HH */ | 1012 #endif /* HB_OPEN_TYPE_PRIVATE_HH */ |
OLD | NEW |