blob: d923b884929426883dfd72edbd23de54e8bbc31f [file] [log] [blame]
Behdad Esfahbod64aef3a2008-01-23 16:14:38 -05001/*
Behdad Esfahbodee58aae2009-05-17 05:14:33 -04002 * Copyright (C) 2007,2008,2009 Red Hat, Inc.
Behdad Esfahbod64aef3a2008-01-23 16:14:38 -05003 *
4 * This is part of HarfBuzz, an OpenType Layout engine library.
5 *
6 * Permission is hereby granted, without written agreement and without
7 * license or royalty fees, to use, copy, modify, and distribute this
8 * software and its documentation for any purpose, provided that the
9 * above copyright notice and the following two paragraphs appear in
10 * all copies of this software.
11 *
12 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
13 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
14 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
15 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
16 * DAMAGE.
17 *
18 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
19 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
21 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
22 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
23 *
24 * Red Hat Author(s): Behdad Esfahbod
25 */
26
Behdad Esfahbod5f5b24f2009-08-02 20:03:12 -040027#ifndef HB_OPEN_TYPES_PRIVATE_HH
28#define HB_OPEN_TYPES_PRIVATE_HH
Behdad Esfahbod12c45682006-12-28 06:10:59 -050029
Behdad Esfahbod2098a022009-08-02 19:57:00 -040030#include "hb-private.h"
Behdad Esfahbod12c45682006-12-28 06:10:59 -050031
Behdad Esfahbod70de50c2009-08-04 00:58:28 -040032#include "hb-blob.h"
33
Behdad Esfahboda16ecbf2008-01-23 17:01:55 -050034
Behdad Esfahbod706ab252008-01-28 05:58:50 -050035#define NO_INDEX ((unsigned int) 0xFFFF)
Behdad Esfahbod2e8fb6c2009-05-18 04:37:37 -040036#define NO_CONTEXT ((unsigned int) 0x110000)
37#define NOT_COVERED ((unsigned int) 0x110000)
38#define MAX_NESTING_LEVEL 8
Behdad Esfahbod5a0b7912009-04-16 04:45:30 -040039
Behdad Esfahbod706ab252008-01-28 05:58:50 -050040
Behdad Esfahbod196598b2009-08-04 11:04:32 -040041/*
42 * Casts
43 */
44
Behdad Esfahbod2b5a59c2009-08-04 11:38:50 -040045#define CONST_CHARP(X) (reinterpret_cast<const char *>(X))
46#define DECONST_CHARP(X) ((char *)reinterpret_cast<const char *>(X))
47#define CHARP(X) (reinterpret_cast<char *>(X))
48
49#define CONST_CAST(T,X,Ofs) (*(reinterpret_cast<const T *>(CONST_CHARP(&(X)) + Ofs)))
50#define DECONST_CAST(T,X,Ofs) (*(reinterpret_cast<T *>((char *)CONST_CHARP(&(X)) + Ofs)))
51#define CAST(T,X,Ofs) (*(reinterpret_cast<T *>(CHARP(&(X)) + Ofs)))
Behdad Esfahbod196598b2009-08-04 11:04:32 -040052
Behdad Esfahbod70de50c2009-08-04 00:58:28 -040053
54/*
55 * Sanitize
56 */
57
58typedef struct _hb_sanitize_context_t hb_sanitize_context_t;
59struct _hb_sanitize_context_t
60{
61 const char *start, *end;
62 hb_blob_t *blob;
63};
64
65#define SANITIZE_ARG_DEF \
66 hb_sanitize_context_t *context
67#define SANITIZE_ARG \
68 context
69
70#define SANITIZE(X) HB_LIKELY ((X).sanitize (SANITIZE_ARG))
Behdad Esfahbod42b778f2009-08-04 13:30:49 -040071#define SANITIZE2(X,Y) (SANITIZE (X) && SANITIZE (Y))
Behdad Esfahbod70de50c2009-08-04 00:58:28 -040072
Behdad Esfahbod2b5a59c2009-08-04 11:38:50 -040073#define SANITIZE_THIS(X) HB_LIKELY ((X).sanitize (SANITIZE_ARG, CONST_CHARP(this)))
Behdad Esfahbod42b778f2009-08-04 13:30:49 -040074#define SANITIZE_THIS2(X,Y) (SANITIZE_THIS (X) && SANITIZE_THIS (Y))
75#define SANITIZE_THIS3(X,Y,Z) (SANITIZE_THIS (X) && SANITIZE_THIS (Y) && SANITIZE_THIS(Z))
76
77#define SANITIZE_BASE(X,B) HB_LIKELY ((X).sanitize (SANITIZE_ARG, B))
78#define SANITIZE_BASE2(X,Y,B) (SANITIZE_BASE (X,B) && SANITIZE_BASE (Y,B))
Behdad Esfahbod70de50c2009-08-04 00:58:28 -040079
80#define SANITIZE_SELF() SANITIZE_OBJ (*this)
81#define SANITIZE_OBJ(X) SANITIZE_MEM(&(X), sizeof (X))
Behdad Esfahboddc9c4d92009-08-04 12:26:26 -040082#define SANITIZE_GET_SIZE() SANITIZE_SELF() && SANITIZE_MEM (this, this->get_size ())
Behdad Esfahbod70de50c2009-08-04 00:58:28 -040083
Behdad Esfahbod2b5a59c2009-08-04 11:38:50 -040084#define SANITIZE_MEM(B,L) HB_LIKELY (context->start <= CONST_CHARP(B) && CONST_CHARP(B) + (L) <= context->end) /* XXX overflow */
Behdad Esfahbod70de50c2009-08-04 00:58:28 -040085
Behdad Esfahbodac26e2a2009-08-04 14:10:39 -040086#define NEUTER(Var, Val) (SANITIZE_OBJ (Var) && hb_blob_try_writeable_inplace (context->blob) && ((Var) = (Val), true))
Behdad Esfahbod70de50c2009-08-04 00:58:28 -040087
88
Behdad Esfahbodb6e62bc2006-12-22 02:21:55 -050089/*
Behdad Esfahbodb6e62bc2006-12-22 02:21:55 -050090 * Array types
91 */
92
93/* get_len() is a method returning the number of items in an array-like object */
94#define DEFINE_LEN(Type, array, num) \
95 inline unsigned int get_len(void) const { return num; } \
96
Behdad Esfahbodb6e62bc2006-12-22 02:21:55 -050097/* An array type is one that contains a variable number of objects
Behdad Esfahbod238c8552009-05-17 00:22:37 -040098 * as its last item. An array object is extended with get_len()
Behdad Esfahbodb6e62bc2006-12-22 02:21:55 -050099 * methods, as well as overloaded [] operator. */
100#define DEFINE_ARRAY_TYPE(Type, array, num) \
Behdad Esfahbod1f437e62008-01-23 04:36:40 -0500101 DEFINE_INDEX_OPERATOR(Type, array, num) \
Behdad Esfahbod0dff25f2009-05-08 21:12:18 -0400102 DEFINE_LEN(Type, array, num)
Behdad Esfahbod1f437e62008-01-23 04:36:40 -0500103#define DEFINE_INDEX_OPERATOR(Type, array, num) \
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400104 inline const Type& operator[] (unsigned int i) const \
105 { \
Behdad Esfahbod8b835802009-05-16 22:48:14 -0400106 if (HB_UNLIKELY (i >= num)) return Null(Type); \
Behdad Esfahbodb6e62bc2006-12-22 02:21:55 -0500107 return array[i]; \
108 }
109
110/* An offset array type is like an array type, but it contains a table
111 * of offsets to the objects, relative to the beginning of the current
112 * object. */
113#define DEFINE_OFFSET_ARRAY_TYPE(Type, array, num) \
Behdad Esfahbod1f437e62008-01-23 04:36:40 -0500114 DEFINE_OFFSET_INDEX_OPERATOR(Type, array, num) \
Behdad Esfahbod0dff25f2009-05-08 21:12:18 -0400115 DEFINE_LEN(Offset, array, num)
Behdad Esfahbod1f437e62008-01-23 04:36:40 -0500116#define DEFINE_OFFSET_INDEX_OPERATOR(Type, array, num) \
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400117 inline const Type& operator[] (unsigned int i) const \
118 { \
Behdad Esfahbod8b835802009-05-16 22:48:14 -0400119 if (HB_UNLIKELY (i >= num)) return Null(Type); \
120 if (HB_UNLIKELY (!array[i])) return Null(Type); \
Behdad Esfahbod4497af02009-05-25 03:20:18 -0400121 return *(const Type)((const char*)this + array[i]); \
Behdad Esfahbodb6e62bc2006-12-22 02:21:55 -0500122 }
123
Behdad Esfahbodfd92a3d2008-01-24 03:11:09 -0500124
125#define DEFINE_ARRAY_INTERFACE(Type, name) \
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400126 inline const Type& get_##name (unsigned int i) const { return (*this)[i]; } \
127 inline unsigned int get_##name##_count (void) const { return this->get_len (); }
Behdad Esfahbodfd92a3d2008-01-24 03:11:09 -0500128#define DEFINE_INDEX_ARRAY_INTERFACE(name) \
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400129 inline unsigned int get_##name##_index (unsigned int i) const \
130 { \
Behdad Esfahbod4a26ea42008-01-28 07:40:10 -0500131 if (HB_UNLIKELY (i >= get_len ())) return NO_INDEX; \
Behdad Esfahbodfd92a3d2008-01-24 03:11:09 -0500132 return (*this)[i]; \
133 } \
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400134 inline unsigned int get_##name##_count (void) const { return get_len (); }
Behdad Esfahbodfd92a3d2008-01-24 03:11:09 -0500135
Behdad Esfahbodfd92a3d2008-01-24 03:11:09 -0500136
Behdad Esfahbod1f437e62008-01-23 04:36:40 -0500137/*
138 * List types
139 */
Behdad Esfahbodb6e62bc2006-12-22 02:21:55 -0500140
Behdad Esfahbod40a81312008-01-28 02:30:48 -0500141#define DEFINE_LIST_INTERFACE(Type, name) \
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400142 inline const Type& get_##name (unsigned int i) const { return (this+name##List)[i]; } \
143 inline unsigned int get_##name##_count (void) const { return (this+name##List).len; }
Behdad Esfahbod40a81312008-01-28 02:30:48 -0500144
145/*
146 * Tag types
147 */
148
149#define DEFINE_TAG_ARRAY_INTERFACE(Type, name) \
150 DEFINE_ARRAY_INTERFACE (Type, name); \
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400151 inline const Tag& get_##name##_tag (unsigned int i) const { return (*this)[i].tag; }
Behdad Esfahbod40a81312008-01-28 02:30:48 -0500152#define DEFINE_TAG_LIST_INTERFACE(Type, name) \
153 DEFINE_LIST_INTERFACE (Type, name); \
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400154 inline const Tag& get_##name##_tag (unsigned int i) const { return (this+name##List).get_tag (i); }
Behdad Esfahbod40a81312008-01-28 02:30:48 -0500155
156#define DEFINE_TAG_FIND_INTERFACE(Type, name) \
Behdad Esfahbodcc6c6442009-05-25 03:10:06 -0400157 inline bool find_##name##_index (hb_tag_t tag, unsigned int *index) const { \
Behdad Esfahbod706ab252008-01-28 05:58:50 -0500158 const Tag t = tag; \
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400159 for (unsigned int i = 0; i < get_##name##_count (); i++) \
160 { \
161 if (t == get_##name##_tag (i)) \
162 { \
Behdad Esfahbodcc6c6442009-05-25 03:10:06 -0400163 if (index) *index = i; \
Behdad Esfahbod706ab252008-01-28 05:58:50 -0500164 return true; \
165 } \
166 } \
Behdad Esfahbodcc6c6442009-05-25 03:10:06 -0400167 if (index) *index = NO_INDEX; \
Behdad Esfahbod706ab252008-01-28 05:58:50 -0500168 return false; \
Behdad Esfahbod40a81312008-01-28 02:30:48 -0500169 } \
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400170 inline const Type& get_##name##_by_tag (hb_tag_t tag) const \
171 { \
Behdad Esfahbod706ab252008-01-28 05:58:50 -0500172 unsigned int i; \
173 if (find_##name##_index (tag, &i)) \
174 return get_##name (i); \
Behdad Esfahbod40a81312008-01-28 02:30:48 -0500175 else \
Behdad Esfahbod8b835802009-05-16 22:48:14 -0400176 return Null(Type); \
Behdad Esfahbod1f437e62008-01-23 04:36:40 -0500177 }
Behdad Esfahbod600e5eb2008-01-23 02:01:37 -0500178
179/*
180 * Class features
181 */
182
Behdad Esfahbod8b835802009-05-16 22:48:14 -0400183
184/* Null objects */
185
186/* Global nul-content Null pool. Enlarge as necessary. */
187static const char NullPool[16] = "";
188
189/* Generic template for nul-content sizeof-sized Null objects. */
190template <typename Type>
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400191struct Null
192{
Behdad Esfahbodf8dc67b2009-05-17 19:47:54 -0400193 ASSERT_STATIC (sizeof (Type) <= sizeof (NullPool));
Behdad Esfahbod4497af02009-05-25 03:20:18 -0400194 static inline const Type &get () { return *(const Type*)NullPool; }
Behdad Esfahbod8b835802009-05-16 22:48:14 -0400195};
196
Behdad Esfahbod8b835802009-05-16 22:48:14 -0400197/* Specializaiton for arbitrary-content arbitrary-sized Null objects. */
198#define DEFINE_NULL_DATA(Type, size, data) \
Behdad Esfahbodcc6c6442009-05-25 03:10:06 -0400199static const char _Null##Type[size] = data; \
Behdad Esfahbod8b835802009-05-16 22:48:14 -0400200template <> \
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400201struct Null <Type> \
202{ \
Behdad Esfahbod4497af02009-05-25 03:20:18 -0400203 static inline const Type &get () { return *(const Type*)_Null##Type; } \
Behdad Esfahbod8b835802009-05-16 22:48:14 -0400204}
205
206/* Accessor macro. */
207#define Null(Type) (Null<Type>::get())
208
209
210#define ASSERT_SIZE_DATA(Type, size, data) \
Behdad Esfahbod1f437e62008-01-23 04:36:40 -0500211 ASSERT_SIZE (Type, size); \
212 DEFINE_NULL_DATA (Type, size, data)
Behdad Esfahbod1f437e62008-01-23 04:36:40 -0500213
Behdad Esfahbod600e5eb2008-01-23 02:01:37 -0500214/* get_for_data() is a static class method returning a reference to an
215 * instance of Type located at the input data location. It's just a
Behdad Esfahbod54e5aac2008-01-27 21:19:51 -0500216 * fancy, NULL-safe, cast! */
Behdad Esfahbod600e5eb2008-01-23 02:01:37 -0500217#define STATIC_DEFINE_GET_FOR_DATA(Type) \
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400218 static inline const Type& get_for_data (const char *data) \
219 { \
Behdad Esfahbod8b835802009-05-16 22:48:14 -0400220 if (HB_UNLIKELY (data == NULL)) return Null(Type); \
Behdad Esfahbod4497af02009-05-25 03:20:18 -0400221 return *(const Type*)data; \
Behdad Esfahbod212aba62009-05-24 00:50:27 -0400222 }
223/* Like get_for_data(), but checks major version first. */
Behdad Esfahbodcd3827e2009-08-04 02:09:34 -0400224#define STATIC_DEFINE_GET_FOR_DATA_CHECK_MAJOR_VERSION(Type, MajorMin, MajorMax) \
Behdad Esfahbod212aba62009-05-24 00:50:27 -0400225 static inline const Type& get_for_data (const char *data) \
226 { \
227 if (HB_UNLIKELY (data == NULL)) return Null(Type); \
Behdad Esfahbod4497af02009-05-25 03:20:18 -0400228 const Type& t = *(const Type*)data; \
Behdad Esfahbodcd3827e2009-08-04 02:09:34 -0400229 if (HB_UNLIKELY (t.version.major < MajorMin || t.version.major > MajorMax)) return Null(Type); \
Behdad Esfahbod212aba62009-05-24 00:50:27 -0400230 return t; \
231 }
Behdad Esfahbod600e5eb2008-01-23 02:01:37 -0500232
233
Behdad Esfahbod2d15e722009-04-15 19:50:16 -0400234
Behdad Esfahbodf78e70c2006-12-21 22:30:38 -0500235/*
236 *
237 * The OpenType Font File
238 *
239 */
240
Behdad Esfahbod6b4ce012006-12-21 22:31:10 -0500241
Behdad Esfahbodf78e70c2006-12-21 22:30:38 -0500242/*
Behdad Esfahbod6b4ce012006-12-21 22:31:10 -0500243 * Data Types
Behdad Esfahbodf78e70c2006-12-21 22:30:38 -0500244 */
245
246
Behdad Esfahbod6b4ce012006-12-21 22:31:10 -0500247/* "The following data types are used in the OpenType font file.
248 * All OpenType fonts use Motorola-style byte ordering (Big Endian):" */
Behdad Esfahbodf78e70c2006-12-21 22:30:38 -0500249
Behdad Esfahbod5f810362009-05-17 00:54:25 -0400250/*
251 * Int types
252 */
253
Behdad Esfahbod20cc86b2009-05-25 02:41:49 -0400254/* TODO On machines that do not allow unaligned access, fix the accessors. */
255#define DEFINE_INT_TYPE1(NAME, TYPE, BIG_ENDIAN, BYTES) \
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400256 struct NAME \
257 { \
Behdad Esfahbod20cc86b2009-05-25 02:41:49 -0400258 inline NAME& operator = (TYPE i) { (TYPE&) v = BIG_ENDIAN (i); return *this; } \
259 inline operator TYPE(void) const { return BIG_ENDIAN ((TYPE&) v); } \
260 inline bool operator== (NAME o) const { return (TYPE&) v == (TYPE&) o.v; } \
Behdad Esfahbod70de50c2009-08-04 00:58:28 -0400261 inline bool sanitize (SANITIZE_ARG_DEF) { return SANITIZE_SELF (); } \
Behdad Esfahbod20cc86b2009-05-25 02:41:49 -0400262 private: char v[BYTES]; \
Behdad Esfahbod5f810362009-05-17 00:54:25 -0400263 }; \
Behdad Esfahbod20cc86b2009-05-25 02:41:49 -0400264 ASSERT_SIZE (NAME, BYTES)
Behdad Esfahboddf660282009-08-01 20:46:02 -0400265#define DEFINE_INT_TYPE0(NAME, type, b) DEFINE_INT_TYPE1 (NAME, type##_t, hb_be_##type, b)
266#define DEFINE_INT_TYPE(NAME, u, w) DEFINE_INT_TYPE0 (NAME, u##int##w, (w / 8))
Behdad Esfahbod5f810362009-05-17 00:54:25 -0400267
Behdad Esfahbodf78e70c2006-12-21 22:30:38 -0500268
Behdad Esfahbod20cc86b2009-05-25 02:41:49 -0400269DEFINE_INT_TYPE (USHORT, u, 16); /* 16-bit unsigned integer. */
270DEFINE_INT_TYPE (SHORT, , 16); /* 16-bit signed integer. */
271DEFINE_INT_TYPE (ULONG, u, 32); /* 32-bit unsigned integer. */
272DEFINE_INT_TYPE (LONG, , 32); /* 32-bit signed integer. */
Behdad Esfahbod6b4ce012006-12-21 22:31:10 -0500273
Behdad Esfahbod6b4ce012006-12-21 22:31:10 -0500274/* Array of four uint8s (length = 32 bits) used to identify a script, language
275 * system, feature, or baseline */
Behdad Esfahbod20cc86b2009-05-25 02:41:49 -0400276struct Tag : ULONG
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400277{
Behdad Esfahbod4497af02009-05-25 03:20:18 -0400278 inline Tag (const Tag &o) { *(ULONG*)this = (ULONG&) o; }
279 inline Tag (uint32_t i) { *(ULONG*)this = i; }
280 inline Tag (const char *c) { *(ULONG*)this = *(ULONG*)c; }
281 inline bool operator== (const char *c) const { return *(ULONG*)this == *(ULONG*)c; }
Behdad Esfahbodbefc0222006-12-25 09:14:52 -0500282 /* What the char* converters return is NOT nul-terminated. Print using "%.4s" */
Behdad Esfahbod2b5a59c2009-08-04 11:38:50 -0400283 inline operator const char* (void) const { return CONST_CHARP(this); }
284 inline operator char* (void) { return CHARP(this); }
Behdad Esfahbod738c54d2009-08-04 14:42:46 -0400285
286 inline bool sanitize (SANITIZE_ARG_DEF) {
287 /* Note: Only accept ASCII-visible tags (mind DEL)
288 * This is one of the few times (only time?) we check
289 * for data integrity, as opposed o just boundary checks
290 */
291 return SANITIZE_SELF () && (((uint32_t) *this) & 0x80808080) == 0;
292 }
Behdad Esfahbod6b4ce012006-12-21 22:31:10 -0500293};
Behdad Esfahbod303fe622008-01-23 00:20:48 -0500294ASSERT_SIZE (Tag, 4);
Behdad Esfahbodda1097b2009-05-17 19:31:18 -0400295#define _NULL_TAG_INIT {' ', ' ', ' ', ' '}
296DEFINE_NULL_DATA (Tag, 4, _NULL_TAG_INIT);
297#undef _NULL_TAG_INIT
Behdad Esfahbod6b4ce012006-12-21 22:31:10 -0500298
299/* Glyph index number, same as uint16 (length = 16 bits) */
Behdad Esfahbod6ad8d5f2009-05-25 02:27:29 -0400300typedef USHORT GlyphID;
Behdad Esfahbod6b4ce012006-12-21 22:31:10 -0500301
Behdad Esfahbod1f437e62008-01-23 04:36:40 -0500302/* Offset to a table, same as uint16 (length = 16 bits), Null offset = 0x0000 */
Behdad Esfahbod6ad8d5f2009-05-25 02:27:29 -0400303typedef USHORT Offset;
Behdad Esfahbod8b835802009-05-16 22:48:14 -0400304
Behdad Esfahbod6ad8d5f2009-05-25 02:27:29 -0400305/* LongOffset to a table, same as uint32 (length = 32 bits), Null offset = 0x00000000 */
306typedef ULONG LongOffset;
307
Behdad Esfahbod6b4ce012006-12-21 22:31:10 -0500308
309/* CheckSum */
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400310struct CheckSum : ULONG
311{
312 static uint32_t CalcTableChecksum (ULONG *Table, uint32_t Length)
313 {
Behdad Esfahbod6b4ce012006-12-21 22:31:10 -0500314 uint32_t Sum = 0L;
Behdad Esfahbod01e4fcb2006-12-21 22:31:31 -0500315 ULONG *EndPtr = Table+((Length+3) & ~3) / sizeof(ULONG);
Behdad Esfahbod6b4ce012006-12-21 22:31:10 -0500316
317 while (Table < EndPtr)
318 Sum += *Table++;
319 return Sum;
320 }
321};
Behdad Esfahbod8b835802009-05-16 22:48:14 -0400322ASSERT_SIZE (CheckSum, 4);
Behdad Esfahbod6b4ce012006-12-21 22:31:10 -0500323
324
Behdad Esfahbod6b4ce012006-12-21 22:31:10 -0500325/*
326 * Version Numbers
327 */
328
Behdad Esfahbod87fcdcb2009-05-24 01:03:24 -0400329struct FixedVersion
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400330{
Behdad Esfahbod09c292e2009-05-26 19:48:16 -0400331 inline operator uint32_t (void) const { return (major << 16) + minor; }
Behdad Esfahbod96908b82009-05-24 12:30:40 -0400332
Behdad Esfahbodcd3827e2009-08-04 02:09:34 -0400333 inline bool sanitize (SANITIZE_ARG_DEF) {
334 return SANITIZE_SELF ();
335 }
336
Behdad Esfahbod6ad8d5f2009-05-25 02:27:29 -0400337 USHORT major;
Behdad Esfahbod87fcdcb2009-05-24 01:03:24 -0400338 USHORT minor;
Behdad Esfahbod6b4ce012006-12-21 22:31:10 -0500339};
Behdad Esfahbod87fcdcb2009-05-24 01:03:24 -0400340ASSERT_SIZE (FixedVersion, 4);
Behdad Esfahbod6b4ce012006-12-21 22:31:10 -0500341
Behdad Esfahbod92b5dd82009-08-04 10:41:32 -0400342
343
344/*
345 * Template subclasses of Offset and LongOffset that do the dereferencing.
346 * Use: (this+memberName)
347 */
348
349template <typename OffsetType, typename Type>
350struct GenericOffsetTo : OffsetType
351{
352 inline const Type& operator() (const void *base) const
353 {
354 unsigned int offset = *this;
355 if (HB_UNLIKELY (!offset)) return Null(Type);
Behdad Esfahbod95639fc2009-08-04 12:05:24 -0400356 return CONST_CAST(Type, *CONST_CHARP(base), offset);
Behdad Esfahbod92b5dd82009-08-04 10:41:32 -0400357 }
358
359 inline bool sanitize (SANITIZE_ARG_DEF, const void *base) {
360 if (!SANITIZE_OBJ (*this)) return false;
361 unsigned int offset = *this;
362 if (HB_UNLIKELY (!offset)) return true;
Behdad Esfahbodac26e2a2009-08-04 14:10:39 -0400363 return SANITIZE (CAST(Type, *DECONST_CHARP(base), offset)) || NEUTER (DECONST_CAST(OffsetType,*this,0), 0);
Behdad Esfahbod92b5dd82009-08-04 10:41:32 -0400364 }
Behdad Esfahbod42b778f2009-08-04 13:30:49 -0400365 inline bool sanitize (SANITIZE_ARG_DEF, const void *base, unsigned int user_data) {
366 if (!SANITIZE_OBJ (*this)) return false;
367 unsigned int offset = *this;
368 if (HB_UNLIKELY (!offset)) return true;
Behdad Esfahbodac26e2a2009-08-04 14:10:39 -0400369 return SANITIZE_BASE (CAST(Type, *DECONST_CHARP(base), offset), user_data) || NEUTER (DECONST_CAST(OffsetType,*this,0), 0);
Behdad Esfahbod42b778f2009-08-04 13:30:49 -0400370 }
Behdad Esfahbod92b5dd82009-08-04 10:41:32 -0400371};
372template <typename Base, typename OffsetType, typename Type>
373inline const Type& operator + (const Base &base, GenericOffsetTo<OffsetType, Type> offset) { return offset (base); }
374
375template <typename Type>
376struct OffsetTo : GenericOffsetTo<Offset, Type> {};
377
378template <typename Type>
379struct LongOffsetTo : GenericOffsetTo<LongOffset, Type> {};
Behdad Esfahbod5f810362009-05-17 00:54:25 -0400380/*
381 * Array Types
382 */
383
Behdad Esfahbod92b5dd82009-08-04 10:41:32 -0400384template <typename LenType, typename Type>
385struct GenericArrayOf
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400386{
387 inline const Type& operator [] (unsigned int i) const
388 {
Behdad Esfahbod5f810362009-05-17 00:54:25 -0400389 if (HB_UNLIKELY (i >= len)) return Null(Type);
390 return array[i];
391 }
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400392 inline unsigned int get_size () const
Behdad Esfahbod79420ad2009-05-26 12:24:16 -0400393 { return sizeof (len) + len * sizeof (array[0]); }
Behdad Esfahbode8cbaaf2009-05-18 02:03:58 -0400394
Behdad Esfahbod70de50c2009-08-04 00:58:28 -0400395 inline bool sanitize (SANITIZE_ARG_DEF) {
Behdad Esfahboddc9c4d92009-08-04 12:26:26 -0400396 if (!SANITIZE_GET_SIZE()) return false;
Behdad Esfahboda97ce572009-08-04 02:10:48 -0400397 /* Note; for non-recursive types, this is not much needed
Behdad Esfahbod70de50c2009-08-04 00:58:28 -0400398 unsigned int count = len;
399 for (unsigned int i = 0; i < count; i++)
400 if (!SANITIZE (array[i]))
401 return false;
Behdad Esfahboda97ce572009-08-04 02:10:48 -0400402 */
Behdad Esfahbod70de50c2009-08-04 00:58:28 -0400403 }
Behdad Esfahbod2b5a59c2009-08-04 11:38:50 -0400404 inline bool sanitize (SANITIZE_ARG_DEF, const void *base) {
Behdad Esfahboddc9c4d92009-08-04 12:26:26 -0400405 if (!SANITIZE_GET_SIZE()) return false;
Behdad Esfahbode6ab2c52009-08-04 10:23:01 -0400406 unsigned int count = len;
407 for (unsigned int i = 0; i < count; i++)
Behdad Esfahbod95639fc2009-08-04 12:05:24 -0400408 if (!array[i].sanitize (SANITIZE_ARG, base))
Behdad Esfahbode6ab2c52009-08-04 10:23:01 -0400409 return false;
410 }
Behdad Esfahbod42b778f2009-08-04 13:30:49 -0400411 inline bool sanitize (SANITIZE_ARG_DEF, const void *base, unsigned int user_data) {
412 if (!SANITIZE_GET_SIZE()) return false;
413 unsigned int count = len;
414 for (unsigned int i = 0; i < count; i++)
415 if (!array[i].sanitize (SANITIZE_ARG, base, user_data))
416 return false;
417 }
Behdad Esfahbod70de50c2009-08-04 00:58:28 -0400418
Behdad Esfahbod92b5dd82009-08-04 10:41:32 -0400419 LenType len;
Behdad Esfahbode8cbaaf2009-05-18 02:03:58 -0400420 Type array[];
421};
422
Behdad Esfahbod92b5dd82009-08-04 10:41:32 -0400423/* An array with a USHORT number of elements. */
424template <typename Type>
425struct ArrayOf : GenericArrayOf<USHORT, Type> {};
426
427/* An array with a ULONG number of elements. */
428template <typename Type>
429struct LongArrayOf : GenericArrayOf<ULONG, Type> {};
430
431/* Array of Offset's */
432template <typename Type>
433struct OffsetArrayOf : ArrayOf<OffsetTo<Type> > {};
434
435/* Array of LongOffset's */
436template <typename Type>
437struct LongOffsetArrayOf : ArrayOf<LongOffsetTo<Type> > {};
438
439/* LongArray of LongOffset's */
440template <typename Type>
441struct LongOffsetLongArrayOf : LongArrayOf<LongOffsetTo<Type> > {};
442
Behdad Esfahbode8cbaaf2009-05-18 02:03:58 -0400443/* An array with a USHORT number of elements,
444 * starting at second element. */
445template <typename Type>
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400446struct HeadlessArrayOf
447{
448 inline const Type& operator [] (unsigned int i) const
449 {
Behdad Esfahbode8cbaaf2009-05-18 02:03:58 -0400450 if (HB_UNLIKELY (i >= len || !i)) return Null(Type);
451 return array[i-1];
452 }
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400453 inline unsigned int get_size () const
Behdad Esfahbod79420ad2009-05-26 12:24:16 -0400454 { return sizeof (len) + (len ? len - 1 : 0) * sizeof (array[0]); }
Behdad Esfahbod5f810362009-05-17 00:54:25 -0400455
Behdad Esfahbod70de50c2009-08-04 00:58:28 -0400456 inline bool sanitize (SANITIZE_ARG_DEF) {
Behdad Esfahboddc9c4d92009-08-04 12:26:26 -0400457 if (!SANITIZE_GET_SIZE()) return false;
Behdad Esfahboda97ce572009-08-04 02:10:48 -0400458 /* Note; for non-recursive types, this is not much needed
Behdad Esfahbod15164d92009-08-04 13:57:41 -0400459 unsigned int count = len ? len - 1 : 0;
Behdad Esfahbod70de50c2009-08-04 00:58:28 -0400460 for (unsigned int i = 0; i < count; i++)
461 if (!SANITIZE (array[i]))
462 return false;
Behdad Esfahboda97ce572009-08-04 02:10:48 -0400463 */
Behdad Esfahbod70de50c2009-08-04 00:58:28 -0400464 }
465
Behdad Esfahbod5f810362009-05-17 00:54:25 -0400466 USHORT len;
Behdad Esfahbod5f810362009-05-17 00:54:25 -0400467 Type array[];
468};
469
Behdad Esfahbod6b4ce012006-12-21 22:31:10 -0500470
Behdad Esfahbod5f5b24f2009-08-02 20:03:12 -0400471#endif /* HB_OPEN_TYPES_PRIVATE_HH */