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 24 matching lines...) Expand all Loading... |
35 namespace OT { | 35 namespace OT { |
36 | 36 |
37 | 37 |
38 | 38 |
39 /* | 39 /* |
40 * Casts | 40 * Casts |
41 */ | 41 */ |
42 | 42 |
43 /* Cast to struct T, reference to reference */ | 43 /* Cast to struct T, reference to reference */ |
44 template<typename Type, typename TObject> | 44 template<typename Type, typename TObject> |
45 inline const Type& CastR(const TObject &X) | 45 static inline const Type& CastR(const TObject &X) |
46 { return reinterpret_cast<const Type&> (X); } | 46 { return reinterpret_cast<const Type&> (X); } |
47 template<typename Type, typename TObject> | 47 template<typename Type, typename TObject> |
48 inline Type& CastR(TObject &X) | 48 static inline Type& CastR(TObject &X) |
49 { return reinterpret_cast<Type&> (X); } | 49 { return reinterpret_cast<Type&> (X); } |
50 | 50 |
51 /* Cast to struct T, pointer to pointer */ | 51 /* Cast to struct T, pointer to pointer */ |
52 template<typename Type, typename TObject> | 52 template<typename Type, typename TObject> |
53 inline const Type* CastP(const TObject *X) | 53 static inline const Type* CastP(const TObject *X) |
54 { return reinterpret_cast<const Type*> (X); } | 54 { return reinterpret_cast<const Type*> (X); } |
55 template<typename Type, typename TObject> | 55 template<typename Type, typename TObject> |
56 inline Type* CastP(TObject *X) | 56 static inline Type* CastP(TObject *X) |
57 { return reinterpret_cast<Type*> (X); } | 57 { return reinterpret_cast<Type*> (X); } |
58 | 58 |
59 /* StructAtOffset<T>(P,Ofs) returns the struct T& that is placed at memory | 59 /* StructAtOffset<T>(P,Ofs) returns the struct T& that is placed at memory |
60 * location pointed to by P plus Ofs bytes. */ | 60 * location pointed to by P plus Ofs bytes. */ |
61 template<typename Type> | 61 template<typename Type> |
62 inline const Type& StructAtOffset(const void *P, unsigned int offset) | 62 static inline const Type& StructAtOffset(const void *P, unsigned int offset) |
63 { return * reinterpret_cast<const Type*> ((const char *) P + offset); } | 63 { return * reinterpret_cast<const Type*> ((const char *) P + offset); } |
64 template<typename Type> | 64 template<typename Type> |
65 inline Type& StructAtOffset(void *P, unsigned int offset) | 65 static inline Type& StructAtOffset(void *P, unsigned int offset) |
66 { return * reinterpret_cast<Type*> ((char *) P + offset); } | 66 { return * reinterpret_cast<Type*> ((char *) P + offset); } |
67 | 67 |
68 /* StructAfter<T>(X) returns the struct T& that is placed after X. | 68 /* StructAfter<T>(X) returns the struct T& that is placed after X. |
69 * Works with X of variable size also. X must implement get_size() */ | 69 * Works with X of variable size also. X must implement get_size() */ |
70 template<typename Type, typename TObject> | 70 template<typename Type, typename TObject> |
71 inline const Type& StructAfter(const TObject &X) | 71 static inline const Type& StructAfter(const TObject &X) |
72 { return StructAtOffset<Type>(&X, X.get_size()); } | 72 { return StructAtOffset<Type>(&X, X.get_size()); } |
73 template<typename Type, typename TObject> | 73 template<typename Type, typename TObject> |
74 inline Type& StructAfter(TObject &X) | 74 static inline Type& StructAfter(TObject &X) |
75 { return StructAtOffset<Type>(&X, X.get_size()); } | 75 { return StructAtOffset<Type>(&X, X.get_size()); } |
76 | 76 |
77 | 77 |
78 | 78 |
79 /* | 79 /* |
80 * Size checking | 80 * Size checking |
81 */ | 81 */ |
82 | 82 |
83 /* Check _assertion in a method environment */ | 83 /* Check _assertion in a method environment */ |
84 #define _DEFINE_INSTANCE_ASSERTION1(_line, _assertion) \ | 84 #define _DEFINE_INSTANCE_ASSERTION1(_line, _assertion) \ |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
125 static const unsigned int min_size = (size) | 125 static const unsigned int min_size = (size) |
126 | 126 |
127 | 127 |
128 | 128 |
129 /* | 129 /* |
130 * Null objects | 130 * Null objects |
131 */ | 131 */ |
132 | 132 |
133 /* Global nul-content Null pool. Enlarge as necessary. */ | 133 /* Global nul-content Null pool. Enlarge as necessary. */ |
134 /* TODO This really should be a extern HB_INTERNAL and defined somewhere... */ | 134 /* TODO This really should be a extern HB_INTERNAL and defined somewhere... */ |
135 static const void *_NullPool[64 / sizeof (void *)]; | 135 static const void *_NullPool[(256+8) / sizeof (void *)]; |
136 | 136 |
137 /* Generic nul-content Null objects. */ | 137 /* Generic nul-content Null objects. */ |
138 template <typename Type> | 138 template <typename Type> |
139 static inline const Type& Null (void) { | 139 static inline const Type& Null (void) { |
140 ASSERT_STATIC (sizeof (Type) <= sizeof (_NullPool)); | 140 ASSERT_STATIC (sizeof (Type) <= sizeof (_NullPool)); |
141 return *CastP<Type> (_NullPool); | 141 return *CastP<Type> (_NullPool); |
142 } | 142 } |
143 | 143 |
144 /* Specializaiton for arbitrary-content arbitrary-sized Null objects. */ | 144 /* Specializaiton for arbitrary-content arbitrary-sized Null objects. */ |
145 #define DEFINE_NULL_DATA(Type, data) \ | 145 #define DEFINE_NULL_DATA(Type, data) \ |
146 static const char _Null##Type[sizeof (Type) + 1] = data; /* +1 is for nul-termin
ation in data */ \ | 146 static const char _Null##Type[sizeof (Type) + 1] = data; /* +1 is for nul-termin
ation in data */ \ |
147 template <> \ | 147 template <> \ |
148 inline const Type& Null<Type> (void) { \ | 148 /*static*/ inline const Type& Null<Type> (void) { \ |
149 return *CastP<Type> (_Null##Type); \ | 149 return *CastP<Type> (_Null##Type); \ |
150 } /* The following line really exists such that we end in a place needing semico
lon */ \ | 150 } /* The following line really exists such that we end in a place needing semico
lon */ \ |
151 ASSERT_STATIC (Type::min_size + 1 <= sizeof (_Null##Type)) | 151 ASSERT_STATIC (Type::min_size + 1 <= sizeof (_Null##Type)) |
152 | 152 |
153 /* Accessor macro. */ | 153 /* Accessor macro. */ |
154 #define Null(Type) Null<Type>() | 154 #define Null(Type) Null<Type>() |
155 | 155 |
156 | 156 |
157 | 157 |
158 /* | 158 /* |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
259 (&this->debug_depth, "SANITIZE", this->blob, NULL, | 259 (&this->debug_depth, "SANITIZE", this->blob, NULL, |
260 "may_edit(%u) [%p..%p] (%d bytes) in [%p..%p] -> %s", | 260 "may_edit(%u) [%p..%p] (%d bytes) in [%p..%p] -> %s", |
261 this->edit_count, | 261 this->edit_count, |
262 p, p + len, len, | 262 p, p + len, len, |
263 this->start, this->end, | 263 this->start, this->end, |
264 this->writable ? "GRANTED" : "DENIED"); | 264 this->writable ? "GRANTED" : "DENIED"); |
265 | 265 |
266 return TRACE_RETURN (this->writable); | 266 return TRACE_RETURN (this->writable); |
267 } | 267 } |
268 | 268 |
| 269 template <typename Type, typename ValueType> |
| 270 inline bool try_set (Type *obj, const ValueType &v) { |
| 271 if (this->may_edit (obj, obj->static_size)) { |
| 272 obj->set (v); |
| 273 return true; |
| 274 } |
| 275 return false; |
| 276 } |
| 277 |
269 mutable unsigned int debug_depth; | 278 mutable unsigned int debug_depth; |
270 const char *start, *end; | 279 const char *start, *end; |
271 bool writable; | 280 bool writable; |
272 unsigned int edit_count; | 281 unsigned int edit_count; |
273 hb_blob_t *blob; | 282 hb_blob_t *blob; |
274 }; | 283 }; |
275 | 284 |
276 | 285 |
277 | 286 |
278 /* Template to sanitize an object. */ | 287 /* Template to sanitize an object. */ |
(...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
565 inline bool sanitize (hb_sanitize_context_t *c) { | 574 inline bool sanitize (hb_sanitize_context_t *c) { |
566 TRACE_SANITIZE (this); | 575 TRACE_SANITIZE (this); |
567 return TRACE_RETURN (likely (c->check_struct (this))); | 576 return TRACE_RETURN (likely (c->check_struct (this))); |
568 } | 577 } |
569 protected: | 578 protected: |
570 BEInt<Type, Size> v; | 579 BEInt<Type, Size> v; |
571 public: | 580 public: |
572 DEFINE_SIZE_STATIC (Size); | 581 DEFINE_SIZE_STATIC (Size); |
573 }; | 582 }; |
574 | 583 |
| 584 typedef uint8_t BYTE; /* 8-bit unsigned integer. */ |
575 typedef IntType<uint16_t, 2> USHORT; /* 16-bit unsigned integer. */ | 585 typedef IntType<uint16_t, 2> USHORT; /* 16-bit unsigned integer. */ |
576 typedef IntType<int16_t, 2> SHORT; /* 16-bit signed integer. */ | 586 typedef IntType<int16_t, 2> SHORT; /* 16-bit signed integer. */ |
577 typedef IntType<uint32_t, 4> ULONG; /* 32-bit unsigned integer. */ | 587 typedef IntType<uint32_t, 4> ULONG; /* 32-bit unsigned integer. */ |
578 typedef IntType<int32_t, 4> LONG; /* 32-bit signed integer. */ | 588 typedef IntType<int32_t, 4> LONG; /* 32-bit signed integer. */ |
579 typedef IntType<uint32_t, 3> UINT24; /* 24-bit unsigned integer. */ | 589 typedef IntType<uint32_t, 3> UINT24; /* 24-bit unsigned integer. */ |
580 | 590 |
581 /* 16-bit signed integer (SHORT) that describes a quantity in FUnits. */ | 591 /* 16-bit signed integer (SHORT) that describes a quantity in FUnits. */ |
582 typedef SHORT FWORD; | 592 typedef SHORT FWORD; |
583 | 593 |
584 /* 16-bit unsigned integer (USHORT) that describes a quantity in FUnits. */ | 594 /* 16-bit unsigned integer (USHORT) that describes a quantity in FUnits. */ |
(...skipping 24 matching lines...) Expand all Loading... |
609 public: | 619 public: |
610 DEFINE_SIZE_STATIC (4); | 620 DEFINE_SIZE_STATIC (4); |
611 }; | 621 }; |
612 DEFINE_NULL_DATA (Tag, " "); | 622 DEFINE_NULL_DATA (Tag, " "); |
613 | 623 |
614 /* Glyph index number, same as uint16 (length = 16 bits) */ | 624 /* Glyph index number, same as uint16 (length = 16 bits) */ |
615 typedef USHORT GlyphID; | 625 typedef USHORT GlyphID; |
616 | 626 |
617 /* Script/language-system/feature index */ | 627 /* Script/language-system/feature index */ |
618 struct Index : USHORT { | 628 struct Index : USHORT { |
619 static const unsigned int NOT_FOUND_INDEX = 0xFFFF; | 629 static const unsigned int NOT_FOUND_INDEX = 0xFFFFu; |
620 }; | 630 }; |
621 DEFINE_NULL_DATA (Index, "\xff\xff"); | 631 DEFINE_NULL_DATA (Index, "\xff\xff"); |
622 | 632 |
623 /* Offset to a table, same as uint16 (length = 16 bits), Null offset = 0x0000 */ | 633 /* Offset, Null offset = 0 */ |
624 struct Offset : USHORT | 634 template <typename Type=USHORT> |
| 635 struct Offset : Type |
625 { | 636 { |
626 inline bool is_null (void) const { return 0 == *this; } | 637 inline bool is_null (void) const { return 0 == *this; } |
627 public: | 638 public: |
628 DEFINE_SIZE_STATIC (2); | 639 DEFINE_SIZE_STATIC (sizeof(Type)); |
629 }; | |
630 | |
631 /* LongOffset to a table, same as uint32 (length = 32 bits), Null offset = 0x000
00000 */ | |
632 struct LongOffset : ULONG | |
633 { | |
634 inline bool is_null (void) const { return 0 == *this; } | |
635 public: | |
636 DEFINE_SIZE_STATIC (4); | |
637 }; | 640 }; |
638 | 641 |
639 | 642 |
640 /* CheckSum */ | 643 /* CheckSum */ |
641 struct CheckSum : ULONG | 644 struct CheckSum : ULONG |
642 { | 645 { |
643 /* This is reference implementation from the spec. */ | 646 /* This is reference implementation from the spec. */ |
644 static inline uint32_t CalcTableChecksum (const ULONG *Table, uint32_t Length) | 647 static inline uint32_t CalcTableChecksum (const ULONG *Table, uint32_t Length) |
645 { | 648 { |
646 uint32_t Sum = 0L; | 649 uint32_t Sum = 0L; |
(...skipping 28 matching lines...) Expand all Loading... |
675 | 678 |
676 USHORT major; | 679 USHORT major; |
677 USHORT minor; | 680 USHORT minor; |
678 public: | 681 public: |
679 DEFINE_SIZE_STATIC (4); | 682 DEFINE_SIZE_STATIC (4); |
680 }; | 683 }; |
681 | 684 |
682 | 685 |
683 | 686 |
684 /* | 687 /* |
685 * Template subclasses of Offset and LongOffset that do the dereferencing. | 688 * Template subclasses of Offset that do the dereferencing. |
686 * Use: (base+offset) | 689 * Use: (base+offset) |
687 */ | 690 */ |
688 | 691 |
689 template <typename OffsetType, typename Type> | 692 template <typename Type, typename OffsetType=USHORT> |
690 struct GenericOffsetTo : OffsetType | 693 struct OffsetTo : Offset<OffsetType> |
691 { | 694 { |
692 inline const Type& operator () (const void *base) const | 695 inline const Type& operator () (const void *base) const |
693 { | 696 { |
694 unsigned int offset = *this; | 697 unsigned int offset = *this; |
695 if (unlikely (!offset)) return Null(Type); | 698 if (unlikely (!offset)) return Null(Type); |
696 return StructAtOffset<Type> (base, offset); | 699 return StructAtOffset<Type> (base, offset); |
697 } | 700 } |
698 | 701 |
699 inline Type& serialize (hb_serialize_context_t *c, void *base) | 702 inline Type& serialize (hb_serialize_context_t *c, void *base) |
700 { | 703 { |
(...skipping 13 matching lines...) Expand all Loading... |
714 template <typename T> | 717 template <typename T> |
715 inline bool sanitize (hb_sanitize_context_t *c, void *base, T user_data) { | 718 inline bool sanitize (hb_sanitize_context_t *c, void *base, T user_data) { |
716 TRACE_SANITIZE (this); | 719 TRACE_SANITIZE (this); |
717 if (unlikely (!c->check_struct (this))) return TRACE_RETURN (false); | 720 if (unlikely (!c->check_struct (this))) return TRACE_RETURN (false); |
718 unsigned int offset = *this; | 721 unsigned int offset = *this; |
719 if (unlikely (!offset)) return TRACE_RETURN (true); | 722 if (unlikely (!offset)) return TRACE_RETURN (true); |
720 Type &obj = StructAtOffset<Type> (base, offset); | 723 Type &obj = StructAtOffset<Type> (base, offset); |
721 return TRACE_RETURN (likely (obj.sanitize (c, user_data)) || neuter (c)); | 724 return TRACE_RETURN (likely (obj.sanitize (c, user_data)) || neuter (c)); |
722 } | 725 } |
723 | 726 |
724 inline bool try_set (hb_sanitize_context_t *c, const OffsetType &v) { | |
725 if (c->may_edit (this, this->static_size)) { | |
726 this->set (v); | |
727 return true; | |
728 } | |
729 return false; | |
730 } | |
731 /* Set the offset to Null */ | 727 /* Set the offset to Null */ |
732 inline bool neuter (hb_sanitize_context_t *c) { | 728 inline bool neuter (hb_sanitize_context_t *c) { |
733 if (c->may_edit (this, this->static_size)) { | 729 return c->try_set (this, 0); |
734 this->set (0); /* 0 is Null offset */ | |
735 return true; | |
736 } | |
737 return false; | |
738 } | 730 } |
| 731 DEFINE_SIZE_STATIC (sizeof(OffsetType)); |
739 }; | 732 }; |
740 template <typename Base, typename OffsetType, typename Type> | 733 template <typename Base, typename OffsetType, typename Type> |
741 inline const Type& operator + (const Base &base, const GenericOffsetTo<OffsetTyp
e, Type> &offset) { return offset (base); } | 734 static inline const Type& operator + (const Base &base, const OffsetTo<Type, Off
setType> &offset) { return offset (base); } |
742 template <typename Base, typename OffsetType, typename Type> | 735 template <typename Base, typename OffsetType, typename Type> |
743 inline Type& operator + (Base &base, GenericOffsetTo<OffsetType, Type> &offset)
{ return offset (base); } | 736 static inline Type& operator + (Base &base, OffsetTo<Type, OffsetType> &offset)
{ return offset (base); } |
744 | |
745 template <typename Type> | |
746 struct OffsetTo : GenericOffsetTo<Offset, Type> {}; | |
747 | |
748 template <typename Type> | |
749 struct LongOffsetTo : GenericOffsetTo<LongOffset, Type> {}; | |
750 | 737 |
751 | 738 |
752 /* | 739 /* |
753 * Array Types | 740 * Array Types |
754 */ | 741 */ |
755 | 742 |
756 template <typename LenType, typename Type> | 743 /* An array with a number of elements. */ |
757 struct GenericArrayOf | 744 template <typename Type, typename LenType=USHORT> |
| 745 struct ArrayOf |
758 { | 746 { |
759 const Type *sub_array (unsigned int start_offset, unsigned int *pcount /* IN/O
UT */) const | 747 const Type *sub_array (unsigned int start_offset, unsigned int *pcount /* IN/O
UT */) const |
760 { | 748 { |
761 unsigned int count = len; | 749 unsigned int count = len; |
762 if (unlikely (start_offset > count)) | 750 if (unlikely (start_offset > count)) |
763 count = 0; | 751 count = 0; |
764 else | 752 else |
765 count -= start_offset; | 753 count -= start_offset; |
766 count = MIN (count, *pcount); | 754 count = MIN (count, *pcount); |
767 *pcount = count; | 755 *pcount = count; |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
830 inline bool sanitize (hb_sanitize_context_t *c, void *base, T user_data) { | 818 inline bool sanitize (hb_sanitize_context_t *c, void *base, T user_data) { |
831 TRACE_SANITIZE (this); | 819 TRACE_SANITIZE (this); |
832 if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false); | 820 if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false); |
833 unsigned int count = len; | 821 unsigned int count = len; |
834 for (unsigned int i = 0; i < count; i++) | 822 for (unsigned int i = 0; i < count; i++) |
835 if (unlikely (!array[i].sanitize (c, base, user_data))) | 823 if (unlikely (!array[i].sanitize (c, base, user_data))) |
836 return TRACE_RETURN (false); | 824 return TRACE_RETURN (false); |
837 return TRACE_RETURN (true); | 825 return TRACE_RETURN (true); |
838 } | 826 } |
839 | 827 |
| 828 template <typename SearchType> |
| 829 inline int lsearch (const SearchType &x) const |
| 830 { |
| 831 unsigned int count = len; |
| 832 for (unsigned int i = 0; i < count; i++) |
| 833 if (!this->array[i].cmp (x)) |
| 834 return i; |
| 835 return -1; |
| 836 } |
| 837 |
840 private: | 838 private: |
841 inline bool sanitize_shallow (hb_sanitize_context_t *c) { | 839 inline bool sanitize_shallow (hb_sanitize_context_t *c) { |
842 TRACE_SANITIZE (this); | 840 TRACE_SANITIZE (this); |
843 return TRACE_RETURN (c->check_struct (this) && c->check_array (this, Type::s
tatic_size, len)); | 841 return TRACE_RETURN (c->check_struct (this) && c->check_array (this, Type::s
tatic_size, len)); |
844 } | 842 } |
845 | 843 |
846 public: | 844 public: |
847 LenType len; | 845 LenType len; |
848 Type array[VAR]; | 846 Type array[VAR]; |
849 public: | 847 public: |
850 DEFINE_SIZE_ARRAY (sizeof (LenType), array); | 848 DEFINE_SIZE_ARRAY (sizeof (LenType), array); |
851 }; | 849 }; |
852 | 850 |
853 /* An array with a USHORT number of elements. */ | |
854 template <typename Type> | |
855 struct ArrayOf : GenericArrayOf<USHORT, Type> {}; | |
856 | |
857 /* An array with a ULONG number of elements. */ | |
858 template <typename Type> | |
859 struct LongArrayOf : GenericArrayOf<ULONG, Type> {}; | |
860 | |
861 /* Array of Offset's */ | 851 /* Array of Offset's */ |
862 template <typename Type> | 852 template <typename Type> |
863 struct OffsetArrayOf : ArrayOf<OffsetTo<Type> > {}; | 853 struct OffsetArrayOf : ArrayOf<OffsetTo<Type> > {}; |
864 | 854 |
865 /* Array of LongOffset's */ | |
866 template <typename Type> | |
867 struct LongOffsetArrayOf : ArrayOf<LongOffsetTo<Type> > {}; | |
868 | |
869 /* LongArray of LongOffset's */ | |
870 template <typename Type> | |
871 struct LongOffsetLongArrayOf : LongArrayOf<LongOffsetTo<Type> > {}; | |
872 | |
873 /* Array of offsets relative to the beginning of the array itself. */ | 855 /* Array of offsets relative to the beginning of the array itself. */ |
874 template <typename Type> | 856 template <typename Type> |
875 struct OffsetListOf : OffsetArrayOf<Type> | 857 struct OffsetListOf : OffsetArrayOf<Type> |
876 { | 858 { |
877 inline const Type& operator [] (unsigned int i) const | 859 inline const Type& operator [] (unsigned int i) const |
878 { | 860 { |
879 if (unlikely (i >= this->len)) return Null(Type); | 861 if (unlikely (i >= this->len)) return Null(Type); |
880 return this+this->array[i]; | 862 return this+this->array[i]; |
881 } | 863 } |
882 | 864 |
883 inline bool sanitize (hb_sanitize_context_t *c) { | 865 inline bool sanitize (hb_sanitize_context_t *c) { |
884 TRACE_SANITIZE (this); | 866 TRACE_SANITIZE (this); |
885 return TRACE_RETURN (OffsetArrayOf<Type>::sanitize (c, this)); | 867 return TRACE_RETURN (OffsetArrayOf<Type>::sanitize (c, this)); |
886 } | 868 } |
887 template <typename T> | 869 template <typename T> |
888 inline bool sanitize (hb_sanitize_context_t *c, T user_data) { | 870 inline bool sanitize (hb_sanitize_context_t *c, T user_data) { |
889 TRACE_SANITIZE (this); | 871 TRACE_SANITIZE (this); |
890 return TRACE_RETURN (OffsetArrayOf<Type>::sanitize (c, this, user_data)); | 872 return TRACE_RETURN (OffsetArrayOf<Type>::sanitize (c, this, user_data)); |
891 } | 873 } |
892 }; | 874 }; |
893 | 875 |
894 | 876 |
895 /* An array with a USHORT number of elements, | 877 /* An array starting at second element. */ |
896 * starting at second element. */ | 878 template <typename Type, typename LenType=USHORT> |
897 template <typename Type> | |
898 struct HeadlessArrayOf | 879 struct HeadlessArrayOf |
899 { | 880 { |
900 inline const Type& operator [] (unsigned int i) const | 881 inline const Type& operator [] (unsigned int i) const |
901 { | 882 { |
902 if (unlikely (i >= len || !i)) return Null(Type); | 883 if (unlikely (i >= len || !i)) return Null(Type); |
903 return array[i-1]; | 884 return array[i-1]; |
904 } | 885 } |
905 inline unsigned int get_size (void) const | 886 inline unsigned int get_size (void) const |
906 { return len.static_size + (len ? len - 1 : 0) * Type::static_size; } | 887 { return len.static_size + (len ? len - 1 : 0) * Type::static_size; } |
907 | 888 |
(...skipping 26 matching lines...) Expand all Loading... |
934 * a bound check on the aggregate array size. We just include | 915 * a bound check on the aggregate array size. We just include |
935 * a small unreachable expression to make sure the structs | 916 * a small unreachable expression to make sure the structs |
936 * pointed to do have a simple sanitize(), ie. they do not | 917 * pointed to do have a simple sanitize(), ie. they do not |
937 * reference other structs via offsets. | 918 * reference other structs via offsets. |
938 */ | 919 */ |
939 (void) (false && array[0].sanitize (c)); | 920 (void) (false && array[0].sanitize (c)); |
940 | 921 |
941 return TRACE_RETURN (true); | 922 return TRACE_RETURN (true); |
942 } | 923 } |
943 | 924 |
944 USHORT len; | 925 LenType len; |
945 Type array[VAR]; | 926 Type array[VAR]; |
946 public: | 927 public: |
947 DEFINE_SIZE_ARRAY (sizeof (USHORT), array); | 928 DEFINE_SIZE_ARRAY (sizeof (LenType), array); |
948 }; | 929 }; |
949 | 930 |
950 | 931 |
951 /* An array with sorted elements. Supports binary searching. */ | 932 /* An array with sorted elements. Supports binary searching. */ |
952 template <typename Type> | 933 template <typename Type, typename LenType=USHORT> |
953 struct SortedArrayOf : ArrayOf<Type> { | 934 struct SortedArrayOf : ArrayOf<Type, LenType> |
954 | 935 { |
955 template <typename SearchType> | 936 template <typename SearchType> |
956 inline int search (const SearchType &x) const | 937 inline int bsearch (const SearchType &x) const |
957 { | 938 { |
958 /* Hand-coded bsearch here since this is in the hot inner loop. */ | 939 /* Hand-coded bsearch here since this is in the hot inner loop. */ |
959 int min = 0, max = (int) this->len - 1; | 940 int min = 0, max = (int) this->len - 1; |
960 while (min <= max) | 941 while (min <= max) |
961 { | 942 { |
962 int mid = (min + max) / 2; | 943 int mid = (min + max) / 2; |
963 int c = this->array[mid].cmp (x); | 944 int c = this->array[mid].cmp (x); |
964 if (c < 0) | 945 if (c < 0) |
965 max = mid - 1; | 946 max = mid - 1; |
966 else if (c > 0) | 947 else if (c > 0) |
967 min = mid + 1; | 948 min = mid + 1; |
968 else | 949 else |
969 return mid; | 950 return mid; |
970 } | 951 } |
971 return -1; | 952 return -1; |
972 } | 953 } |
973 }; | 954 }; |
974 | 955 |
975 | 956 |
976 } /* namespace OT */ | 957 } /* namespace OT */ |
977 | 958 |
978 | 959 |
979 #endif /* HB_OPEN_TYPE_PRIVATE_HH */ | 960 #endif /* HB_OPEN_TYPE_PRIVATE_HH */ |
OLD | NEW |