hb-open-type-private.hh revision cf5585cfa6cac6fdf627a99941299e76af5ae0f7
164aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod/* 2f9b37727985191c9b4aedb0e9835736027e59260Behdad Esfahbod * Copyright (C) 2007,2008,2009,2010 Red Hat, Inc. 364aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * 4c755cb3e3ac55156d0d2ec05adea7a650b97cc41Behdad Esfahbod * This is part of HarfBuzz, a text shaping library. 564aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * 664aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * Permission is hereby granted, without written agreement and without 764aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * license or royalty fees, to use, copy, modify, and distribute this 864aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * software and its documentation for any purpose, provided that the 964aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * above copyright notice and the following two paragraphs appear in 1064aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * all copies of this software. 1164aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * 1264aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR 1364aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 1464aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN 1564aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 1664aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * DAMAGE. 1764aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * 1864aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, 1964aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 2064aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS 2164aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO 2264aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 2364aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * 2464aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * Red Hat Author(s): Behdad Esfahbod 2564aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod */ 2664aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod 275f5b24f99f52bbc922e238b65c06061ba07c8548Behdad Esfahbod#ifndef HB_OPEN_TYPES_PRIVATE_HH 285f5b24f99f52bbc922e238b65c06061ba07c8548Behdad Esfahbod#define HB_OPEN_TYPES_PRIVATE_HH 2912c4568c680ea2b9b98a16a8b7402ca185c90ef6Behdad Esfahbod 302098a021a826e76ee27d5db74e32738d7d1c3d30Behdad Esfahbod#include "hb-private.h" 3112c4568c680ea2b9b98a16a8b7402ca185c90ef6Behdad Esfahbod 3270de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod#include "hb-blob.h" 3370de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod 34a16ecbf0564a6e2576da22c12827f3c0719da549Behdad Esfahbod 35a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbod 36196598bbccff08415ff5192314cba044df258cadBehdad Esfahbod/* 37196598bbccff08415ff5192314cba044df258cadBehdad Esfahbod * Casts 38196598bbccff08415ff5192314cba044df258cadBehdad Esfahbod */ 39196598bbccff08415ff5192314cba044df258cadBehdad Esfahbod 40187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbod/* Cast to struct T, reference to reference */ 41a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbodtemplate<typename Type, typename TObject> 42187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbodinline const Type& CastR(const TObject &X) 43a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbod{ return reinterpret_cast<const Type&> (X); } 44a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbodtemplate<typename Type, typename TObject> 45187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbodinline Type& CastR(TObject &X) 46a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbod{ return reinterpret_cast<Type&> (X); } 47196598bbccff08415ff5192314cba044df258cadBehdad Esfahbod 48187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbod/* Cast to struct T, pointer to pointer */ 49187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbodtemplate<typename Type, typename TObject> 50187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbodinline const Type* CastP(const TObject *X) 51187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbod{ return reinterpret_cast<const Type*> (X); } 52187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbodtemplate<typename Type, typename TObject> 53187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbodinline Type* CastP(TObject *X) 54187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbod{ return reinterpret_cast<Type*> (X); } 55187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbod 5609766b1ec5ec55a61edbcd7a89ed3613cc92d4cbBehdad Esfahbod/* StructAtOffset<T>(P,Ofs) returns the struct T& that is placed at memory 5709766b1ec5ec55a61edbcd7a89ed3613cc92d4cbBehdad Esfahbod * location pointed to by P plus Ofs bytes. */ 5809766b1ec5ec55a61edbcd7a89ed3613cc92d4cbBehdad Esfahbodtemplate<typename Type> 5909766b1ec5ec55a61edbcd7a89ed3613cc92d4cbBehdad Esfahbodinline const Type& StructAtOffset(const void *P, unsigned int offset) 60a82ef7a893b773a17f7548375de9f588dfc83abaBehdad Esfahbod{ return * reinterpret_cast<const Type*> ((const char *) P + offset); } 6109766b1ec5ec55a61edbcd7a89ed3613cc92d4cbBehdad Esfahbodtemplate<typename Type> 6209766b1ec5ec55a61edbcd7a89ed3613cc92d4cbBehdad Esfahbodinline Type& StructAtOffset(void *P, unsigned int offset) 63a82ef7a893b773a17f7548375de9f588dfc83abaBehdad Esfahbod{ return * reinterpret_cast<Type*> ((char *) P + offset); } 6470de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod 652e2f43edf2f49f4047e28b1ce2ea95938536de9cBehdad Esfahbod/* StructAfter<T>(X) returns the struct T& that is placed after X. 6629c3f5e1b6212c775a7b911becd44ba093b7b0ebBehdad Esfahbod * Works with X of variable size also. X must implement get_size() */ 67e961c86c579fd98ee604342a9c70c4e7f8d4f220Behdad Esfahbodtemplate<typename Type, typename TObject> 68e961c86c579fd98ee604342a9c70c4e7f8d4f220Behdad Esfahbodinline const Type& StructAfter(const TObject &X) 6909766b1ec5ec55a61edbcd7a89ed3613cc92d4cbBehdad Esfahbod{ return StructAtOffset<Type>(&X, X.get_size()); } 70e961c86c579fd98ee604342a9c70c4e7f8d4f220Behdad Esfahbodtemplate<typename Type, typename TObject> 71e961c86c579fd98ee604342a9c70c4e7f8d4f220Behdad Esfahbodinline Type& StructAfter(TObject &X) 7209766b1ec5ec55a61edbcd7a89ed3613cc92d4cbBehdad Esfahbod{ return StructAtOffset<Type>(&X, X.get_size()); } 73a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbod 74e961c86c579fd98ee604342a9c70c4e7f8d4f220Behdad Esfahbod 75d3480ba37fbb5d4be75b094060f5b2f1ce98fb53Behdad Esfahbod 7670de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod/* 77e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod * Size checking 78e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod */ 79e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod 80f679635893eebc13402c5ee51a6f106eed0c76beBehdad Esfahbod/* Check _assertion in a method environment */ 81596e471aa5053d955fb5d5b5923088c8814469b1Behdad Esfahbod#define _DEFINE_SIZE_ASSERTION(_assertion) \ 8233afa4e2dc352f08cc094703e3f01d3ecd83b354Behdad Esfahbod inline void _size_assertion (void) const \ 83596e471aa5053d955fb5d5b5923088c8814469b1Behdad Esfahbod { ASSERT_STATIC (_assertion); } 84f679635893eebc13402c5ee51a6f106eed0c76beBehdad Esfahbod/* Check that _code compiles in a method environment */ 85f679635893eebc13402c5ee51a6f106eed0c76beBehdad Esfahbod#define _DEFINE_COMPILES_ASSERTION(_code) \ 86f679635893eebc13402c5ee51a6f106eed0c76beBehdad Esfahbod inline void _compiles_assertion (void) const \ 87f679635893eebc13402c5ee51a6f106eed0c76beBehdad Esfahbod { _code; } 880abcc3b48cfd51a22695c9e988938b2f45cb19d8Behdad Esfahbod 890abcc3b48cfd51a22695c9e988938b2f45cb19d8Behdad Esfahbod 90e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod#define DEFINE_SIZE_STATIC(size) \ 91596e471aa5053d955fb5d5b5923088c8814469b1Behdad Esfahbod _DEFINE_SIZE_ASSERTION (sizeof (*this) == (size)); \ 92e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod static const unsigned int static_size = (size); \ 93e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod static const unsigned int min_size = (size) 94e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod 95b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod/* Size signifying variable-sized array */ 96b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod#define VAR 1 97b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod 98596e471aa5053d955fb5d5b5923088c8814469b1Behdad Esfahbod#define DEFINE_SIZE_UNION(size, _member) \ 99596e471aa5053d955fb5d5b5923088c8814469b1Behdad Esfahbod _DEFINE_SIZE_ASSERTION (this->u._member.static_size == (size)); \ 100596e471aa5053d955fb5d5b5923088c8814469b1Behdad Esfahbod static const unsigned int min_size = (size) 101596e471aa5053d955fb5d5b5923088c8814469b1Behdad Esfahbod 102bea34c7cbb583cf7660776e95cab3171590b8427Behdad Esfahbod#define DEFINE_SIZE_MIN(size) \ 103596e471aa5053d955fb5d5b5923088c8814469b1Behdad Esfahbod _DEFINE_SIZE_ASSERTION (sizeof (*this) >= (size)); \ 104b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod static const unsigned int min_size = (size) 105b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod 1060eb9fc6e37935707dba2bf4b3705de2161a08cb7Behdad Esfahbod#define DEFINE_SIZE_ARRAY(size, array) \ 107f679635893eebc13402c5ee51a6f106eed0c76beBehdad Esfahbod _DEFINE_SIZE_ASSERTION (sizeof (*this) == (size) + sizeof (array[0])); \ 108f679635893eebc13402c5ee51a6f106eed0c76beBehdad Esfahbod _DEFINE_COMPILES_ASSERTION ((void) array[0].static_size) \ 109e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod static const unsigned int min_size = (size) 110e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod 1110eb9fc6e37935707dba2bf4b3705de2161a08cb7Behdad Esfahbod#define DEFINE_SIZE_ARRAY2(size, array1, array2) \ 112f679635893eebc13402c5ee51a6f106eed0c76beBehdad Esfahbod _DEFINE_SIZE_ASSERTION (sizeof (*this) == (size) + sizeof (this->array1[0]) + sizeof (this->array2[0])); \ 113f679635893eebc13402c5ee51a6f106eed0c76beBehdad Esfahbod _DEFINE_COMPILES_ASSERTION ((void) array1[0].static_size; (void) array2[0].static_size) \ 114e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod static const unsigned int min_size = (size) 115e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod 116e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod 117e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod 118e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod/* 119f0abcd69408a3af65207cdf8847575ade4579bd4Behdad Esfahbod * Null objects 120600e5eb80f553ea8eb862e6784133574c74ca513Behdad Esfahbod */ 121600e5eb80f553ea8eb862e6784133574c74ca513Behdad Esfahbod 1228b8358033184198ff638ee1379093717596e162dBehdad Esfahbod/* Global nul-content Null pool. Enlarge as necessary. */ 123cf5585cfa6cac6fdf627a99941299e76af5ae0f7Behdad Esfahbodstatic const void *_NullPool[64 / sizeof (void *)]; 1248b8358033184198ff638ee1379093717596e162dBehdad Esfahbod 125d2c2ca8faf62fc380d4717d286556139a62d2356Behdad Esfahbod/* Generic nul-content Null objects. */ 1268b8358033184198ff638ee1379093717596e162dBehdad Esfahbodtemplate <typename Type> 1279d3677899f90abdc7fb3e3d854db654a8707a84bBehdad Esfahbodstatic inline const Type& Null () { 128ed07422c33bbb52ff4d79e65986171e3f07697d8Behdad Esfahbod ASSERT_STATIC (Type::min_size <= sizeof (_NullPool)); 129187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbod return *CastP<Type> (_NullPool); 1309d3677899f90abdc7fb3e3d854db654a8707a84bBehdad Esfahbod} 1318b8358033184198ff638ee1379093717596e162dBehdad Esfahbod 1328b8358033184198ff638ee1379093717596e162dBehdad Esfahbod/* Specializaiton for arbitrary-content arbitrary-sized Null objects. */ 13365f46b00333e20ab8a52a4b350747507541ec1dbBehdad Esfahbod#define DEFINE_NULL_DATA(Type, data) \ 13465f46b00333e20ab8a52a4b350747507541ec1dbBehdad Esfahbodstatic const char _Null##Type[Type::min_size + 1] = data; /* +1 is for nul-termination in data */ \ 1358b8358033184198ff638ee1379093717596e162dBehdad Esfahbodtemplate <> \ 1369d3677899f90abdc7fb3e3d854db654a8707a84bBehdad Esfahbodinline const Type& Null<Type> () { \ 137187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbod return *CastP<Type> (_Null##Type); \ 138565c80bd2960366ace2d10dd71beaaf2a80213c8Behdad Esfahbod} /* The following line really exists such that we end in a place needing semicolon */ \ 139bea34c7cbb583cf7660776e95cab3171590b8427Behdad EsfahbodASSERT_STATIC (Type::min_size + 1 <= sizeof (_Null##Type)) 1408b8358033184198ff638ee1379093717596e162dBehdad Esfahbod 1418b8358033184198ff638ee1379093717596e162dBehdad Esfahbod/* Accessor macro. */ 1429d3677899f90abdc7fb3e3d854db654a8707a84bBehdad Esfahbod#define Null(Type) Null<Type>() 1438b8358033184198ff638ee1379093717596e162dBehdad Esfahbod 1448b8358033184198ff638ee1379093717596e162dBehdad Esfahbod 14520e3dd5d292b65f70d2eae63b8d8713a1c889d47Behdad Esfahbod/* 146dfc8cbe85479dde1ffdc6b2e73f4907331d77a19Behdad Esfahbod * Trace 14720e3dd5d292b65f70d2eae63b8d8713a1c889d47Behdad Esfahbod */ 14820e3dd5d292b65f70d2eae63b8d8713a1c889d47Behdad Esfahbod 149dfc8cbe85479dde1ffdc6b2e73f4907331d77a19Behdad Esfahbod 150dfc8cbe85479dde1ffdc6b2e73f4907331d77a19Behdad Esfahbodtemplate <int max_depth> 151dfc8cbe85479dde1ffdc6b2e73f4907331d77a19Behdad Esfahbodstruct hb_trace_t { 152458ecbb60bb7e8e32aca62a562586d921d5396aaBehdad Esfahbod explicit hb_trace_t (unsigned int *pdepth, const char *what, const char *function, const void *obj) : pdepth(pdepth) { 153dfc8cbe85479dde1ffdc6b2e73f4907331d77a19Behdad Esfahbod if (*pdepth < max_depth) 154dfc8cbe85479dde1ffdc6b2e73f4907331d77a19Behdad Esfahbod fprintf (stderr, "%s(%p) %-*d-> %s\n", what, obj, *pdepth, *pdepth, function); 155458ecbb60bb7e8e32aca62a562586d921d5396aaBehdad Esfahbod if (max_depth) ++*pdepth; 156dfc8cbe85479dde1ffdc6b2e73f4907331d77a19Behdad Esfahbod } 157458ecbb60bb7e8e32aca62a562586d921d5396aaBehdad Esfahbod ~hb_trace_t (void) { if (max_depth) --*pdepth; } 15820e3dd5d292b65f70d2eae63b8d8713a1c889d47Behdad Esfahbod 15920e3dd5d292b65f70d2eae63b8d8713a1c889d47Behdad Esfahbod private: 160dfc8cbe85479dde1ffdc6b2e73f4907331d77a19Behdad Esfahbod unsigned int *pdepth; 16120e3dd5d292b65f70d2eae63b8d8713a1c889d47Behdad Esfahbod}; 162dfc8cbe85479dde1ffdc6b2e73f4907331d77a19Behdad Esfahbodtemplate <> /* Optimize when tracing is disabled */ 163dfc8cbe85479dde1ffdc6b2e73f4907331d77a19Behdad Esfahbodstruct hb_trace_t<0> { 16475651b20871047d3ec17f4221794b8ef5d60e14bBehdad Esfahbod explicit hb_trace_t (unsigned int *pdepth HB_UNUSED, const char *what HB_UNUSED, const char *function HB_UNUSED, const void *obj HB_UNUSED) {} 16520e3dd5d292b65f70d2eae63b8d8713a1c889d47Behdad Esfahbod}; 16620e3dd5d292b65f70d2eae63b8d8713a1c889d47Behdad Esfahbod 16720e3dd5d292b65f70d2eae63b8d8713a1c889d47Behdad Esfahbod 168600e5eb80f553ea8eb862e6784133574c74ca513Behdad Esfahbod 169577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod/* 170577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod * Sanitize 171577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod */ 172577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod 17395e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod#ifndef HB_DEBUG_SANITIZE 174807c5b03a2251a3c29a520852639421783101b55Behdad Esfahbod#define HB_DEBUG_SANITIZE HB_DEBUG+0 17595e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod#endif 17695e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod 17720e3dd5d292b65f70d2eae63b8d8713a1c889d47Behdad Esfahbod 178bc200457430c083914a64bf4b056153506749610Behdad Esfahbod#define TRACE_SANITIZE() \ 179d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod hb_trace_t<HB_DEBUG_SANITIZE> trace (&c->debug_depth, "SANITIZE", HB_FUNC, this); \ 180807c5b03a2251a3c29a520852639421783101b55Behdad Esfahbod 181b28815c1f6e46d38471cacbc31248ca6fda8c4d1Behdad Esfahbod 1821376fb7bf9ef07970f0ba13dc64d6a8ab8252762Behdad Esfahbodstruct hb_sanitize_context_t 183577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod{ 18498daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod inline void init (hb_blob_t *blob) 18598daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod { 18698daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod this->blob = hb_blob_reference (blob); 18798daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod this->start = hb_blob_lock (blob); 18898daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod this->end = this->start + hb_blob_get_length (blob); 18998daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod this->writable = hb_blob_is_writable (blob); 19098daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod this->edit_count = 0; 19120e3dd5d292b65f70d2eae63b8d8713a1c889d47Behdad Esfahbod this->debug_depth = 0; 192577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod 19398daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod if (HB_DEBUG_SANITIZE) 19498daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod fprintf (stderr, "sanitize %p init [%p..%p] (%u bytes)\n", 19598daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod this->blob, this->start, this->end, this->end - this->start); 19698daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod } 1971376fb7bf9ef07970f0ba13dc64d6a8ab8252762Behdad Esfahbod 19898daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod inline void finish (void) 19998daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod { 20098daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod if (HB_DEBUG_SANITIZE) 20198daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod fprintf (stderr, "sanitize %p fini [%p..%p] %u edit requests\n", 20298daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod this->blob, this->start, this->end, this->edit_count); 203577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod 20498daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod hb_blob_unlock (this->blob); 20598daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod hb_blob_destroy (this->blob); 20698daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod this->blob = NULL; 20798daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod this->start = this->end = NULL; 20898daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod } 2094f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod 2104ad2cc5dec6b0639da2b1846282bdd99d06d5ff1Behdad Esfahbod inline bool check_range (const void *base, unsigned int len) const 21198daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod { 212a82ef7a893b773a17f7548375de9f588dfc83abaBehdad Esfahbod const char *p = (const char *) base; 213a82ef7a893b773a17f7548375de9f588dfc83abaBehdad Esfahbod bool ret = this->start <= p && 214a82ef7a893b773a17f7548375de9f588dfc83abaBehdad Esfahbod p <= this->end && 215a82ef7a893b773a17f7548375de9f588dfc83abaBehdad Esfahbod (unsigned int) (this->end - p) >= len; 21698daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod 21720e3dd5d292b65f70d2eae63b8d8713a1c889d47Behdad Esfahbod if (HB_DEBUG_SANITIZE && (int) this->debug_depth < (int) HB_DEBUG_SANITIZE) \ 2184ad2cc5dec6b0639da2b1846282bdd99d06d5ff1Behdad Esfahbod fprintf (stderr, "SANITIZE(%p) %-*d-> range [%p..%p] (%d bytes) in [%p..%p] -> %s\n", \ 219a82ef7a893b773a17f7548375de9f588dfc83abaBehdad Esfahbod p, 22020e3dd5d292b65f70d2eae63b8d8713a1c889d47Behdad Esfahbod this->debug_depth, this->debug_depth, 221a82ef7a893b773a17f7548375de9f588dfc83abaBehdad Esfahbod p, p + len, len, 22298daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod this->start, this->end, 22398daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod ret ? "pass" : "FAIL"); 22498daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod 22527e302dc8e794ff6bf878bc76e17d336d510849eBehdad Esfahbod return likely (ret); 22698daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod } 227577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod 2281cd1e117d060d38e314618b627d7663cb01ed584Behdad Esfahbod inline bool check_array (const void *base, unsigned int record_size, unsigned int len) const 22998daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod { 230a82ef7a893b773a17f7548375de9f588dfc83abaBehdad Esfahbod const char *p = (const char *) base; 23198daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod bool overflows = len >= ((unsigned int) -1) / record_size; 23241895506cb6a41b1a833866f8822261ea449ea0bBehdad Esfahbod 23320e3dd5d292b65f70d2eae63b8d8713a1c889d47Behdad Esfahbod if (HB_DEBUG_SANITIZE && (int) this->debug_depth < (int) HB_DEBUG_SANITIZE) 23498daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod fprintf (stderr, "SANITIZE(%p) %-*d-> array [%p..%p] (%d*%d=%ld bytes) in [%p..%p] -> %s\n", \ 235a82ef7a893b773a17f7548375de9f588dfc83abaBehdad Esfahbod p, 23620e3dd5d292b65f70d2eae63b8d8713a1c889d47Behdad Esfahbod this->debug_depth, this->debug_depth, 237a82ef7a893b773a17f7548375de9f588dfc83abaBehdad Esfahbod p, p + (record_size * len), record_size, len, (unsigned long) record_size * len, 23898daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod this->start, this->end, 23998daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod !overflows ? "does not overflow" : "OVERFLOWS FAIL"); 240fa030175ca998b00cc42cbced6e98de323ec01ecBehdad Esfahbod 2414ad2cc5dec6b0639da2b1846282bdd99d06d5ff1Behdad Esfahbod return likely (!overflows && this->check_range (base, record_size * len)); 24298daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod } 243254933c397f1ce9796f59689a25f9fc2e58df4eaBehdad Esfahbod 244b157617644d1e38f680163889d1dc2e2f64d9ba3Behdad Esfahbod template <typename Type> 245b157617644d1e38f680163889d1dc2e2f64d9ba3Behdad Esfahbod inline bool check_struct (const Type *obj) const 246b157617644d1e38f680163889d1dc2e2f64d9ba3Behdad Esfahbod { 24754842374c2b291ef208c51ae1d853ec0403ccf84Behdad Esfahbod return likely (this->check_range (obj, obj->min_size)); 248b157617644d1e38f680163889d1dc2e2f64d9ba3Behdad Esfahbod } 249b157617644d1e38f680163889d1dc2e2f64d9ba3Behdad Esfahbod 25040cbefe858192531ed64dd51d402f7ca7b8153a3Behdad Esfahbod inline bool can_edit (const void *base HB_UNUSED, unsigned int len HB_UNUSED) 25198daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod { 252a82ef7a893b773a17f7548375de9f588dfc83abaBehdad Esfahbod const char *p = (const char *) base; 25398daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod this->edit_count++; 25498daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod 25520e3dd5d292b65f70d2eae63b8d8713a1c889d47Behdad Esfahbod if (HB_DEBUG_SANITIZE && (int) this->debug_depth < (int) HB_DEBUG_SANITIZE) 25698daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod fprintf (stderr, "SANITIZE(%p) %-*d-> edit(%u) [%p..%p] (%d bytes) in [%p..%p] -> %s\n", \ 257a82ef7a893b773a17f7548375de9f588dfc83abaBehdad Esfahbod p, 25820e3dd5d292b65f70d2eae63b8d8713a1c889d47Behdad Esfahbod this->debug_depth, this->debug_depth, 25998daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod this->edit_count, 260a82ef7a893b773a17f7548375de9f588dfc83abaBehdad Esfahbod p, p + len, len, 26198daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod this->start, this->end, 26298daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod this->writable ? "granted" : "REJECTED"); 26398daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod 26498daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod return this->writable; 26598daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod } 26698daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod 267705e215268aa95c2bc6af8af9b48b72b690ec1f7Behdad Esfahbod unsigned int debug_depth; 26898daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod const char *start, *end; 26998daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod bool writable; 27098daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod unsigned int edit_count; 27198daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod hb_blob_t *blob; 27298daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod}; 273815a73e4202ca17677f12e862b70ca8724cf2f57Behdad Esfahbod 274577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod 275577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod 2764e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod/* Template to sanitize an object. */ 2774e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbodtemplate <typename Type> 2784e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbodstruct Sanitizer 2794e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod{ 2804e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod static hb_blob_t *sanitize (hb_blob_t *blob) { 281d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod hb_sanitize_context_t c[1] = {{0}}; 2824e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod bool sane; 2834e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod 284d0b657379bbe63602953412d6bc944b2a0f430ebBehdad Esfahbod /* TODO is_sane() stuff */ 2854e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod 2864e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod retry: 287fa030175ca998b00cc42cbced6e98de323ec01ecBehdad Esfahbod if (HB_DEBUG_SANITIZE) 2887d3a126334f8e6f6441561c1bb592bd3fa7a2c5cBehdad Esfahbod fprintf (stderr, "Sanitizer %p start %s\n", blob, HB_FUNC); 2894f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod 290d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod c->init (blob); 2914e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod 292d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod if (unlikely (!c->start)) { 293d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod c->finish (); 29448146e5612f6d272d6962f6829c6d64a31edef89Behdad Esfahbod return blob; 29548146e5612f6d272d6962f6829c6d64a31edef89Behdad Esfahbod } 29648146e5612f6d272d6962f6829c6d64a31edef89Behdad Esfahbod 297d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod Type *t = CastP<Type> (const_cast<char *> (c->start)); 2984e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod 299d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod sane = t->sanitize (c); 3004e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod if (sane) { 301d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod if (c->edit_count) { 302fa030175ca998b00cc42cbced6e98de323ec01ecBehdad Esfahbod if (HB_DEBUG_SANITIZE) 303fa030175ca998b00cc42cbced6e98de323ec01ecBehdad Esfahbod fprintf (stderr, "Sanitizer %p passed first round with %d edits; doing a second round %s\n", 304d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod blob, c->edit_count, HB_FUNC); 305fa030175ca998b00cc42cbced6e98de323ec01ecBehdad Esfahbod 3068b5346130425c7c101f6ff2432874ba2fd372edcBehdad Esfahbod /* sanitize again to ensure no toe-stepping */ 307d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod c->edit_count = 0; 308d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod sane = t->sanitize (c); 309d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod if (c->edit_count) { 310fa030175ca998b00cc42cbced6e98de323ec01ecBehdad Esfahbod if (HB_DEBUG_SANITIZE) 311fa030175ca998b00cc42cbced6e98de323ec01ecBehdad Esfahbod fprintf (stderr, "Sanitizer %p requested %d edits in second round; FAILLING %s\n", 312d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod blob, c->edit_count, HB_FUNC); 3134e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod sane = false; 3144e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod } 3154e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod } 316d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod c->finish (); 3174e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod } else { 318d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod unsigned int edit_count = c->edit_count; 319d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod c->finish (); 320977eeb714454630bd045bb11f58ff6397f10b143Behdad Esfahbod if (edit_count && !hb_blob_is_writable (blob) && hb_blob_try_writable (blob)) { 321977eeb714454630bd045bb11f58ff6397f10b143Behdad Esfahbod /* ok, we made it writable by relocating. try again */ 322fa030175ca998b00cc42cbced6e98de323ec01ecBehdad Esfahbod if (HB_DEBUG_SANITIZE) 3237d3a126334f8e6f6441561c1bb592bd3fa7a2c5cBehdad Esfahbod fprintf (stderr, "Sanitizer %p retry %s\n", blob, HB_FUNC); 3244e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod goto retry; 3254e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod } 3264e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod } 3274e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod 328fa030175ca998b00cc42cbced6e98de323ec01ecBehdad Esfahbod if (HB_DEBUG_SANITIZE) 3297d3a126334f8e6f6441561c1bb592bd3fa7a2c5cBehdad Esfahbod fprintf (stderr, "Sanitizer %p %s %s\n", blob, sane ? "passed" : "FAILED", HB_FUNC); 3304e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod if (sane) 3314e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod return blob; 3324e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod else { 3334e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod hb_blob_destroy (blob); 3344e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod return hb_blob_create_empty (); 3354e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod } 3364e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod } 337b435ab7e29c388e3b100f729957319931625a3a8Behdad Esfahbod 338b435ab7e29c388e3b100f729957319931625a3a8Behdad Esfahbod static const Type* lock_instance (hb_blob_t *blob) { 339b435ab7e29c388e3b100f729957319931625a3a8Behdad Esfahbod const char *base = hb_blob_lock (blob); 340b435ab7e29c388e3b100f729957319931625a3a8Behdad Esfahbod return unlikely (!base) ? &Null(Type) : CastP<Type> (base); 341b435ab7e29c388e3b100f729957319931625a3a8Behdad Esfahbod } 3424e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod}; 3434e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod 3442d15e72c75931398db5e027e660f1320bb979117Behdad Esfahbod 345f0abcd69408a3af65207cdf8847575ade4579bd4Behdad Esfahbod 346f0abcd69408a3af65207cdf8847575ade4579bd4Behdad Esfahbod 347b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod/* 348b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod * 349bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod * The OpenType Font File: Data Types 350b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod */ 351b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod 352b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod 353b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod/* "The following data types are used in the OpenType font file. 354b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod * All OpenType fonts use Motorola-style byte ordering (Big Endian):" */ 355b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod 3565f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod/* 3575f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod * Int types 3585f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod */ 3595f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod 3606b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod 361e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodtemplate <typename Type, int Bytes> class BEInt; 362e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod 363f1aaa2a43654c28405ffd393de2cb127437c99a5Behdad Esfahbod/* LONGTERMTODO: On machines allowing unaligned access, we can make the 364f1aaa2a43654c28405ffd393de2cb127437c99a5Behdad Esfahbod * following tighter by using byteswap instructions on ints directly. */ 365e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodtemplate <typename Type> 366e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodclass BEInt<Type, 2> 367e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod{ 368e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod public: 36901c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod inline class BEInt<Type,2>& operator = (Type i) { hb_be_uint16_put (v,i); return *this; } 37001c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod inline operator Type () const { return hb_be_uint16_get (v); } 37101c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod inline bool operator == (const BEInt<Type, 2>& o) const { return hb_be_uint16_cmp (v, o.v); } 37201c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod inline bool operator != (const BEInt<Type, 2>& o) const { return !(*this == o); } 373e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod private: uint8_t v[2]; 374e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod}; 375e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodtemplate <typename Type> 376e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodclass BEInt<Type, 4> 377e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod{ 378e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod public: 37901c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod inline class BEInt<Type,4>& operator = (Type i) { hb_be_uint32_put (v,i); return *this; } 38001c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod inline operator Type () const { return hb_be_uint32_get (v); } 38101c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod inline bool operator == (const BEInt<Type, 4>& o) const { return hb_be_uint32_cmp (v, o.v); } 38201c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod inline bool operator != (const BEInt<Type, 4>& o) const { return !(*this == o); } 383e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod private: uint8_t v[4]; 384e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod}; 385e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod 3862467c669c2aee4de2a6621a9d06cba0262376d41Behdad Esfahbod/* Integer types in big-endian order and no alignment requirement */ 387e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodtemplate <typename Type> 388e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodstruct IntType 389e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod{ 39001c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod inline void set (Type i) { v = i; } 39101c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod inline operator Type(void) const { return v; } 39201c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod inline bool operator == (const IntType<Type> &o) const { return v == o.v; } 39301c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod inline bool operator != (const IntType<Type> &o) const { return v != o.v; } 394d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod inline bool sanitize (hb_sanitize_context_t *c) { 395e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod TRACE_SANITIZE (); 396d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod return likely (c->check_struct (this)); 397e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod } 398a82ef7a893b773a17f7548375de9f588dfc83abaBehdad Esfahbod protected: 399569da92bc6956f42d9b2d65c784e184fb6380efeBehdad Esfahbod BEInt<Type, sizeof (Type)> v; 400569da92bc6956f42d9b2d65c784e184fb6380efeBehdad Esfahbod public: 401e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod DEFINE_SIZE_STATIC (sizeof (Type)); 402e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod}; 403e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod 404e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodtypedef IntType<uint16_t> USHORT; /* 16-bit unsigned integer. */ 405e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodtypedef IntType<int16_t> SHORT; /* 16-bit signed integer. */ 406e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodtypedef IntType<uint32_t> ULONG; /* 32-bit unsigned integer. */ 407e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodtypedef IntType<int32_t> LONG; /* 32-bit signed integer. */ 408e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod 409e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod/* Date represented in number of seconds since 12:00 midnight, January 1, 410e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod * 1904. The value is represented as a signed 64-bit integer. */ 411e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbodstruct LONGDATETIME 412e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod{ 413e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod inline bool sanitize (hb_sanitize_context_t *c) { 414e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod TRACE_SANITIZE (); 415e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod return likely (c->check_struct (this)); 416e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod } 417e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod private: 418e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod LONG major; 419e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod ULONG minor; 420e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod public: 421e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod DEFINE_SIZE_STATIC (8); 422e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod}; 423e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod 4246b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod/* Array of four uint8s (length = 32 bits) used to identify a script, language 4256b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod * system, feature, or baseline */ 42620cc86b3592db33731de671f008d7d222776be49Behdad Esfahbodstruct Tag : ULONG 42760d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{ 428befc022affd2386b3f46cd7d11e4262f6c8bce9fBehdad Esfahbod /* What the char* converters return is NOT nul-terminated. Print using "%.4s" */ 429a82ef7a893b773a17f7548375de9f588dfc83abaBehdad Esfahbod inline operator const char* (void) const { return reinterpret_cast<const char *> (&this->v); } 430a82ef7a893b773a17f7548375de9f588dfc83abaBehdad Esfahbod inline operator char* (void) { return reinterpret_cast<char *> (&this->v); } 431b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod public: 432b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod DEFINE_SIZE_STATIC (4); 4336b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod}; 43465f46b00333e20ab8a52a4b350747507541ec1dbBehdad EsfahbodDEFINE_NULL_DATA (Tag, " "); 4356b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod 4366b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod/* Glyph index number, same as uint16 (length = 16 bits) */ 4376ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbodtypedef USHORT GlyphID; 4386b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod 439b5db4f1e4eefa266a71a28b5496f47ff9d1a81e8Behdad Esfahbod/* Script/language-system/feature index */ 440b5db4f1e4eefa266a71a28b5496f47ff9d1a81e8Behdad Esfahbodstruct Index : USHORT { 441b5db4f1e4eefa266a71a28b5496f47ff9d1a81e8Behdad Esfahbod static const unsigned int NOT_FOUND_INDEX = 0xFFFF; 442b5db4f1e4eefa266a71a28b5496f47ff9d1a81e8Behdad Esfahbod}; 443b5db4f1e4eefa266a71a28b5496f47ff9d1a81e8Behdad EsfahbodDEFINE_NULL_DATA (Index, "\xff\xff"); 444b5db4f1e4eefa266a71a28b5496f47ff9d1a81e8Behdad Esfahbod 4451f437e6f47fb6c15761021bd2078f31778f2179cBehdad Esfahbod/* Offset to a table, same as uint16 (length = 16 bits), Null offset = 0x0000 */ 4466ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbodtypedef USHORT Offset; 4476ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbod 4486ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbod/* LongOffset to a table, same as uint32 (length = 32 bits), Null offset = 0x00000000 */ 4496ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbodtypedef ULONG LongOffset; 4506ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbod 4516b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod 4526b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod/* CheckSum */ 45360d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbodstruct CheckSum : ULONG 45460d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{ 45560d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod static uint32_t CalcTableChecksum (ULONG *Table, uint32_t Length) 45660d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod { 4576b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod uint32_t Sum = 0L; 458e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod ULONG *EndPtr = Table+((Length+3) & ~3) / ULONG::static_size; 4596b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod 4606b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod while (Table < EndPtr) 4616b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod Sum += *Table++; 4626b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod return Sum; 4636b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod } 464b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod public: 465b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod DEFINE_SIZE_STATIC (4); 4666b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod}; 4676b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod 4686b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod 4696b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod/* 4706b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod * Version Numbers 4716b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod */ 4726b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod 47387fcdcbe3644da10154688765db2d62eb9ac079aBehdad Esfahbodstruct FixedVersion 47460d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{ 47509c292e3b688a67fbae67b645d1e6ffcf8d8eb6eBehdad Esfahbod inline operator uint32_t (void) const { return (major << 16) + minor; } 47696908b898476ca5d7da5f386b15be76f9e83d76eBehdad Esfahbod 477d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod inline bool sanitize (hb_sanitize_context_t *c) { 4783e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod TRACE_SANITIZE (); 479d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod return c->check_struct (this); 480cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod } 481cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod 4826ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbod USHORT major; 48387fcdcbe3644da10154688765db2d62eb9ac079aBehdad Esfahbod USHORT minor; 484b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod public: 485b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod DEFINE_SIZE_STATIC (4); 4866b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod}; 4876b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod 48892b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 48992b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 4905f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod/* 49192b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod * Template subclasses of Offset and LongOffset that do the dereferencing. 492f0abcd69408a3af65207cdf8847575ade4579bd4Behdad Esfahbod * Use: (base+offset) 4935f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod */ 4945f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod 49592b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename OffsetType, typename Type> 49692b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct GenericOffsetTo : OffsetType 49792b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod{ 49800e23fcc6fd0eee5c582251bf3de6a2703fbbd3eBehdad Esfahbod inline const Type& operator () (const void *base) const 49992b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod { 50092b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod unsigned int offset = *this; 50164d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod if (unlikely (!offset)) return Null(Type); 50209766b1ec5ec55a61edbcd7a89ed3613cc92d4cbBehdad Esfahbod return StructAtOffset<Type> (base, offset); 50392b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod } 50492b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 505d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod inline bool sanitize (hb_sanitize_context_t *c, void *base) { 5063e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod TRACE_SANITIZE (); 507d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod if (unlikely (!c->check_struct (this))) return false; 50892b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod unsigned int offset = *this; 50964d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod if (unlikely (!offset)) return true; 51009766b1ec5ec55a61edbcd7a89ed3613cc92d4cbBehdad Esfahbod Type &obj = StructAtOffset<Type> (base, offset); 511d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod return likely (obj.sanitize (c)) || neuter (c); 51292b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod } 5134a446ac35136eff23d55f47bdd7b40095ad707abBehdad Esfahbod template <typename T> 514d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod inline bool sanitize (hb_sanitize_context_t *c, void *base, T user_data) { 5153e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod TRACE_SANITIZE (); 516d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod if (unlikely (!c->check_struct (this))) return false; 51742b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod unsigned int offset = *this; 51864d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod if (unlikely (!offset)) return true; 51909766b1ec5ec55a61edbcd7a89ed3613cc92d4cbBehdad Esfahbod Type &obj = StructAtOffset<Type> (base, offset); 520d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod return likely (obj.sanitize (c, user_data)) || neuter (c); 521c9f14687a30866181feb57ee2736a147ec9f25a1Behdad Esfahbod } 522c9f14687a30866181feb57ee2736a147ec9f25a1Behdad Esfahbod 523c9f14687a30866181feb57ee2736a147ec9f25a1Behdad Esfahbod private: 524c9f14687a30866181feb57ee2736a147ec9f25a1Behdad Esfahbod /* Set the offset to Null */ 525d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod inline bool neuter (hb_sanitize_context_t *c) { 526d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod if (c->can_edit (this, this->static_size)) { 527c9f14687a30866181feb57ee2736a147ec9f25a1Behdad Esfahbod this->set (0); /* 0 is Null offset */ 528c9f14687a30866181feb57ee2736a147ec9f25a1Behdad Esfahbod return true; 529c9f14687a30866181feb57ee2736a147ec9f25a1Behdad Esfahbod } 530c9f14687a30866181feb57ee2736a147ec9f25a1Behdad Esfahbod return false; 53142b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod } 53292b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod}; 53392b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Base, typename OffsetType, typename Type> 53492b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodinline const Type& operator + (const Base &base, GenericOffsetTo<OffsetType, Type> offset) { return offset (base); } 53592b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 5365f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbodtemplate <typename Type> 53792b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct OffsetTo : GenericOffsetTo<Offset, Type> {}; 53892b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 53992b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Type> 54092b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct LongOffsetTo : GenericOffsetTo<LongOffset, Type> {}; 541bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod 542bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod 54392b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod/* 54492b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod * Array Types 54592b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod */ 54692b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 54792b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename LenType, typename Type> 54892b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct GenericArrayOf 54960d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{ 5504f5f1c34dda1e0629bfa6d7b0ffa2e1ce003b7c7Behdad Esfahbod const Type *sub_array (unsigned int start_offset, unsigned int *pcount /* IN/OUT */) const 55148de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod { 55248de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod unsigned int count = len; 55364d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod if (unlikely (start_offset > count)) 55448de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod count = 0; 55548de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod else 55648de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod count -= start_offset; 55748de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod count = MIN (count, *pcount); 55848de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod *pcount = count; 559b961518b9611471ff7060e97686e5625974847ebBehdad Esfahbod return array + start_offset; 56048de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod } 56148de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod 56260d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod inline const Type& operator [] (unsigned int i) const 56360d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod { 56464d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod if (unlikely (i >= len)) return Null(Type); 565b961518b9611471ff7060e97686e5625974847ebBehdad Esfahbod return array[i]; 5665f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod } 56760d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod inline unsigned int get_size () const 568e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod { return len.static_size + len * Type::static_size; } 569e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod 570d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod inline bool sanitize (hb_sanitize_context_t *c) { 5713e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod TRACE_SANITIZE (); 572d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod if (unlikely (!sanitize_shallow (c))) return false; 57340d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod /* Note: for structs that do not reference other structs, 57440d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod * we do not need to call their sanitize() as we already did 57540d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod * a bound check on the aggregate array size, hence the return. 57640d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod */ 5773564ee5216004d45d30b0ded61184cf8dde5dd89Behdad Esfahbod return true; 57840d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod /* We do keep this code though to make sure the structs pointed 57940d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod * to do have a simple sanitize(), ie. they do not reference 58040d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod * other structs. */ 58170de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod unsigned int count = len; 58270de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod for (unsigned int i = 0; i < count; i++) 583d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod if (array[i].sanitize (c)) 58470de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod return false; 5859bd629ccd064e739789e504c41ad875eed93abbaBehdad Esfahbod return true; 58670de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod } 587d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod inline bool sanitize (hb_sanitize_context_t *c, void *base) { 5883e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod TRACE_SANITIZE (); 589d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod if (unlikely (!sanitize_shallow (c))) return false; 590e6ab2c59ba2d37942ac5fcbfe61d38b7e359ac8cBehdad Esfahbod unsigned int count = len; 591e6ab2c59ba2d37942ac5fcbfe61d38b7e359ac8cBehdad Esfahbod for (unsigned int i = 0; i < count; i++) 592d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod if (unlikely (!array[i].sanitize (c, base))) 593e6ab2c59ba2d37942ac5fcbfe61d38b7e359ac8cBehdad Esfahbod return false; 5949bd629ccd064e739789e504c41ad875eed93abbaBehdad Esfahbod return true; 595e6ab2c59ba2d37942ac5fcbfe61d38b7e359ac8cBehdad Esfahbod } 5964a446ac35136eff23d55f47bdd7b40095ad707abBehdad Esfahbod template <typename T> 597d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod inline bool sanitize (hb_sanitize_context_t *c, void *base, T user_data) { 5983e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod TRACE_SANITIZE (); 599d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod if (unlikely (!sanitize_shallow (c))) return false; 60042b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod unsigned int count = len; 60142b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod for (unsigned int i = 0; i < count; i++) 602d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod if (unlikely (!array[i].sanitize (c, base, user_data))) 60342b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod return false; 6049bd629ccd064e739789e504c41ad875eed93abbaBehdad Esfahbod return true; 60542b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod } 60670de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod 60730fa2821c277df99a14089749313dfe2b541e2d0Behdad Esfahbod private: 608d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod inline bool sanitize_shallow (hb_sanitize_context_t *c) { 60930fa2821c277df99a14089749313dfe2b541e2d0Behdad Esfahbod TRACE_SANITIZE (); 610d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod return c->check_struct (this) 611d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod && c->check_array (this, Type::static_size, len); 61230fa2821c277df99a14089749313dfe2b541e2d0Behdad Esfahbod } 61330fa2821c277df99a14089749313dfe2b541e2d0Behdad Esfahbod 61430fa2821c277df99a14089749313dfe2b541e2d0Behdad Esfahbod public: 61592b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod LenType len; 616b961518b9611471ff7060e97686e5625974847ebBehdad Esfahbod Type array[VAR]; 617b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod public: 6180eb9fc6e37935707dba2bf4b3705de2161a08cb7Behdad Esfahbod DEFINE_SIZE_ARRAY (sizeof (LenType), array); 619e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod}; 620e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod 62192b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod/* An array with a USHORT number of elements. */ 62292b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Type> 62392b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct ArrayOf : GenericArrayOf<USHORT, Type> {}; 62492b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 62592b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod/* An array with a ULONG number of elements. */ 62692b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Type> 62792b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct LongArrayOf : GenericArrayOf<ULONG, Type> {}; 62892b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 62992b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod/* Array of Offset's */ 63092b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Type> 63192b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct OffsetArrayOf : ArrayOf<OffsetTo<Type> > {}; 63292b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 63392b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod/* Array of LongOffset's */ 63492b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Type> 63592b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct LongOffsetArrayOf : ArrayOf<LongOffsetTo<Type> > {}; 63692b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 63792b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod/* LongArray of LongOffset's */ 63892b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Type> 63992b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct LongOffsetLongArrayOf : LongArrayOf<LongOffsetTo<Type> > {}; 64092b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 64180e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod/* Array of offsets relative to the beginning of the array itself. */ 64280e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbodtemplate <typename Type> 64380e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbodstruct OffsetListOf : OffsetArrayOf<Type> 64480e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod{ 64580e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod inline const Type& operator [] (unsigned int i) const 64680e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod { 64764d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod if (unlikely (i >= this->len)) return Null(Type); 648b961518b9611471ff7060e97686e5625974847ebBehdad Esfahbod return this+this->array[i]; 64980e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod } 65080e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod 651d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod inline bool sanitize (hb_sanitize_context_t *c) { 6523e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod TRACE_SANITIZE (); 653d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod return OffsetArrayOf<Type>::sanitize (c, this); 65480e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod } 6554a446ac35136eff23d55f47bdd7b40095ad707abBehdad Esfahbod template <typename T> 656d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod inline bool sanitize (hb_sanitize_context_t *c, T user_data) { 6573e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod TRACE_SANITIZE (); 658d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod return OffsetArrayOf<Type>::sanitize (c, this, user_data); 65980e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod } 66080e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod}; 66180e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod 66280e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod 663e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod/* An array with a USHORT number of elements, 664e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod * starting at second element. */ 665e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbodtemplate <typename Type> 66660d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbodstruct HeadlessArrayOf 66760d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{ 66860d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod inline const Type& operator [] (unsigned int i) const 66960d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod { 67064d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod if (unlikely (i >= len || !i)) return Null(Type); 671b961518b9611471ff7060e97686e5625974847ebBehdad Esfahbod return array[i-1]; 672e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod } 67360d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod inline unsigned int get_size () const 674e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod { return len.static_size + (len ? len - 1 : 0) * Type::static_size; } 6755f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod 676d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod inline bool sanitize_shallow (hb_sanitize_context_t *c) { 677d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod return c->check_struct (this) 678d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod && c->check_array (this, Type::static_size, len); 679e5546a4352c54311ac4a9ef138b187378155ebe1Behdad Esfahbod } 680e5546a4352c54311ac4a9ef138b187378155ebe1Behdad Esfahbod 681d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod inline bool sanitize (hb_sanitize_context_t *c) { 6823e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod TRACE_SANITIZE (); 683d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod if (unlikely (!sanitize_shallow (c))) return false; 68440d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod /* Note: for structs that do not reference other structs, 68540d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod * we do not need to call their sanitize() as we already did 68640d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod * a bound check on the aggregate array size, hence the return. 68740d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod */ 6883564ee5216004d45d30b0ded61184cf8dde5dd89Behdad Esfahbod return true; 68940d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod /* We do keep this code though to make sure the structs pointed 69040d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod * to do have a simple sanitize(), ie. they do not reference 69140d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod * other structs. */ 69215164d9258a74122a4db748d35532bd72c47cec2Behdad Esfahbod unsigned int count = len ? len - 1 : 0; 693b961518b9611471ff7060e97686e5625974847ebBehdad Esfahbod Type *a = array; 69470de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod for (unsigned int i = 0; i < count; i++) 695d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod if (unlikely (!a[i].sanitize (c))) 69670de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod return false; 6979bd629ccd064e739789e504c41ad875eed93abbaBehdad Esfahbod return true; 69870de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod } 69970de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod 7005f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod USHORT len; 701b961518b9611471ff7060e97686e5625974847ebBehdad Esfahbod Type array[VAR]; 702ed07422c33bbb52ff4d79e65986171e3f07697d8Behdad Esfahbod public: 7030eb9fc6e37935707dba2bf4b3705de2161a08cb7Behdad Esfahbod DEFINE_SIZE_ARRAY (sizeof (USHORT), array); 7045f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod}; 7055f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod 7066b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod 7071e91434569a9e9535ef021ca52b60b2e2af75d19Behdad Esfahbod#endif /* HB_OPEN_TYPE_PRIVATE_HH */ 708