| 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 |