Allow Offset<>'s that have no 0==null

This commit is contained in:
Behdad Esfahbod 2018-09-13 18:45:35 +02:00
parent 82f4d776c2
commit 29faebe911
1 changed files with 21 additions and 22 deletions

View File

@ -155,10 +155,10 @@ struct Index : HBUINT16 {
DECLARE_NULL_NAMESPACE_BYTES (OT, Index); DECLARE_NULL_NAMESPACE_BYTES (OT, Index);
/* Offset, Null offset = 0 */ /* Offset, Null offset = 0 */
template <typename Type> template <typename Type, bool has_null=true>
struct Offset : Type 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) inline void *serialize (hb_serialize_context_t *c, const void *base)
{ {
@ -226,20 +226,18 @@ struct FixedVersion
* Use: (base+offset) * Use: (base+offset)
*/ */
template <typename Type, typename OffsetType=HBUINT16> template <typename Type, typename OffsetType=HBUINT16, bool has_null=true>
struct OffsetTo : Offset<OffsetType> struct OffsetTo : Offset<OffsetType, has_null>
{ {
inline const Type& operator () (const void *base) const inline const Type& operator () (const void *base) const
{ {
unsigned int offset = *this; if (unlikely (this->is_null ())) return Null(Type);
if (unlikely (!offset)) return Null(Type); return StructAtOffset<const Type> (base, *this);
return StructAtOffset<const Type> (base, offset);
} }
inline Type& operator () (void *base) const inline Type& operator () (void *base) const
{ {
unsigned int offset = *this; if (unlikely (this->is_null ())) return Crap(Type);
if (unlikely (!offset)) return Crap(Type); return StructAtOffset<Type> (base, *this);
return StructAtOffset<Type> (base, offset);
} }
inline Type& serialize (hb_serialize_context_t *c, const void *base) inline Type& serialize (hb_serialize_context_t *c, const void *base)
@ -264,9 +262,8 @@ struct OffsetTo : Offset<OffsetType>
{ {
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
if (unlikely (!c->check_struct (this))) return_trace (false); if (unlikely (!c->check_struct (this))) return_trace (false);
unsigned int offset = *this; if (unlikely (this->is_null ())) return_trace (true);
if (unlikely (!offset)) return_trace (true); if (unlikely (!c->check_range (base, *this))) return_trace (false);
if (unlikely (!c->check_range (base, offset))) return_trace (false);
return_trace (true); return_trace (true);
} }
@ -274,7 +271,7 @@ struct OffsetTo : Offset<OffsetType>
{ {
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return_trace (sanitize_shallow (c, base) && return_trace (sanitize_shallow (c, base) &&
(!*this || (this->is_null () ||
StructAtOffset<Type> (base, *this).sanitize (c) || StructAtOffset<Type> (base, *this).sanitize (c) ||
neuter (c))); neuter (c)));
} }
@ -283,7 +280,7 @@ struct OffsetTo : Offset<OffsetType>
{ {
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return_trace (sanitize_shallow (c, base) && return_trace (sanitize_shallow (c, base) &&
(!*this || (this->is_null () ||
StructAtOffset<Type> (base, *this).sanitize (c, d1) || StructAtOffset<Type> (base, *this).sanitize (c, d1) ||
neuter (c))); neuter (c)));
} }
@ -292,7 +289,7 @@ struct OffsetTo : Offset<OffsetType>
{ {
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return_trace (sanitize_shallow (c, base) && return_trace (sanitize_shallow (c, base) &&
(!*this || (this->is_null () ||
StructAtOffset<Type> (base, *this).sanitize (c, d1, d2) || StructAtOffset<Type> (base, *this).sanitize (c, d1, d2) ||
neuter (c))); neuter (c)));
} }
@ -301,22 +298,24 @@ struct OffsetTo : Offset<OffsetType>
{ {
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return_trace (sanitize_shallow (c, base) && return_trace (sanitize_shallow (c, base) &&
(!*this || (this->is_null () ||
StructAtOffset<Type> (base, *this).sanitize (c, d1, d2, d3) || StructAtOffset<Type> (base, *this).sanitize (c, d1, d2, d3) ||
neuter (c))); neuter (c)));
} }
/* Set the offset to Null */ /* 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); return c->try_set (this, 0);
} }
DEFINE_SIZE_STATIC (sizeof(OffsetType)); DEFINE_SIZE_STATIC (sizeof(OffsetType));
}; };
template <typename Type> struct LOffsetTo : OffsetTo<Type, HBUINT32> {}; template <typename Type> struct LOffsetTo : OffsetTo<Type, HBUINT32> {};
template <typename Base, typename OffsetType, typename Type> template <typename Base, typename OffsetType, bool has_null, typename Type>
static inline const Type& operator + (const Base &base, const OffsetTo<Type, OffsetType> &offset) { return offset (base); } static inline const Type& operator + (const Base &base, const OffsetTo<Type, OffsetType, has_null> &offset) { return offset (base); }
template <typename Base, typename OffsetType, typename Type> template <typename Base, typename OffsetType, bool has_null, typename Type>
static inline Type& operator + (Base &base, OffsetTo<Type, OffsetType> &offset) { return offset (base); } static inline Type& operator + (Base &base, OffsetTo<Type, OffsetType, has_null> &offset) { return offset (base); }
/* /*