hb-open-type-private.hh revision bc5be24014371ceb811b9ffd37062ede63d87bb1
164aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod/*
22409d5f8d7dd8b535ce5ea29e933f7db27d33793Behdad Esfahbod * Copyright © 2007,2008,2009,2010  Red Hat, Inc.
30ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod * Copyright © 2012  Google, Inc.
464aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod *
5c755cb3e3ac55156d0d2ec05adea7a650b97cc41Behdad Esfahbod *  This is part of HarfBuzz, a text shaping library.
664aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod *
764aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * Permission is hereby granted, without written agreement and without
864aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * license or royalty fees, to use, copy, modify, and distribute this
964aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * software and its documentation for any purpose, provided that the
1064aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * above copyright notice and the following two paragraphs appear in
1164aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * all copies of this software.
1264aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod *
1364aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
1464aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
1564aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
1664aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
1764aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * DAMAGE.
1864aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod *
1964aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
2064aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
2164aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
2264aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
2364aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
2464aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod *
2564aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * Red Hat Author(s): Behdad Esfahbod
260ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod * Google Author(s): Behdad Esfahbod
2764aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod */
2864aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod
290f0cd9d361f1bb614aa3fd4616160d027062370eBehdad Esfahbod#ifndef HB_OPEN_TYPE_PRIVATE_HH
300f0cd9d361f1bb614aa3fd4616160d027062370eBehdad Esfahbod#define HB_OPEN_TYPE_PRIVATE_HH
3112c4568c680ea2b9b98a16a8b7402ca185c90ef6Behdad Esfahbod
32c57d454accff66e5f2c58006e8fb40bc020b6182Behdad Esfahbod#include "hb-private.hh"
3312c4568c680ea2b9b98a16a8b7402ca185c90ef6Behdad Esfahbod
3470de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod#include "hb-blob.h"
3570de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod
36a16ecbf0564a6e2576da22c12827f3c0719da549Behdad Esfahbod
377c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbodnamespace OT {
387c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod
39a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbod
40196598bbccff08415ff5192314cba044df258cadBehdad Esfahbod/*
41196598bbccff08415ff5192314cba044df258cadBehdad Esfahbod * Casts
42196598bbccff08415ff5192314cba044df258cadBehdad Esfahbod */
43196598bbccff08415ff5192314cba044df258cadBehdad Esfahbod
44187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbod/* Cast to struct T, reference to reference */
45a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbodtemplate<typename Type, typename TObject>
46187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbodinline const Type& CastR(const TObject &X)
47a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbod{ return reinterpret_cast<const Type&> (X); }
48a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbodtemplate<typename Type, typename TObject>
49187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbodinline Type& CastR(TObject &X)
50a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbod{ return reinterpret_cast<Type&> (X); }
51196598bbccff08415ff5192314cba044df258cadBehdad Esfahbod
52187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbod/* Cast to struct T, pointer to pointer */
53187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbodtemplate<typename Type, typename TObject>
54187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbodinline const Type* CastP(const TObject *X)
55187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbod{ return reinterpret_cast<const Type*> (X); }
56187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbodtemplate<typename Type, typename TObject>
57187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbodinline Type* CastP(TObject *X)
58187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbod{ return reinterpret_cast<Type*> (X); }
59187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbod
6009766b1ec5ec55a61edbcd7a89ed3613cc92d4cbBehdad Esfahbod/* StructAtOffset<T>(P,Ofs) returns the struct T& that is placed at memory
6109766b1ec5ec55a61edbcd7a89ed3613cc92d4cbBehdad Esfahbod * location pointed to by P plus Ofs bytes. */
6209766b1ec5ec55a61edbcd7a89ed3613cc92d4cbBehdad Esfahbodtemplate<typename Type>
6309766b1ec5ec55a61edbcd7a89ed3613cc92d4cbBehdad Esfahbodinline const Type& StructAtOffset(const void *P, unsigned int offset)
64a82ef7a893b773a17f7548375de9f588dfc83abaBehdad Esfahbod{ return * reinterpret_cast<const Type*> ((const char *) P + offset); }
6509766b1ec5ec55a61edbcd7a89ed3613cc92d4cbBehdad Esfahbodtemplate<typename Type>
6609766b1ec5ec55a61edbcd7a89ed3613cc92d4cbBehdad Esfahbodinline Type& StructAtOffset(void *P, unsigned int offset)
67a82ef7a893b773a17f7548375de9f588dfc83abaBehdad Esfahbod{ return * reinterpret_cast<Type*> ((char *) P + offset); }
6870de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod
692e2f43edf2f49f4047e28b1ce2ea95938536de9cBehdad Esfahbod/* StructAfter<T>(X) returns the struct T& that is placed after X.
7029c3f5e1b6212c775a7b911becd44ba093b7b0ebBehdad Esfahbod * Works with X of variable size also.  X must implement get_size() */
71e961c86c579fd98ee604342a9c70c4e7f8d4f220Behdad Esfahbodtemplate<typename Type, typename TObject>
72e961c86c579fd98ee604342a9c70c4e7f8d4f220Behdad Esfahbodinline const Type& StructAfter(const TObject &X)
7309766b1ec5ec55a61edbcd7a89ed3613cc92d4cbBehdad Esfahbod{ return StructAtOffset<Type>(&X, X.get_size()); }
74e961c86c579fd98ee604342a9c70c4e7f8d4f220Behdad Esfahbodtemplate<typename Type, typename TObject>
75e961c86c579fd98ee604342a9c70c4e7f8d4f220Behdad Esfahbodinline Type& StructAfter(TObject &X)
7609766b1ec5ec55a61edbcd7a89ed3613cc92d4cbBehdad Esfahbod{ return StructAtOffset<Type>(&X, X.get_size()); }
77a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbod
78e961c86c579fd98ee604342a9c70c4e7f8d4f220Behdad Esfahbod
79d3480ba37fbb5d4be75b094060f5b2f1ce98fb53Behdad Esfahbod
8070de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod/*
81e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod * Size checking
82e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod */
83e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod
84f679635893eebc13402c5ee51a6f106eed0c76beBehdad Esfahbod/* Check _assertion in a method environment */
85a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod#define _DEFINE_INSTANCE_ASSERTION1(_line, _assertion) \
86a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod  inline void _instance_assertion_on_line_##_line (void) const \
87a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod  { \
88a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod    ASSERT_STATIC (_assertion); \
89a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod    ASSERT_INSTANCE_POD (*this); /* Make sure it's POD. */ \
90a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod  }
91a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod# define _DEFINE_INSTANCE_ASSERTION0(_line, _assertion) _DEFINE_INSTANCE_ASSERTION1 (_line, _assertion)
92a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod# define DEFINE_INSTANCE_ASSERTION(_assertion) _DEFINE_INSTANCE_ASSERTION0 (__LINE__, _assertion)
93a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod
94f679635893eebc13402c5ee51a6f106eed0c76beBehdad Esfahbod/* Check that _code compiles in a method environment */
95a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod#define _DEFINE_COMPILES_ASSERTION1(_line, _code) \
96a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod  inline void _compiles_assertion_on_line_##_line (void) const \
97f679635893eebc13402c5ee51a6f106eed0c76beBehdad Esfahbod  { _code; }
98a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod# define _DEFINE_COMPILES_ASSERTION0(_line, _code) _DEFINE_COMPILES_ASSERTION1 (_line, _code)
99a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod# define DEFINE_COMPILES_ASSERTION(_code) _DEFINE_COMPILES_ASSERTION0 (__LINE__, _code)
1000abcc3b48cfd51a22695c9e988938b2f45cb19d8Behdad Esfahbod
1010abcc3b48cfd51a22695c9e988938b2f45cb19d8Behdad Esfahbod
102e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod#define DEFINE_SIZE_STATIC(size) \
103a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod  DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size)); \
104e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod  static const unsigned int static_size = (size); \
105e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod  static const unsigned int min_size = (size)
106e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod
107b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod/* Size signifying variable-sized array */
108b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod#define VAR 1
109b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod
110596e471aa5053d955fb5d5b5923088c8814469b1Behdad Esfahbod#define DEFINE_SIZE_UNION(size, _member) \
111a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod  DEFINE_INSTANCE_ASSERTION (this->u._member.static_size == (size)); \
112596e471aa5053d955fb5d5b5923088c8814469b1Behdad Esfahbod  static const unsigned int min_size = (size)
113596e471aa5053d955fb5d5b5923088c8814469b1Behdad Esfahbod
114bea34c7cbb583cf7660776e95cab3171590b8427Behdad Esfahbod#define DEFINE_SIZE_MIN(size) \
115a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod  DEFINE_INSTANCE_ASSERTION (sizeof (*this) >= (size)); \
116b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod  static const unsigned int min_size = (size)
117b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod
1180eb9fc6e37935707dba2bf4b3705de2161a08cb7Behdad Esfahbod#define DEFINE_SIZE_ARRAY(size, array) \
119a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod  DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size) + sizeof (array[0])); \
120a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod  DEFINE_COMPILES_ASSERTION ((void) array[0].static_size) \
121e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod  static const unsigned int min_size = (size)
122e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod
1230eb9fc6e37935707dba2bf4b3705de2161a08cb7Behdad Esfahbod#define DEFINE_SIZE_ARRAY2(size, array1, array2) \
124a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod  DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size) + sizeof (this->array1[0]) + sizeof (this->array2[0])); \
125a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod  DEFINE_COMPILES_ASSERTION ((void) array1[0].static_size; (void) array2[0].static_size) \
126e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod  static const unsigned int min_size = (size)
127e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod
128e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod
129e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod
130e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod/*
131f0abcd69408a3af65207cdf8847575ade4579bd4Behdad Esfahbod * Null objects
132600e5eb80f553ea8eb862e6784133574c74ca513Behdad Esfahbod */
133600e5eb80f553ea8eb862e6784133574c74ca513Behdad Esfahbod
1348b8358033184198ff638ee1379093717596e162dBehdad Esfahbod/* Global nul-content Null pool.  Enlarge as necessary. */
1350bb0f5d41976ae27c5c7a51cbb82144b48315a4bBehdad Esfahbod/* TODO This really should be a extern HB_INTERNAL and defined somewhere... */
136cf5585cfa6cac6fdf627a99941299e76af5ae0f7Behdad Esfahbodstatic const void *_NullPool[64 / sizeof (void *)];
1378b8358033184198ff638ee1379093717596e162dBehdad Esfahbod
138d2c2ca8faf62fc380d4717d286556139a62d2356Behdad Esfahbod/* Generic nul-content Null objects. */
1398b8358033184198ff638ee1379093717596e162dBehdad Esfahbodtemplate <typename Type>
1407f97d2cd904ea999c099c73c52187c5d65aeec67Behdad Esfahbodstatic inline const Type& Null (void) {
141ed07422c33bbb52ff4d79e65986171e3f07697d8Behdad Esfahbod  ASSERT_STATIC (Type::min_size <= sizeof (_NullPool));
142187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbod  return *CastP<Type> (_NullPool);
1439d3677899f90abdc7fb3e3d854db654a8707a84bBehdad Esfahbod}
1448b8358033184198ff638ee1379093717596e162dBehdad Esfahbod
1458b8358033184198ff638ee1379093717596e162dBehdad Esfahbod/* Specializaiton for arbitrary-content arbitrary-sized Null objects. */
14665f46b00333e20ab8a52a4b350747507541ec1dbBehdad Esfahbod#define DEFINE_NULL_DATA(Type, data) \
14765f46b00333e20ab8a52a4b350747507541ec1dbBehdad Esfahbodstatic const char _Null##Type[Type::min_size + 1] = data; /* +1 is for nul-termination in data */ \
1488b8358033184198ff638ee1379093717596e162dBehdad Esfahbodtemplate <> \
1497f97d2cd904ea999c099c73c52187c5d65aeec67Behdad Esfahbodinline const Type& Null<Type> (void) { \
150187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbod  return *CastP<Type> (_Null##Type); \
151565c80bd2960366ace2d10dd71beaaf2a80213c8Behdad Esfahbod} /* The following line really exists such that we end in a place needing semicolon */ \
152bea34c7cbb583cf7660776e95cab3171590b8427Behdad EsfahbodASSERT_STATIC (Type::min_size + 1 <= sizeof (_Null##Type))
1538b8358033184198ff638ee1379093717596e162dBehdad Esfahbod
1548b8358033184198ff638ee1379093717596e162dBehdad Esfahbod/* Accessor macro. */
1559d3677899f90abdc7fb3e3d854db654a8707a84bBehdad Esfahbod#define Null(Type) Null<Type>()
1568b8358033184198ff638ee1379093717596e162dBehdad Esfahbod
1578b8358033184198ff638ee1379093717596e162dBehdad Esfahbod
158600e5eb80f553ea8eb862e6784133574c74ca513Behdad Esfahbod
159577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod/*
160577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod * Sanitize
161577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod */
162577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod
16395e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod#ifndef HB_DEBUG_SANITIZE
16411e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod#define HB_DEBUG_SANITIZE (HB_DEBUG+0)
16595e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod#endif
16695e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod
16720e3dd5d292b65f70d2eae63b8d8713a1c889d47Behdad Esfahbod
168bc200457430c083914a64bf4b056153506749610Behdad Esfahbod#define TRACE_SANITIZE() \
1690ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod	hb_auto_trace_t<HB_DEBUG_SANITIZE> trace (&c->debug_depth, "SANITIZE", this, HB_FUNC, "");
170807c5b03a2251a3c29a520852639421783101b55Behdad Esfahbod
171b28815c1f6e46d38471cacbc31248ca6fda8c4d1Behdad Esfahbod
1721376fb7bf9ef07970f0ba13dc64d6a8ab8252762Behdad Esfahbodstruct hb_sanitize_context_t
173577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod{
17431f18abecb149f8888a72510f2660328dd6de16dBehdad Esfahbod  inline void init (hb_blob_t *b)
17598daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod  {
17631f18abecb149f8888a72510f2660328dd6de16dBehdad Esfahbod    this->blob = hb_blob_reference (b);
1771c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod    this->writable = false;
1781c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod  }
1791c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod
180cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod  inline void start_processing (void)
1811c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod  {
1824101ca7dbbdf1438fa116fb8cad935501ac7cca8Behdad Esfahbod    this->start = hb_blob_get_data (this->blob, NULL);
1834101ca7dbbdf1438fa116fb8cad935501ac7cca8Behdad Esfahbod    this->end = this->start + hb_blob_get_length (this->blob);
18498daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod    this->edit_count = 0;
18520e3dd5d292b65f70d2eae63b8d8713a1c889d47Behdad Esfahbod    this->debug_depth = 0;
186577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod
1871e08830b4fac3a60ae52349cab6e101d389d30cdBehdad Esfahbod    DEBUG_MSG_LEVEL (SANITIZE, this->blob, 0, +1,
188cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod		     "start [%p..%p] (%lu bytes)",
1891e08830b4fac3a60ae52349cab6e101d389d30cdBehdad Esfahbod		     this->start, this->end,
1901e08830b4fac3a60ae52349cab6e101d389d30cdBehdad Esfahbod		     (unsigned long) (this->end - this->start));
19198daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod  }
1921376fb7bf9ef07970f0ba13dc64d6a8ab8252762Behdad Esfahbod
193cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod  inline void end_processing (void)
19498daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod  {
1951e08830b4fac3a60ae52349cab6e101d389d30cdBehdad Esfahbod    DEBUG_MSG_LEVEL (SANITIZE, this->blob, 0, -1,
196cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod		     "end [%p..%p] %u edit requests",
1971e08830b4fac3a60ae52349cab6e101d389d30cdBehdad Esfahbod		     this->start, this->end, this->edit_count);
198577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod
19998daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod    hb_blob_destroy (this->blob);
20098daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod    this->blob = NULL;
20198daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod    this->start = this->end = NULL;
20298daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod  }
2034f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod
2044ad2cc5dec6b0639da2b1846282bdd99d06d5ff1Behdad Esfahbod  inline bool check_range (const void *base, unsigned int len) const
20598daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod  {
206a82ef7a893b773a17f7548375de9f588dfc83abaBehdad Esfahbod    const char *p = (const char *) base;
20798daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod
208cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod    hb_auto_trace_t<HB_DEBUG_SANITIZE> trace (&this->debug_depth, "SANITIZE", this->blob, NULL,
209cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod					      "check_range [%p..%p] (%d bytes) in [%p..%p]",
210cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod					      p, p + len, len,
211cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod					      this->start, this->end);
21298daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod
213cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod    return TRACE_RETURN (likely (this->start <= p && p <= this->end && (unsigned int) (this->end - p) >= len));
21498daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod  }
215577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod
2161cd1e117d060d38e314618b627d7663cb01ed584Behdad Esfahbod  inline bool check_array (const void *base, unsigned int record_size, unsigned int len) const
21798daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod  {
218a82ef7a893b773a17f7548375de9f588dfc83abaBehdad Esfahbod    const char *p = (const char *) base;
219080a0eb7d82d7195be72c16ece6e0a3ffed636b6Behdad Esfahbod    bool overflows = _hb_unsigned_int_mul_overflows (len, record_size);
22041895506cb6a41b1a833866f8822261ea449ea0bBehdad Esfahbod
221cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod    hb_auto_trace_t<HB_DEBUG_SANITIZE> trace (&this->debug_depth, "SANITIZE", this->blob, NULL,
222cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod					      "check_array [%p..%p] (%d*%d=%ld bytes) in [%p..%p]",
223cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod					      p, p + (record_size * len), record_size, len, (unsigned long) record_size * len,
224cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod					      this->start, this->end);
225fa030175ca998b00cc42cbced6e98de323ec01ecBehdad Esfahbod
226cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod    return TRACE_RETURN (likely (!overflows && this->check_range (base, record_size * len)));
22798daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod  }
228254933c397f1ce9796f59689a25f9fc2e58df4eaBehdad Esfahbod
229b157617644d1e38f680163889d1dc2e2f64d9ba3Behdad Esfahbod  template <typename Type>
230b157617644d1e38f680163889d1dc2e2f64d9ba3Behdad Esfahbod  inline bool check_struct (const Type *obj) const
231b157617644d1e38f680163889d1dc2e2f64d9ba3Behdad Esfahbod  {
23254842374c2b291ef208c51ae1d853ec0403ccf84Behdad Esfahbod    return likely (this->check_range (obj, obj->min_size));
233b157617644d1e38f680163889d1dc2e2f64d9ba3Behdad Esfahbod  }
234b157617644d1e38f680163889d1dc2e2f64d9ba3Behdad Esfahbod
235cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod  inline bool may_edit (const void *base HB_UNUSED, unsigned int len HB_UNUSED)
23698daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod  {
237a82ef7a893b773a17f7548375de9f588dfc83abaBehdad Esfahbod    const char *p = (const char *) base;
23898daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod    this->edit_count++;
23998daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod
240cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod    hb_auto_trace_t<HB_DEBUG_SANITIZE> trace (&this->debug_depth, "SANITIZE", this->blob, NULL,
241cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod					      "may_edit(%u) [%p..%p] (%d bytes) in [%p..%p] -> %s",
242cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod					      this->edit_count,
243cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod					      p, p + len, len,
244cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod					      this->start, this->end);
24598daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod
246cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod    return TRACE_RETURN (this->writable);
24798daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod  }
24898daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod
249cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod  mutable unsigned int debug_depth;
25098daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod  const char *start, *end;
25198daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod  bool writable;
25298daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod  unsigned int edit_count;
25398daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod  hb_blob_t *blob;
25498daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod};
255815a73e4202ca17677f12e862b70ca8724cf2f57Behdad Esfahbod
256577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod
257577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod
2584e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod/* Template to sanitize an object. */
2594e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbodtemplate <typename Type>
2604e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbodstruct Sanitizer
2614e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod{
2624e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod  static hb_blob_t *sanitize (hb_blob_t *blob) {
263d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod    hb_sanitize_context_t c[1] = {{0}};
2644e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod    bool sane;
2654e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod
266d0b657379bbe63602953412d6bc944b2a0f430ebBehdad Esfahbod    /* TODO is_sane() stuff */
2674e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod
2681c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod    c->init (blob);
2691c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod
2704e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod  retry:
271cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod    DEBUG_MSG_FUNC (SANITIZE, blob, "start");
2724f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod
273cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod    c->start_processing ();
2744e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod
275d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod    if (unlikely (!c->start)) {
276cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod      c->end_processing ();
27748146e5612f6d272d6962f6829c6d64a31edef89Behdad Esfahbod      return blob;
27848146e5612f6d272d6962f6829c6d64a31edef89Behdad Esfahbod    }
27948146e5612f6d272d6962f6829c6d64a31edef89Behdad Esfahbod
280d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod    Type *t = CastP<Type> (const_cast<char *> (c->start));
2814e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod
282d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod    sane = t->sanitize (c);
2834e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod    if (sane) {
284d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod      if (c->edit_count) {
285cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod	DEBUG_MSG_FUNC (SANITIZE, blob, "passed first round with %d edits; going for second round", c->edit_count);
286fa030175ca998b00cc42cbced6e98de323ec01ecBehdad Esfahbod
2878b5346130425c7c101f6ff2432874ba2fd372edcBehdad Esfahbod        /* sanitize again to ensure no toe-stepping */
288d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod        c->edit_count = 0;
289d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod	sane = t->sanitize (c);
290d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod	if (c->edit_count) {
291cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod	  DEBUG_MSG_FUNC (SANITIZE, blob, "requested %d edits in second round; FAILLING", c->edit_count);
2924e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod	  sane = false;
2934e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod	}
2944e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod      }
2954e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod    } else {
296d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod      unsigned int edit_count = c->edit_count;
2971c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod      if (edit_count && !c->writable) {
2981c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod        c->start = hb_blob_get_data_writable (blob, NULL);
2991c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod	c->end = c->start + hb_blob_get_length (blob);
3001c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod
3011c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod	if (c->start) {
3021c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod	  c->writable = true;
3031c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod	  /* ok, we made it writable by relocating.  try again */
304cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod	  DEBUG_MSG_FUNC (SANITIZE, blob, "retry");
3051c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod	  goto retry;
3061c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod	}
3074e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod      }
3084e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod    }
3094e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod
310cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod    c->end_processing ();
3114101ca7dbbdf1438fa116fb8cad935501ac7cca8Behdad Esfahbod
312cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod    DEBUG_MSG_FUNC (SANITIZE, blob, sane ? "PASSED" : "FAILED");
3134e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod    if (sane)
3144e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod      return blob;
3154e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod    else {
3164e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod      hb_blob_destroy (blob);
3174911062d5be0d937ee8f1a70cc93e05d162f45b3Behdad Esfahbod      return hb_blob_get_empty ();
3184e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod    }
3194e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod  }
320b435ab7e29c388e3b100f729957319931625a3a8Behdad Esfahbod
321b435ab7e29c388e3b100f729957319931625a3a8Behdad Esfahbod  static const Type* lock_instance (hb_blob_t *blob) {
3221c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod    hb_blob_make_immutable (blob);
3231c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod    const char *base = hb_blob_get_data (blob, NULL);
324b435ab7e29c388e3b100f729957319931625a3a8Behdad Esfahbod    return unlikely (!base) ? &Null(Type) : CastP<Type> (base);
325b435ab7e29c388e3b100f729957319931625a3a8Behdad Esfahbod  }
3264e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod};
3274e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod
3282d15e72c75931398db5e027e660f1320bb979117Behdad Esfahbod
329f0abcd69408a3af65207cdf8847575ade4579bd4Behdad Esfahbod
330e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod/*
331e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod * Serialize
332e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod */
333e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod
334e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod#ifndef HB_DEBUG_SERIALIZE
335e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod#define HB_DEBUG_SERIALIZE (HB_DEBUG+0)
336e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod#endif
337e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod
338e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod
339e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod#define TRACE_SERIALIZE() \
3409f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod	hb_auto_trace_t<HB_DEBUG_SERIALIZE> trace (&c->debug_depth, "SERIALIZE", c, HB_FUNC, "");
341e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod
342e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod
343e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbodstruct hb_serialize_context_t
344e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod{
345e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod  inline void init (void *start, unsigned int size)
346e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod  {
347e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod    this->start = (char *) start;
348e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod    this->end = this->start + size;
349e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod  }
350e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod
351e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod  inline void start_processing (void)
352e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod  {
353e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod    this->ran_out_of_room = false;
354e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod    this->head = this->start;
355e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod    this->debug_depth = 0;
356e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod
357e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod    DEBUG_MSG_LEVEL (SERIALIZE, this->start, 0, +1,
358e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod		     "start [%p..%p] (%lu bytes)",
359e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod		     this->start, this->end,
360e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod		     (unsigned long) (this->end - this->start));
361e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod  }
362e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod
363e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod  inline void end_processing (void)
364e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod  {
365e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod    DEBUG_MSG_LEVEL (SERIALIZE, this->start, 0, -1,
366e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod		     "end [%p..%p] %s",
367e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod		     this->start, this->end,
368e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod		     this->ran_out_of_room ? "RAN OUT OF ROOM" : "did not ran out of room");
369e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod
370e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod    this->start = this->end = this->head = NULL;
371e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod  }
372e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod
373e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod  template <typename Type>
374bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod  inline Type *allocate_size (unsigned int size, unsigned int alignment = 1)
375e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod  {
376bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod    unsigned int padding = alignment < 2 ? 0 : (alignment - (this->head - this->start) % alignment) % alignment;
377e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod    if (unlikely (this->ran_out_of_room || this->end - this->head > padding + size)) {
378e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod      this->ran_out_of_room = true;
379e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod      return NULL;
380e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod    }
381bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod    memset (this->head, 0, padding + size);
382e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod    this->head += padding;
3839f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod    char *ret = this->head;
384e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod    this->head += size;
385e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod    return reinterpret_cast<Type *> (ret);
386e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod  }
387e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod
388e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod  template <typename Type>
3899f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod  inline Type *allocate_min (unsigned int alignment = 2)
3909f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod  {
391bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod    return this->allocate_size<Type> (Type::min_size, alignment);
3929f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod  }
3939f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod
3949f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod  template <typename Type>
395e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod  inline Type *embed (const Type &obj, unsigned int alignment = 2)
396e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod  {
397bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod    unsigned int size = obj.get_size ();
398bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod    Type *ret = this->allocate_size<Type> (size, alignment);
399bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod    if (unlikely (!ret)) return NULL;
400bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod    memcpy (ret, obj, size);
401bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod    return ret;
4029f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod  }
4039f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod
4049f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod  template <typename Type>
405bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod  inline Type *extend_min (Type &obj, unsigned int alignment = 2)
4069f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod  {
407bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod    unsigned int size = obj.min_size;
4089f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod    assert (this->start < (char *) &obj && (char *) &obj <= this->head && (char *) &obj + size >= this->head);
409bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod    this->allocate_size<Type> (((char *) &obj) + size - this->head, alignment);
4109f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod    return reinterpret_cast<Type *> (&obj);
4119f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod  }
4129f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod
4139f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod  template <typename Type>
414bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod  inline Type *extend (Type &obj, unsigned int alignment = 2)
4159f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod  {
416bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod    unsigned int size = obj.get_size ();
417bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod    assert (this->start < (char *) &obj && (char *) &obj <= this->head && (char *) &obj + size >= this->head);
418bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod    this->allocate_size<Type> (((char *) &obj) + size - this->head, alignment);
419bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod    return reinterpret_cast<Type *> (&obj);
420e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod  }
421e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod
422e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod  inline void truncate (void *head)
423e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod  {
424e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod    assert (this->start < head && head <= this->head);
425e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod    this->head = (char *) head;
426e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod  }
427e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod
428e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod  unsigned int debug_depth;
429e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod  char *start, *end, *head;
430e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod  bool ran_out_of_room;
431e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod};
432e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod
433e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod
434f0abcd69408a3af65207cdf8847575ade4579bd4Behdad Esfahbod
435b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod/*
436b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod *
437bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod * The OpenType Font File: Data Types
438b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod */
439b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod
440b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod
441b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod/* "The following data types are used in the OpenType font file.
442b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod *  All OpenType fonts use Motorola-style byte ordering (Big Endian):" */
443b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod
4445f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod/*
4455f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod * Int types
4465f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod */
4475f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod
4486b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod
449d7bf473ef222ab420456ff155ffaa09bacb3a394Behdad Esfahbodtemplate <typename Type, int Bytes> struct BEInt;
450e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod
451e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodtemplate <typename Type>
452d7bf473ef222ab420456ff155ffaa09bacb3a394Behdad Esfahbodstruct BEInt<Type, 2>
453e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod{
454e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod  public:
45581408cd51ce575891e79e6483be187130f864c28Behdad Esfahbod  inline void set (Type i) { hb_be_uint16_put (v,i); }
4567f97d2cd904ea999c099c73c52187c5d65aeec67Behdad Esfahbod  inline operator Type (void) const { return hb_be_uint16_get (v); }
457153142dac8dd9abaf164bb88af07c600c17fc3a1Behdad Esfahbod  inline bool operator == (const BEInt<Type, 2>& o) const { return hb_be_uint16_eq (v, o.v); }
45801c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod  inline bool operator != (const BEInt<Type, 2>& o) const { return !(*this == o); }
459e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod  private: uint8_t v[2];
460e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod};
461e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodtemplate <typename Type>
462d7bf473ef222ab420456ff155ffaa09bacb3a394Behdad Esfahbodstruct BEInt<Type, 4>
463e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod{
464e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod  public:
46581408cd51ce575891e79e6483be187130f864c28Behdad Esfahbod  inline void set (Type i) { hb_be_uint32_put (v,i); }
4667f97d2cd904ea999c099c73c52187c5d65aeec67Behdad Esfahbod  inline operator Type (void) const { return hb_be_uint32_get (v); }
467153142dac8dd9abaf164bb88af07c600c17fc3a1Behdad Esfahbod  inline bool operator == (const BEInt<Type, 4>& o) const { return hb_be_uint32_eq (v, o.v); }
46801c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod  inline bool operator != (const BEInt<Type, 4>& o) const { return !(*this == o); }
469e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod  private: uint8_t v[4];
470e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod};
471e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod
4722467c669c2aee4de2a6621a9d06cba0262376d41Behdad Esfahbod/* Integer types in big-endian order and no alignment requirement */
473e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodtemplate <typename Type>
474e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodstruct IntType
475e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod{
47681408cd51ce575891e79e6483be187130f864c28Behdad Esfahbod  inline void set (Type i) { v.set (i); }
47701c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod  inline operator Type(void) const { return v; }
47801c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod  inline bool operator == (const IntType<Type> &o) const { return v == o.v; }
47901c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod  inline bool operator != (const IntType<Type> &o) const { return v != o.v; }
4804e573715ae5f5ed486ad66382bb44c47a86591ffBehdad Esfahbod  inline int cmp (Type a) const { Type b = v; return a < b ? -1 : a == b ? 0 : +1; }
481d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *c) {
482e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod    TRACE_SANITIZE ();
4830ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod    return TRACE_RETURN (likely (c->check_struct (this)));
484e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod  }
485a82ef7a893b773a17f7548375de9f588dfc83abaBehdad Esfahbod  protected:
486569da92bc6956f42d9b2d65c784e184fb6380efeBehdad Esfahbod  BEInt<Type, sizeof (Type)> v;
487569da92bc6956f42d9b2d65c784e184fb6380efeBehdad Esfahbod  public:
488e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod  DEFINE_SIZE_STATIC (sizeof (Type));
489e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod};
490e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod
491e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodtypedef IntType<uint16_t> USHORT;	/* 16-bit unsigned integer. */
492e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodtypedef IntType<int16_t>  SHORT;	/* 16-bit signed integer. */
493e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodtypedef IntType<uint32_t> ULONG;	/* 32-bit unsigned integer. */
494e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodtypedef IntType<int32_t>  LONG;		/* 32-bit signed integer. */
495e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod
496ae9877dea6a1aed3566d9b87a75ede84259deacaBehdad Esfahbod/* 16-bit signed integer (SHORT) that describes a quantity in FUnits. */
497ae9877dea6a1aed3566d9b87a75ede84259deacaBehdad Esfahbodtypedef SHORT FWORD;
498ae9877dea6a1aed3566d9b87a75ede84259deacaBehdad Esfahbod
499ae9877dea6a1aed3566d9b87a75ede84259deacaBehdad Esfahbod/* 16-bit unsigned integer (USHORT) that describes a quantity in FUnits. */
500ae9877dea6a1aed3566d9b87a75ede84259deacaBehdad Esfahbodtypedef USHORT UFWORD;
501ae9877dea6a1aed3566d9b87a75ede84259deacaBehdad Esfahbod
502e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod/* Date represented in number of seconds since 12:00 midnight, January 1,
503e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod * 1904. The value is represented as a signed 64-bit integer. */
504e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbodstruct LONGDATETIME
505e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod{
506e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *c) {
507e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod    TRACE_SANITIZE ();
5080ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod    return TRACE_RETURN (likely (c->check_struct (this)));
509e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod  }
510e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod  private:
511e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod  LONG major;
512e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod  ULONG minor;
513e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod  public:
514e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod  DEFINE_SIZE_STATIC (8);
515e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod};
516e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod
5176b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod/* Array of four uint8s (length = 32 bits) used to identify a script, language
5186b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod * system, feature, or baseline */
51920cc86b3592db33731de671f008d7d222776be49Behdad Esfahbodstruct Tag : ULONG
52060d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
521befc022affd2386b3f46cd7d11e4262f6c8bce9fBehdad Esfahbod  /* What the char* converters return is NOT nul-terminated.  Print using "%.4s" */
522a82ef7a893b773a17f7548375de9f588dfc83abaBehdad Esfahbod  inline operator const char* (void) const { return reinterpret_cast<const char *> (&this->v); }
523a82ef7a893b773a17f7548375de9f588dfc83abaBehdad Esfahbod  inline operator char* (void) { return reinterpret_cast<char *> (&this->v); }
524b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod  public:
525b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod  DEFINE_SIZE_STATIC (4);
5266b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod};
52765f46b00333e20ab8a52a4b350747507541ec1dbBehdad EsfahbodDEFINE_NULL_DATA (Tag, "    ");
5286b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod
5296b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod/* Glyph index number, same as uint16 (length = 16 bits) */
5306ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbodtypedef USHORT GlyphID;
5316b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod
532b5db4f1e4eefa266a71a28b5496f47ff9d1a81e8Behdad Esfahbod/* Script/language-system/feature index */
533b5db4f1e4eefa266a71a28b5496f47ff9d1a81e8Behdad Esfahbodstruct Index : USHORT {
534b5db4f1e4eefa266a71a28b5496f47ff9d1a81e8Behdad Esfahbod  static const unsigned int NOT_FOUND_INDEX = 0xFFFF;
535b5db4f1e4eefa266a71a28b5496f47ff9d1a81e8Behdad Esfahbod};
536b5db4f1e4eefa266a71a28b5496f47ff9d1a81e8Behdad EsfahbodDEFINE_NULL_DATA (Index, "\xff\xff");
537b5db4f1e4eefa266a71a28b5496f47ff9d1a81e8Behdad Esfahbod
5381f437e6f47fb6c15761021bd2078f31778f2179cBehdad Esfahbod/* Offset to a table, same as uint16 (length = 16 bits), Null offset = 0x0000 */
5396ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbodtypedef USHORT Offset;
5406ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbod
5416ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbod/* LongOffset to a table, same as uint32 (length = 32 bits), Null offset = 0x00000000 */
5426ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbodtypedef ULONG LongOffset;
5436ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbod
5446b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod
5456b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod/* CheckSum */
54660d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbodstruct CheckSum : ULONG
54760d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
54860d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  static uint32_t CalcTableChecksum (ULONG *Table, uint32_t Length)
54960d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  {
5506b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod    uint32_t Sum = 0L;
551e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod    ULONG *EndPtr = Table+((Length+3) & ~3) / ULONG::static_size;
5526b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod
5536b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod    while (Table < EndPtr)
5546b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod      Sum += *Table++;
5556b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod    return Sum;
5566b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod  }
557b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod  public:
558b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod  DEFINE_SIZE_STATIC (4);
5596b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod};
5606b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod
5616b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod
5626b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod/*
5636b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod * Version Numbers
5646b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod */
5656b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod
56687fcdcbe3644da10154688765db2d62eb9ac079aBehdad Esfahbodstruct FixedVersion
56760d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
5684f28fbdd804fabeec57a98fe267d892ab58b3a6dBehdad Esfahbod  inline uint32_t to_int (void) const { return (major << 16) + minor; }
56996908b898476ca5d7da5f386b15be76f9e83d76eBehdad Esfahbod
570d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *c) {
5713e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
5720ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod    return TRACE_RETURN (c->check_struct (this));
573cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod  }
574cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod
5756ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbod  USHORT major;
57687fcdcbe3644da10154688765db2d62eb9ac079aBehdad Esfahbod  USHORT minor;
577b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod  public:
578b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod  DEFINE_SIZE_STATIC (4);
5796b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod};
5806b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod
58192b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod
58292b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod
5835f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod/*
58492b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod * Template subclasses of Offset and LongOffset that do the dereferencing.
585f0abcd69408a3af65207cdf8847575ade4579bd4Behdad Esfahbod * Use: (base+offset)
5865f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod */
5875f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod
58892b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename OffsetType, typename Type>
58992b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct GenericOffsetTo : OffsetType
59092b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod{
59100e23fcc6fd0eee5c582251bf3de6a2703fbbd3eBehdad Esfahbod  inline const Type& operator () (const void *base) const
59292b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod  {
59392b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod    unsigned int offset = *this;
59464d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod    if (unlikely (!offset)) return Null(Type);
59509766b1ec5ec55a61edbcd7a89ed3613cc92d4cbBehdad Esfahbod    return StructAtOffset<Type> (base, offset);
59692b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod  }
597bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod  inline Type& operator () (void *base)
598bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod  {
599bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod    unsigned int offset = *this;
600bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod    return StructAtOffset<Type> (base, offset);
601bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod  }
602bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod
603bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod  inline void set_offset (void *base, void *obj)
604bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod  {
605bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod    this->set ((char *) obj - (char *) base);
606bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod  }
60792b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod
608d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *c, void *base) {
6093e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
6100ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod    if (unlikely (!c->check_struct (this))) return TRACE_RETURN (false);
61192b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod    unsigned int offset = *this;
6120ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod    if (unlikely (!offset)) return TRACE_RETURN (true);
61309766b1ec5ec55a61edbcd7a89ed3613cc92d4cbBehdad Esfahbod    Type &obj = StructAtOffset<Type> (base, offset);
6140ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod    return TRACE_RETURN (likely (obj.sanitize (c)) || neuter (c));
61592b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod  }
6164a446ac35136eff23d55f47bdd7b40095ad707abBehdad Esfahbod  template <typename T>
617d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *c, void *base, T user_data) {
6183e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
6190ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod    if (unlikely (!c->check_struct (this))) return TRACE_RETURN (false);
62042b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod    unsigned int offset = *this;
6210ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod    if (unlikely (!offset)) return TRACE_RETURN (true);
62209766b1ec5ec55a61edbcd7a89ed3613cc92d4cbBehdad Esfahbod    Type &obj = StructAtOffset<Type> (base, offset);
6230ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod    return TRACE_RETURN (likely (obj.sanitize (c, user_data)) || neuter (c));
624c9f14687a30866181feb57ee2736a147ec9f25a1Behdad Esfahbod  }
625c9f14687a30866181feb57ee2736a147ec9f25a1Behdad Esfahbod
626c9f14687a30866181feb57ee2736a147ec9f25a1Behdad Esfahbod  private:
627c9f14687a30866181feb57ee2736a147ec9f25a1Behdad Esfahbod  /* Set the offset to Null */
628d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod  inline bool neuter (hb_sanitize_context_t *c) {
629cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod    if (c->may_edit (this, this->static_size)) {
630c9f14687a30866181feb57ee2736a147ec9f25a1Behdad Esfahbod      this->set (0); /* 0 is Null offset */
631c9f14687a30866181feb57ee2736a147ec9f25a1Behdad Esfahbod      return true;
632c9f14687a30866181feb57ee2736a147ec9f25a1Behdad Esfahbod    }
633c9f14687a30866181feb57ee2736a147ec9f25a1Behdad Esfahbod    return false;
63442b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod  }
63592b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod};
63692b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Base, typename OffsetType, typename Type>
637bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbodinline const Type& operator + (const Base &base, const GenericOffsetTo<OffsetType, Type> &offset) { return offset (base); }
638bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbodtemplate <typename Base, typename OffsetType, typename Type>
639bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbodinline Type& operator + (Base &base, GenericOffsetTo<OffsetType, Type> &offset) { return offset (base); }
64092b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod
6415f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbodtemplate <typename Type>
64292b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct OffsetTo : GenericOffsetTo<Offset, Type> {};
64392b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod
64492b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Type>
64592b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct LongOffsetTo : GenericOffsetTo<LongOffset, Type> {};
646bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod
647bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod
64892b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod/*
64992b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod * Array Types
65092b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod */
65192b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod
65292b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename LenType, typename Type>
65392b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct GenericArrayOf
65460d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
6554f5f1c34dda1e0629bfa6d7b0ffa2e1ce003b7c7Behdad Esfahbod  const Type *sub_array (unsigned int start_offset, unsigned int *pcount /* IN/OUT */) const
65648de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod  {
65748de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod    unsigned int count = len;
65864d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod    if (unlikely (start_offset > count))
65948de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod      count = 0;
66048de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod    else
66148de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod      count -= start_offset;
66248de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod    count = MIN (count, *pcount);
66348de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod    *pcount = count;
664b961518b9611471ff7060e97686e5625974847ebBehdad Esfahbod    return array + start_offset;
66548de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod  }
66648de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod
66760d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  inline const Type& operator [] (unsigned int i) const
66860d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  {
66964d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod    if (unlikely (i >= len)) return Null(Type);
670b961518b9611471ff7060e97686e5625974847ebBehdad Esfahbod    return array[i];
6715f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod  }
6729f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod  inline Type& operator [] (unsigned int i)
6739f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod  {
6749f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod    return array[i];
6759f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod  }
6767f97d2cd904ea999c099c73c52187c5d65aeec67Behdad Esfahbod  inline unsigned int get_size (void) const
677e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod  { return len.static_size + len * Type::static_size; }
678e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod
679d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *c) {
6803e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
6810ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod    if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false);
68211e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod
68340d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod    /* Note: for structs that do not reference other structs,
68440d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod     * we do not need to call their sanitize() as we already did
68511e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod     * a bound check on the aggregate array size.  We just include
68611e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod     * a small unreachable expression to make sure the structs
68711e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod     * pointed to do have a simple sanitize(), ie. they do not
68811e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod     * reference other structs via offsets.
68940d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod     */
69011e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod    (void) (false && array[0].sanitize (c));
69111e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod
6920ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod    return TRACE_RETURN (true);
69370de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod  }
694d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *c, void *base) {
6953e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
6960ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod    if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false);
697e6ab2c59ba2d37942ac5fcbfe61d38b7e359ac8cBehdad Esfahbod    unsigned int count = len;
698e6ab2c59ba2d37942ac5fcbfe61d38b7e359ac8cBehdad Esfahbod    for (unsigned int i = 0; i < count; i++)
699d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod      if (unlikely (!array[i].sanitize (c, base)))
7000ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod        return TRACE_RETURN (false);
7010ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod    return TRACE_RETURN (true);
702e6ab2c59ba2d37942ac5fcbfe61d38b7e359ac8cBehdad Esfahbod  }
7034a446ac35136eff23d55f47bdd7b40095ad707abBehdad Esfahbod  template <typename T>
704d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *c, void *base, T user_data) {
7053e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
7060ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod    if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false);
70742b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod    unsigned int count = len;
70842b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod    for (unsigned int i = 0; i < count; i++)
709d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod      if (unlikely (!array[i].sanitize (c, base, user_data)))
7100ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod        return TRACE_RETURN (false);
7110ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod    return TRACE_RETURN (true);
71242b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod  }
71370de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod
71430fa2821c277df99a14089749313dfe2b541e2d0Behdad Esfahbod  private:
715d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod  inline bool sanitize_shallow (hb_sanitize_context_t *c) {
71630fa2821c277df99a14089749313dfe2b541e2d0Behdad Esfahbod    TRACE_SANITIZE ();
7170ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod    return TRACE_RETURN (c->check_struct (this) && c->check_array (this, Type::static_size, len));
71830fa2821c277df99a14089749313dfe2b541e2d0Behdad Esfahbod  }
71930fa2821c277df99a14089749313dfe2b541e2d0Behdad Esfahbod
72030fa2821c277df99a14089749313dfe2b541e2d0Behdad Esfahbod  public:
72192b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod  LenType len;
722b961518b9611471ff7060e97686e5625974847ebBehdad Esfahbod  Type array[VAR];
723b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod  public:
7240eb9fc6e37935707dba2bf4b3705de2161a08cb7Behdad Esfahbod  DEFINE_SIZE_ARRAY (sizeof (LenType), array);
725e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod};
726e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod
72792b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod/* An array with a USHORT number of elements. */
72892b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Type>
72992b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct ArrayOf : GenericArrayOf<USHORT, Type> {};
73092b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod
73192b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod/* An array with a ULONG number of elements. */
73292b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Type>
73392b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct LongArrayOf : GenericArrayOf<ULONG, Type> {};
73492b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod
73592b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod/* Array of Offset's */
73692b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Type>
73792b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct OffsetArrayOf : ArrayOf<OffsetTo<Type> > {};
73892b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod
73992b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod/* Array of LongOffset's */
74092b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Type>
74192b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct LongOffsetArrayOf : ArrayOf<LongOffsetTo<Type> > {};
74292b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod
74392b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod/* LongArray of LongOffset's */
74492b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Type>
74592b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct LongOffsetLongArrayOf : LongArrayOf<LongOffsetTo<Type> > {};
74692b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod
74780e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod/* Array of offsets relative to the beginning of the array itself. */
74880e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbodtemplate <typename Type>
74980e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbodstruct OffsetListOf : OffsetArrayOf<Type>
75080e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod{
75180e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod  inline const Type& operator [] (unsigned int i) const
75280e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod  {
75364d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod    if (unlikely (i >= this->len)) return Null(Type);
754b961518b9611471ff7060e97686e5625974847ebBehdad Esfahbod    return this+this->array[i];
75580e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod  }
75680e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod
757d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *c) {
7583e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
7590ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod    return TRACE_RETURN (OffsetArrayOf<Type>::sanitize (c, this));
76080e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod  }
7614a446ac35136eff23d55f47bdd7b40095ad707abBehdad Esfahbod  template <typename T>
762d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *c, T user_data) {
7633e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
7640ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod    return TRACE_RETURN (OffsetArrayOf<Type>::sanitize (c, this, user_data));
76580e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod  }
76680e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod};
76780e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod
76880e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod
769e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod/* An array with a USHORT number of elements,
770e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod * starting at second element. */
771e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbodtemplate <typename Type>
77260d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbodstruct HeadlessArrayOf
77360d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
77460d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  inline const Type& operator [] (unsigned int i) const
77560d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  {
77664d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod    if (unlikely (i >= len || !i)) return Null(Type);
777b961518b9611471ff7060e97686e5625974847ebBehdad Esfahbod    return array[i-1];
778e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod  }
7797f97d2cd904ea999c099c73c52187c5d65aeec67Behdad Esfahbod  inline unsigned int get_size (void) const
780e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod  { return len.static_size + (len ? len - 1 : 0) * Type::static_size; }
7815f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod
782d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod  inline bool sanitize_shallow (hb_sanitize_context_t *c) {
783d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod    return c->check_struct (this)
784d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod	&& c->check_array (this, Type::static_size, len);
785e5546a4352c54311ac4a9ef138b187378155ebe1Behdad Esfahbod  }
786e5546a4352c54311ac4a9ef138b187378155ebe1Behdad Esfahbod
787d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *c) {
7883e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
7890ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod    if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false);
79011e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod
79140d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod    /* Note: for structs that do not reference other structs,
79240d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod     * we do not need to call their sanitize() as we already did
79311e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod     * a bound check on the aggregate array size.  We just include
79411e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod     * a small unreachable expression to make sure the structs
79511e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod     * pointed to do have a simple sanitize(), ie. they do not
79611e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod     * reference other structs via offsets.
79740d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod     */
79811e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod    (void) (false && array[0].sanitize (c));
79911e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod
8000ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod    return TRACE_RETURN (true);
80170de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod  }
80270de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod
8035f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod  USHORT len;
804b961518b9611471ff7060e97686e5625974847ebBehdad Esfahbod  Type array[VAR];
805ed07422c33bbb52ff4d79e65986171e3f07697d8Behdad Esfahbod  public:
8060eb9fc6e37935707dba2bf4b3705de2161a08cb7Behdad Esfahbod  DEFINE_SIZE_ARRAY (sizeof (USHORT), array);
8075f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod};
8085f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod
8096b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod
810cc8a4abea68f2dba26feb5785f9e518e6853c744Behdad Esfahbod/* An array with sorted elements.  Supports binary searching. */
811cc8a4abea68f2dba26feb5785f9e518e6853c744Behdad Esfahbodtemplate <typename Type>
812cc8a4abea68f2dba26feb5785f9e518e6853c744Behdad Esfahbodstruct SortedArrayOf : ArrayOf<Type> {
813cc8a4abea68f2dba26feb5785f9e518e6853c744Behdad Esfahbod
814cc8a4abea68f2dba26feb5785f9e518e6853c744Behdad Esfahbod  template <typename SearchType>
815cc8a4abea68f2dba26feb5785f9e518e6853c744Behdad Esfahbod  inline int search (const SearchType &x) const {
81699159e52a3c9d5ae6c0fbdec64e7ed684fa70b61Behdad Esfahbod    unsigned int count = this->len;
81799159e52a3c9d5ae6c0fbdec64e7ed684fa70b61Behdad Esfahbod    /* Linear search is *much* faster for small counts. */
81899159e52a3c9d5ae6c0fbdec64e7ed684fa70b61Behdad Esfahbod    if (likely (count < 32)) {
81999159e52a3c9d5ae6c0fbdec64e7ed684fa70b61Behdad Esfahbod      for (unsigned int i = 0; i < count; i++)
82099159e52a3c9d5ae6c0fbdec64e7ed684fa70b61Behdad Esfahbod	if (this->array[i].cmp (x) == 0)
82199159e52a3c9d5ae6c0fbdec64e7ed684fa70b61Behdad Esfahbod	  return i;
82299159e52a3c9d5ae6c0fbdec64e7ed684fa70b61Behdad Esfahbod      return -1;
82399159e52a3c9d5ae6c0fbdec64e7ed684fa70b61Behdad Esfahbod    } else {
82499159e52a3c9d5ae6c0fbdec64e7ed684fa70b61Behdad Esfahbod      struct Cmp {
82599159e52a3c9d5ae6c0fbdec64e7ed684fa70b61Behdad Esfahbod	static int cmp (const SearchType *a, const Type *b) { return b->cmp (*a); }
82699159e52a3c9d5ae6c0fbdec64e7ed684fa70b61Behdad Esfahbod      };
82799159e52a3c9d5ae6c0fbdec64e7ed684fa70b61Behdad Esfahbod      const Type *p = (const Type *) bsearch (&x, this->array, this->len, sizeof (this->array[0]), (hb_compare_func_t) Cmp::cmp);
82899159e52a3c9d5ae6c0fbdec64e7ed684fa70b61Behdad Esfahbod      return p ? p - this->array : -1;
82999159e52a3c9d5ae6c0fbdec64e7ed684fa70b61Behdad Esfahbod    }
830cc8a4abea68f2dba26feb5785f9e518e6853c744Behdad Esfahbod  }
831cc8a4abea68f2dba26feb5785f9e518e6853c744Behdad Esfahbod};
832cc8a4abea68f2dba26feb5785f9e518e6853c744Behdad Esfahbod
833cc8a4abea68f2dba26feb5785f9e518e6853c744Behdad Esfahbod
8347c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod} // namespace OT
8357c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod
836acdba3f90b232fc12fcb200dca2584481b339118Behdad Esfahbod
8371e91434569a9e9535ef021ca52b60b2e2af75d19Behdad Esfahbod#endif /* HB_OPEN_TYPE_PRIVATE_HH */
838