Make all code NULL-free and assert-free
diff --git a/src/harfbuzz-open-private.h b/src/harfbuzz-open-private.h
index 4633ef1..9db3044 100644
--- a/src/harfbuzz-open-private.h
+++ b/src/harfbuzz-open-private.h
@@ -53,12 +53,11 @@
* as its last item. An array object is extended with len() and size()
* methods, as well as overloaded [] operator. */
#define DEFINE_ARRAY_TYPE(Type, array, num) \
- DEFINE_INDEX_OPERATOR(const, Type, array, num) \
- DEFINE_INDEX_OPERATOR( , Type, array, num) \
+ DEFINE_INDEX_OPERATOR(Type, array, num) \
DEFINE_LEN_AND_SIZE(Type, array, num)
-#define DEFINE_INDEX_OPERATOR(const, Type, array, num) \
+#define DEFINE_INDEX_OPERATOR(Type, array, num) \
inline const Type& operator[] (unsigned int i) const { \
- assert (i < num); \
+ if (i >= num) return Null##Type; \
return array[i]; \
}
@@ -66,34 +65,42 @@
* of offsets to the objects, relative to the beginning of the current
* object. */
#define DEFINE_OFFSET_ARRAY_TYPE(Type, array, num) \
- DEFINE_OFFSET_INDEX_OPERATOR(const, Type, array, num) \
- DEFINE_OFFSET_INDEX_OPERATOR( , Type, array, num) \
+ DEFINE_OFFSET_INDEX_OPERATOR(Type, array, num) \
DEFINE_LEN_AND_SIZE(Offset, array, num)
-#define DEFINE_OFFSET_INDEX_OPERATOR(const, Type, array, num) \
+#define DEFINE_OFFSET_INDEX_OPERATOR(Type, array, num) \
inline const Type& operator[] (unsigned int i) const { \
- assert (i < num); \
- assert (array[i]); /* TODO: should just skip them */ \
+ if (i >= num) return Null##Type; \
+ if (!array[i]) return Null##Type; \
return *(const Type *)((const char*)this + array[i]); \
}
#define DEFINE_RECORD_ARRAY_TYPE(Type, array, num) \
- DEFINE_RECORD_ACCESSOR(const, Type, array, num) \
- DEFINE_RECORD_ACCESSOR( , Type, array, num) \
+ DEFINE_RECORD_ACCESSOR(Type, array, num) \
DEFINE_LEN_AND_SIZE(Record, array, num)
-#define DEFINE_RECORD_ACCESSOR(const, Type, array, num) \
+#define DEFINE_RECORD_ACCESSOR(Type, array, num) \
inline const Type& operator[] (unsigned int i) const { \
- assert (i < num); \
- assert (array[i].offset); /* TODO: should just skip them */ \
+ if (i >= num) return Null##Type; \
+ if (!array[i].offset) return Null##Type; \
return *(const Type *)((const char*)this + array[i].offset); \
} \
inline const Tag& get_tag (unsigned int i) const { \
- assert (i < num); \
+ if (i >= num) return NullTag; \
return array[i].tag; \
} \
/* TODO: implement find_tag() */
+/*
+ * List types
+ */
-
+#define DEFINE_LIST_ACCESSOR(Type, name) \
+ inline const Type##List& get_##name##_list (void) const { \
+ if (!name##List) return Null##Type##List; \
+ return *(const Type##List *)((const char*)this + name##List); \
+ } \
+ inline const Type& get_##name (unsigned int i) const { \
+ return get_##name##_list()[i]; \
+ }
/*
* Class features
@@ -105,6 +112,20 @@
private: inline Type() {} /* cannot be instantiated */ \
public:
+/* defines Null##Type as a safe nil instance of Type */
+#define DEFINE_NULL_DATA(Type, size, data) \
+ static const unsigned char Null##Type##Data[size] = data; \
+ DEFINE_NULL_ALIAS (Type, Type)
+#define DEFINE_NULL(Type, size) \
+ DEFINE_NULL_DATA(Type, size, "")
+#define DEFINE_NULL_ASSERT_SIZE(Type, size) \
+ DEFINE_NULL_ASSERT_SIZE_DATA(Type, size, "")
+#define DEFINE_NULL_ASSERT_SIZE_DATA(Type, size, data) \
+ ASSERT_SIZE (Type, size); \
+ DEFINE_NULL_DATA (Type, size, data)
+#define DEFINE_NULL_ALIAS(NewType, OldType) \
+ static const NewType &Null##NewType = *(NewType *)Null##OldType##Data
+
/* get_for_data() is a static class method returning a reference to an
* instance of Type located at the input data location. It's just a
* fancy cast! */
@@ -117,6 +138,13 @@
STATIC_DEFINE_GET_FOR_DATA0( , Type)
+#define DEFINE_ACCESSOR(Type, name, Name) \
+ inline const Type& name (void) const { \
+ if (!Name) return Null##Type; \
+ return *(const Type*)((const char*)this + Name); \
+ }
+
+
/*
*
@@ -136,17 +164,17 @@
DEFINE_INT_TYPE_STRUCT (BYTE, u, 8); /* 8-bit unsigned integer. */
-ASSERT_SIZE (BYTE, 1);
+DEFINE_NULL_ASSERT_SIZE (BYTE, 1);
DEFINE_INT_TYPE_STRUCT (CHAR, , 8); /* 8-bit signed integer. */
-ASSERT_SIZE (CHAR, 1);
+DEFINE_NULL_ASSERT_SIZE (CHAR, 1);
DEFINE_INT_TYPE_STRUCT (USHORT, u, 16); /* 16-bit unsigned integer. */
-ASSERT_SIZE (USHORT, 2);
+DEFINE_NULL_ASSERT_SIZE (USHORT, 2);
DEFINE_INT_TYPE_STRUCT (SHORT, , 16); /* 16-bit signed integer. */
-ASSERT_SIZE (SHORT, 2);
+DEFINE_NULL_ASSERT_SIZE (SHORT, 2);
DEFINE_INT_TYPE_STRUCT (ULONG, u, 32); /* 32-bit unsigned integer. */
-ASSERT_SIZE (ULONG, 4);
+DEFINE_NULL_ASSERT_SIZE (ULONG, 4);
DEFINE_INT_TYPE_STRUCT (LONG, , 32); /* 32-bit signed integer. */
-ASSERT_SIZE (LONG, 4);
+DEFINE_NULL_ASSERT_SIZE (LONG, 4);
/* Date represented in number of seconds since 12:00 midnight, January 1,
* 1904. The value is represented as a signed 64-bit integer. */
@@ -166,7 +194,7 @@
SHORT i;
USHORT f;
};
-ASSERT_SIZE (Fixed, 4);
+DEFINE_NULL_ASSERT_SIZE (Fixed, 4);
/* Smallest measurable distance in the em space. */
struct FUNIT;
@@ -174,18 +202,18 @@
/* 16-bit signed integer (SHORT) that describes a quantity in FUnits. */
struct FWORD : SHORT {
};
-ASSERT_SIZE (FWORD, 2);
+DEFINE_NULL_ASSERT_SIZE (FWORD, 2);
/* 16-bit unsigned integer (USHORT) that describes a quantity in FUnits. */
struct UFWORD : USHORT {
};
-ASSERT_SIZE (UFWORD, 2);
+DEFINE_NULL_ASSERT_SIZE (UFWORD, 2);
/* 16-bit signed fixed number with the low 14 bits of fraction (2.14). */
struct F2DOT14 : SHORT {
inline operator double() const { return (uint32_t) this / 16384.; }
};
-ASSERT_SIZE (F2DOT14, 2);
+DEFINE_NULL_ASSERT_SIZE (F2DOT14, 2);
/* Array of four uint8s (length = 32 bits) used to identify a script, language
* system, feature, or baseline */
@@ -205,14 +233,15 @@
char v[4];
};
ASSERT_SIZE (Tag, 4);
+DEFINE_NULL_DATA (Tag, 5, " ");
/* Glyph index number, same as uint16 (length = 16 bits) */
DEFINE_INT_TYPE_STRUCT (GlyphID, u, 16);
-ASSERT_SIZE (GlyphID, 2);
+DEFINE_NULL_ASSERT_SIZE (GlyphID, 2);
-/* Offset to a table, same as uint16 (length = 16 bits), NULL offset = 0x0000 */
+/* Offset to a table, same as uint16 (length = 16 bits), Null offset = 0x0000 */
DEFINE_INT_TYPE_STRUCT (Offset, u, 16);
-ASSERT_SIZE (Offset, 2);
+DEFINE_NULL_ASSERT_SIZE (Offset, 2);
/* CheckSum */
struct CheckSum : ULONG {
@@ -225,7 +254,7 @@
return Sum;
}
};
-ASSERT_SIZE (CheckSum, 4);
+DEFINE_NULL_ASSERT_SIZE (CheckSum, 4);
/*
@@ -234,13 +263,13 @@
struct USHORT_Version : USHORT {
};
-ASSERT_SIZE (USHORT_Version, 2);
+DEFINE_NULL_ASSERT_SIZE (USHORT_Version, 2);
struct Fixed_Version : Fixed {
inline int16_t major (void) const { return this->int_part(); }
inline int16_t minor (void) const { return this->frac_part(); }
};
-ASSERT_SIZE (Fixed_Version, 4);
+DEFINE_NULL_ASSERT_SIZE (Fixed_Version, 4);
/*
@@ -267,7 +296,7 @@
* file. */
ULONG length; /* Length of this table. */
} OpenTypeTable;
-ASSERT_SIZE (TableDirectory, 16);
+DEFINE_NULL_ASSERT_SIZE (TableDirectory, 16);
typedef struct OffsetTable {
/* OpenTypeTables, in no particular order */
@@ -282,7 +311,8 @@
USHORT rangeShift; /* NumTables x 16-searchRange. */
TableDirectory tableDir[]; /* TableDirectory entries. numTables items */
} OpenTypeFontFace;
-ASSERT_SIZE (OffsetTable, 12);
+DEFINE_NULL_ASSERT_SIZE (OffsetTable, 12);
+DEFINE_NULL_ALIAS (OpenTypeFontFace, OffsetTable);
/*
* TrueType Collections
@@ -300,7 +330,7 @@
ULONG offsetTable[]; /* Array of offsets to the OffsetTable for each font
* from the beginning of the file */
};
-ASSERT_SIZE (TTCHeader, 12);
+DEFINE_NULL_ASSERT_SIZE (TTCHeader, 12);
/*
@@ -338,25 +368,18 @@
}
}
inline const OpenTypeFontFace& operator[] (unsigned int i) const {
- assert (i < get_len ());
+ if (i >= get_len ()) return NullOpenTypeFontFace;
switch (tag) {
default: case TrueTypeTag: case CFFTag: return (const OffsetTable&)*this;
case TTCTag: return ((const TTCHeader&)*this)[i];
}
}
- inline OpenTypeFontFace& operator[] (unsigned int i) {
- assert (i < get_len ());
- switch (tag) {
- default: case TrueTypeTag: case CFFTag: return (OffsetTable&)*this;
- case TTCTag: return ((TTCHeader&)*this)[i];
- }
- }
inline const Tag& get_tag (void) const { return tag; }
private:
Tag tag; /* 4-byte identifier. */
};
-ASSERT_SIZE (OpenTypeFontFile, 4);
+DEFINE_NULL_ASSERT_SIZE (OpenTypeFontFile, 4);
@@ -370,59 +393,12 @@
* Script, ScriptList, LangSys, Feature, FeatureList, Lookup, LookupList
*/
-struct Script;
-struct ScriptList;
-struct LangSys;
-struct Feature;
-struct FeatureList;
-struct Lookup;
-struct LookupList;
-
typedef struct Record {
Tag tag; /* 4-byte Tag identifier */
Offset offset; /* Offset from beginning of object holding
* the Record */
} ScriptRecord, LangSysRecord, FeatureRecord;
-ASSERT_SIZE (Record, 6);
-
-struct ScriptList {
- /* Scripts, in sorted alphabetical tag order */
- DEFINE_RECORD_ARRAY_TYPE (Script, scriptRecord, scriptCount);
-
- private:
- USHORT scriptCount; /* Number of ScriptRecords */
- ScriptRecord scriptRecord[]; /* Array of ScriptRecords--listed alphabetically
- * by ScriptTag */
-};
-ASSERT_SIZE (ScriptList, 2);
-
-struct Script {
- /* LangSys', in sorted alphabetical tag order */
- DEFINE_RECORD_ARRAY_TYPE (LangSys, langSysRecord, langSysCount);
-
- /* Return NULL if none */
- inline const LangSys* get_default_language_system (void) const {
- if (!defaultLangSys)
- return NULL;
- return (const LangSys *)((const char*)this + defaultLangSys);
- }
- inline LangSys* get_default_language_system (void) {
- if (!defaultLangSys)
- return NULL;
- return (LangSys *)((char*)this + defaultLangSys);
- }
-
- /* TODO implement find_language_system based on find_tag */
-
- private:
- Offset defaultLangSys; /* Offset to DefaultLangSys table--from
- * beginning of Script table--may be NULL */
- USHORT langSysCount; /* Number of LangSysRecords for this script--
- * excluding the DefaultLangSys */
- LangSysRecord langSysRecord[];/* Array of LangSysRecords--listed
- * alphabetically by LangSysTag */
-};
-ASSERT_SIZE (Script, 4);
+DEFINE_NULL_ASSERT_SIZE (Record, 6);
struct LangSys {
/* Feature indices, in no particular order */
@@ -438,7 +414,7 @@
/* TODO implement find_feature */
private:
- Offset lookupOrder; /* = NULL (reserved for an offset to a
+ Offset lookupOrder; /* = Null (reserved for an offset to a
* reordering table) */
USHORT reqFeatureIndex;/* Index of a feature required for this
* language system--if no required features
@@ -449,7 +425,60 @@
USHORT featureIndex[]; /* Array of indices into the FeatureList--in
* arbitrary order. featureCount entires long */
};
-ASSERT_SIZE (LangSys, 6);
+DEFINE_NULL_ASSERT_SIZE_DATA (LangSys, 6, "\0\0\xFF\xFF");
+
+struct Script {
+ /* LangSys', in sorted alphabetical tag order */
+ DEFINE_RECORD_ARRAY_TYPE (LangSys, langSysRecord, langSysCount);
+
+ inline const bool has_default_language_system (void) const {
+ return defaultLangSys != 0;
+ }
+ inline const LangSys& get_default_language_system (void) const {
+ if (!defaultLangSys)
+ return NullLangSys;
+ return *(LangSys*)((const char*)this + defaultLangSys);
+ }
+
+ /* TODO implement find_language_system based on find_tag */
+
+ private:
+ Offset defaultLangSys; /* Offset to DefaultLangSys table--from
+ * beginning of Script table--may be Null */
+ USHORT langSysCount; /* Number of LangSysRecords for this script--
+ * excluding the DefaultLangSys */
+ LangSysRecord langSysRecord[];/* Array of LangSysRecords--listed
+ * alphabetically by LangSysTag */
+};
+DEFINE_NULL_ASSERT_SIZE (Script, 4);
+
+struct ScriptList {
+ /* Scripts, in sorted alphabetical tag order */
+ DEFINE_RECORD_ARRAY_TYPE (Script, scriptRecord, scriptCount);
+
+private:
+ USHORT scriptCount; /* Number of ScriptRecords */
+ ScriptRecord scriptRecord[]; /* Array of ScriptRecords--listed alphabetically
+ * by ScriptTag */
+};
+DEFINE_NULL_ASSERT_SIZE (ScriptList, 2);
+
+struct Feature {
+ /* LookupList indices, in no particular order */
+ DEFINE_ARRAY_TYPE (USHORT, lookupIndex, lookupCount);
+
+ private:
+ Offset featureParams; /* Offset to Feature Parameters table (if one
+ * has been defined for the feature), relative
+ * to the beginning of the Feature Table; = Null
+ * if not required */
+ USHORT lookupCount; /* Number of LookupList indices for this
+ * feature */
+ USHORT lookupIndex[]; /* Array of LookupList indices for this
+ * feature--zero-based (first lookup is
+ * LookupListIndex = 0) */
+};
+DEFINE_NULL_ASSERT_SIZE (Feature, 4);
struct FeatureList {
/* Feature indices, in sorted alphabetical tag order */
@@ -461,38 +490,7 @@
* feature has FeatureIndex = 0)--listed
* alphabetically by FeatureTag */
};
-ASSERT_SIZE (FeatureList, 2);
-
-struct Feature {
- /* LookupList indices, in no particular order */
- DEFINE_ARRAY_TYPE (USHORT, lookupIndex, lookupCount);
-
- // TODO: implement get_feature_params()
-
- private:
- Offset featureParams; /* Offset to Feature Parameters table (if one
- * has been defined for the feature), relative
- * to the beginning of the Feature Table; = NULL
- * if not required */
- USHORT lookupCount; /* Number of LookupList indices for this
- * feature */
- USHORT lookupIndex[]; /* Array of LookupList indices for this
- * feature--zero-based (first lookup is
- * LookupListIndex = 0) */
-};
-ASSERT_SIZE (Feature, 4);
-
-struct LookupList {
- /* Lookup indices, in sorted alphabetical tag order */
- DEFINE_OFFSET_ARRAY_TYPE (Lookup, lookupOffset, lookupCount);
-
- private:
- USHORT lookupCount; /* Number of lookups in this table */
- Offset lookupOffset[]; /* Array of offsets to Lookup tables--from
- * beginning of LookupList--zero based (first
- * lookup is Lookup index = 0) */
-};
-ASSERT_SIZE (LookupList, 2);
+DEFINE_NULL_ASSERT_SIZE (FeatureList, 2);
struct LookupFlag : USHORT {
static const uint16_t RightToLeft = 0x0001u;
@@ -502,11 +500,20 @@
static const uint16_t Reserved = 0x00F0u;
static const uint16_t MarkAttachmentType = 0xFF00u;
};
-ASSERT_SIZE (LookupFlag, 2);
+DEFINE_NULL_ASSERT_SIZE (LookupFlag, 2);
+
+struct LookupSubTable {
+ DEFINE_NON_INSTANTIABLE(LookupSubTable);
+
+ private:
+ USHORT format; /* Subtable format. Different for GSUB and GPOS */
+};
+DEFINE_NULL_ASSERT_SIZE (LookupSubTable, 2);
+
struct Lookup {
/* SubTables, in the desired order */
- DEFINE_OFFSET_ARRAY_TYPE (char*, subTableOffset, subTableCount);
+ DEFINE_OFFSET_ARRAY_TYPE (LookupSubTable, subTableOffset, subTableCount);
inline bool is_right_to_left (void) const { return lookupFlag & LookupFlag::RightToLeft; }
inline bool ignore_base_glyphs(void) const { return lookupFlag & LookupFlag::IgnoreBaseGlyphs; }
@@ -524,7 +531,19 @@
Offset subTableOffset[];/* Array of offsets to SubTables-from
* beginning of Lookup table */
};
-ASSERT_SIZE (Lookup, 6);
+DEFINE_NULL_ASSERT_SIZE (Lookup, 6);
+
+struct LookupList {
+ /* Lookup indices, in sorted alphabetical tag order */
+ DEFINE_OFFSET_ARRAY_TYPE (Lookup, lookupOffset, lookupCount);
+
+ private:
+ USHORT lookupCount; /* Number of lookups in this table */
+ Offset lookupOffset[]; /* Array of offsets to Lookup tables--from
+ * beginning of LookupList--zero based (first
+ * lookup is Lookup index = 0) */
+};
+DEFINE_NULL_ASSERT_SIZE (LookupList, 2);
/*
* Coverage Table
@@ -565,7 +584,7 @@
USHORT startCoverageIndex; /* Coverage Index of first GlyphID in
* range */
};
-ASSERT_SIZE (CoverageRangeRecord, 6);
+DEFINE_NULL_ASSERT_SIZE_DATA (CoverageRangeRecord, 6, "\001");
struct CoverageFormat2 {
/* CoverageRangeRecords, in sorted numerical start order */
@@ -617,6 +636,7 @@
CoverageFormat2 format2;
} u;
};
+DEFINE_NULL (Coverage, 2);
/*
* Class Definition Table
@@ -653,7 +673,7 @@
GlyphID end; /* Last GlyphID in the range */
USHORT classValue; /* Applied to all glyphs in the range */
};
-ASSERT_SIZE (ClassRangeRecord, 6);
+DEFINE_NULL_ASSERT_SIZE_DATA (ClassRangeRecord, 6, "\001");
struct ClassDefFormat2 {
/* ClassRangeRecords, in sorted numerical start order */
@@ -704,6 +724,7 @@
ClassDefFormat2 format2;
} u;
};
+DEFINE_NULL (ClassDef, 2);
/*
* Device Tables
@@ -748,23 +769,13 @@
USHORT deltaFormat; /* Format of DeltaValue array data: 1, 2, or 3 */
USHORT deltaValue[]; /* Array of compressed data */
};
-ASSERT_SIZE (Device, 6);
+DEFINE_NULL_ASSERT_SIZE (Device, 6);
+/*
+ * GSUB/GPOS Header
+ */
-
-#define DEFINE_LIST_ACCESSOR0(const, Type, name) \
- inline const Type##List* get_##name##_list (void) const { \
- assert (name##List); \
- return (const Type##List *)((const char*)this + name##List); \
- } \
- inline const Type& get_##name (unsigned int i) const { \
- return (*get_##name##_list())[i]; \
- }
-#define DEFINE_LIST_ACCESSOR(Type, name) \
- DEFINE_LIST_ACCESSOR0(const, Type, name) \
- DEFINE_LIST_ACCESSOR0( , Type, name)
-
-struct GSUBGPOSHeader {
+typedef struct GSUBGPOSHeader {
static const hb_tag_t GSUBTag = HB_TAG ('G','S','U','B');
static const hb_tag_t GPOSTag = HB_TAG ('G','P','O','S');
@@ -785,7 +796,9 @@
* GSUB/GPOS table */
Offset lookupList; /* Offset to LookupList table--from beginning of
* GSUB/GPOS table */
-};
-ASSERT_SIZE (GSUBGPOSHeader, 10);
+} GSUBHeader, GPOSHeader;
+DEFINE_NULL_ASSERT_SIZE (GSUBGPOSHeader, 10);
+DEFINE_NULL_ALIAS (GSUBHeader, GSUBGPOSHeader);
+DEFINE_NULL_ALIAS (GPOSHeader, GSUBGPOSHeader);
#endif /* HARFBUZZ_OPEN_PRIVATE_H */