hb-open-type-private.hh revision 0d77ab8a73f57c9fca4c6f9301dae394d79526e3
164aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod/*
2ee58aaebd296ea8237516754fd4e825d524b11b7Behdad Esfahbod * Copyright (C) 2007,2008,2009  Red Hat, Inc.
364aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod *
464aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod *  This is part of HarfBuzz, an OpenType Layout engine library.
564aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod *
664aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * Permission is hereby granted, without written agreement and without
764aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * license or royalty fees, to use, copy, modify, and distribute this
864aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * software and its documentation for any purpose, provided that the
964aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * above copyright notice and the following two paragraphs appear in
1064aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * all copies of this software.
1164aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod *
1264aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
1364aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
1464aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
1564aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
1664aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * DAMAGE.
1764aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod *
1864aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
1964aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
2064aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
2164aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
2264aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
2364aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod *
2464aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * Red Hat Author(s): Behdad Esfahbod
2564aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod */
2664aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod
275f5b24f99f52bbc922e238b65c06061ba07c8548Behdad Esfahbod#ifndef HB_OPEN_TYPES_PRIVATE_HH
285f5b24f99f52bbc922e238b65c06061ba07c8548Behdad Esfahbod#define HB_OPEN_TYPES_PRIVATE_HH
2912c4568c680ea2b9b98a16a8b7402ca185c90ef6Behdad Esfahbod
302098a021a826e76ee27d5db74e32738d7d1c3d30Behdad Esfahbod#include "hb-private.h"
3112c4568c680ea2b9b98a16a8b7402ca185c90ef6Behdad Esfahbod
3270de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod#include "hb-blob.h"
3370de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod
34a16ecbf0564a6e2576da22c12827f3c0719da549Behdad Esfahbod
35706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod#define NO_INDEX		((unsigned int) 0xFFFF)
362e8fb6c38dbc01cb77b384c0ae0212514dfbb588Behdad Esfahbod#define NO_CONTEXT		((unsigned int) 0x110000)
372e8fb6c38dbc01cb77b384c0ae0212514dfbb588Behdad Esfahbod#define NOT_COVERED		((unsigned int) 0x110000)
382e8fb6c38dbc01cb77b384c0ae0212514dfbb588Behdad Esfahbod#define MAX_NESTING_LEVEL	8
395a0b791184cf6ef39eae0570e14aca21abc32845Behdad Esfahbod
40706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
41196598bbccff08415ff5192314cba044df258cadBehdad Esfahbod/*
42196598bbccff08415ff5192314cba044df258cadBehdad Esfahbod * Casts
43196598bbccff08415ff5192314cba044df258cadBehdad Esfahbod */
44196598bbccff08415ff5192314cba044df258cadBehdad Esfahbod
452b5a59c277f4c5bf7aac9a9005054763e322e02dBehdad Esfahbod#define CONST_CHARP(X)		(reinterpret_cast<const char *>(X))
462b5a59c277f4c5bf7aac9a9005054763e322e02dBehdad Esfahbod#define DECONST_CHARP(X)	((char *)reinterpret_cast<const char *>(X))
472b5a59c277f4c5bf7aac9a9005054763e322e02dBehdad Esfahbod#define CHARP(X)		(reinterpret_cast<char *>(X))
482b5a59c277f4c5bf7aac9a9005054763e322e02dBehdad Esfahbod
492b5a59c277f4c5bf7aac9a9005054763e322e02dBehdad Esfahbod#define CONST_CAST(T,X,Ofs)	(*(reinterpret_cast<const T *>(CONST_CHARP(&(X)) + Ofs)))
502b5a59c277f4c5bf7aac9a9005054763e322e02dBehdad Esfahbod#define DECONST_CAST(T,X,Ofs)	(*(reinterpret_cast<T *>((char *)CONST_CHARP(&(X)) + Ofs)))
512b5a59c277f4c5bf7aac9a9005054763e322e02dBehdad Esfahbod#define CAST(T,X,Ofs) 		(*(reinterpret_cast<T *>(CHARP(&(X)) + Ofs)))
52196598bbccff08415ff5192314cba044df258cadBehdad Esfahbod
5370de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod
5470de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod/*
55b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod * Array types
56b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod */
57b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod
58b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod/* get_len() is a method returning the number of items in an array-like object */
59b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod#define DEFINE_LEN(Type, array, num) \
60b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod  inline unsigned int get_len(void) const { return num; } \
61b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod
62b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod/* An array type is one that contains a variable number of objects
63238c855fcd4f0ef97a94a8662d2a2f2bb5c21ecbBehdad Esfahbod * as its last item.  An array object is extended with get_len()
64b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod * methods, as well as overloaded [] operator. */
65b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod#define DEFINE_ARRAY_TYPE(Type, array, num) \
661f437e6f47fb6c15761021bd2078f31778f2179cBehdad Esfahbod  DEFINE_INDEX_OPERATOR(Type, array, num) \
670dff25f0368c5f14ebb0a4af35f3bb6658740d57Behdad Esfahbod  DEFINE_LEN(Type, array, num)
681f437e6f47fb6c15761021bd2078f31778f2179cBehdad Esfahbod#define DEFINE_INDEX_OPERATOR(Type, array, num) \
6960d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  inline const Type& operator[] (unsigned int i) const \
7060d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  { \
718b8358033184198ff638ee1379093717596e162dBehdad Esfahbod    if (HB_UNLIKELY (i >= num)) return Null(Type); \
72b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod    return array[i]; \
73b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod  }
74b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod
75b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod/* An offset array type is like an array type, but it contains a table
76b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod * of offsets to the objects, relative to the beginning of the current
77b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod * object. */
78b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod#define DEFINE_OFFSET_ARRAY_TYPE(Type, array, num) \
791f437e6f47fb6c15761021bd2078f31778f2179cBehdad Esfahbod  DEFINE_OFFSET_INDEX_OPERATOR(Type, array, num) \
800dff25f0368c5f14ebb0a4af35f3bb6658740d57Behdad Esfahbod  DEFINE_LEN(Offset, array, num)
811f437e6f47fb6c15761021bd2078f31778f2179cBehdad Esfahbod#define DEFINE_OFFSET_INDEX_OPERATOR(Type, array, num) \
8260d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  inline const Type& operator[] (unsigned int i) const \
8360d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  { \
848b8358033184198ff638ee1379093717596e162dBehdad Esfahbod    if (HB_UNLIKELY (i >= num)) return Null(Type); \
858b8358033184198ff638ee1379093717596e162dBehdad Esfahbod    if (HB_UNLIKELY (!array[i])) return Null(Type); \
864497af0069a94c69fc1518b1db2c1282721b732aBehdad Esfahbod    return *(const Type)((const char*)this + array[i]); \
87b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod  }
88b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod
89fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod
90fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod#define DEFINE_ARRAY_INTERFACE(Type, name) \
9160d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  inline const Type& get_##name (unsigned int i) const { return (*this)[i]; } \
9260d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  inline unsigned int get_##name##_count (void) const { return this->get_len (); }
93fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod#define DEFINE_INDEX_ARRAY_INTERFACE(name) \
9460d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  inline unsigned int get_##name##_index (unsigned int i) const \
9560d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  { \
964a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod    if (HB_UNLIKELY (i >= get_len ())) return NO_INDEX; \
97fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod    return (*this)[i]; \
98fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod  } \
9960d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  inline unsigned int get_##name##_count (void) const { return get_len (); }
100fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod
101fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod
1021f437e6f47fb6c15761021bd2078f31778f2179cBehdad Esfahbod/*
1031f437e6f47fb6c15761021bd2078f31778f2179cBehdad Esfahbod * List types
1041f437e6f47fb6c15761021bd2078f31778f2179cBehdad Esfahbod */
105b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod
10640a81314fa3eb7c701aea47b43f81bfad985f717Behdad Esfahbod#define DEFINE_LIST_INTERFACE(Type, name) \
10760d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  inline const Type& get_##name (unsigned int i) const { return (this+name##List)[i]; } \
10860d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  inline unsigned int get_##name##_count (void) const { return (this+name##List).len; }
10940a81314fa3eb7c701aea47b43f81bfad985f717Behdad Esfahbod
110577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod
11140a81314fa3eb7c701aea47b43f81bfad985f717Behdad Esfahbod/*
11240a81314fa3eb7c701aea47b43f81bfad985f717Behdad Esfahbod * Tag types
11340a81314fa3eb7c701aea47b43f81bfad985f717Behdad Esfahbod */
11440a81314fa3eb7c701aea47b43f81bfad985f717Behdad Esfahbod
11540a81314fa3eb7c701aea47b43f81bfad985f717Behdad Esfahbod#define DEFINE_TAG_ARRAY_INTERFACE(Type, name) \
11640a81314fa3eb7c701aea47b43f81bfad985f717Behdad Esfahbod  DEFINE_ARRAY_INTERFACE (Type, name); \
11760d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  inline const Tag& get_##name##_tag (unsigned int i) const { return (*this)[i].tag; }
11840a81314fa3eb7c701aea47b43f81bfad985f717Behdad Esfahbod#define DEFINE_TAG_LIST_INTERFACE(Type, name) \
11940a81314fa3eb7c701aea47b43f81bfad985f717Behdad Esfahbod  DEFINE_LIST_INTERFACE (Type, name); \
12060d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  inline const Tag& get_##name##_tag (unsigned int i) const { return (this+name##List).get_tag (i); }
12140a81314fa3eb7c701aea47b43f81bfad985f717Behdad Esfahbod
12240a81314fa3eb7c701aea47b43f81bfad985f717Behdad Esfahbod#define DEFINE_TAG_FIND_INTERFACE(Type, name) \
123cc6c644ff2af5f6669b6ec100ff13e904872b21cBehdad Esfahbod  inline bool find_##name##_index (hb_tag_t tag, unsigned int *index) const { \
124706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod    const Tag t = tag; \
12560d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod    for (unsigned int i = 0; i < get_##name##_count (); i++) \
12660d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod    { \
12760d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod      if (t == get_##name##_tag (i)) \
12860d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod      { \
129cc6c644ff2af5f6669b6ec100ff13e904872b21cBehdad Esfahbod        if (index) *index = i; \
130706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod        return true; \
131706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod      } \
132706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod    } \
133cc6c644ff2af5f6669b6ec100ff13e904872b21cBehdad Esfahbod    if (index) *index = NO_INDEX; \
134706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod    return false; \
13540a81314fa3eb7c701aea47b43f81bfad985f717Behdad Esfahbod  } \
13660d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  inline const Type& get_##name##_by_tag (hb_tag_t tag) const \
13760d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  { \
138706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod    unsigned int i; \
139706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod    if (find_##name##_index (tag, &i)) \
140706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod      return get_##name (i); \
14140a81314fa3eb7c701aea47b43f81bfad985f717Behdad Esfahbod    else \
1428b8358033184198ff638ee1379093717596e162dBehdad Esfahbod      return Null(Type); \
1431f437e6f47fb6c15761021bd2078f31778f2179cBehdad Esfahbod  }
144600e5eb80f553ea8eb862e6784133574c74ca513Behdad Esfahbod
145577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod
146577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod
147600e5eb80f553ea8eb862e6784133574c74ca513Behdad Esfahbod/*
148600e5eb80f553ea8eb862e6784133574c74ca513Behdad Esfahbod * Class features
149600e5eb80f553ea8eb862e6784133574c74ca513Behdad Esfahbod */
150600e5eb80f553ea8eb862e6784133574c74ca513Behdad Esfahbod
1518b8358033184198ff638ee1379093717596e162dBehdad Esfahbod
1528b8358033184198ff638ee1379093717596e162dBehdad Esfahbod/* Null objects */
1538b8358033184198ff638ee1379093717596e162dBehdad Esfahbod
1548b8358033184198ff638ee1379093717596e162dBehdad Esfahbod/* Global nul-content Null pool.  Enlarge as necessary. */
1558b8358033184198ff638ee1379093717596e162dBehdad Esfahbodstatic const char NullPool[16] = "";
1568b8358033184198ff638ee1379093717596e162dBehdad Esfahbod
1578b8358033184198ff638ee1379093717596e162dBehdad Esfahbod/* Generic template for nul-content sizeof-sized Null objects. */
1588b8358033184198ff638ee1379093717596e162dBehdad Esfahbodtemplate <typename Type>
15960d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbodstruct Null
16060d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
161f8dc67b3c24dfc805da756a73cb217b36e16b4b8Behdad Esfahbod  ASSERT_STATIC (sizeof (Type) <= sizeof (NullPool));
1624497af0069a94c69fc1518b1db2c1282721b732aBehdad Esfahbod  static inline const Type &get () { return *(const Type*)NullPool; }
1638b8358033184198ff638ee1379093717596e162dBehdad Esfahbod};
1648b8358033184198ff638ee1379093717596e162dBehdad Esfahbod
1658b8358033184198ff638ee1379093717596e162dBehdad Esfahbod/* Specializaiton for arbitrary-content arbitrary-sized Null objects. */
1668b8358033184198ff638ee1379093717596e162dBehdad Esfahbod#define DEFINE_NULL_DATA(Type, size, data) \
167cc6c644ff2af5f6669b6ec100ff13e904872b21cBehdad Esfahbodstatic const char _Null##Type[size] = data; \
1688b8358033184198ff638ee1379093717596e162dBehdad Esfahbodtemplate <> \
16960d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbodstruct Null <Type> \
17060d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{ \
1714497af0069a94c69fc1518b1db2c1282721b732aBehdad Esfahbod  static inline const Type &get () { return *(const Type*)_Null##Type; } \
1728b8358033184198ff638ee1379093717596e162dBehdad Esfahbod}
1738b8358033184198ff638ee1379093717596e162dBehdad Esfahbod
1748b8358033184198ff638ee1379093717596e162dBehdad Esfahbod/* Accessor macro. */
1758b8358033184198ff638ee1379093717596e162dBehdad Esfahbod#define Null(Type) (Null<Type>::get())
1768b8358033184198ff638ee1379093717596e162dBehdad Esfahbod
1778b8358033184198ff638ee1379093717596e162dBehdad Esfahbod
1788b8358033184198ff638ee1379093717596e162dBehdad Esfahbod#define ASSERT_SIZE_DATA(Type, size, data) \
1791f437e6f47fb6c15761021bd2078f31778f2179cBehdad Esfahbod  ASSERT_SIZE (Type, size); \
1801f437e6f47fb6c15761021bd2078f31778f2179cBehdad Esfahbod  DEFINE_NULL_DATA (Type, size, data)
1811f437e6f47fb6c15761021bd2078f31778f2179cBehdad Esfahbod
182600e5eb80f553ea8eb862e6784133574c74ca513Behdad Esfahbod/* get_for_data() is a static class method returning a reference to an
183600e5eb80f553ea8eb862e6784133574c74ca513Behdad Esfahbod * instance of Type located at the input data location.  It's just a
18454e5aac5e2947d4e2864c6f2987e4d275da73100Behdad Esfahbod * fancy, NULL-safe, cast! */
185fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod#define STATIC_DEFINE_GET_FOR_DATA(Type) \
18660d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  static inline const Type& get_for_data (const char *data) \
18760d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  { \
1888b8358033184198ff638ee1379093717596e162dBehdad Esfahbod    if (HB_UNLIKELY (data == NULL)) return Null(Type); \
1894497af0069a94c69fc1518b1db2c1282721b732aBehdad Esfahbod    return *(const Type*)data; \
190212aba6189d7aaac0bab169b77ae6bdab16800a5Behdad Esfahbod  }
191212aba6189d7aaac0bab169b77ae6bdab16800a5Behdad Esfahbod/* Like get_for_data(), but checks major version first. */
192cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod#define STATIC_DEFINE_GET_FOR_DATA_CHECK_MAJOR_VERSION(Type, MajorMin, MajorMax) \
193212aba6189d7aaac0bab169b77ae6bdab16800a5Behdad Esfahbod  static inline const Type& get_for_data (const char *data) \
194212aba6189d7aaac0bab169b77ae6bdab16800a5Behdad Esfahbod  { \
195212aba6189d7aaac0bab169b77ae6bdab16800a5Behdad Esfahbod    if (HB_UNLIKELY (data == NULL)) return Null(Type); \
1964497af0069a94c69fc1518b1db2c1282721b732aBehdad Esfahbod    const Type& t = *(const Type*)data; \
197cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod    if (HB_UNLIKELY (t.version.major < MajorMin || t.version.major > MajorMax)) return Null(Type); \
198212aba6189d7aaac0bab169b77ae6bdab16800a5Behdad Esfahbod    return t; \
199212aba6189d7aaac0bab169b77ae6bdab16800a5Behdad Esfahbod  }
200600e5eb80f553ea8eb862e6784133574c74ca513Behdad Esfahbod
201600e5eb80f553ea8eb862e6784133574c74ca513Behdad Esfahbod
202577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod/*
203577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod * Sanitize
204577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod */
205577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod
2067acb389569cf99c6bae9db31a8ed7c7007fbb566Behdad Esfahbod#if HB_DEBUG >= 5
207b28815c1f6e46d38471cacbc31248ca6fda8c4d1Behdad Esfahbod#define SANITIZE_DEBUG_ARG_DEF	, unsigned int sanitize_depth
208b28815c1f6e46d38471cacbc31248ca6fda8c4d1Behdad Esfahbod#define SANITIZE_DEBUG_ARG	, sanitize_depth + 1
209b28815c1f6e46d38471cacbc31248ca6fda8c4d1Behdad Esfahbod#define SANITIZE_DEBUG_ARG_INIT	, 0
210b28815c1f6e46d38471cacbc31248ca6fda8c4d1Behdad Esfahbod#define SANITIZE_DEBUG() \
211b28815c1f6e46d38471cacbc31248ca6fda8c4d1Behdad Esfahbod	HB_STMT_START { \
2127acb389569cf99c6bae9db31a8ed7c7007fbb566Behdad Esfahbod		fprintf (stderr, "SANITIZE(%p) %-*d-> %s\n", \
2137acb389569cf99c6bae9db31a8ed7c7007fbb566Behdad Esfahbod			 (CONST_CHARP (this) == NullPool) ? 0 : this, \
2147acb389569cf99c6bae9db31a8ed7c7007fbb566Behdad Esfahbod			 sanitize_depth+1, sanitize_depth, \
2157acb389569cf99c6bae9db31a8ed7c7007fbb566Behdad Esfahbod			 __PRETTY_FUNCTION__); \
216b28815c1f6e46d38471cacbc31248ca6fda8c4d1Behdad Esfahbod	} HB_STMT_END
217b28815c1f6e46d38471cacbc31248ca6fda8c4d1Behdad Esfahbod#else
218b28815c1f6e46d38471cacbc31248ca6fda8c4d1Behdad Esfahbod#define SANITIZE_DEBUG_ARG_DEF
219b28815c1f6e46d38471cacbc31248ca6fda8c4d1Behdad Esfahbod#define SANITIZE_DEBUG_ARG
220b28815c1f6e46d38471cacbc31248ca6fda8c4d1Behdad Esfahbod#define SANITIZE_DEBUG_ARG_INIT
221b28815c1f6e46d38471cacbc31248ca6fda8c4d1Behdad Esfahbod#define SANITIZE_DEBUG() HB_STMT_START {} HB_STMT_END
222b28815c1f6e46d38471cacbc31248ca6fda8c4d1Behdad Esfahbod#endif
223b28815c1f6e46d38471cacbc31248ca6fda8c4d1Behdad Esfahbod
224577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbodtypedef struct _hb_sanitize_context_t hb_sanitize_context_t;
225577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbodstruct _hb_sanitize_context_t
226577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod{
227577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod  const char *start, *end;
228577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod  int edit_count;
229577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod  hb_blob_t *blob;
230577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod};
231577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod
232577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbodstatic HB_GNUC_UNUSED void
2334e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod_hb_sanitize_init (hb_sanitize_context_t *context,
2344e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod		   hb_blob_t *blob)
235577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod{
236577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod  context->blob = blob;
237577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod  context->start = hb_blob_lock (blob);
238577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod  context->end = context->start + hb_blob_get_length (blob);
239577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod  context->edit_count = 0;
2404f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod
2414f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod#if HB_DEBUG
2427acb389569cf99c6bae9db31a8ed7c7007fbb566Behdad Esfahbod  fprintf (stderr, "sanitize %p init [%p..%p] (%u bytes)\n",
2437acb389569cf99c6bae9db31a8ed7c7007fbb566Behdad Esfahbod	   context->blob, context->start, context->end, context->start - context->end);
2444f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod#endif
245577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod}
246577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod
247577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbodstatic HB_GNUC_UNUSED void
2484e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod_hb_sanitize_fini (hb_sanitize_context_t *context,
2494e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod		   bool unlock)
250577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod{
2514f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod#if HB_DEBUG
2527acb389569cf99c6bae9db31a8ed7c7007fbb566Behdad Esfahbod  fprintf (stderr, "sanitize %p fini [%p..%p] %u edit requests\n",
2537acb389569cf99c6bae9db31a8ed7c7007fbb566Behdad Esfahbod	   context->blob, context->start, context->end, context->edit_count);
2544f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod#endif
2554f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod
256577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod  if (unlock)
257577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod    hb_blob_unlock (context->blob);
258577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod}
259577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod
2604f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbodstatic HB_GNUC_UNUSED inline bool
2614f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod_hb_sanitize_edit (hb_sanitize_context_t *context,
2624f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod		   const char *base HB_GNUC_UNUSED,
2634f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod		   unsigned int len HB_GNUC_UNUSED)
264577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod{
2654f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod  bool perm = hb_blob_try_writeable_inplace (context->blob);
266f4b58d3fc2956a9d1b6178588d809c781f7a5c0cBehdad Esfahbod  context->edit_count++;
2674f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod
2684f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod#if HB_DEBUG
2697acb389569cf99c6bae9db31a8ed7c7007fbb566Behdad Esfahbod  fprintf (stderr, "sanitize %p edit %u requested for [%p..%p] (%d bytes) in [%p..%p] -> %s\n",
2707acb389569cf99c6bae9db31a8ed7c7007fbb566Behdad Esfahbod	   context->blob,
2714f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod	  context->edit_count,
2724f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod	  base, base+len, len,
2734f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod	  context->start, context->end,
2744f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod	  perm ? "granted" : "rejected");
2754f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod#endif
2764f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod  return perm;
277577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod}
278577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod
279577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod#define SANITIZE_ARG_DEF \
280b28815c1f6e46d38471cacbc31248ca6fda8c4d1Behdad Esfahbod	hb_sanitize_context_t *context SANITIZE_DEBUG_ARG_DEF
281577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod#define SANITIZE_ARG \
282b28815c1f6e46d38471cacbc31248ca6fda8c4d1Behdad Esfahbod	context SANITIZE_DEBUG_ARG
283b28815c1f6e46d38471cacbc31248ca6fda8c4d1Behdad Esfahbod#define SANITIZE_ARG_INIT \
284b28815c1f6e46d38471cacbc31248ca6fda8c4d1Behdad Esfahbod	&context SANITIZE_DEBUG_ARG_INIT
285577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod
286577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod#define SANITIZE(X) HB_LIKELY ((X).sanitize (SANITIZE_ARG))
287577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod#define SANITIZE2(X,Y) (SANITIZE (X) && SANITIZE (Y))
288577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod
289577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod#define SANITIZE_THIS(X) HB_LIKELY ((X).sanitize (SANITIZE_ARG, CONST_CHARP(this)))
290577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod#define SANITIZE_THIS2(X,Y) (SANITIZE_THIS (X) && SANITIZE_THIS (Y))
291577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod#define SANITIZE_THIS3(X,Y,Z) (SANITIZE_THIS (X) && SANITIZE_THIS (Y) && SANITIZE_THIS(Z))
292577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod
293577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod#define SANITIZE_BASE(X,B) HB_LIKELY ((X).sanitize (SANITIZE_ARG, B))
294577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod#define SANITIZE_BASE2(X,Y,B) (SANITIZE_BASE (X,B) && SANITIZE_BASE (Y,B))
295577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod
296577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod#define SANITIZE_SELF() SANITIZE_OBJ (*this)
297577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod#define SANITIZE_OBJ(X) SANITIZE_MEM(&(X), sizeof (X))
298577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod#define SANITIZE_GET_SIZE() SANITIZE_SELF() && SANITIZE_MEM (this, this->get_size ())
299577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod
300577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod#define SANITIZE_MEM(B,L) HB_LIKELY (context->start <= CONST_CHARP(B) && CONST_CHARP(B) + (L) <= context->end) /* XXX overflow */
301577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod
3024f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod#define NEUTER(Var, Val) (SANITIZE_OBJ (Var) && _hb_sanitize_edit (context, CONST_CHARP(&(Var)), sizeof (Var)) && ((Var) = (Val), true))
303577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod
304577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod
3054e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod/* Template to sanitize an object. */
3064e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbodtemplate <typename Type>
3074e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbodstruct Sanitizer
3084e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod{
3094e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod  static hb_blob_t *sanitize (hb_blob_t *blob) {
3104e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod    hb_sanitize_context_t context;
3114e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod    bool sane;
3124e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod
3134e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod    /* XXX is_sane() stuff */
3144e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod
3154e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod  retry:
3164f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod#if HB_DEBUG
3177acb389569cf99c6bae9db31a8ed7c7007fbb566Behdad Esfahbod    fprintf (stderr, "Sanitizer %p start %s\n", blob, __PRETTY_FUNCTION__);
3184f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod#endif
3194f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod
3204e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod    _hb_sanitize_init (&context, blob);
3214e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod
3228cd6fa28d1b77100491519b8dedb2e113508bf59Behdad Esfahbod    Type *t = &CAST (Type, *DECONST_CHARP(context.start), 0);
3234e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod
324b28815c1f6e46d38471cacbc31248ca6fda8c4d1Behdad Esfahbod    sane = t->sanitize (SANITIZE_ARG_INIT);
3254e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod    if (sane) {
3264e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod      if (context.edit_count) {
3270d77ab8a73f57c9fca4c6f9301dae394d79526e3Behdad Esfahbod#if HB_DEBUG
3280d77ab8a73f57c9fca4c6f9301dae394d79526e3Behdad Esfahbod	fprintf (stderr, "Sanitizer %p passed first round with %d edits; going a second round %s\n",
3290d77ab8a73f57c9fca4c6f9301dae394d79526e3Behdad Esfahbod		 blob, context.edit_count, __PRETTY_FUNCTION__);
3300d77ab8a73f57c9fca4c6f9301dae394d79526e3Behdad Esfahbod#endif
3314e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod        /* sanitize again to ensure not toe-stepping */
3324e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod        context.edit_count = 0;
333b28815c1f6e46d38471cacbc31248ca6fda8c4d1Behdad Esfahbod	sane = t->sanitize (SANITIZE_ARG_INIT);
3344e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod	if (context.edit_count) {
3350d77ab8a73f57c9fca4c6f9301dae394d79526e3Behdad Esfahbod#if HB_DEBUG
3360d77ab8a73f57c9fca4c6f9301dae394d79526e3Behdad Esfahbod	  fprintf (stderr, "Sanitizer %p requested %d edits in second round; failing %s\n",
3370d77ab8a73f57c9fca4c6f9301dae394d79526e3Behdad Esfahbod		   blob, context.edit_count, __PRETTY_FUNCTION__);
3380d77ab8a73f57c9fca4c6f9301dae394d79526e3Behdad Esfahbod#endif
3394e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod	  sane = false;
3404e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod	}
3414e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod      }
3424e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod      _hb_sanitize_fini (&context, true);
3434e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod    } else {
3444f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod      unsigned int edit_count = context.edit_count;
3454e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod      _hb_sanitize_fini (&context, true);
3464f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod      if (edit_count && !hb_blob_is_writeable (blob) && hb_blob_try_writeable (blob)) {
3474e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod        /* ok, we made it writeable by relocating.  try again */
3484f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod#if HB_DEBUG
3497acb389569cf99c6bae9db31a8ed7c7007fbb566Behdad Esfahbod	fprintf (stderr, "Sanitizer %p retry %s\n", blob, __PRETTY_FUNCTION__);
3504f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod#endif
3514e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod        goto retry;
3524e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod      }
3534e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod    }
3544e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod
3554f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod#if HB_DEBUG
3567acb389569cf99c6bae9db31a8ed7c7007fbb566Behdad Esfahbod    fprintf (stderr, "Sanitizer %p %s %s\n", blob, sane ? "passed" : "failed", __PRETTY_FUNCTION__);
3574f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod#endif
3584e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod    if (sane)
3594e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod      return blob;
3604e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod    else {
3614e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod      hb_blob_destroy (blob);
3624e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod      return hb_blob_create_empty ();
3634e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod    }
3644e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod  }
3654e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod
366d60bb8ca2ae6edf29b2227b56c57f0d16879370bBehdad Esfahbod  static const Type& lock_instance (hb_blob_t *blob) {
3674e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod    return Type::get_for_data (hb_blob_lock (blob));
3684e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod  }
3694e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod};
3704e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod
3712d15e72c75931398db5e027e660f1320bb979117Behdad Esfahbod
372b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod/*
373b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod *
374b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod * The OpenType Font File
375b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod *
376b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod */
377b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod
378b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod
379b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod/*
380b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod * Data Types
381b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod */
382b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod
383b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod
384b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod/* "The following data types are used in the OpenType font file.
385b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod *  All OpenType fonts use Motorola-style byte ordering (Big Endian):" */
386b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod
3875f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod/*
3885f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod * Int types
3895f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod */
3905f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod
39120cc86b3592db33731de671f008d7d222776be49Behdad Esfahbod/* TODO On machines that do not allow unaligned access, fix the accessors. */
39220cc86b3592db33731de671f008d7d222776be49Behdad Esfahbod#define DEFINE_INT_TYPE1(NAME, TYPE, BIG_ENDIAN, BYTES) \
39360d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  struct NAME \
39460d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  { \
39520cc86b3592db33731de671f008d7d222776be49Behdad Esfahbod    inline NAME& operator = (TYPE i) { (TYPE&) v = BIG_ENDIAN (i); return *this; } \
39620cc86b3592db33731de671f008d7d222776be49Behdad Esfahbod    inline operator TYPE(void) const { return BIG_ENDIAN ((TYPE&) v); } \
39720cc86b3592db33731de671f008d7d222776be49Behdad Esfahbod    inline bool operator== (NAME o) const { return (TYPE&) v == (TYPE&) o.v; } \
398b28815c1f6e46d38471cacbc31248ca6fda8c4d1Behdad Esfahbod    inline bool sanitize (SANITIZE_ARG_DEF) { \
399b28815c1f6e46d38471cacbc31248ca6fda8c4d1Behdad Esfahbod      SANITIZE_DEBUG (); \
400b28815c1f6e46d38471cacbc31248ca6fda8c4d1Behdad Esfahbod      return SANITIZE_SELF (); \
401b28815c1f6e46d38471cacbc31248ca6fda8c4d1Behdad Esfahbod    } \
40220cc86b3592db33731de671f008d7d222776be49Behdad Esfahbod    private: char v[BYTES]; \
4035f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod  }; \
40420cc86b3592db33731de671f008d7d222776be49Behdad Esfahbod  ASSERT_SIZE (NAME, BYTES)
405df66028781a7609a515980e64396e6f1044d764aBehdad Esfahbod#define DEFINE_INT_TYPE0(NAME, type, b)	DEFINE_INT_TYPE1 (NAME, type##_t, hb_be_##type, b)
406df66028781a7609a515980e64396e6f1044d764aBehdad Esfahbod#define DEFINE_INT_TYPE(NAME, u, w)	DEFINE_INT_TYPE0 (NAME, u##int##w, (w / 8))
4075f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod
408b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod
40920cc86b3592db33731de671f008d7d222776be49Behdad EsfahbodDEFINE_INT_TYPE (USHORT,  u, 16);	/* 16-bit unsigned integer. */
41020cc86b3592db33731de671f008d7d222776be49Behdad EsfahbodDEFINE_INT_TYPE (SHORT,	  , 16);	/* 16-bit signed integer. */
41120cc86b3592db33731de671f008d7d222776be49Behdad EsfahbodDEFINE_INT_TYPE (ULONG,	 u, 32);	/* 32-bit unsigned integer. */
41220cc86b3592db33731de671f008d7d222776be49Behdad EsfahbodDEFINE_INT_TYPE (LONG,	  , 32);	/* 32-bit signed integer. */
4136b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod
4146b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod/* Array of four uint8s (length = 32 bits) used to identify a script, language
4156b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod * system, feature, or baseline */
41620cc86b3592db33731de671f008d7d222776be49Behdad Esfahbodstruct Tag : ULONG
41760d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
4184497af0069a94c69fc1518b1db2c1282721b732aBehdad Esfahbod  inline Tag (const Tag &o) { *(ULONG*)this = (ULONG&) o; }
4194497af0069a94c69fc1518b1db2c1282721b732aBehdad Esfahbod  inline Tag (uint32_t i) { *(ULONG*)this = i; }
4204497af0069a94c69fc1518b1db2c1282721b732aBehdad Esfahbod  inline Tag (const char *c) { *(ULONG*)this = *(ULONG*)c; }
4214497af0069a94c69fc1518b1db2c1282721b732aBehdad Esfahbod  inline bool operator== (const char *c) const { return *(ULONG*)this == *(ULONG*)c; }
422befc022affd2386b3f46cd7d11e4262f6c8bce9fBehdad Esfahbod  /* What the char* converters return is NOT nul-terminated.  Print using "%.4s" */
4232b5a59c277f4c5bf7aac9a9005054763e322e02dBehdad Esfahbod  inline operator const char* (void) const { return CONST_CHARP(this); }
4242b5a59c277f4c5bf7aac9a9005054763e322e02dBehdad Esfahbod  inline operator char* (void) { return CHARP(this); }
425738c54d9caa3affc4b434e56bfb810ff6dc9b0b3Behdad Esfahbod
426738c54d9caa3affc4b434e56bfb810ff6dc9b0b3Behdad Esfahbod  inline bool sanitize (SANITIZE_ARG_DEF) {
427b28815c1f6e46d38471cacbc31248ca6fda8c4d1Behdad Esfahbod    SANITIZE_DEBUG ();
428738c54d9caa3affc4b434e56bfb810ff6dc9b0b3Behdad Esfahbod    /* Note: Only accept ASCII-visible tags (mind DEL)
429738c54d9caa3affc4b434e56bfb810ff6dc9b0b3Behdad Esfahbod     * This is one of the few times (only time?) we check
430738c54d9caa3affc4b434e56bfb810ff6dc9b0b3Behdad Esfahbod     * for data integrity, as opposed o just boundary checks
431738c54d9caa3affc4b434e56bfb810ff6dc9b0b3Behdad Esfahbod     */
432738c54d9caa3affc4b434e56bfb810ff6dc9b0b3Behdad Esfahbod    return SANITIZE_SELF () && (((uint32_t) *this) & 0x80808080) == 0;
433738c54d9caa3affc4b434e56bfb810ff6dc9b0b3Behdad Esfahbod  }
4346b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod};
435303fe62824d4e99df554b6bfaacba05d068522fbBehdad EsfahbodASSERT_SIZE (Tag, 4);
436da1097bc3b1995776c205707fd2b17603b804646Behdad Esfahbod#define _NULL_TAG_INIT  {' ', ' ', ' ', ' '}
437da1097bc3b1995776c205707fd2b17603b804646Behdad EsfahbodDEFINE_NULL_DATA (Tag, 4, _NULL_TAG_INIT);
438da1097bc3b1995776c205707fd2b17603b804646Behdad Esfahbod#undef _NULL_TAG_INIT
4396b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod
4406b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod/* Glyph index number, same as uint16 (length = 16 bits) */
4416ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbodtypedef USHORT GlyphID;
4426b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod
4431f437e6f47fb6c15761021bd2078f31778f2179cBehdad Esfahbod/* Offset to a table, same as uint16 (length = 16 bits), Null offset = 0x0000 */
4446ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbodtypedef USHORT Offset;
4456ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbod
4466ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbod/* LongOffset to a table, same as uint32 (length = 32 bits), Null offset = 0x00000000 */
4476ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbodtypedef ULONG LongOffset;
4486ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbod
4496b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod
4506b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod/* CheckSum */
45160d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbodstruct CheckSum : ULONG
45260d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
45360d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  static uint32_t CalcTableChecksum (ULONG *Table, uint32_t Length)
45460d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  {
4556b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod    uint32_t Sum = 0L;
45601e4fcb032be601f272e62228881e2aabfb9d925Behdad Esfahbod    ULONG *EndPtr = Table+((Length+3) & ~3) / sizeof(ULONG);
4576b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod
4586b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod    while (Table < EndPtr)
4596b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod      Sum += *Table++;
4606b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod    return Sum;
4616b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod  }
4626b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod};
4638b8358033184198ff638ee1379093717596e162dBehdad EsfahbodASSERT_SIZE (CheckSum, 4);
4646b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod
4656b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod
4666b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod/*
4676b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod * Version Numbers
4686b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod */
4696b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod
47087fcdcbe3644da10154688765db2d62eb9ac079aBehdad Esfahbodstruct FixedVersion
47160d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
47209c292e3b688a67fbae67b645d1e6ffcf8d8eb6eBehdad Esfahbod  inline operator uint32_t (void) const { return (major << 16) + minor; }
47396908b898476ca5d7da5f386b15be76f9e83d76eBehdad Esfahbod
474cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod  inline bool sanitize (SANITIZE_ARG_DEF) {
475b28815c1f6e46d38471cacbc31248ca6fda8c4d1Behdad Esfahbod    SANITIZE_DEBUG ();
476cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod    return SANITIZE_SELF ();
477cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod  }
478cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod
4796ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbod  USHORT major;
48087fcdcbe3644da10154688765db2d62eb9ac079aBehdad Esfahbod  USHORT minor;
4816b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod};
48287fcdcbe3644da10154688765db2d62eb9ac079aBehdad EsfahbodASSERT_SIZE (FixedVersion, 4);
4836b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod
48492b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod
48592b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod
4865f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod/*
48792b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod * Template subclasses of Offset and LongOffset that do the dereferencing.
48892b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod * Use: (this+memberName)
4895f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod */
4905f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod
49192b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename OffsetType, typename Type>
49292b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct GenericOffsetTo : OffsetType
49392b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod{
49492b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod  inline const Type& operator() (const void *base) const
49592b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod  {
49692b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod    unsigned int offset = *this;
49792b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod    if (HB_UNLIKELY (!offset)) return Null(Type);
49895639fccc1ef18eadeb737e8b611d1d1f1315fc2Behdad Esfahbod    return CONST_CAST(Type, *CONST_CHARP(base), offset);
49992b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod  }
50092b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod
50192b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod  inline bool sanitize (SANITIZE_ARG_DEF, const void *base) {
502b28815c1f6e46d38471cacbc31248ca6fda8c4d1Behdad Esfahbod    SANITIZE_DEBUG ();
50392b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod    if (!SANITIZE_OBJ (*this)) return false;
50492b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod    unsigned int offset = *this;
50592b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod    if (HB_UNLIKELY (!offset)) return true;
506ac26e2a838d1266bb5f39c43245eb2a52c5e072dBehdad Esfahbod    return SANITIZE (CAST(Type, *DECONST_CHARP(base), offset)) || NEUTER (DECONST_CAST(OffsetType,*this,0), 0);
50792b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod  }
508b508e5ccd528f3f0f49f545bd5f30a525d5abd5aBehdad Esfahbod  inline bool sanitize (SANITIZE_ARG_DEF, const void *base, const void *base2) {
509b28815c1f6e46d38471cacbc31248ca6fda8c4d1Behdad Esfahbod    SANITIZE_DEBUG ();
510b508e5ccd528f3f0f49f545bd5f30a525d5abd5aBehdad Esfahbod    if (!SANITIZE_OBJ (*this)) return false;
511b508e5ccd528f3f0f49f545bd5f30a525d5abd5aBehdad Esfahbod    unsigned int offset = *this;
512b508e5ccd528f3f0f49f545bd5f30a525d5abd5aBehdad Esfahbod    if (HB_UNLIKELY (!offset)) return true;
513b508e5ccd528f3f0f49f545bd5f30a525d5abd5aBehdad Esfahbod    return SANITIZE_BASE (CAST(Type, *DECONST_CHARP(base), offset), base2) || NEUTER (DECONST_CAST(OffsetType,*this,0), 0);
514b508e5ccd528f3f0f49f545bd5f30a525d5abd5aBehdad Esfahbod  }
51542b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod  inline bool sanitize (SANITIZE_ARG_DEF, const void *base, unsigned int user_data) {
516b28815c1f6e46d38471cacbc31248ca6fda8c4d1Behdad Esfahbod    SANITIZE_DEBUG ();
51742b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod    if (!SANITIZE_OBJ (*this)) return false;
51842b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod    unsigned int offset = *this;
51942b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod    if (HB_UNLIKELY (!offset)) return true;
520ac26e2a838d1266bb5f39c43245eb2a52c5e072dBehdad Esfahbod    return SANITIZE_BASE (CAST(Type, *DECONST_CHARP(base), offset), user_data) || NEUTER (DECONST_CAST(OffsetType,*this,0), 0);
52142b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod  }
52292b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod};
52392b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Base, typename OffsetType, typename Type>
52492b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodinline const Type& operator + (const Base &base, GenericOffsetTo<OffsetType, Type> offset) { return offset (base); }
52592b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod
5265f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbodtemplate <typename Type>
52792b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct OffsetTo : GenericOffsetTo<Offset, Type> {};
52892b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod
52992b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Type>
53092b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct LongOffsetTo : GenericOffsetTo<LongOffset, Type> {};
53192b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod/*
53292b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod * Array Types
53392b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod */
53492b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod
53592b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename LenType, typename Type>
53692b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct GenericArrayOf
53760d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
53860d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  inline const Type& operator [] (unsigned int i) const
53960d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  {
5405f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod    if (HB_UNLIKELY (i >= len)) return Null(Type);
5415f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod    return array[i];
5425f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod  }
54360d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  inline unsigned int get_size () const
54479420ad9caf2d5fc94c3693e8292edfa27060b2dBehdad Esfahbod  { return sizeof (len) + len * sizeof (array[0]); }
545e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod
54670de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod  inline bool sanitize (SANITIZE_ARG_DEF) {
547b28815c1f6e46d38471cacbc31248ca6fda8c4d1Behdad Esfahbod    SANITIZE_DEBUG ();
548dc9c4d93cd0f3ac991f32df08c1c17fc389054c0Behdad Esfahbod    if (!SANITIZE_GET_SIZE()) return false;
549a97ce570ab693190350886e4e80942851c4d5727Behdad Esfahbod    /* Note; for non-recursive types, this is not much needed
55070de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod    unsigned int count = len;
55170de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod    for (unsigned int i = 0; i < count; i++)
55270de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod      if (!SANITIZE (array[i]))
55370de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod        return false;
554a97ce570ab693190350886e4e80942851c4d5727Behdad Esfahbod    */
5559bd629ccd064e739789e504c41ad875eed93abbaBehdad Esfahbod    return true;
55670de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod  }
5572b5a59c277f4c5bf7aac9a9005054763e322e02dBehdad Esfahbod  inline bool sanitize (SANITIZE_ARG_DEF, const void *base) {
558b28815c1f6e46d38471cacbc31248ca6fda8c4d1Behdad Esfahbod    SANITIZE_DEBUG ();
559dc9c4d93cd0f3ac991f32df08c1c17fc389054c0Behdad Esfahbod    if (!SANITIZE_GET_SIZE()) return false;
560e6ab2c59ba2d37942ac5fcbfe61d38b7e359ac8cBehdad Esfahbod    unsigned int count = len;
561e6ab2c59ba2d37942ac5fcbfe61d38b7e359ac8cBehdad Esfahbod    for (unsigned int i = 0; i < count; i++)
56295639fccc1ef18eadeb737e8b611d1d1f1315fc2Behdad Esfahbod      if (!array[i].sanitize (SANITIZE_ARG, base))
563e6ab2c59ba2d37942ac5fcbfe61d38b7e359ac8cBehdad Esfahbod        return false;
5649bd629ccd064e739789e504c41ad875eed93abbaBehdad Esfahbod    return true;
565e6ab2c59ba2d37942ac5fcbfe61d38b7e359ac8cBehdad Esfahbod  }
566b508e5ccd528f3f0f49f545bd5f30a525d5abd5aBehdad Esfahbod  inline bool sanitize (SANITIZE_ARG_DEF, const void *base, const void *base2) {
567b28815c1f6e46d38471cacbc31248ca6fda8c4d1Behdad Esfahbod    SANITIZE_DEBUG ();
568b508e5ccd528f3f0f49f545bd5f30a525d5abd5aBehdad Esfahbod    if (!SANITIZE_GET_SIZE()) return false;
569b508e5ccd528f3f0f49f545bd5f30a525d5abd5aBehdad Esfahbod    unsigned int count = len;
570b508e5ccd528f3f0f49f545bd5f30a525d5abd5aBehdad Esfahbod    for (unsigned int i = 0; i < count; i++)
571b508e5ccd528f3f0f49f545bd5f30a525d5abd5aBehdad Esfahbod      if (!array[i].sanitize (SANITIZE_ARG, base, base2))
572b508e5ccd528f3f0f49f545bd5f30a525d5abd5aBehdad Esfahbod        return false;
5739bd629ccd064e739789e504c41ad875eed93abbaBehdad Esfahbod    return true;
574b508e5ccd528f3f0f49f545bd5f30a525d5abd5aBehdad Esfahbod  }
57542b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod  inline bool sanitize (SANITIZE_ARG_DEF, const void *base, unsigned int user_data) {
576b28815c1f6e46d38471cacbc31248ca6fda8c4d1Behdad Esfahbod    SANITIZE_DEBUG ();
57742b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod    if (!SANITIZE_GET_SIZE()) return false;
57842b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod    unsigned int count = len;
57942b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod    for (unsigned int i = 0; i < count; i++)
58042b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod      if (!array[i].sanitize (SANITIZE_ARG, base, user_data))
58142b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod        return false;
5829bd629ccd064e739789e504c41ad875eed93abbaBehdad Esfahbod    return true;
58342b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod  }
58470de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod
58592b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod  LenType len;
586e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod  Type array[];
587e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod};
588e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod
58992b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod/* An array with a USHORT number of elements. */
59092b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Type>
59192b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct ArrayOf : GenericArrayOf<USHORT, Type> {};
59292b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod
59392b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod/* An array with a ULONG number of elements. */
59492b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Type>
59592b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct LongArrayOf : GenericArrayOf<ULONG, Type> {};
59692b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod
59792b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod/* Array of Offset's */
59892b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Type>
59992b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct OffsetArrayOf : ArrayOf<OffsetTo<Type> > {};
60092b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod
60192b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod/* Array of LongOffset's */
60292b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Type>
60392b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct LongOffsetArrayOf : ArrayOf<LongOffsetTo<Type> > {};
60492b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod
60592b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod/* LongArray of LongOffset's */
60692b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Type>
60792b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct LongOffsetLongArrayOf : LongArrayOf<LongOffsetTo<Type> > {};
60892b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod
609e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod/* An array with a USHORT number of elements,
610e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod * starting at second element. */
611e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbodtemplate <typename Type>
61260d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbodstruct HeadlessArrayOf
61360d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
61460d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  inline const Type& operator [] (unsigned int i) const
61560d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  {
616e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod    if (HB_UNLIKELY (i >= len || !i)) return Null(Type);
617e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod    return array[i-1];
618e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod  }
61960d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  inline unsigned int get_size () const
62079420ad9caf2d5fc94c3693e8292edfa27060b2dBehdad Esfahbod  { return sizeof (len) + (len ? len - 1 : 0) * sizeof (array[0]); }
6215f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod
62270de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod  inline bool sanitize (SANITIZE_ARG_DEF) {
623b28815c1f6e46d38471cacbc31248ca6fda8c4d1Behdad Esfahbod    SANITIZE_DEBUG ();
624dc9c4d93cd0f3ac991f32df08c1c17fc389054c0Behdad Esfahbod    if (!SANITIZE_GET_SIZE()) return false;
625a97ce570ab693190350886e4e80942851c4d5727Behdad Esfahbod    /* Note; for non-recursive types, this is not much needed
62615164d9258a74122a4db748d35532bd72c47cec2Behdad Esfahbod    unsigned int count = len ? len - 1 : 0;
62770de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod    for (unsigned int i = 0; i < count; i++)
62870de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod      if (!SANITIZE (array[i]))
62970de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod        return false;
630a97ce570ab693190350886e4e80942851c4d5727Behdad Esfahbod    */
6319bd629ccd064e739789e504c41ad875eed93abbaBehdad Esfahbod    return true;
63270de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod  }
63370de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod
6345f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod  USHORT len;
6355f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod  Type array[];
6365f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod};
6375f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod
6386b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod
6395f5b24f99f52bbc922e238b65c06061ba07c8548Behdad Esfahbod#endif /* HB_OPEN_TYPES_PRIVATE_HH */
640