hb-open-type-private.hh revision d632ec4000b3079150e6424e88a3ab7509f7445c
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
35c85c3620675f38ffdca59134aeec2641485f40caBehdad Esfahbod/* Table/script/language-system/feature/... not found */
36706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod#define NO_INDEX		((unsigned int) 0xFFFF)
375a0b791184cf6ef39eae0570e14aca21abc32845Behdad Esfahbod
38706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
39a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbod
40196598bbccff08415ff5192314cba044df258cadBehdad Esfahbod/*
41196598bbccff08415ff5192314cba044df258cadBehdad Esfahbod * Casts
42196598bbccff08415ff5192314cba044df258cadBehdad Esfahbod */
43196598bbccff08415ff5192314cba044df258cadBehdad Esfahbod
440dfcc13a4668cdd2c2ebdd5f4a7540a51222cf2fBehdad Esfahbod/* Cast to "const char *" and "char *" */
45a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbodtemplate <typename Type>
46a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbodinline const char * CharP (const Type* X)
47a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbod{ return reinterpret_cast<const char *>(X); }
48a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbodtemplate <typename Type>
49a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbodinline char * CharP (Type* X)
50a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbod{ return reinterpret_cast<char *>(X); }
512b5a59c277f4c5bf7aac9a9005054763e322e02dBehdad Esfahbod
52a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbod/* Cast to struct T& */
53a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbodtemplate<typename Type, typename TObject>
54a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbodinline const Type& Cast(const TObject &X)
55a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbod{ return reinterpret_cast<const Type&> (X); }
56a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbodtemplate<typename Type, typename TObject>
57a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbodinline Type& Cast(TObject &X)
58a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbod{ return reinterpret_cast<Type&> (X); }
59196598bbccff08415ff5192314cba044df258cadBehdad Esfahbod
60a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbod/* StructAtOffset<T>(X,Ofs) returns the struct T& that is placed at memory
61a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbod * location of X plus Ofs bytes. */
62a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbodtemplate<typename Type, typename TObject>
63a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbodinline const Type& StructAtOffset(const TObject &X, unsigned int offset)
64d632ec4000b3079150e6424e88a3ab7509f7445cBehdad Esfahbod{ return * reinterpret_cast<const Type*> (CharP(&X) + offset); }
65a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbodtemplate<typename Type, typename TObject>
66a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbodinline Type& StructAtOffset(TObject &X, unsigned int offset)
67d632ec4000b3079150e6424e88a3ab7509f7445cBehdad Esfahbod{ return * reinterpret_cast<Type*> (CharP(&X) + 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)
73a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbod{ return StructAtOffset<Type>(X, X.get_size()); }
74e961c86c579fd98ee604342a9c70c4e7f8d4f220Behdad Esfahbodtemplate<typename Type, typename TObject>
75e961c86c579fd98ee604342a9c70c4e7f8d4f220Behdad Esfahbodinline Type& StructAfter(TObject &X)
76a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbod{ return StructAtOffset<Type>(X, X.get_size()); }
77a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbod
78e961c86c579fd98ee604342a9c70c4e7f8d4f220Behdad Esfahbod
79d3480ba37fbb5d4be75b094060f5b2f1ce98fb53Behdad Esfahbod
8070de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod/*
81600e5eb80f553ea8eb862e6784133574c74ca513Behdad Esfahbod * Class features
82600e5eb80f553ea8eb862e6784133574c74ca513Behdad Esfahbod */
83600e5eb80f553ea8eb862e6784133574c74ca513Behdad Esfahbod
848b8358033184198ff638ee1379093717596e162dBehdad Esfahbod
858b8358033184198ff638ee1379093717596e162dBehdad Esfahbod/* Null objects */
868b8358033184198ff638ee1379093717596e162dBehdad Esfahbod
878b8358033184198ff638ee1379093717596e162dBehdad Esfahbod/* Global nul-content Null pool.  Enlarge as necessary. */
889d3677899f90abdc7fb3e3d854db654a8707a84bBehdad Esfahbodstatic const void *_NullPool[32 / sizeof (void *)];
898b8358033184198ff638ee1379093717596e162dBehdad Esfahbod
908b8358033184198ff638ee1379093717596e162dBehdad Esfahbod/* Generic template for nul-content sizeof-sized Null objects. */
918b8358033184198ff638ee1379093717596e162dBehdad Esfahbodtemplate <typename Type>
929d3677899f90abdc7fb3e3d854db654a8707a84bBehdad Esfahbodstatic inline const Type& Null () {
939d3677899f90abdc7fb3e3d854db654a8707a84bBehdad Esfahbod  ASSERT_STATIC (sizeof (Type) <= sizeof (_NullPool));
94a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbod  return Cast<Type> (*_NullPool);
959d3677899f90abdc7fb3e3d854db654a8707a84bBehdad Esfahbod}
968b8358033184198ff638ee1379093717596e162dBehdad Esfahbod
978b8358033184198ff638ee1379093717596e162dBehdad Esfahbod/* Specializaiton for arbitrary-content arbitrary-sized Null objects. */
988b8358033184198ff638ee1379093717596e162dBehdad Esfahbod#define DEFINE_NULL_DATA(Type, size, data) \
99565c80bd2960366ace2d10dd71beaaf2a80213c8Behdad Esfahbodstatic const char _Null##Type[size + 1] = data; /* +1 is for nul-termination in data */ \
1008b8358033184198ff638ee1379093717596e162dBehdad Esfahbodtemplate <> \
1019d3677899f90abdc7fb3e3d854db654a8707a84bBehdad Esfahbodinline const Type& Null<Type> () { \
102a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbod  return Cast<Type> (*_Null##Type); \
103565c80bd2960366ace2d10dd71beaaf2a80213c8Behdad Esfahbod} /* The following line really exists such that we end in a place needing semicolon */ \
104565c80bd2960366ace2d10dd71beaaf2a80213c8Behdad EsfahbodASSERT_STATIC (sizeof (Type) + 1 <= sizeof (_Null##Type))
1058b8358033184198ff638ee1379093717596e162dBehdad Esfahbod
1068b8358033184198ff638ee1379093717596e162dBehdad Esfahbod/* Accessor macro. */
1079d3677899f90abdc7fb3e3d854db654a8707a84bBehdad Esfahbod#define Null(Type) Null<Type>()
1088b8358033184198ff638ee1379093717596e162dBehdad Esfahbod
1098b8358033184198ff638ee1379093717596e162dBehdad Esfahbod
110600e5eb80f553ea8eb862e6784133574c74ca513Behdad Esfahbod/* get_for_data() is a static class method returning a reference to an
111600e5eb80f553ea8eb862e6784133574c74ca513Behdad Esfahbod * instance of Type located at the input data location.  It's just a
11254e5aac5e2947d4e2864c6f2987e4d275da73100Behdad Esfahbod * fancy, NULL-safe, cast! */
113fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod#define STATIC_DEFINE_GET_FOR_DATA(Type) \
11460d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  static inline const Type& get_for_data (const char *data) \
11560d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  { \
1168b8358033184198ff638ee1379093717596e162dBehdad Esfahbod    if (HB_UNLIKELY (data == NULL)) return Null(Type); \
117a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbod    return Cast<Type> (*data); \
118212aba6189d7aaac0bab169b77ae6bdab16800a5Behdad Esfahbod  }
119212aba6189d7aaac0bab169b77ae6bdab16800a5Behdad Esfahbod/* Like get_for_data(), but checks major version first. */
120cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod#define STATIC_DEFINE_GET_FOR_DATA_CHECK_MAJOR_VERSION(Type, MajorMin, MajorMax) \
121212aba6189d7aaac0bab169b77ae6bdab16800a5Behdad Esfahbod  static inline const Type& get_for_data (const char *data) \
122212aba6189d7aaac0bab169b77ae6bdab16800a5Behdad Esfahbod  { \
123212aba6189d7aaac0bab169b77ae6bdab16800a5Behdad Esfahbod    if (HB_UNLIKELY (data == NULL)) return Null(Type); \
124a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbod    const Type& t = Cast<Type> (*data); \
125cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod    if (HB_UNLIKELY (t.version.major < MajorMin || t.version.major > MajorMax)) return Null(Type); \
126212aba6189d7aaac0bab169b77ae6bdab16800a5Behdad Esfahbod    return t; \
127212aba6189d7aaac0bab169b77ae6bdab16800a5Behdad Esfahbod  }
128600e5eb80f553ea8eb862e6784133574c74ca513Behdad Esfahbod
129600e5eb80f553ea8eb862e6784133574c74ca513Behdad Esfahbod
130577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod/*
131577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod * Sanitize
132577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod */
133577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod
13495e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod#ifndef HB_DEBUG_SANITIZE
13595e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod#define HB_DEBUG_SANITIZE HB_DEBUG
13695e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod#endif
13795e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod
13895e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod#if HB_DEBUG_SANITIZE
139d0351314cd29fbdf0efb5c7f89a569648f7a7fc7Behdad Esfahbod#include <stdio.h>
1400e206de98621ed8a55824b42e9e6bf320f4c6cc8Behdad Esfahbod#define TRACE_SANITIZE_ARG_DEF	, unsigned int sanitize_depth HB_GNUC_UNUSED
1413e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod#define TRACE_SANITIZE_ARG	, sanitize_depth + 1
1423e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod#define TRACE_SANITIZE_ARG_INIT	, 1
1433e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod#define TRACE_SANITIZE() \
144b28815c1f6e46d38471cacbc31248ca6fda8c4d1Behdad Esfahbod	HB_STMT_START { \
14595e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod	    if (sanitize_depth < HB_DEBUG_SANITIZE) \
1467acb389569cf99c6bae9db31a8ed7c7007fbb566Behdad Esfahbod		fprintf (stderr, "SANITIZE(%p) %-*d-> %s\n", \
147d632ec4000b3079150e6424e88a3ab7509f7445cBehdad Esfahbod			 (CharP(this) == CharP(&NullPool)) ? 0 : this, \
1489b76a290a94f2603f3cb9498ae976125347cf54bBehdad Esfahbod			 sanitize_depth, sanitize_depth, \
1497acb389569cf99c6bae9db31a8ed7c7007fbb566Behdad Esfahbod			 __PRETTY_FUNCTION__); \
150b28815c1f6e46d38471cacbc31248ca6fda8c4d1Behdad Esfahbod	} HB_STMT_END
151b28815c1f6e46d38471cacbc31248ca6fda8c4d1Behdad Esfahbod#else
1523e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod#define TRACE_SANITIZE_ARG_DEF
1533e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod#define TRACE_SANITIZE_ARG
1543e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod#define TRACE_SANITIZE_ARG_INIT
1553e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod#define TRACE_SANITIZE() HB_STMT_START {} HB_STMT_END
156b28815c1f6e46d38471cacbc31248ca6fda8c4d1Behdad Esfahbod#endif
157b28815c1f6e46d38471cacbc31248ca6fda8c4d1Behdad Esfahbod
15841895506cb6a41b1a833866f8822261ea449ea0bBehdad Esfahbod#define SANITIZE_ARG_DEF \
1593e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod	hb_sanitize_context_t *context TRACE_SANITIZE_ARG_DEF
16041895506cb6a41b1a833866f8822261ea449ea0bBehdad Esfahbod#define SANITIZE_ARG \
1613e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod	context TRACE_SANITIZE_ARG
16241895506cb6a41b1a833866f8822261ea449ea0bBehdad Esfahbod#define SANITIZE_ARG_INIT \
1633e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod	&context TRACE_SANITIZE_ARG_INIT
16441895506cb6a41b1a833866f8822261ea449ea0bBehdad Esfahbod
165577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbodtypedef struct _hb_sanitize_context_t hb_sanitize_context_t;
166577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbodstruct _hb_sanitize_context_t
167577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod{
168577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod  const char *start, *end;
169577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod  int edit_count;
170577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod  hb_blob_t *blob;
171577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod};
172577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod
173577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbodstatic HB_GNUC_UNUSED void
1744e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod_hb_sanitize_init (hb_sanitize_context_t *context,
1754e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod		   hb_blob_t *blob)
176577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod{
177577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod  context->blob = blob;
178577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod  context->start = hb_blob_lock (blob);
179577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod  context->end = context->start + hb_blob_get_length (blob);
180577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod  context->edit_count = 0;
1814f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod
18295e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod#if HB_DEBUG_SANITIZE
1837acb389569cf99c6bae9db31a8ed7c7007fbb566Behdad Esfahbod  fprintf (stderr, "sanitize %p init [%p..%p] (%u bytes)\n",
1847f96b39a9d5a81ba77e0c3dea8fe2cdb9957c4c7Behdad Esfahbod	   context->blob, context->start, context->end, context->end - context->start);
1854f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod#endif
186577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod}
187577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod
188577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbodstatic HB_GNUC_UNUSED void
1894e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod_hb_sanitize_fini (hb_sanitize_context_t *context,
1904e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod		   bool unlock)
191577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod{
19295e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod#if HB_DEBUG_SANITIZE
1937acb389569cf99c6bae9db31a8ed7c7007fbb566Behdad Esfahbod  fprintf (stderr, "sanitize %p fini [%p..%p] %u edit requests\n",
1947acb389569cf99c6bae9db31a8ed7c7007fbb566Behdad Esfahbod	   context->blob, context->start, context->end, context->edit_count);
1954f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod#endif
1964f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod
197577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod  if (unlock)
198577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod    hb_blob_unlock (context->blob);
199577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod}
200577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod
2014f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbodstatic HB_GNUC_UNUSED inline bool
20241895506cb6a41b1a833866f8822261ea449ea0bBehdad Esfahbod_hb_sanitize_check (SANITIZE_ARG_DEF,
20341895506cb6a41b1a833866f8822261ea449ea0bBehdad Esfahbod		    const char *base,
20441895506cb6a41b1a833866f8822261ea449ea0bBehdad Esfahbod		    unsigned int len)
20541895506cb6a41b1a833866f8822261ea449ea0bBehdad Esfahbod{
206ae728e51e94d18d731b7c8dc524da1a4f427d63bBehdad Esfahbod  bool ret = context->start <= base &&
207ae728e51e94d18d731b7c8dc524da1a4f427d63bBehdad Esfahbod	     base <= context->end &&
208ae728e51e94d18d731b7c8dc524da1a4f427d63bBehdad Esfahbod	     (unsigned int) (context->end - base) >= len;
209ae728e51e94d18d731b7c8dc524da1a4f427d63bBehdad Esfahbod
21095e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod#if HB_DEBUG_SANITIZE
21195e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod  if (sanitize_depth < HB_DEBUG_SANITIZE) \
212ae728e51e94d18d731b7c8dc524da1a4f427d63bBehdad Esfahbod    fprintf (stderr, "SANITIZE(%p) %-*d-> check [%p..%p] (%d bytes) in [%p..%p] -> %s\n", \
213ae728e51e94d18d731b7c8dc524da1a4f427d63bBehdad Esfahbod	     base,
214ae728e51e94d18d731b7c8dc524da1a4f427d63bBehdad Esfahbod	     sanitize_depth, sanitize_depth,
215ae728e51e94d18d731b7c8dc524da1a4f427d63bBehdad Esfahbod	     base, base+len, len,
216ae728e51e94d18d731b7c8dc524da1a4f427d63bBehdad Esfahbod	     context->start, context->end,
217ae728e51e94d18d731b7c8dc524da1a4f427d63bBehdad Esfahbod	     ret ? "pass" : "FAIL");
218ae728e51e94d18d731b7c8dc524da1a4f427d63bBehdad Esfahbod#endif
219ae728e51e94d18d731b7c8dc524da1a4f427d63bBehdad Esfahbod  return ret;
22041895506cb6a41b1a833866f8822261ea449ea0bBehdad Esfahbod}
22141895506cb6a41b1a833866f8822261ea449ea0bBehdad Esfahbod
22241895506cb6a41b1a833866f8822261ea449ea0bBehdad Esfahbodstatic HB_GNUC_UNUSED inline bool
223815a73e4202ca17677f12e862b70ca8724cf2f57Behdad Esfahbod_hb_sanitize_array (SANITIZE_ARG_DEF,
224815a73e4202ca17677f12e862b70ca8724cf2f57Behdad Esfahbod		    const char *base,
225815a73e4202ca17677f12e862b70ca8724cf2f57Behdad Esfahbod		    unsigned int record_size,
226815a73e4202ca17677f12e862b70ca8724cf2f57Behdad Esfahbod		    unsigned int len)
227815a73e4202ca17677f12e862b70ca8724cf2f57Behdad Esfahbod{
228815a73e4202ca17677f12e862b70ca8724cf2f57Behdad Esfahbod  bool overflows = len >= ((unsigned int) -1) / record_size;
229815a73e4202ca17677f12e862b70ca8724cf2f57Behdad Esfahbod
23095e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod#if HB_DEBUG_SANITIZE
23195e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod  if (sanitize_depth < HB_DEBUG_SANITIZE) \
232815a73e4202ca17677f12e862b70ca8724cf2f57Behdad Esfahbod    fprintf (stderr, "SANITIZE(%p) %-*d-> array [%p..%p] (%d*%d=%ld bytes) in [%p..%p] -> %s\n", \
233815a73e4202ca17677f12e862b70ca8724cf2f57Behdad Esfahbod	     base,
234815a73e4202ca17677f12e862b70ca8724cf2f57Behdad Esfahbod	     sanitize_depth, sanitize_depth,
235815a73e4202ca17677f12e862b70ca8724cf2f57Behdad Esfahbod	     base, base + (record_size * len), record_size, len, (unsigned long) record_size * len,
236815a73e4202ca17677f12e862b70ca8724cf2f57Behdad Esfahbod	     context->start, context->end,
237815a73e4202ca17677f12e862b70ca8724cf2f57Behdad Esfahbod	     !overflows ? "does not overflow" : "OVERFLOWS FAIL");
238815a73e4202ca17677f12e862b70ca8724cf2f57Behdad Esfahbod#endif
239815a73e4202ca17677f12e862b70ca8724cf2f57Behdad Esfahbod  return HB_LIKELY (!overflows) && _hb_sanitize_check (SANITIZE_ARG, base, record_size * len);
240815a73e4202ca17677f12e862b70ca8724cf2f57Behdad Esfahbod}
241815a73e4202ca17677f12e862b70ca8724cf2f57Behdad Esfahbod
242815a73e4202ca17677f12e862b70ca8724cf2f57Behdad Esfahbodstatic HB_GNUC_UNUSED inline bool
24341895506cb6a41b1a833866f8822261ea449ea0bBehdad Esfahbod_hb_sanitize_edit (SANITIZE_ARG_DEF,
2444f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod		   const char *base HB_GNUC_UNUSED,
2454f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod		   unsigned int len HB_GNUC_UNUSED)
246577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod{
247977eeb714454630bd045bb11f58ff6397f10b143Behdad Esfahbod  bool perm = hb_blob_try_writable_inplace (context->blob);
248f4b58d3fc2956a9d1b6178588d809c781f7a5c0cBehdad Esfahbod  context->edit_count++;
2494f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod
25095e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod#if HB_DEBUG_SANITIZE
251ae728e51e94d18d731b7c8dc524da1a4f427d63bBehdad Esfahbod  fprintf (stderr, "SANITIZE(%p) %-*d-> edit(%u) [%p..%p] (%d bytes) in [%p..%p] -> %s\n", \
252ae728e51e94d18d731b7c8dc524da1a4f427d63bBehdad Esfahbod	   base,
253ae728e51e94d18d731b7c8dc524da1a4f427d63bBehdad Esfahbod	   sanitize_depth, sanitize_depth,
254ae728e51e94d18d731b7c8dc524da1a4f427d63bBehdad Esfahbod	   context->edit_count,
255ae728e51e94d18d731b7c8dc524da1a4f427d63bBehdad Esfahbod	   base, base+len, len,
256ae728e51e94d18d731b7c8dc524da1a4f427d63bBehdad Esfahbod	   context->start, context->end,
257ae728e51e94d18d731b7c8dc524da1a4f427d63bBehdad Esfahbod	   perm ? "granted" : "REJECTED");
2584f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod#endif
2594f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod  return perm;
260577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod}
261577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod
262577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod#define SANITIZE(X) HB_LIKELY ((X).sanitize (SANITIZE_ARG))
263577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod#define SANITIZE2(X,Y) (SANITIZE (X) && SANITIZE (Y))
264577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod
26562c0fd75737a69721dbf29e773405a4c529f8b6dBehdad Esfahbod#define SANITIZE_THIS(X) HB_LIKELY ((X).sanitize (SANITIZE_ARG, CharP(this)))
266577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod#define SANITIZE_THIS2(X,Y) (SANITIZE_THIS (X) && SANITIZE_THIS (Y))
267577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod#define SANITIZE_THIS3(X,Y,Z) (SANITIZE_THIS (X) && SANITIZE_THIS (Y) && SANITIZE_THIS(Z))
268577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod
269577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod#define SANITIZE_BASE(X,B) HB_LIKELY ((X).sanitize (SANITIZE_ARG, B))
270577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod#define SANITIZE_BASE2(X,Y,B) (SANITIZE_BASE (X,B) && SANITIZE_BASE (Y,B))
271577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod
272577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod#define SANITIZE_SELF() SANITIZE_OBJ (*this)
273577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod#define SANITIZE_OBJ(X) SANITIZE_MEM(&(X), sizeof (X))
274577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod
2750dfcc13a4668cdd2c2ebdd5f4a7540a51222cf2fBehdad Esfahbod#define SANITIZE_MEM(B,L) HB_LIKELY (_hb_sanitize_check (SANITIZE_ARG, CharP(B), (L)))
276577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod
2770dfcc13a4668cdd2c2ebdd5f4a7540a51222cf2fBehdad Esfahbod#define SANITIZE_ARRAY(A,S,L) HB_LIKELY (_hb_sanitize_array (SANITIZE_ARG, CharP(A), S, L))
278815a73e4202ca17677f12e862b70ca8724cf2f57Behdad Esfahbod
279d0b657379bbe63602953412d6bc944b2a0f430ebBehdad Esfahbod#define NEUTER(Var, Val) \
280d0b657379bbe63602953412d6bc944b2a0f430ebBehdad Esfahbod	(SANITIZE_OBJ (Var) && \
2811faa76c6e848c6b0e360d9ddcf567533b87f8f31Behdad Esfahbod	 _hb_sanitize_edit (SANITIZE_ARG, CharP(&(Var)), (Var).get_size ()) && \
282807b8aa486753474e05e09f4fcca8ac94021b97cBehdad Esfahbod	 ((Var).set (Val), true))
283577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod
284577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod
2854e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod/* Template to sanitize an object. */
2864e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbodtemplate <typename Type>
2874e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbodstruct Sanitizer
2884e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod{
2894e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod  static hb_blob_t *sanitize (hb_blob_t *blob) {
2904e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod    hb_sanitize_context_t context;
2914e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod    bool sane;
2924e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod
293d0b657379bbe63602953412d6bc944b2a0f430ebBehdad Esfahbod    /* TODO is_sane() stuff */
2944e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod
2954e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod  retry:
29695e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod#if HB_DEBUG_SANITIZE
2977acb389569cf99c6bae9db31a8ed7c7007fbb566Behdad Esfahbod    fprintf (stderr, "Sanitizer %p start %s\n", blob, __PRETTY_FUNCTION__);
2984f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod#endif
2994f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod
3004e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod    _hb_sanitize_init (&context, blob);
3014e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod
302c293581e962b7982622e7d607fa3909b40da718eBehdad Esfahbod    /* We drop const here */
303a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbod    Type *t = &Cast<Type> (* (char *) CharP(context.start));
3044e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod
305b28815c1f6e46d38471cacbc31248ca6fda8c4d1Behdad Esfahbod    sane = t->sanitize (SANITIZE_ARG_INIT);
3064e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod    if (sane) {
3074e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod      if (context.edit_count) {
30895e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod#if HB_DEBUG_SANITIZE
3090d77ab8a73f57c9fca4c6f9301dae394d79526e3Behdad Esfahbod	fprintf (stderr, "Sanitizer %p passed first round with %d edits; going a second round %s\n",
3100d77ab8a73f57c9fca4c6f9301dae394d79526e3Behdad Esfahbod		 blob, context.edit_count, __PRETTY_FUNCTION__);
3110d77ab8a73f57c9fca4c6f9301dae394d79526e3Behdad Esfahbod#endif
3128b5346130425c7c101f6ff2432874ba2fd372edcBehdad Esfahbod        /* sanitize again to ensure no toe-stepping */
3134e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod        context.edit_count = 0;
314b28815c1f6e46d38471cacbc31248ca6fda8c4d1Behdad Esfahbod	sane = t->sanitize (SANITIZE_ARG_INIT);
3154e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod	if (context.edit_count) {
31695e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod#if HB_DEBUG_SANITIZE
317ae728e51e94d18d731b7c8dc524da1a4f427d63bBehdad Esfahbod	  fprintf (stderr, "Sanitizer %p requested %d edits in second round; FAILLING %s\n",
3180d77ab8a73f57c9fca4c6f9301dae394d79526e3Behdad Esfahbod		   blob, context.edit_count, __PRETTY_FUNCTION__);
3190d77ab8a73f57c9fca4c6f9301dae394d79526e3Behdad Esfahbod#endif
3204e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod	  sane = false;
3214e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod	}
3224e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod      }
3234e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod      _hb_sanitize_fini (&context, true);
3244e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod    } else {
3254f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod      unsigned int edit_count = context.edit_count;
3264e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod      _hb_sanitize_fini (&context, true);
327977eeb714454630bd045bb11f58ff6397f10b143Behdad Esfahbod      if (edit_count && !hb_blob_is_writable (blob) && hb_blob_try_writable (blob)) {
328977eeb714454630bd045bb11f58ff6397f10b143Behdad Esfahbod        /* ok, we made it writable by relocating.  try again */
32995e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod#if HB_DEBUG_SANITIZE
3307acb389569cf99c6bae9db31a8ed7c7007fbb566Behdad Esfahbod	fprintf (stderr, "Sanitizer %p retry %s\n", blob, __PRETTY_FUNCTION__);
3314f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod#endif
3324e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod        goto retry;
3334e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod      }
3344e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod    }
3354e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod
33695e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod#if HB_DEBUG_SANITIZE
337ae728e51e94d18d731b7c8dc524da1a4f427d63bBehdad Esfahbod    fprintf (stderr, "Sanitizer %p %s %s\n", blob, sane ? "passed" : "FAILED", __PRETTY_FUNCTION__);
3384f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod#endif
3394e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod    if (sane)
3404e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod      return blob;
3414e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod    else {
3424e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod      hb_blob_destroy (blob);
3434e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod      return hb_blob_create_empty ();
3444e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod    }
3454e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod  }
3464e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod
347d60bb8ca2ae6edf29b2227b56c57f0d16879370bBehdad Esfahbod  static const Type& lock_instance (hb_blob_t *blob) {
3484e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod    return Type::get_for_data (hb_blob_lock (blob));
3494e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod  }
3504e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod};
3514e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod
3522d15e72c75931398db5e027e660f1320bb979117Behdad Esfahbod
353b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod/*
354b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod *
355bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod * The OpenType Font File: Data Types
356b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod */
357b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod
358b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod
359b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod/* "The following data types are used in the OpenType font file.
360b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod *  All OpenType fonts use Motorola-style byte ordering (Big Endian):" */
361b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod
3625f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod/*
3635f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod * Int types
3645f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod */
3655f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod
3666b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod
367e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodtemplate <typename Type, int Bytes> class BEInt;
368e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod
369e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodtemplate <typename Type>
370e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodclass BEInt<Type, 2>
371e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod{
372e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod  public:
37301c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod  inline class BEInt<Type,2>& operator = (Type i) { hb_be_uint16_put (v,i); return *this; }
37401c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod  inline operator Type () const { return hb_be_uint16_get (v); }
37501c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod  inline bool operator == (const BEInt<Type, 2>& o) const { return hb_be_uint16_cmp (v, o.v); }
37601c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod  inline bool operator != (const BEInt<Type, 2>& o) const { return !(*this == o); }
377e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod  private: uint8_t v[2];
378e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod};
379e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodtemplate <typename Type>
380e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodclass BEInt<Type, 4>
381e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod{
382e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod  public:
38301c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod  inline class BEInt<Type,4>& operator = (Type i) { hb_be_uint32_put (v,i); return *this; }
38401c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod  inline operator Type () const { return hb_be_uint32_get (v); }
38501c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod  inline bool operator == (const BEInt<Type, 4>& o) const { return hb_be_uint32_cmp (v, o.v); }
38601c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod  inline bool operator != (const BEInt<Type, 4>& o) const { return !(*this == o); }
387e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod  private: uint8_t v[4];
388e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod};
389e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod
3902467c669c2aee4de2a6621a9d06cba0262376d41Behdad Esfahbod/* Integer types in big-endian order and no alignment requirement */
391e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodtemplate <typename Type>
392e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodstruct IntType
393e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod{
394e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod  static inline unsigned int get_size () { return sizeof (Type); }
39501c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod  inline void set (Type i) { v = i; }
39601c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod  inline operator Type(void) const { return v; }
39701c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod  inline bool operator == (const IntType<Type> &o) const { return v == o.v; }
39801c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod  inline bool operator != (const IntType<Type> &o) const { return v != o.v; }
399e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod  inline bool sanitize (SANITIZE_ARG_DEF) {
400e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod    TRACE_SANITIZE ();
401e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod    return SANITIZE_SELF ();
402e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod  }
403e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod  private: BEInt<Type, sizeof (Type)> v;
404e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod};
405e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod
406e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodtypedef IntType<uint16_t> USHORT;	/* 16-bit unsigned integer. */
407e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodtypedef IntType<int16_t>  SHORT;	/* 16-bit signed integer. */
408e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodtypedef IntType<uint32_t> ULONG;	/* 32-bit unsigned integer. */
409e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodtypedef IntType<int32_t>  LONG;		/* 32-bit signed integer. */
410e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod
411e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad EsfahbodASSERT_SIZE (USHORT, 2);
412e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad EsfahbodASSERT_SIZE (SHORT, 2);
413e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad EsfahbodASSERT_SIZE (ULONG, 4);
414e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad EsfahbodASSERT_SIZE (LONG, 4);
415bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod
4166b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod/* Array of four uint8s (length = 32 bits) used to identify a script, language
4176b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod * system, feature, or baseline */
41820cc86b3592db33731de671f008d7d222776be49Behdad Esfahbodstruct Tag : ULONG
41960d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
420befc022affd2386b3f46cd7d11e4262f6c8bce9fBehdad Esfahbod  /* What the char* converters return is NOT nul-terminated.  Print using "%.4s" */
4210dfcc13a4668cdd2c2ebdd5f4a7540a51222cf2fBehdad Esfahbod  inline operator const char* (void) const { return CharP(this); }
422198facdc55756cb48cdfb8ba7fa50916fac54ec3Behdad Esfahbod  inline operator char* (void) { return CharP(this); }
4236b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod};
424303fe62824d4e99df554b6bfaacba05d068522fbBehdad EsfahbodASSERT_SIZE (Tag, 4);
4259d3677899f90abdc7fb3e3d854db654a8707a84bBehdad EsfahbodDEFINE_NULL_DATA (Tag, 4, "    ");
4266b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod
4276b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod/* Glyph index number, same as uint16 (length = 16 bits) */
4286ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbodtypedef USHORT GlyphID;
4296b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad 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;
4434b8487d83e0c10076a6c573cb3487790ce366607Behdad Esfahbod    ULONG *EndPtr = Table+((Length+3) & ~3) / ULONG::get_size ();
4446b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod
4456b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod    while (Table < EndPtr)
4466b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod      Sum += *Table++;
4476b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod    return Sum;
4486b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod  }
4496b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod};
4508b8358033184198ff638ee1379093717596e162dBehdad EsfahbodASSERT_SIZE (CheckSum, 4);
4516b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod
4526b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod
4536b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod/*
4546b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod * Version Numbers
4556b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod */
4566b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod
45787fcdcbe3644da10154688765db2d62eb9ac079aBehdad Esfahbodstruct FixedVersion
45860d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
45909c292e3b688a67fbae67b645d1e6ffcf8d8eb6eBehdad Esfahbod  inline operator uint32_t (void) const { return (major << 16) + minor; }
46096908b898476ca5d7da5f386b15be76f9e83d76eBehdad Esfahbod
461cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod  inline bool sanitize (SANITIZE_ARG_DEF) {
4623e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
463cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod    return SANITIZE_SELF ();
464cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod  }
465cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod
4666ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbod  USHORT major;
46787fcdcbe3644da10154688765db2d62eb9ac079aBehdad Esfahbod  USHORT minor;
4686b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod};
46987fcdcbe3644da10154688765db2d62eb9ac079aBehdad EsfahbodASSERT_SIZE (FixedVersion, 4);
4706b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod
47192b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod
47292b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod
4735f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod/*
47492b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod * Template subclasses of Offset and LongOffset that do the dereferencing.
47592b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod * Use: (this+memberName)
4765f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod */
4775f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod
47892b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename OffsetType, typename Type>
47992b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct GenericOffsetTo : OffsetType
48092b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod{
48100e23fcc6fd0eee5c582251bf3de6a2703fbbd3eBehdad Esfahbod  inline const Type& operator () (const void *base) const
48292b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod  {
48392b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod    unsigned int offset = *this;
48492b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod    if (HB_UNLIKELY (!offset)) return Null(Type);
485a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbod    return StructAtOffset<Type> (*CharP(base), offset);
48692b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod  }
48792b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod
48862c0fd75737a69721dbf29e773405a4c529f8b6dBehdad Esfahbod  inline bool sanitize (SANITIZE_ARG_DEF, void *base) {
4893e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
49095528131b5ab9fc9e265ace715832135ebd457a4Behdad Esfahbod    if (!SANITIZE_SELF ()) return false;
49192b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod    unsigned int offset = *this;
49292b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod    if (HB_UNLIKELY (!offset)) return true;
493a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbod    return SANITIZE (StructAtOffset<Type> (*CharP(base), offset)) || NEUTER (*this, 0);
49492b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod  }
49562c0fd75737a69721dbf29e773405a4c529f8b6dBehdad Esfahbod  inline bool sanitize (SANITIZE_ARG_DEF, void *base, void *base2) {
4963e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
49795528131b5ab9fc9e265ace715832135ebd457a4Behdad Esfahbod    if (!SANITIZE_SELF ()) return false;
498b508e5ccd528f3f0f49f545bd5f30a525d5abd5aBehdad Esfahbod    unsigned int offset = *this;
499b508e5ccd528f3f0f49f545bd5f30a525d5abd5aBehdad Esfahbod    if (HB_UNLIKELY (!offset)) return true;
500a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbod    return SANITIZE_BASE (StructAtOffset<Type> (*CharP(base), offset), base2) || NEUTER (*this, 0);
501b508e5ccd528f3f0f49f545bd5f30a525d5abd5aBehdad Esfahbod  }
50262c0fd75737a69721dbf29e773405a4c529f8b6dBehdad Esfahbod  inline bool sanitize (SANITIZE_ARG_DEF, void *base, unsigned int user_data) {
5033e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
50495528131b5ab9fc9e265ace715832135ebd457a4Behdad Esfahbod    if (!SANITIZE_SELF ()) return false;
50542b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod    unsigned int offset = *this;
50642b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod    if (HB_UNLIKELY (!offset)) return true;
507a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbod    return SANITIZE_BASE (StructAtOffset<Type> (*CharP(base), offset), user_data) || NEUTER (*this, 0);
50842b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod  }
50992b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod};
51092b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Base, typename OffsetType, typename Type>
51192b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodinline const Type& operator + (const Base &base, GenericOffsetTo<OffsetType, Type> offset) { return offset (base); }
51292b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod
5135f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbodtemplate <typename Type>
51492b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct OffsetTo : GenericOffsetTo<Offset, Type> {};
51592b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod
51692b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Type>
51792b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct LongOffsetTo : GenericOffsetTo<LongOffset, Type> {};
518bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod
519bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod
52092b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod/*
52192b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod * Array Types
52292b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod */
52392b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod
52492b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename LenType, typename Type>
52592b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct GenericArrayOf
52660d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
5272cb08458f674301cde9d962c13911035a251f7c5Behdad Esfahbod  const Type *array(void) const { return &StructAfter<Type> (len); }
5282e2f43edf2f49f4047e28b1ce2ea95938536de9cBehdad Esfahbod  Type *array(void) { return &StructAfter<Type> (len); }
529d3480ba37fbb5d4be75b094060f5b2f1ce98fb53Behdad Esfahbod
5304f5f1c34dda1e0629bfa6d7b0ffa2e1ce003b7c7Behdad Esfahbod  const Type *sub_array (unsigned int start_offset, unsigned int *pcount /* IN/OUT */) const
53148de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod  {
53248de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod    unsigned int count = len;
53348de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod    if (HB_UNLIKELY (start_offset > count))
53448de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod      count = 0;
53548de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod    else
53648de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod      count -= start_offset;
53748de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod    count = MIN (count, *pcount);
53848de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod    *pcount = count;
5392cb08458f674301cde9d962c13911035a251f7c5Behdad Esfahbod    return array() + start_offset;
54048de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod  }
54148de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod
54260d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  inline const Type& operator [] (unsigned int i) const
54360d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  {
5445f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod    if (HB_UNLIKELY (i >= len)) return Null(Type);
5452cb08458f674301cde9d962c13911035a251f7c5Behdad Esfahbod    return array()[i];
5465f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod  }
54760d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  inline unsigned int get_size () const
5484b8487d83e0c10076a6c573cb3487790ce366607Behdad Esfahbod  { return len.get_size () + len * Type::get_size (); }
549e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod
550e5546a4352c54311ac4a9ef138b187378155ebe1Behdad Esfahbod  inline bool sanitize_shallow (SANITIZE_ARG_DEF) {
551e5546a4352c54311ac4a9ef138b187378155ebe1Behdad Esfahbod    TRACE_SANITIZE ();
552e5546a4352c54311ac4a9ef138b187378155ebe1Behdad Esfahbod    return SANITIZE_SELF() && SANITIZE_ARRAY (this, Type::get_size (), len);
553e5546a4352c54311ac4a9ef138b187378155ebe1Behdad Esfahbod  }
554e5546a4352c54311ac4a9ef138b187378155ebe1Behdad Esfahbod
55520b035dad41247076815a2bbb0346d63058b322fBehdad Esfahbod  inline bool sanitize (SANITIZE_ARG_DEF) {
5563e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
557e5546a4352c54311ac4a9ef138b187378155ebe1Behdad Esfahbod    if (!HB_LIKELY (sanitize_shallow (SANITIZE_ARG))) 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++)
568d3480ba37fbb5d4be75b094060f5b2f1ce98fb53Behdad Esfahbod      if (!SANITIZE (array()[i]))
56970de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod        return false;
5709bd629ccd064e739789e504c41ad875eed93abbaBehdad Esfahbod    return true;
57170de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod  }
57262c0fd75737a69721dbf29e773405a4c529f8b6dBehdad Esfahbod  inline bool sanitize (SANITIZE_ARG_DEF, void *base) {
5733e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
574e5546a4352c54311ac4a9ef138b187378155ebe1Behdad Esfahbod    if (!HB_LIKELY (sanitize_shallow (SANITIZE_ARG))) return false;
575e6ab2c59ba2d37942ac5fcbfe61d38b7e359ac8cBehdad Esfahbod    unsigned int count = len;
576e6ab2c59ba2d37942ac5fcbfe61d38b7e359ac8cBehdad Esfahbod    for (unsigned int i = 0; i < count; i++)
577d3480ba37fbb5d4be75b094060f5b2f1ce98fb53Behdad Esfahbod      if (!array()[i].sanitize (SANITIZE_ARG, base))
578e6ab2c59ba2d37942ac5fcbfe61d38b7e359ac8cBehdad Esfahbod        return false;
5799bd629ccd064e739789e504c41ad875eed93abbaBehdad Esfahbod    return true;
580e6ab2c59ba2d37942ac5fcbfe61d38b7e359ac8cBehdad Esfahbod  }
58162c0fd75737a69721dbf29e773405a4c529f8b6dBehdad Esfahbod  inline bool sanitize (SANITIZE_ARG_DEF, void *base, void *base2) {
5823e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
583e5546a4352c54311ac4a9ef138b187378155ebe1Behdad Esfahbod    if (!HB_LIKELY (sanitize_shallow (SANITIZE_ARG))) return false;
584b508e5ccd528f3f0f49f545bd5f30a525d5abd5aBehdad Esfahbod    unsigned int count = len;
585b508e5ccd528f3f0f49f545bd5f30a525d5abd5aBehdad Esfahbod    for (unsigned int i = 0; i < count; i++)
586d3480ba37fbb5d4be75b094060f5b2f1ce98fb53Behdad Esfahbod      if (!array()[i].sanitize (SANITIZE_ARG, base, base2))
587b508e5ccd528f3f0f49f545bd5f30a525d5abd5aBehdad Esfahbod        return false;
5889bd629ccd064e739789e504c41ad875eed93abbaBehdad Esfahbod    return true;
589b508e5ccd528f3f0f49f545bd5f30a525d5abd5aBehdad Esfahbod  }
59062c0fd75737a69721dbf29e773405a4c529f8b6dBehdad Esfahbod  inline bool sanitize (SANITIZE_ARG_DEF, void *base, unsigned int user_data) {
5913e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
592e5546a4352c54311ac4a9ef138b187378155ebe1Behdad Esfahbod    if (!HB_LIKELY (sanitize_shallow (SANITIZE_ARG))) return false;
59342b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod    unsigned int count = len;
59442b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod    for (unsigned int i = 0; i < count; i++)
595d3480ba37fbb5d4be75b094060f5b2f1ce98fb53Behdad Esfahbod      if (!array()[i].sanitize (SANITIZE_ARG, base, user_data))
59642b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod        return false;
5979bd629ccd064e739789e504c41ad875eed93abbaBehdad Esfahbod    return true;
59842b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod  }
59970de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod
60092b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod  LenType len;
601d3480ba37fbb5d4be75b094060f5b2f1ce98fb53Behdad Esfahbod/*Type array[VAR];*/
602e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod};
603e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod
60492b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod/* An array with a USHORT number of elements. */
60592b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Type>
60692b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct ArrayOf : GenericArrayOf<USHORT, Type> {};
60792b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod
60892b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod/* An array with a ULONG number of elements. */
60992b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Type>
61092b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct LongArrayOf : GenericArrayOf<ULONG, Type> {};
61192b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod
61292b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod/* Array of Offset's */
61392b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Type>
61492b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct OffsetArrayOf : ArrayOf<OffsetTo<Type> > {};
61592b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod
61692b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod/* Array of LongOffset's */
61792b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Type>
61892b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct LongOffsetArrayOf : ArrayOf<LongOffsetTo<Type> > {};
61992b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod
62092b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod/* LongArray of LongOffset's */
62192b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Type>
62292b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct LongOffsetLongArrayOf : LongArrayOf<LongOffsetTo<Type> > {};
62392b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod
62480e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod/* Array of offsets relative to the beginning of the array itself. */
62580e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbodtemplate <typename Type>
62680e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbodstruct OffsetListOf : OffsetArrayOf<Type>
62780e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod{
62880e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod  inline const Type& operator [] (unsigned int i) const
62980e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod  {
63080e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod    if (HB_UNLIKELY (i >= this->len)) return Null(Type);
6312cb08458f674301cde9d962c13911035a251f7c5Behdad Esfahbod    return this+this->array()[i];
63280e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod  }
63380e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod
63480e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod  inline bool sanitize (SANITIZE_ARG_DEF) {
6353e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
63662c0fd75737a69721dbf29e773405a4c529f8b6dBehdad Esfahbod    return OffsetArrayOf<Type>::sanitize (SANITIZE_ARG, CharP(this));
63780e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod  }
63880e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod  inline bool sanitize (SANITIZE_ARG_DEF, unsigned int user_data) {
6393e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
64062c0fd75737a69721dbf29e773405a4c529f8b6dBehdad Esfahbod    return OffsetArrayOf<Type>::sanitize (SANITIZE_ARG, CharP(this), user_data);
64180e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod  }
64280e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod};
64380e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod
64480e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod
645e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod/* An array with a USHORT number of elements,
646e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod * starting at second element. */
647e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbodtemplate <typename Type>
64860d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbodstruct HeadlessArrayOf
64960d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
6502cb08458f674301cde9d962c13911035a251f7c5Behdad Esfahbod  const Type *array(void) const { return &StructAfter<Type> (len); }
6512e2f43edf2f49f4047e28b1ce2ea95938536de9cBehdad Esfahbod  Type *array(void) { return &StructAfter<Type> (len); }
652d3480ba37fbb5d4be75b094060f5b2f1ce98fb53Behdad Esfahbod
65360d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  inline const Type& operator [] (unsigned int i) const
65460d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  {
655e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod    if (HB_UNLIKELY (i >= len || !i)) return Null(Type);
6562cb08458f674301cde9d962c13911035a251f7c5Behdad Esfahbod    return array()[i-1];
657e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod  }
65860d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  inline unsigned int get_size () const
6594b8487d83e0c10076a6c573cb3487790ce366607Behdad Esfahbod  { return len.get_size () + (len ? len - 1 : 0) * Type::get_size (); }
6605f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod
661e5546a4352c54311ac4a9ef138b187378155ebe1Behdad Esfahbod  inline bool sanitize_shallow (SANITIZE_ARG_DEF) {
662e5546a4352c54311ac4a9ef138b187378155ebe1Behdad Esfahbod    TRACE_SANITIZE ();
663e5546a4352c54311ac4a9ef138b187378155ebe1Behdad Esfahbod    return SANITIZE_SELF() && SANITIZE_ARRAY (this, Type::get_size (), len);
664e5546a4352c54311ac4a9ef138b187378155ebe1Behdad Esfahbod  }
665e5546a4352c54311ac4a9ef138b187378155ebe1Behdad Esfahbod
66620b035dad41247076815a2bbb0346d63058b322fBehdad Esfahbod  inline bool sanitize (SANITIZE_ARG_DEF) {
6673e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
668e5546a4352c54311ac4a9ef138b187378155ebe1Behdad Esfahbod    if (!HB_LIKELY (sanitize_shallow (SANITIZE_ARG))) 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;
678d3480ba37fbb5d4be75b094060f5b2f1ce98fb53Behdad Esfahbod    Type *a = array();
67970de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod    for (unsigned int i = 0; i < count; i++)
680d3480ba37fbb5d4be75b094060f5b2f1ce98fb53Behdad Esfahbod      if (!SANITIZE (a[i]))
68170de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod        return false;
6829bd629ccd064e739789e504c41ad875eed93abbaBehdad Esfahbod    return true;
68370de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod  }
68470de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod
6855f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod  USHORT len;
686d3480ba37fbb5d4be75b094060f5b2f1ce98fb53Behdad Esfahbod/*Type array[VAR];*/
6875f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod};
6885f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod
6896b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod
6901e91434569a9e9535ef021ca52b60b2e2af75d19Behdad Esfahbod#endif /* HB_OPEN_TYPE_PRIVATE_HH */
691