hb-open-type-private.hh revision f679635893eebc13402c5ee51a6f106eed0c76be
164aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod/*
2f9b37727985191c9b4aedb0e9835736027e59260Behdad Esfahbod * Copyright (C) 2007,2008,2009,2010  Red Hat, Inc.
364aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod *
4c755cb3e3ac55156d0d2ec05adea7a650b97cc41Behdad Esfahbod *  This is part of HarfBuzz, a text shaping 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
35a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbod
36196598bbccff08415ff5192314cba044df258cadBehdad Esfahbod/*
37196598bbccff08415ff5192314cba044df258cadBehdad Esfahbod * Casts
38196598bbccff08415ff5192314cba044df258cadBehdad Esfahbod */
39196598bbccff08415ff5192314cba044df258cadBehdad Esfahbod
40187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbod/* Cast to struct T, reference to reference */
41a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbodtemplate<typename Type, typename TObject>
42187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbodinline const Type& CastR(const TObject &X)
43a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbod{ return reinterpret_cast<const Type&> (X); }
44a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbodtemplate<typename Type, typename TObject>
45187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbodinline Type& CastR(TObject &X)
46a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbod{ return reinterpret_cast<Type&> (X); }
47196598bbccff08415ff5192314cba044df258cadBehdad Esfahbod
48187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbod/* Cast to struct T, pointer to pointer */
49187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbodtemplate<typename Type, typename TObject>
50187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbodinline const Type* CastP(const TObject *X)
51187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbod{ return reinterpret_cast<const Type*> (X); }
52187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbodtemplate<typename Type, typename TObject>
53187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbodinline Type* CastP(TObject *X)
54187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbod{ return reinterpret_cast<Type*> (X); }
55187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbod
5609766b1ec5ec55a61edbcd7a89ed3613cc92d4cbBehdad Esfahbod/* StructAtOffset<T>(P,Ofs) returns the struct T& that is placed at memory
5709766b1ec5ec55a61edbcd7a89ed3613cc92d4cbBehdad Esfahbod * location pointed to by P plus Ofs bytes. */
5809766b1ec5ec55a61edbcd7a89ed3613cc92d4cbBehdad Esfahbodtemplate<typename Type>
5909766b1ec5ec55a61edbcd7a89ed3613cc92d4cbBehdad Esfahbodinline const Type& StructAtOffset(const void *P, unsigned int offset)
60a82ef7a893b773a17f7548375de9f588dfc83abaBehdad Esfahbod{ return * reinterpret_cast<const Type*> ((const char *) P + offset); }
6109766b1ec5ec55a61edbcd7a89ed3613cc92d4cbBehdad Esfahbodtemplate<typename Type>
6209766b1ec5ec55a61edbcd7a89ed3613cc92d4cbBehdad Esfahbodinline Type& StructAtOffset(void *P, unsigned int offset)
63a82ef7a893b773a17f7548375de9f588dfc83abaBehdad Esfahbod{ return * reinterpret_cast<Type*> ((char *) P + offset); }
6470de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod
652e2f43edf2f49f4047e28b1ce2ea95938536de9cBehdad Esfahbod/* StructAfter<T>(X) returns the struct T& that is placed after X.
6629c3f5e1b6212c775a7b911becd44ba093b7b0ebBehdad Esfahbod * Works with X of variable size also.  X must implement get_size() */
67e961c86c579fd98ee604342a9c70c4e7f8d4f220Behdad Esfahbodtemplate<typename Type, typename TObject>
68e961c86c579fd98ee604342a9c70c4e7f8d4f220Behdad Esfahbodinline const Type& StructAfter(const TObject &X)
6909766b1ec5ec55a61edbcd7a89ed3613cc92d4cbBehdad Esfahbod{ return StructAtOffset<Type>(&X, X.get_size()); }
70e961c86c579fd98ee604342a9c70c4e7f8d4f220Behdad Esfahbodtemplate<typename Type, typename TObject>
71e961c86c579fd98ee604342a9c70c4e7f8d4f220Behdad Esfahbodinline Type& StructAfter(TObject &X)
7209766b1ec5ec55a61edbcd7a89ed3613cc92d4cbBehdad Esfahbod{ return StructAtOffset<Type>(&X, X.get_size()); }
73a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbod
74e961c86c579fd98ee604342a9c70c4e7f8d4f220Behdad Esfahbod
75d3480ba37fbb5d4be75b094060f5b2f1ce98fb53Behdad Esfahbod
7670de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod/*
77e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod * Size checking
78e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod */
79e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod
80f679635893eebc13402c5ee51a6f106eed0c76beBehdad Esfahbod/* Check _assertion in a method environment */
81596e471aa5053d955fb5d5b5923088c8814469b1Behdad Esfahbod#define _DEFINE_SIZE_ASSERTION(_assertion) \
8233afa4e2dc352f08cc094703e3f01d3ecd83b354Behdad Esfahbod  inline void _size_assertion (void) const \
83596e471aa5053d955fb5d5b5923088c8814469b1Behdad Esfahbod  { ASSERT_STATIC (_assertion); }
84f679635893eebc13402c5ee51a6f106eed0c76beBehdad Esfahbod/* Check that _code compiles in a method environment */
85f679635893eebc13402c5ee51a6f106eed0c76beBehdad Esfahbod#define _DEFINE_COMPILES_ASSERTION(_code) \
86f679635893eebc13402c5ee51a6f106eed0c76beBehdad Esfahbod  inline void _compiles_assertion (void) const \
87f679635893eebc13402c5ee51a6f106eed0c76beBehdad Esfahbod  { _code; }
880abcc3b48cfd51a22695c9e988938b2f45cb19d8Behdad Esfahbod
890abcc3b48cfd51a22695c9e988938b2f45cb19d8Behdad Esfahbod
90e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod#define DEFINE_SIZE_STATIC(size) \
91596e471aa5053d955fb5d5b5923088c8814469b1Behdad Esfahbod  _DEFINE_SIZE_ASSERTION (sizeof (*this) == (size)); \
92e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod  static const unsigned int static_size = (size); \
93e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod  static const unsigned int min_size = (size)
94e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod
95b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod/* Size signifying variable-sized array */
96b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod#define VAR 1
97b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod
98596e471aa5053d955fb5d5b5923088c8814469b1Behdad Esfahbod#define DEFINE_SIZE_UNION(size, _member) \
99596e471aa5053d955fb5d5b5923088c8814469b1Behdad Esfahbod  _DEFINE_SIZE_ASSERTION (this->u._member.static_size == (size)); \
100596e471aa5053d955fb5d5b5923088c8814469b1Behdad Esfahbod  static const unsigned int min_size = (size)
101596e471aa5053d955fb5d5b5923088c8814469b1Behdad Esfahbod
102bea34c7cbb583cf7660776e95cab3171590b8427Behdad Esfahbod#define DEFINE_SIZE_MIN(size) \
103596e471aa5053d955fb5d5b5923088c8814469b1Behdad Esfahbod  _DEFINE_SIZE_ASSERTION (sizeof (*this) >= (size)); \
104b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod  static const unsigned int min_size = (size)
105b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod
1060eb9fc6e37935707dba2bf4b3705de2161a08cb7Behdad Esfahbod#define DEFINE_SIZE_ARRAY(size, array) \
107f679635893eebc13402c5ee51a6f106eed0c76beBehdad Esfahbod  _DEFINE_SIZE_ASSERTION (sizeof (*this) == (size) + sizeof (array[0])); \
108f679635893eebc13402c5ee51a6f106eed0c76beBehdad Esfahbod  _DEFINE_COMPILES_ASSERTION ((void) array[0].static_size) \
109e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod  static const unsigned int min_size = (size)
110e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod
1110eb9fc6e37935707dba2bf4b3705de2161a08cb7Behdad Esfahbod#define DEFINE_SIZE_ARRAY2(size, array1, array2) \
112f679635893eebc13402c5ee51a6f106eed0c76beBehdad Esfahbod  _DEFINE_SIZE_ASSERTION (sizeof (*this) == (size) + sizeof (this->array1[0]) + sizeof (this->array2[0])); \
113f679635893eebc13402c5ee51a6f106eed0c76beBehdad Esfahbod  _DEFINE_COMPILES_ASSERTION ((void) array1[0].static_size; (void) array2[0].static_size) \
114e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod  static const unsigned int min_size = (size)
115e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod
116e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod
117e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod
118e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod/*
119f0abcd69408a3af65207cdf8847575ade4579bd4Behdad Esfahbod * Null objects
120600e5eb80f553ea8eb862e6784133574c74ca513Behdad Esfahbod */
121600e5eb80f553ea8eb862e6784133574c74ca513Behdad Esfahbod
1228b8358033184198ff638ee1379093717596e162dBehdad Esfahbod/* Global nul-content Null pool.  Enlarge as necessary. */
123f7adc5e9be352ac31ad3ab847abb6fceb239aa12Behdad Esfahbodstatic const void *_NullPool[16 / sizeof (void *)];
1248b8358033184198ff638ee1379093717596e162dBehdad Esfahbod
125d2c2ca8faf62fc380d4717d286556139a62d2356Behdad Esfahbod/* Generic nul-content Null objects. */
1268b8358033184198ff638ee1379093717596e162dBehdad Esfahbodtemplate <typename Type>
1279d3677899f90abdc7fb3e3d854db654a8707a84bBehdad Esfahbodstatic inline const Type& Null () {
128ed07422c33bbb52ff4d79e65986171e3f07697d8Behdad Esfahbod  ASSERT_STATIC (Type::min_size <= sizeof (_NullPool));
129187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbod  return *CastP<Type> (_NullPool);
1309d3677899f90abdc7fb3e3d854db654a8707a84bBehdad Esfahbod}
1318b8358033184198ff638ee1379093717596e162dBehdad Esfahbod
1328b8358033184198ff638ee1379093717596e162dBehdad Esfahbod/* Specializaiton for arbitrary-content arbitrary-sized Null objects. */
13365f46b00333e20ab8a52a4b350747507541ec1dbBehdad Esfahbod#define DEFINE_NULL_DATA(Type, data) \
13465f46b00333e20ab8a52a4b350747507541ec1dbBehdad Esfahbodstatic const char _Null##Type[Type::min_size + 1] = data; /* +1 is for nul-termination in data */ \
1358b8358033184198ff638ee1379093717596e162dBehdad Esfahbodtemplate <> \
1369d3677899f90abdc7fb3e3d854db654a8707a84bBehdad Esfahbodinline const Type& Null<Type> () { \
137187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbod  return *CastP<Type> (_Null##Type); \
138565c80bd2960366ace2d10dd71beaaf2a80213c8Behdad Esfahbod} /* The following line really exists such that we end in a place needing semicolon */ \
139bea34c7cbb583cf7660776e95cab3171590b8427Behdad EsfahbodASSERT_STATIC (Type::min_size + 1 <= sizeof (_Null##Type))
1408b8358033184198ff638ee1379093717596e162dBehdad Esfahbod
1418b8358033184198ff638ee1379093717596e162dBehdad Esfahbod/* Accessor macro. */
1429d3677899f90abdc7fb3e3d854db654a8707a84bBehdad Esfahbod#define Null(Type) Null<Type>()
1438b8358033184198ff638ee1379093717596e162dBehdad Esfahbod
1448b8358033184198ff638ee1379093717596e162dBehdad Esfahbod
14520e3dd5d292b65f70d2eae63b8d8713a1c889d47Behdad Esfahbod/*
146dfc8cbe85479dde1ffdc6b2e73f4907331d77a19Behdad Esfahbod * Trace
14720e3dd5d292b65f70d2eae63b8d8713a1c889d47Behdad Esfahbod */
14820e3dd5d292b65f70d2eae63b8d8713a1c889d47Behdad Esfahbod
149dfc8cbe85479dde1ffdc6b2e73f4907331d77a19Behdad Esfahbod
150dfc8cbe85479dde1ffdc6b2e73f4907331d77a19Behdad Esfahbodtemplate <int max_depth>
151dfc8cbe85479dde1ffdc6b2e73f4907331d77a19Behdad Esfahbodstruct hb_trace_t {
152458ecbb60bb7e8e32aca62a562586d921d5396aaBehdad Esfahbod  explicit hb_trace_t (unsigned int *pdepth, const char *what, const char *function, const void *obj) : pdepth(pdepth) {
153dfc8cbe85479dde1ffdc6b2e73f4907331d77a19Behdad Esfahbod    if (*pdepth < max_depth)
154dfc8cbe85479dde1ffdc6b2e73f4907331d77a19Behdad Esfahbod      fprintf (stderr, "%s(%p) %-*d-> %s\n", what, obj, *pdepth, *pdepth, function);
155458ecbb60bb7e8e32aca62a562586d921d5396aaBehdad Esfahbod    if (max_depth) ++*pdepth;
156dfc8cbe85479dde1ffdc6b2e73f4907331d77a19Behdad Esfahbod  }
157458ecbb60bb7e8e32aca62a562586d921d5396aaBehdad Esfahbod  ~hb_trace_t (void) { if (max_depth) --*pdepth; }
15820e3dd5d292b65f70d2eae63b8d8713a1c889d47Behdad Esfahbod
15920e3dd5d292b65f70d2eae63b8d8713a1c889d47Behdad Esfahbod  private:
160dfc8cbe85479dde1ffdc6b2e73f4907331d77a19Behdad Esfahbod  unsigned int *pdepth;
16120e3dd5d292b65f70d2eae63b8d8713a1c889d47Behdad Esfahbod};
162dfc8cbe85479dde1ffdc6b2e73f4907331d77a19Behdad Esfahbodtemplate <> /* Optimize when tracing is disabled */
163dfc8cbe85479dde1ffdc6b2e73f4907331d77a19Behdad Esfahbodstruct hb_trace_t<0> {
16475651b20871047d3ec17f4221794b8ef5d60e14bBehdad Esfahbod  explicit hb_trace_t (unsigned int *pdepth HB_UNUSED, const char *what HB_UNUSED, const char *function HB_UNUSED, const void *obj HB_UNUSED) {}
16520e3dd5d292b65f70d2eae63b8d8713a1c889d47Behdad Esfahbod};
16620e3dd5d292b65f70d2eae63b8d8713a1c889d47Behdad Esfahbod
16720e3dd5d292b65f70d2eae63b8d8713a1c889d47Behdad Esfahbod
168600e5eb80f553ea8eb862e6784133574c74ca513Behdad Esfahbod
169577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod/*
170577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod * Sanitize
171577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod */
172577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod
17395e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod#ifndef HB_DEBUG_SANITIZE
174807c5b03a2251a3c29a520852639421783101b55Behdad Esfahbod#define HB_DEBUG_SANITIZE HB_DEBUG+0
17595e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod#endif
17695e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod
17720e3dd5d292b65f70d2eae63b8d8713a1c889d47Behdad Esfahbod
178bc200457430c083914a64bf4b056153506749610Behdad Esfahbod#define TRACE_SANITIZE() \
179458ecbb60bb7e8e32aca62a562586d921d5396aaBehdad Esfahbod	hb_trace_t<HB_DEBUG_SANITIZE> trace (&context->debug_depth, "SANITIZE", HB_FUNC, this); \
180807c5b03a2251a3c29a520852639421783101b55Behdad Esfahbod
181b28815c1f6e46d38471cacbc31248ca6fda8c4d1Behdad Esfahbod
1821376fb7bf9ef07970f0ba13dc64d6a8ab8252762Behdad Esfahbodstruct hb_sanitize_context_t
183577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod{
18498daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod  inline void init (hb_blob_t *blob)
18598daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod  {
18698daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod    this->blob = hb_blob_reference (blob);
18798daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod    this->start = hb_blob_lock (blob);
18898daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod    this->end = this->start + hb_blob_get_length (blob);
18998daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod    this->writable = hb_blob_is_writable (blob);
19098daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod    this->edit_count = 0;
19120e3dd5d292b65f70d2eae63b8d8713a1c889d47Behdad Esfahbod    this->debug_depth = 0;
192577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod
19398daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod    if (HB_DEBUG_SANITIZE)
19498daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod      fprintf (stderr, "sanitize %p init [%p..%p] (%u bytes)\n",
19598daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod	       this->blob, this->start, this->end, this->end - this->start);
19698daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod  }
1971376fb7bf9ef07970f0ba13dc64d6a8ab8252762Behdad Esfahbod
19898daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod  inline void finish (void)
19998daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod  {
20098daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod    if (HB_DEBUG_SANITIZE)
20198daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod      fprintf (stderr, "sanitize %p fini [%p..%p] %u edit requests\n",
20298daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod	       this->blob, this->start, this->end, this->edit_count);
203577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod
20498daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod    hb_blob_unlock (this->blob);
20598daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod    hb_blob_destroy (this->blob);
20698daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod    this->blob = NULL;
20798daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod    this->start = this->end = NULL;
20898daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod  }
2094f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod
2104ad2cc5dec6b0639da2b1846282bdd99d06d5ff1Behdad Esfahbod  inline bool check_range (const void *base, unsigned int len) const
21198daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod  {
212a82ef7a893b773a17f7548375de9f588dfc83abaBehdad Esfahbod    const char *p = (const char *) base;
213a82ef7a893b773a17f7548375de9f588dfc83abaBehdad Esfahbod    bool ret = this->start <= p &&
214a82ef7a893b773a17f7548375de9f588dfc83abaBehdad Esfahbod	       p <= this->end &&
215a82ef7a893b773a17f7548375de9f588dfc83abaBehdad Esfahbod	       (unsigned int) (this->end - p) >= len;
21698daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod
21720e3dd5d292b65f70d2eae63b8d8713a1c889d47Behdad Esfahbod    if (HB_DEBUG_SANITIZE && (int) this->debug_depth < (int) HB_DEBUG_SANITIZE) \
2184ad2cc5dec6b0639da2b1846282bdd99d06d5ff1Behdad Esfahbod      fprintf (stderr, "SANITIZE(%p) %-*d-> range [%p..%p] (%d bytes) in [%p..%p] -> %s\n", \
219a82ef7a893b773a17f7548375de9f588dfc83abaBehdad Esfahbod	       p,
22020e3dd5d292b65f70d2eae63b8d8713a1c889d47Behdad Esfahbod	       this->debug_depth, this->debug_depth,
221a82ef7a893b773a17f7548375de9f588dfc83abaBehdad Esfahbod	       p, p + len, len,
22298daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod	       this->start, this->end,
22398daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod	       ret ? "pass" : "FAIL");
22498daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod
22527e302dc8e794ff6bf878bc76e17d336d510849eBehdad Esfahbod    return likely (ret);
22698daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod  }
227577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod
2281cd1e117d060d38e314618b627d7663cb01ed584Behdad Esfahbod  inline bool check_array (const void *base, unsigned int record_size, unsigned int len) const
22998daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod  {
230a82ef7a893b773a17f7548375de9f588dfc83abaBehdad Esfahbod    const char *p = (const char *) base;
23198daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod    bool overflows = len >= ((unsigned int) -1) / record_size;
23241895506cb6a41b1a833866f8822261ea449ea0bBehdad Esfahbod
23320e3dd5d292b65f70d2eae63b8d8713a1c889d47Behdad Esfahbod    if (HB_DEBUG_SANITIZE && (int) this->debug_depth < (int) HB_DEBUG_SANITIZE)
23498daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod      fprintf (stderr, "SANITIZE(%p) %-*d-> array [%p..%p] (%d*%d=%ld bytes) in [%p..%p] -> %s\n", \
235a82ef7a893b773a17f7548375de9f588dfc83abaBehdad Esfahbod	       p,
23620e3dd5d292b65f70d2eae63b8d8713a1c889d47Behdad Esfahbod	       this->debug_depth, this->debug_depth,
237a82ef7a893b773a17f7548375de9f588dfc83abaBehdad Esfahbod	       p, p + (record_size * len), record_size, len, (unsigned long) record_size * len,
23898daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod	       this->start, this->end,
23998daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod	       !overflows ? "does not overflow" : "OVERFLOWS FAIL");
240fa030175ca998b00cc42cbced6e98de323ec01ecBehdad Esfahbod
2414ad2cc5dec6b0639da2b1846282bdd99d06d5ff1Behdad Esfahbod    return likely (!overflows && this->check_range (base, record_size * len));
24298daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod  }
243254933c397f1ce9796f59689a25f9fc2e58df4eaBehdad Esfahbod
244b157617644d1e38f680163889d1dc2e2f64d9ba3Behdad Esfahbod  template <typename Type>
245b157617644d1e38f680163889d1dc2e2f64d9ba3Behdad Esfahbod  inline bool check_struct (const Type *obj) const
246b157617644d1e38f680163889d1dc2e2f64d9ba3Behdad Esfahbod  {
24754842374c2b291ef208c51ae1d853ec0403ccf84Behdad Esfahbod    return likely (this->check_range (obj, obj->min_size));
248b157617644d1e38f680163889d1dc2e2f64d9ba3Behdad Esfahbod  }
249b157617644d1e38f680163889d1dc2e2f64d9ba3Behdad Esfahbod
25040cbefe858192531ed64dd51d402f7ca7b8153a3Behdad Esfahbod  inline bool can_edit (const void *base HB_UNUSED, unsigned int len HB_UNUSED)
25198daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod  {
252a82ef7a893b773a17f7548375de9f588dfc83abaBehdad Esfahbod    const char *p = (const char *) base;
25398daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod    this->edit_count++;
25498daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod
25520e3dd5d292b65f70d2eae63b8d8713a1c889d47Behdad Esfahbod    if (HB_DEBUG_SANITIZE && (int) this->debug_depth < (int) HB_DEBUG_SANITIZE)
25698daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod      fprintf (stderr, "SANITIZE(%p) %-*d-> edit(%u) [%p..%p] (%d bytes) in [%p..%p] -> %s\n", \
257a82ef7a893b773a17f7548375de9f588dfc83abaBehdad Esfahbod	       p,
25820e3dd5d292b65f70d2eae63b8d8713a1c889d47Behdad Esfahbod	       this->debug_depth, this->debug_depth,
25998daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod	       this->edit_count,
260a82ef7a893b773a17f7548375de9f588dfc83abaBehdad Esfahbod	       p, p + len, len,
26198daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod	       this->start, this->end,
26298daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod	       this->writable ? "granted" : "REJECTED");
26398daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod
26498daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod    return this->writable;
26598daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod  }
26698daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod
267705e215268aa95c2bc6af8af9b48b72b690ec1f7Behdad Esfahbod  unsigned int debug_depth;
26898daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod  const char *start, *end;
26998daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod  bool writable;
27098daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod  unsigned int edit_count;
27198daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod  hb_blob_t *blob;
27298daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod};
273815a73e4202ca17677f12e862b70ca8724cf2f57Behdad Esfahbod
274577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod
275577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod
2764e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod/* Template to sanitize an object. */
2774e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbodtemplate <typename Type>
2784e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbodstruct Sanitizer
2794e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod{
2804e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod  static hb_blob_t *sanitize (hb_blob_t *blob) {
281705e215268aa95c2bc6af8af9b48b72b690ec1f7Behdad Esfahbod    hb_sanitize_context_t context[1] = {{0}};
2824e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod    bool sane;
2834e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod
284d0b657379bbe63602953412d6bc944b2a0f430ebBehdad Esfahbod    /* TODO is_sane() stuff */
2854e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod
2864e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod  retry:
287fa030175ca998b00cc42cbced6e98de323ec01ecBehdad Esfahbod    if (HB_DEBUG_SANITIZE)
2887d3a126334f8e6f6441561c1bb592bd3fa7a2c5cBehdad Esfahbod      fprintf (stderr, "Sanitizer %p start %s\n", blob, HB_FUNC);
2894f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod
29098daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod    context->init (blob);
2914e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod
29248146e5612f6d272d6962f6829c6d64a31edef89Behdad Esfahbod    if (unlikely (!context->start)) {
29348146e5612f6d272d6962f6829c6d64a31edef89Behdad Esfahbod      context->finish ();
29448146e5612f6d272d6962f6829c6d64a31edef89Behdad Esfahbod      return blob;
29548146e5612f6d272d6962f6829c6d64a31edef89Behdad Esfahbod    }
29648146e5612f6d272d6962f6829c6d64a31edef89Behdad Esfahbod
29727e302dc8e794ff6bf878bc76e17d336d510849eBehdad Esfahbod    Type *t = CastP<Type> (const_cast<char *> (context->start));
2984e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod
29939840474afd2cda9ff576c08aff9c87095496c27Behdad Esfahbod    sane = t->sanitize (context);
3004e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod    if (sane) {
30127e302dc8e794ff6bf878bc76e17d336d510849eBehdad Esfahbod      if (context->edit_count) {
302fa030175ca998b00cc42cbced6e98de323ec01ecBehdad Esfahbod	if (HB_DEBUG_SANITIZE)
303fa030175ca998b00cc42cbced6e98de323ec01ecBehdad Esfahbod	  fprintf (stderr, "Sanitizer %p passed first round with %d edits; doing a second round %s\n",
30427e302dc8e794ff6bf878bc76e17d336d510849eBehdad Esfahbod		   blob, context->edit_count, HB_FUNC);
305fa030175ca998b00cc42cbced6e98de323ec01ecBehdad Esfahbod
3068b5346130425c7c101f6ff2432874ba2fd372edcBehdad Esfahbod        /* sanitize again to ensure no toe-stepping */
30727e302dc8e794ff6bf878bc76e17d336d510849eBehdad Esfahbod        context->edit_count = 0;
30839840474afd2cda9ff576c08aff9c87095496c27Behdad Esfahbod	sane = t->sanitize (context);
30927e302dc8e794ff6bf878bc76e17d336d510849eBehdad Esfahbod	if (context->edit_count) {
310fa030175ca998b00cc42cbced6e98de323ec01ecBehdad Esfahbod	  if (HB_DEBUG_SANITIZE)
311fa030175ca998b00cc42cbced6e98de323ec01ecBehdad Esfahbod	    fprintf (stderr, "Sanitizer %p requested %d edits in second round; FAILLING %s\n",
31227e302dc8e794ff6bf878bc76e17d336d510849eBehdad Esfahbod		     blob, context->edit_count, HB_FUNC);
3134e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod	  sane = false;
3144e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod	}
3154e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod      }
31698daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod      context->finish ();
3174e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod    } else {
31827e302dc8e794ff6bf878bc76e17d336d510849eBehdad Esfahbod      unsigned int edit_count = context->edit_count;
31998daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod      context->finish ();
320977eeb714454630bd045bb11f58ff6397f10b143Behdad Esfahbod      if (edit_count && !hb_blob_is_writable (blob) && hb_blob_try_writable (blob)) {
321977eeb714454630bd045bb11f58ff6397f10b143Behdad Esfahbod        /* ok, we made it writable by relocating.  try again */
322fa030175ca998b00cc42cbced6e98de323ec01ecBehdad Esfahbod	if (HB_DEBUG_SANITIZE)
3237d3a126334f8e6f6441561c1bb592bd3fa7a2c5cBehdad Esfahbod	  fprintf (stderr, "Sanitizer %p retry %s\n", blob, HB_FUNC);
3244e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod        goto retry;
3254e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod      }
3264e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod    }
3274e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod
328fa030175ca998b00cc42cbced6e98de323ec01ecBehdad Esfahbod    if (HB_DEBUG_SANITIZE)
3297d3a126334f8e6f6441561c1bb592bd3fa7a2c5cBehdad Esfahbod      fprintf (stderr, "Sanitizer %p %s %s\n", blob, sane ? "passed" : "FAILED", HB_FUNC);
3304e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod    if (sane)
3314e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod      return blob;
3324e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod    else {
3334e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod      hb_blob_destroy (blob);
3344e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod      return hb_blob_create_empty ();
3354e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod    }
3364e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod  }
337b435ab7e29c388e3b100f729957319931625a3a8Behdad Esfahbod
338b435ab7e29c388e3b100f729957319931625a3a8Behdad Esfahbod  static const Type* lock_instance (hb_blob_t *blob) {
339b435ab7e29c388e3b100f729957319931625a3a8Behdad Esfahbod    const char *base = hb_blob_lock (blob);
340b435ab7e29c388e3b100f729957319931625a3a8Behdad Esfahbod    return unlikely (!base) ? &Null(Type) : CastP<Type> (base);
341b435ab7e29c388e3b100f729957319931625a3a8Behdad Esfahbod  }
3424e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod};
3434e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod
3442d15e72c75931398db5e027e660f1320bb979117Behdad Esfahbod
345f0abcd69408a3af65207cdf8847575ade4579bd4Behdad Esfahbod
346f0abcd69408a3af65207cdf8847575ade4579bd4Behdad Esfahbod
347b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod/*
348b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod *
349bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod * The OpenType Font File: Data Types
350b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod */
351b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod
352b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod
353b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod/* "The following data types are used in the OpenType font file.
354b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod *  All OpenType fonts use Motorola-style byte ordering (Big Endian):" */
355b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod
3565f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod/*
3575f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod * Int types
3585f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod */
3595f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod
3606b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod
361e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodtemplate <typename Type, int Bytes> class BEInt;
362e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod
363f1aaa2a43654c28405ffd393de2cb127437c99a5Behdad Esfahbod/* LONGTERMTODO: On machines allowing unaligned access, we can make the
364f1aaa2a43654c28405ffd393de2cb127437c99a5Behdad Esfahbod * following tighter by using byteswap instructions on ints directly. */
365e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodtemplate <typename Type>
366e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodclass BEInt<Type, 2>
367e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod{
368e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod  public:
36901c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod  inline class BEInt<Type,2>& operator = (Type i) { hb_be_uint16_put (v,i); return *this; }
37001c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod  inline operator Type () const { return hb_be_uint16_get (v); }
37101c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod  inline bool operator == (const BEInt<Type, 2>& o) const { return hb_be_uint16_cmp (v, o.v); }
37201c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod  inline bool operator != (const BEInt<Type, 2>& o) const { return !(*this == o); }
373e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod  private: uint8_t v[2];
374e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod};
375e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodtemplate <typename Type>
376e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodclass BEInt<Type, 4>
377e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod{
378e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod  public:
37901c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod  inline class BEInt<Type,4>& operator = (Type i) { hb_be_uint32_put (v,i); return *this; }
38001c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod  inline operator Type () const { return hb_be_uint32_get (v); }
38101c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod  inline bool operator == (const BEInt<Type, 4>& o) const { return hb_be_uint32_cmp (v, o.v); }
38201c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod  inline bool operator != (const BEInt<Type, 4>& o) const { return !(*this == o); }
383e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod  private: uint8_t v[4];
384e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod};
385e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod
3862467c669c2aee4de2a6621a9d06cba0262376d41Behdad Esfahbod/* Integer types in big-endian order and no alignment requirement */
387e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodtemplate <typename Type>
388e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodstruct IntType
389e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod{
39001c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod  inline void set (Type i) { v = i; }
39101c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod  inline operator Type(void) const { return v; }
39201c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod  inline bool operator == (const IntType<Type> &o) const { return v == o.v; }
39301c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod  inline bool operator != (const IntType<Type> &o) const { return v != o.v; }
39439840474afd2cda9ff576c08aff9c87095496c27Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *context) {
395e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod    TRACE_SANITIZE ();
3964c20d8c057738b66150a88472714690e137884f8Behdad Esfahbod    return likely (context->check_struct (this));
397e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod  }
398a82ef7a893b773a17f7548375de9f588dfc83abaBehdad Esfahbod  protected:
399569da92bc6956f42d9b2d65c784e184fb6380efeBehdad Esfahbod  BEInt<Type, sizeof (Type)> v;
400569da92bc6956f42d9b2d65c784e184fb6380efeBehdad Esfahbod  public:
401e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod  DEFINE_SIZE_STATIC (sizeof (Type));
402e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod};
403e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod
404e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodtypedef IntType<uint16_t> USHORT;	/* 16-bit unsigned integer. */
405e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodtypedef IntType<int16_t>  SHORT;	/* 16-bit signed integer. */
406e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodtypedef IntType<uint32_t> ULONG;	/* 32-bit unsigned integer. */
407e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodtypedef IntType<int32_t>  LONG;		/* 32-bit signed integer. */
408e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod
4096b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod/* Array of four uint8s (length = 32 bits) used to identify a script, language
4106b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod * system, feature, or baseline */
41120cc86b3592db33731de671f008d7d222776be49Behdad Esfahbodstruct Tag : ULONG
41260d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
413befc022affd2386b3f46cd7d11e4262f6c8bce9fBehdad Esfahbod  /* What the char* converters return is NOT nul-terminated.  Print using "%.4s" */
414a82ef7a893b773a17f7548375de9f588dfc83abaBehdad Esfahbod  inline operator const char* (void) const { return reinterpret_cast<const char *> (&this->v); }
415a82ef7a893b773a17f7548375de9f588dfc83abaBehdad Esfahbod  inline operator char* (void) { return reinterpret_cast<char *> (&this->v); }
416b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod  public:
417b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod  DEFINE_SIZE_STATIC (4);
4186b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod};
41965f46b00333e20ab8a52a4b350747507541ec1dbBehdad EsfahbodDEFINE_NULL_DATA (Tag, "    ");
4206b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod
4216b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod/* Glyph index number, same as uint16 (length = 16 bits) */
4226ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbodtypedef USHORT GlyphID;
4236b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod
424b5db4f1e4eefa266a71a28b5496f47ff9d1a81e8Behdad Esfahbod/* Script/language-system/feature index */
425b5db4f1e4eefa266a71a28b5496f47ff9d1a81e8Behdad Esfahbodstruct Index : USHORT {
426b5db4f1e4eefa266a71a28b5496f47ff9d1a81e8Behdad Esfahbod  static const unsigned int NOT_FOUND_INDEX = 0xFFFF;
427b5db4f1e4eefa266a71a28b5496f47ff9d1a81e8Behdad Esfahbod};
428b5db4f1e4eefa266a71a28b5496f47ff9d1a81e8Behdad EsfahbodDEFINE_NULL_DATA (Index, "\xff\xff");
429b5db4f1e4eefa266a71a28b5496f47ff9d1a81e8Behdad Esfahbod
4301f437e6f47fb6c15761021bd2078f31778f2179cBehdad Esfahbod/* Offset to a table, same as uint16 (length = 16 bits), Null offset = 0x0000 */
4316ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbodtypedef USHORT Offset;
4326ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbod
4336ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbod/* LongOffset to a table, same as uint32 (length = 32 bits), Null offset = 0x00000000 */
4346ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbodtypedef ULONG LongOffset;
4356ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbod
4366b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod
4376b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod/* CheckSum */
43860d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbodstruct CheckSum : ULONG
43960d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
44060d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  static uint32_t CalcTableChecksum (ULONG *Table, uint32_t Length)
44160d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  {
4426b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod    uint32_t Sum = 0L;
443e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod    ULONG *EndPtr = Table+((Length+3) & ~3) / ULONG::static_size;
4446b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod
4456b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod    while (Table < EndPtr)
4466b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod      Sum += *Table++;
4476b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod    return Sum;
4486b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod  }
449b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod  public:
450b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod  DEFINE_SIZE_STATIC (4);
4516b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod};
4526b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod
4536b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod
4546b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod/*
4556b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod * Version Numbers
4566b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod */
4576b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod
45887fcdcbe3644da10154688765db2d62eb9ac079aBehdad Esfahbodstruct FixedVersion
45960d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
46009c292e3b688a67fbae67b645d1e6ffcf8d8eb6eBehdad Esfahbod  inline operator uint32_t (void) const { return (major << 16) + minor; }
46196908b898476ca5d7da5f386b15be76f9e83d76eBehdad Esfahbod
46239840474afd2cda9ff576c08aff9c87095496c27Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *context) {
4633e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
464b157617644d1e38f680163889d1dc2e2f64d9ba3Behdad Esfahbod    return context->check_struct (this);
465cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod  }
466cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod
4676ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbod  USHORT major;
46887fcdcbe3644da10154688765db2d62eb9ac079aBehdad Esfahbod  USHORT minor;
469b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod  public:
470b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod  DEFINE_SIZE_STATIC (4);
4716b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod};
4726b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod
47392b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod
47492b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod
4755f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod/*
47692b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod * Template subclasses of Offset and LongOffset that do the dereferencing.
477f0abcd69408a3af65207cdf8847575ade4579bd4Behdad Esfahbod * Use: (base+offset)
4785f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod */
4795f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod
48092b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename OffsetType, typename Type>
48192b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct GenericOffsetTo : OffsetType
48292b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod{
48300e23fcc6fd0eee5c582251bf3de6a2703fbbd3eBehdad Esfahbod  inline const Type& operator () (const void *base) const
48492b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod  {
48592b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod    unsigned int offset = *this;
48664d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod    if (unlikely (!offset)) return Null(Type);
48709766b1ec5ec55a61edbcd7a89ed3613cc92d4cbBehdad Esfahbod    return StructAtOffset<Type> (base, offset);
48892b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod  }
48992b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod
49039840474afd2cda9ff576c08aff9c87095496c27Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *context, void *base) {
4913e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
4924c20d8c057738b66150a88472714690e137884f8Behdad Esfahbod    if (unlikely (!context->check_struct (this))) return false;
49392b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod    unsigned int offset = *this;
49464d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod    if (unlikely (!offset)) return true;
49509766b1ec5ec55a61edbcd7a89ed3613cc92d4cbBehdad Esfahbod    Type &obj = StructAtOffset<Type> (base, offset);
49639840474afd2cda9ff576c08aff9c87095496c27Behdad Esfahbod    return likely (obj.sanitize (context)) || neuter (context);
49792b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod  }
4984a446ac35136eff23d55f47bdd7b40095ad707abBehdad Esfahbod  template <typename T>
49939840474afd2cda9ff576c08aff9c87095496c27Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *context, void *base, T user_data) {
5003e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
5014c20d8c057738b66150a88472714690e137884f8Behdad Esfahbod    if (unlikely (!context->check_struct (this))) return false;
50242b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod    unsigned int offset = *this;
50364d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod    if (unlikely (!offset)) return true;
50409766b1ec5ec55a61edbcd7a89ed3613cc92d4cbBehdad Esfahbod    Type &obj = StructAtOffset<Type> (base, offset);
50539840474afd2cda9ff576c08aff9c87095496c27Behdad Esfahbod    return likely (obj.sanitize (context, user_data)) || neuter (context);
506c9f14687a30866181feb57ee2736a147ec9f25a1Behdad Esfahbod  }
507c9f14687a30866181feb57ee2736a147ec9f25a1Behdad Esfahbod
508c9f14687a30866181feb57ee2736a147ec9f25a1Behdad Esfahbod  private:
509c9f14687a30866181feb57ee2736a147ec9f25a1Behdad Esfahbod  /* Set the offset to Null */
51039840474afd2cda9ff576c08aff9c87095496c27Behdad Esfahbod  inline bool neuter (hb_sanitize_context_t *context) {
51140cbefe858192531ed64dd51d402f7ca7b8153a3Behdad Esfahbod    if (context->can_edit (this, this->static_size)) {
512c9f14687a30866181feb57ee2736a147ec9f25a1Behdad Esfahbod      this->set (0); /* 0 is Null offset */
513c9f14687a30866181feb57ee2736a147ec9f25a1Behdad Esfahbod      return true;
514c9f14687a30866181feb57ee2736a147ec9f25a1Behdad Esfahbod    }
515c9f14687a30866181feb57ee2736a147ec9f25a1Behdad Esfahbod    return false;
51642b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod  }
51792b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod};
51892b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Base, typename OffsetType, typename Type>
51992b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodinline const Type& operator + (const Base &base, GenericOffsetTo<OffsetType, Type> offset) { return offset (base); }
52092b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod
5215f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbodtemplate <typename Type>
52292b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct OffsetTo : GenericOffsetTo<Offset, Type> {};
52392b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod
52492b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Type>
52592b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct LongOffsetTo : GenericOffsetTo<LongOffset, Type> {};
526bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod
527bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod
52892b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod/*
52992b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod * Array Types
53092b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod */
53192b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod
53292b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename LenType, typename Type>
53392b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct GenericArrayOf
53460d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
5354f5f1c34dda1e0629bfa6d7b0ffa2e1ce003b7c7Behdad Esfahbod  const Type *sub_array (unsigned int start_offset, unsigned int *pcount /* IN/OUT */) const
53648de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod  {
53748de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod    unsigned int count = len;
53864d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod    if (unlikely (start_offset > count))
53948de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod      count = 0;
54048de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod    else
54148de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod      count -= start_offset;
54248de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod    count = MIN (count, *pcount);
54348de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod    *pcount = count;
544b961518b9611471ff7060e97686e5625974847ebBehdad Esfahbod    return array + start_offset;
54548de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod  }
54648de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod
54760d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  inline const Type& operator [] (unsigned int i) const
54860d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  {
54964d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod    if (unlikely (i >= len)) return Null(Type);
550b961518b9611471ff7060e97686e5625974847ebBehdad Esfahbod    return array[i];
5515f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod  }
55260d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  inline unsigned int get_size () const
553e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod  { return len.static_size + len * Type::static_size; }
554e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod
55539840474afd2cda9ff576c08aff9c87095496c27Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *context) {
5563e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
5574c20d8c057738b66150a88472714690e137884f8Behdad Esfahbod    if (unlikely (!sanitize_shallow (context))) return false;
55840d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod    /* Note: for structs that do not reference other structs,
55940d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod     * we do not need to call their sanitize() as we already did
56040d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod     * a bound check on the aggregate array size, hence the return.
56140d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod     */
5623564ee5216004d45d30b0ded61184cf8dde5dd89Behdad Esfahbod    return true;
56340d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod    /* We do keep this code though to make sure the structs pointed
56440d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod     * to do have a simple sanitize(), ie. they do not reference
56540d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod     * other structs. */
56670de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod    unsigned int count = len;
56770de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod    for (unsigned int i = 0; i < count; i++)
568b961518b9611471ff7060e97686e5625974847ebBehdad Esfahbod      if (array[i].sanitize (context))
56970de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod        return false;
5709bd629ccd064e739789e504c41ad875eed93abbaBehdad Esfahbod    return true;
57170de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod  }
57239840474afd2cda9ff576c08aff9c87095496c27Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *context, void *base) {
5733e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
5744c20d8c057738b66150a88472714690e137884f8Behdad Esfahbod    if (unlikely (!sanitize_shallow (context))) return false;
575e6ab2c59ba2d37942ac5fcbfe61d38b7e359ac8cBehdad Esfahbod    unsigned int count = len;
576e6ab2c59ba2d37942ac5fcbfe61d38b7e359ac8cBehdad Esfahbod    for (unsigned int i = 0; i < count; i++)
5774c20d8c057738b66150a88472714690e137884f8Behdad Esfahbod      if (unlikely (!array[i].sanitize (context, base)))
578e6ab2c59ba2d37942ac5fcbfe61d38b7e359ac8cBehdad Esfahbod        return false;
5799bd629ccd064e739789e504c41ad875eed93abbaBehdad Esfahbod    return true;
580e6ab2c59ba2d37942ac5fcbfe61d38b7e359ac8cBehdad Esfahbod  }
5814a446ac35136eff23d55f47bdd7b40095ad707abBehdad Esfahbod  template <typename T>
58239840474afd2cda9ff576c08aff9c87095496c27Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *context, void *base, T user_data) {
5833e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
5844c20d8c057738b66150a88472714690e137884f8Behdad Esfahbod    if (unlikely (!sanitize_shallow (context))) return false;
58542b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod    unsigned int count = len;
58642b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod    for (unsigned int i = 0; i < count; i++)
5874c20d8c057738b66150a88472714690e137884f8Behdad Esfahbod      if (unlikely (!array[i].sanitize (context, base, user_data)))
58842b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod        return false;
5899bd629ccd064e739789e504c41ad875eed93abbaBehdad Esfahbod    return true;
59042b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod  }
59170de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod
59230fa2821c277df99a14089749313dfe2b541e2d0Behdad Esfahbod  private:
59339840474afd2cda9ff576c08aff9c87095496c27Behdad Esfahbod  inline bool sanitize_shallow (hb_sanitize_context_t *context) {
59430fa2821c277df99a14089749313dfe2b541e2d0Behdad Esfahbod    TRACE_SANITIZE ();
595b157617644d1e38f680163889d1dc2e2f64d9ba3Behdad Esfahbod    return context->check_struct (this)
596e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod	&& context->check_array (this, Type::static_size, len);
59730fa2821c277df99a14089749313dfe2b541e2d0Behdad Esfahbod  }
59830fa2821c277df99a14089749313dfe2b541e2d0Behdad Esfahbod
59930fa2821c277df99a14089749313dfe2b541e2d0Behdad Esfahbod  public:
60092b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod  LenType len;
601b961518b9611471ff7060e97686e5625974847ebBehdad Esfahbod  Type array[VAR];
602b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod  public:
6030eb9fc6e37935707dba2bf4b3705de2161a08cb7Behdad Esfahbod  DEFINE_SIZE_ARRAY (sizeof (LenType), array);
604e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod};
605e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod
60692b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod/* An array with a USHORT number of elements. */
60792b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Type>
60892b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct ArrayOf : GenericArrayOf<USHORT, Type> {};
60992b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod
61092b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod/* An array with a ULONG number of elements. */
61192b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Type>
61292b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct LongArrayOf : GenericArrayOf<ULONG, Type> {};
61392b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod
61492b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod/* Array of Offset's */
61592b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Type>
61692b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct OffsetArrayOf : ArrayOf<OffsetTo<Type> > {};
61792b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod
61892b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod/* Array of LongOffset's */
61992b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Type>
62092b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct LongOffsetArrayOf : ArrayOf<LongOffsetTo<Type> > {};
62192b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod
62292b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod/* LongArray of LongOffset's */
62392b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Type>
62492b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct LongOffsetLongArrayOf : LongArrayOf<LongOffsetTo<Type> > {};
62592b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod
62680e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod/* Array of offsets relative to the beginning of the array itself. */
62780e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbodtemplate <typename Type>
62880e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbodstruct OffsetListOf : OffsetArrayOf<Type>
62980e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod{
63080e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod  inline const Type& operator [] (unsigned int i) const
63180e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod  {
63264d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod    if (unlikely (i >= this->len)) return Null(Type);
633b961518b9611471ff7060e97686e5625974847ebBehdad Esfahbod    return this+this->array[i];
63480e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod  }
63580e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod
63639840474afd2cda9ff576c08aff9c87095496c27Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *context) {
6373e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
63840cbefe858192531ed64dd51d402f7ca7b8153a3Behdad Esfahbod    return OffsetArrayOf<Type>::sanitize (context, this);
63980e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod  }
6404a446ac35136eff23d55f47bdd7b40095ad707abBehdad Esfahbod  template <typename T>
64139840474afd2cda9ff576c08aff9c87095496c27Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *context, T user_data) {
6423e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
64340cbefe858192531ed64dd51d402f7ca7b8153a3Behdad Esfahbod    return OffsetArrayOf<Type>::sanitize (context, this, user_data);
64480e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod  }
64580e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod};
64680e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod
64780e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod
648e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod/* An array with a USHORT number of elements,
649e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod * starting at second element. */
650e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbodtemplate <typename Type>
65160d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbodstruct HeadlessArrayOf
65260d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
65360d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  inline const Type& operator [] (unsigned int i) const
65460d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  {
65564d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod    if (unlikely (i >= len || !i)) return Null(Type);
656b961518b9611471ff7060e97686e5625974847ebBehdad Esfahbod    return array[i-1];
657e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod  }
65860d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  inline unsigned int get_size () const
659e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod  { return len.static_size + (len ? len - 1 : 0) * Type::static_size; }
6605f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod
66139840474afd2cda9ff576c08aff9c87095496c27Behdad Esfahbod  inline bool sanitize_shallow (hb_sanitize_context_t *context) {
662b157617644d1e38f680163889d1dc2e2f64d9ba3Behdad Esfahbod    return context->check_struct (this)
663e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod	&& context->check_array (this, Type::static_size, len);
664e5546a4352c54311ac4a9ef138b187378155ebe1Behdad Esfahbod  }
665e5546a4352c54311ac4a9ef138b187378155ebe1Behdad Esfahbod
66639840474afd2cda9ff576c08aff9c87095496c27Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *context) {
6673e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
6684c20d8c057738b66150a88472714690e137884f8Behdad Esfahbod    if (unlikely (!sanitize_shallow (context))) return false;
66940d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod    /* Note: for structs that do not reference other structs,
67040d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod     * we do not need to call their sanitize() as we already did
67140d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod     * a bound check on the aggregate array size, hence the return.
67240d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod     */
6733564ee5216004d45d30b0ded61184cf8dde5dd89Behdad Esfahbod    return true;
67440d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod    /* We do keep this code though to make sure the structs pointed
67540d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod     * to do have a simple sanitize(), ie. they do not reference
67640d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod     * other structs. */
67715164d9258a74122a4db748d35532bd72c47cec2Behdad Esfahbod    unsigned int count = len ? len - 1 : 0;
678b961518b9611471ff7060e97686e5625974847ebBehdad Esfahbod    Type *a = array;
67970de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod    for (unsigned int i = 0; i < count; i++)
6804c20d8c057738b66150a88472714690e137884f8Behdad Esfahbod      if (unlikely (!a[i].sanitize (context)))
68170de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod        return false;
6829bd629ccd064e739789e504c41ad875eed93abbaBehdad Esfahbod    return true;
68370de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod  }
68470de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod
6855f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod  USHORT len;
686b961518b9611471ff7060e97686e5625974847ebBehdad Esfahbod  Type array[VAR];
687ed07422c33bbb52ff4d79e65986171e3f07697d8Behdad Esfahbod  public:
6880eb9fc6e37935707dba2bf4b3705de2161a08cb7Behdad Esfahbod  DEFINE_SIZE_ARRAY (sizeof (USHORT), array);
6895f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod};
6905f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod
6916b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod
6921e91434569a9e9535ef021ca52b60b2e2af75d19Behdad Esfahbod#endif /* HB_OPEN_TYPE_PRIVATE_HH */
693