summaryrefslogtreecommitdiff
path: root/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-open-type.hh
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/libs/harfbuzz/harfbuzz-src/src/hb-open-type.hh')
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-open-type.hh290
1 files changed, 234 insertions, 56 deletions
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-open-type.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-open-type.hh
index ef18163fa56..9d2e1fa7c1d 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-open-type.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-open-type.hh
@@ -92,6 +92,9 @@ typedef IntType<uint32_t, 3> HBUINT24; /* 24-bit unsigned integer. */
/* 16-bit signed integer (HBINT16) that describes a quantity in FUnits. */
typedef HBINT16 FWORD;
+/* 32-bit signed integer (HBINT32) that describes a quantity in FUnits. */
+typedef HBINT32 FWORD32;
+
/* 16-bit unsigned integer (HBUINT16) that describes a quantity in FUnits. */
typedef HBUINT16 UFWORD;
@@ -155,10 +158,10 @@ struct Index : HBUINT16 {
DECLARE_NULL_NAMESPACE_BYTES (OT, Index);
/* Offset, Null offset = 0 */
-template <typename Type>
+template <typename Type, bool has_null=true>
struct Offset : Type
{
- inline bool is_null (void) const { return 0 == *this; }
+ inline bool is_null (void) const { return has_null && 0 == *this; }
inline void *serialize (hb_serialize_context_t *c, const void *base)
{
@@ -226,20 +229,23 @@ struct FixedVersion
* Use: (base+offset)
*/
-template <typename Type, typename OffsetType=HBUINT16>
-struct OffsetTo : Offset<OffsetType>
+template <typename Type, bool has_null_> struct assert_has_min_size { static_assert (Type::min_size > 0, ""); };
+template <typename Type> struct assert_has_min_size<Type, false> {};
+
+template <typename Type, typename OffsetType=HBUINT16, bool has_null=true>
+struct OffsetTo : Offset<OffsetType, has_null>
{
+ static_assert (sizeof (assert_has_min_size<Type, has_null>) || true, "");
+
inline const Type& operator () (const void *base) const
{
- unsigned int offset = *this;
- if (unlikely (!offset)) return Null(Type);
- return StructAtOffset<const Type> (base, offset);
+ if (unlikely (this->is_null ())) return Null(Type);
+ return StructAtOffset<const Type> (base, *this);
}
inline Type& operator () (void *base) const
{
- unsigned int offset = *this;
- if (unlikely (!offset)) return Crap(Type);
- return StructAtOffset<Type> (base, offset);
+ if (unlikely (this->is_null ())) return Crap(Type);
+ return StructAtOffset<Type> (base, *this);
}
inline Type& serialize (hb_serialize_context_t *c, const void *base)
@@ -260,46 +266,70 @@ struct OffsetTo : Offset<OffsetType>
this->set (0);
}
- inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
+ inline bool sanitize_shallow (hb_sanitize_context_t *c, const void *base) const
{
TRACE_SANITIZE (this);
if (unlikely (!c->check_struct (this))) return_trace (false);
- unsigned int offset = *this;
- if (unlikely (!offset)) return_trace (true);
- if (unlikely (!c->check_range (base, offset))) return_trace (false);
- const Type &obj = StructAtOffset<Type> (base, offset);
- return_trace (likely (obj.sanitize (c)) || neuter (c));
+ if (unlikely (this->is_null ())) return_trace (true);
+ if (unlikely (!c->check_range (base, *this))) return_trace (false);
+ return_trace (true);
}
- template <typename T>
- inline bool sanitize (hb_sanitize_context_t *c, const void *base, T user_data) const
+
+ inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
{
TRACE_SANITIZE (this);
- if (unlikely (!c->check_struct (this))) return_trace (false);
- unsigned int offset = *this;
- if (unlikely (!offset)) return_trace (true);
- if (unlikely (!c->check_range (base, offset))) return_trace (false);
- const Type &obj = StructAtOffset<Type> (base, offset);
- return_trace (likely (obj.sanitize (c, user_data)) || neuter (c));
+ return_trace (sanitize_shallow (c, base) &&
+ (this->is_null () ||
+ StructAtOffset<Type> (base, *this).sanitize (c) ||
+ neuter (c)));
+ }
+ template <typename T1>
+ inline bool sanitize (hb_sanitize_context_t *c, const void *base, T1 d1) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (sanitize_shallow (c, base) &&
+ (this->is_null () ||
+ StructAtOffset<Type> (base, *this).sanitize (c, d1) ||
+ neuter (c)));
+ }
+ template <typename T1, typename T2>
+ inline bool sanitize (hb_sanitize_context_t *c, const void *base, T1 d1, T2 d2) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (sanitize_shallow (c, base) &&
+ (this->is_null () ||
+ StructAtOffset<Type> (base, *this).sanitize (c, d1, d2) ||
+ neuter (c)));
+ }
+ template <typename T1, typename T2, typename T3>
+ inline bool sanitize (hb_sanitize_context_t *c, const void *base, T1 d1, T2 d2, T3 d3) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (sanitize_shallow (c, base) &&
+ (this->is_null () ||
+ StructAtOffset<Type> (base, *this).sanitize (c, d1, d2, d3) ||
+ neuter (c)));
}
/* Set the offset to Null */
- inline bool neuter (hb_sanitize_context_t *c) const {
+ inline bool neuter (hb_sanitize_context_t *c) const
+ {
+ if (!has_null) return false;
return c->try_set (this, 0);
}
DEFINE_SIZE_STATIC (sizeof(OffsetType));
};
-template <typename Type> struct LOffsetTo : OffsetTo<Type, HBUINT32> {};
-template <typename Base, typename OffsetType, typename Type>
-static inline const Type& operator + (const Base &base, const OffsetTo<Type, OffsetType> &offset) { return offset (base); }
-template <typename Base, typename OffsetType, typename Type>
-static inline Type& operator + (Base &base, OffsetTo<Type, OffsetType> &offset) { return offset (base); }
+template <typename Type, bool has_null=true> struct LOffsetTo : OffsetTo<Type, HBUINT32, has_null> {};
+template <typename Base, typename OffsetType, bool has_null, typename Type>
+static inline const Type& operator + (const Base &base, const OffsetTo<Type, OffsetType, has_null> &offset) { return offset (base); }
+template <typename Base, typename OffsetType, bool has_null, typename Type>
+static inline Type& operator + (Base &base, OffsetTo<Type, OffsetType, has_null> &offset) { return offset (base); }
/*
* Array Types
*/
-/* TODO Use it in ArrayOf, HeadlessArrayOf, and other places around the code base?? */
template <typename Type>
struct UnsizedArrayOf
{
@@ -345,22 +375,22 @@ struct UnsizedArrayOf
inline bool sanitize_shallow (hb_sanitize_context_t *c, unsigned int count) const
{
TRACE_SANITIZE (this);
- return_trace (c->check_array (arrayZ, arrayZ[0].static_size, count));
+ return_trace (c->check_array (arrayZ, count));
}
public:
- Type arrayZ[VAR];
+ Type arrayZ[VAR];
public:
DEFINE_SIZE_ARRAY (0, arrayZ);
};
/* Unsized array of offset's */
-template <typename Type, typename OffsetType>
-struct UnsizedOffsetArrayOf : UnsizedArrayOf<OffsetTo<Type, OffsetType> > {};
+template <typename Type, typename OffsetType, bool has_null=true>
+struct UnsizedOffsetArrayOf : UnsizedArrayOf<OffsetTo<Type, OffsetType, has_null> > {};
/* Unsized array of offsets relative to the beginning of the array itself. */
-template <typename Type, typename OffsetType>
-struct UnsizedOffsetListOf : UnsizedOffsetArrayOf<Type, OffsetType>
+template <typename Type, typename OffsetType, bool has_null=true>
+struct UnsizedOffsetListOf : UnsizedOffsetArrayOf<Type, OffsetType, has_null>
{
inline const Type& operator [] (unsigned int i) const
{
@@ -370,13 +400,13 @@ struct UnsizedOffsetListOf : UnsizedOffsetArrayOf<Type, OffsetType>
inline bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
{
TRACE_SANITIZE (this);
- return_trace ((UnsizedOffsetArrayOf<Type, OffsetType>::sanitize (c, count, this)));
+ return_trace ((UnsizedOffsetArrayOf<Type, OffsetType, has_null>::sanitize (c, count, this)));
}
template <typename T>
inline bool sanitize (hb_sanitize_context_t *c, unsigned int count, T user_data) const
{
TRACE_SANITIZE (this);
- return_trace ((UnsizedOffsetArrayOf<Type, OffsetType>::sanitize (c, count, this, user_data)));
+ return_trace ((UnsizedOffsetArrayOf<Type, OffsetType, has_null>::sanitize (c, count, this, user_data)));
}
};
@@ -487,12 +517,12 @@ struct ArrayOf
inline bool sanitize_shallow (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (len.sanitize (c) && c->check_array (arrayZ, Type::static_size, len));
+ return_trace (len.sanitize (c) && c->check_array (arrayZ, len));
}
public:
- LenType len;
- Type arrayZ[VAR];
+ LenType len;
+ Type arrayZ[VAR];
public:
DEFINE_SIZE_ARRAY (sizeof (LenType), arrayZ);
};
@@ -548,16 +578,16 @@ struct HeadlessArrayOf
{
inline const Type& operator [] (unsigned int i) const
{
- if (unlikely (i >= len || !i)) return Null(Type);
+ if (unlikely (i >= lenP1 || !i)) return Null(Type);
return arrayZ[i-1];
}
inline Type& operator [] (unsigned int i)
{
- if (unlikely (i >= len || !i)) return Crap(Type);
+ if (unlikely (i >= lenP1 || !i)) return Crap(Type);
return arrayZ[i-1];
}
inline unsigned int get_size (void) const
- { return len.static_size + (len ? len - 1 : 0) * Type::static_size; }
+ { return lenP1.static_size + (lenP1 ? lenP1 - 1 : 0) * Type::static_size; }
inline bool serialize (hb_serialize_context_t *c,
Supplier<Type> &items,
@@ -565,7 +595,7 @@ struct HeadlessArrayOf
{
TRACE_SERIALIZE (this);
if (unlikely (!c->extend_min (*this))) return_trace (false);
- len.set (items_len); /* TODO(serialize) Overflow? */
+ lenP1.set (items_len); /* TODO(serialize) Overflow? */
if (unlikely (!items_len)) return_trace (true);
if (unlikely (!c->extend (*this))) return_trace (false);
for (unsigned int i = 0; i < items_len - 1; i++)
@@ -595,13 +625,57 @@ struct HeadlessArrayOf
inline bool sanitize_shallow (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (len.sanitize (c) &&
- (!len || c->check_array (arrayZ, Type::static_size, len - 1)));
+ return_trace (lenP1.sanitize (c) &&
+ (!lenP1 || c->check_array (arrayZ, lenP1 - 1)));
}
public:
- LenType len;
- Type arrayZ[VAR];
+ LenType lenP1;
+ Type arrayZ[VAR];
+ public:
+ DEFINE_SIZE_ARRAY (sizeof (LenType), arrayZ);
+};
+
+/* An array storing length-1. */
+template <typename Type, typename LenType=HBUINT16>
+struct ArrayOfM1
+{
+ inline const Type& operator [] (unsigned int i) const
+ {
+ if (unlikely (i > lenM1)) return Null(Type);
+ return arrayZ[i];
+ }
+ inline Type& operator [] (unsigned int i)
+ {
+ if (unlikely (i > lenM1)) return Crap(Type);
+ return arrayZ[i];
+ }
+ inline unsigned int get_size (void) const
+ { return lenM1.static_size + (lenM1 + 1) * Type::static_size; }
+
+ template <typename T>
+ inline bool sanitize (hb_sanitize_context_t *c, const void *base, T user_data) const
+ {
+ TRACE_SANITIZE (this);
+ if (unlikely (!sanitize_shallow (c))) return_trace (false);
+ unsigned int count = lenM1 + 1;
+ for (unsigned int i = 0; i < count; i++)
+ if (unlikely (!arrayZ[i].sanitize (c, base, user_data)))
+ return_trace (false);
+ return_trace (true);
+ }
+
+ private:
+ inline bool sanitize_shallow (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (lenM1.sanitize (c) &&
+ (c->check_array (arrayZ, lenM1 + 1)));
+ }
+
+ public:
+ LenType lenM1;
+ Type arrayZ[VAR];
public:
DEFINE_SIZE_ARRAY (sizeof (LenType), arrayZ);
};
@@ -631,7 +705,11 @@ struct SortedArrayOf : ArrayOf<Type, LenType>
}
};
-/* Binary-search arrays */
+/*
+ * Binary-search arrays
+ */
+
+template <typename LenType=HBUINT16>
struct BinSearchHeader
{
inline operator uint32_t (void) const { return len; }
@@ -654,17 +732,117 @@ struct BinSearchHeader
}
protected:
- HBUINT16 len;
- HBUINT16 searchRange;
- HBUINT16 entrySelector;
- HBUINT16 rangeShift;
+ LenType len;
+ LenType searchRange;
+ LenType entrySelector;
+ LenType rangeShift;
public:
DEFINE_SIZE_STATIC (8);
};
+template <typename Type, typename LenType=HBUINT16>
+struct BinSearchArrayOf : SortedArrayOf<Type, BinSearchHeader<LenType> > {};
+
+struct VarSizedBinSearchHeader
+{
+
+ inline bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this));
+ }
+
+ HBUINT16 unitSize; /* Size of a lookup unit for this search in bytes. */
+ HBUINT16 nUnits; /* Number of units of the preceding size to be searched. */
+ HBUINT16 searchRange; /* The value of unitSize times the largest power of 2
+ * that is less than or equal to the value of nUnits. */
+ HBUINT16 entrySelector; /* The log base 2 of the largest power of 2 less than
+ * or equal to the value of nUnits. */
+ HBUINT16 rangeShift; /* The value of unitSize times the difference of the
+ * value of nUnits minus the largest power of 2 less
+ * than or equal to the value of nUnits. */
+ public:
+ DEFINE_SIZE_STATIC (10);
+};
+
template <typename Type>
-struct BinSearchArrayOf : SortedArrayOf<Type, BinSearchHeader> {};
+struct VarSizedBinSearchArrayOf
+{
+ inline const Type& operator [] (unsigned int i) const
+ {
+ if (unlikely (i >= header.nUnits)) return Null(Type);
+ return StructAtOffset<Type> (&bytesZ, i * header.unitSize);
+ }
+ inline Type& operator [] (unsigned int i)
+ {
+ return StructAtOffset<Type> (&bytesZ, i * header.unitSize);
+ }
+ inline unsigned int get_size (void) const
+ { return header.static_size + header.nUnits * header.unitSize; }
+
+ inline bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ if (unlikely (!sanitize_shallow (c))) return_trace (false);
+
+ /* Note: for structs that do not reference other structs,
+ * we do not need to call their sanitize() as we already did
+ * a bound check on the aggregate array size. We just include
+ * a small unreachable expression to make sure the structs
+ * pointed to do have a simple sanitize(), ie. they do not
+ * reference other structs via offsets.
+ */
+ (void) (false && StructAtOffset<Type> (&bytesZ, 0).sanitize (c));
+
+ return_trace (true);
+ }
+ inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
+ {
+ TRACE_SANITIZE (this);
+ if (unlikely (!sanitize_shallow (c))) return_trace (false);
+ unsigned int count = header.nUnits;
+ for (unsigned int i = 0; i < count; i++)
+ if (unlikely (!(*this)[i].sanitize (c, base)))
+ return_trace (false);
+ return_trace (true);
+ }
+
+ template <typename T>
+ inline const Type *bsearch (const T &key) const
+ {
+ unsigned int size = header.unitSize;
+ int min = 0, max = (int) header.nUnits - 1;
+ while (min <= max)
+ {
+ int mid = (min + max) / 2;
+ const Type *p = (const Type *) (((const char *) &bytesZ) + (mid * size));
+ int c = p->cmp (key);
+ if (c < 0)
+ max = mid - 1;
+ else if (c > 0)
+ min = mid + 1;
+ else
+ return p;
+ }
+ return nullptr;
+ }
+
+ private:
+ inline bool sanitize_shallow (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (header.sanitize (c) &&
+ Type::static_size <= header.unitSize &&
+ c->check_array (bytesZ.arrayZ, header.nUnits, header.unitSize));
+ }
+
+ protected:
+ VarSizedBinSearchHeader header;
+ UnsizedArrayOf<HBUINT8> bytesZ;
+ public:
+ DEFINE_SIZE_ARRAY (10, bytesZ);
+};
} /* namespace OT */