hb-open-type-private.hh revision 9b54562d63f1a9e0e5b33d71c32bd1588759ebf1
164aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod/* 22409d5f8d7dd8b535ce5ea29e933f7db27d33793Behdad Esfahbod * Copyright © 2007,2008,2009,2010 Red Hat, Inc. 30ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod * Copyright © 2012 Google, Inc. 464aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * 5c755cb3e3ac55156d0d2ec05adea7a650b97cc41Behdad Esfahbod * This is part of HarfBuzz, a text shaping library. 664aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * 764aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * Permission is hereby granted, without written agreement and without 864aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * license or royalty fees, to use, copy, modify, and distribute this 964aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * software and its documentation for any purpose, provided that the 1064aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * above copyright notice and the following two paragraphs appear in 1164aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * all copies of this software. 1264aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * 1364aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR 1464aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 1564aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN 1664aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 1764aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * DAMAGE. 1864aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * 1964aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, 2064aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 2164aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS 2264aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO 2364aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 2464aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * 2564aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * Red Hat Author(s): Behdad Esfahbod 260ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod * Google Author(s): Behdad Esfahbod 2764aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod */ 2864aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod 290f0cd9d361f1bb614aa3fd4616160d027062370eBehdad Esfahbod#ifndef HB_OPEN_TYPE_PRIVATE_HH 300f0cd9d361f1bb614aa3fd4616160d027062370eBehdad Esfahbod#define HB_OPEN_TYPE_PRIVATE_HH 3112c4568c680ea2b9b98a16a8b7402ca185c90ef6Behdad Esfahbod 32c57d454accff66e5f2c58006e8fb40bc020b6182Behdad Esfahbod#include "hb-private.hh" 3312c4568c680ea2b9b98a16a8b7402ca185c90ef6Behdad Esfahbod 3470de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod#include "hb-blob.h" 3570de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod 36a16ecbf0564a6e2576da22c12827f3c0719da549Behdad Esfahbod 377c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbodnamespace OT { 387c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod 39a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbod 4081822528efc63d867cb2343a8ff7af64fac1c70dBehdad Esfahbod 4181822528efc63d867cb2343a8ff7af64fac1c70dBehdad Esfahbod/* 42196598bbccff08415ff5192314cba044df258cadBehdad Esfahbod * Casts 43196598bbccff08415ff5192314cba044df258cadBehdad Esfahbod */ 44196598bbccff08415ff5192314cba044df258cadBehdad Esfahbod 45187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbod/* Cast to struct T, reference to reference */ 46a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbodtemplate<typename Type, typename TObject> 47187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbodinline const Type& CastR(const TObject &X) 48a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbod{ return reinterpret_cast<const Type&> (X); } 49a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbodtemplate<typename Type, typename TObject> 50187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbodinline Type& CastR(TObject &X) 51a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbod{ return reinterpret_cast<Type&> (X); } 52196598bbccff08415ff5192314cba044df258cadBehdad Esfahbod 53187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbod/* Cast to struct T, pointer to pointer */ 54187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbodtemplate<typename Type, typename TObject> 55187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbodinline const Type* CastP(const TObject *X) 56187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbod{ return reinterpret_cast<const Type*> (X); } 57187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbodtemplate<typename Type, typename TObject> 58187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbodinline Type* CastP(TObject *X) 59187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbod{ return reinterpret_cast<Type*> (X); } 60187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbod 6109766b1ec5ec55a61edbcd7a89ed3613cc92d4cbBehdad Esfahbod/* StructAtOffset<T>(P,Ofs) returns the struct T& that is placed at memory 6209766b1ec5ec55a61edbcd7a89ed3613cc92d4cbBehdad Esfahbod * location pointed to by P plus Ofs bytes. */ 6309766b1ec5ec55a61edbcd7a89ed3613cc92d4cbBehdad Esfahbodtemplate<typename Type> 6409766b1ec5ec55a61edbcd7a89ed3613cc92d4cbBehdad Esfahbodinline const Type& StructAtOffset(const void *P, unsigned int offset) 65a82ef7a893b773a17f7548375de9f588dfc83abaBehdad Esfahbod{ return * reinterpret_cast<const Type*> ((const char *) P + offset); } 6609766b1ec5ec55a61edbcd7a89ed3613cc92d4cbBehdad Esfahbodtemplate<typename Type> 6709766b1ec5ec55a61edbcd7a89ed3613cc92d4cbBehdad Esfahbodinline Type& StructAtOffset(void *P, unsigned int offset) 68a82ef7a893b773a17f7548375de9f588dfc83abaBehdad Esfahbod{ return * reinterpret_cast<Type*> ((char *) P + offset); } 6970de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod 702e2f43edf2f49f4047e28b1ce2ea95938536de9cBehdad Esfahbod/* StructAfter<T>(X) returns the struct T& that is placed after X. 7129c3f5e1b6212c775a7b911becd44ba093b7b0ebBehdad Esfahbod * Works with X of variable size also. X must implement get_size() */ 72e961c86c579fd98ee604342a9c70c4e7f8d4f220Behdad Esfahbodtemplate<typename Type, typename TObject> 73e961c86c579fd98ee604342a9c70c4e7f8d4f220Behdad Esfahbodinline const Type& StructAfter(const TObject &X) 7409766b1ec5ec55a61edbcd7a89ed3613cc92d4cbBehdad Esfahbod{ return StructAtOffset<Type>(&X, X.get_size()); } 75e961c86c579fd98ee604342a9c70c4e7f8d4f220Behdad Esfahbodtemplate<typename Type, typename TObject> 76e961c86c579fd98ee604342a9c70c4e7f8d4f220Behdad Esfahbodinline Type& StructAfter(TObject &X) 7709766b1ec5ec55a61edbcd7a89ed3613cc92d4cbBehdad Esfahbod{ return StructAtOffset<Type>(&X, X.get_size()); } 78a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbod 79e961c86c579fd98ee604342a9c70c4e7f8d4f220Behdad Esfahbod 80d3480ba37fbb5d4be75b094060f5b2f1ce98fb53Behdad Esfahbod 8170de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod/* 82e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod * Size checking 83e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod */ 84e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod 85f679635893eebc13402c5ee51a6f106eed0c76beBehdad Esfahbod/* Check _assertion in a method environment */ 86a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod#define _DEFINE_INSTANCE_ASSERTION1(_line, _assertion) \ 87a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod inline void _instance_assertion_on_line_##_line (void) const \ 88a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod { \ 89a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod ASSERT_STATIC (_assertion); \ 90a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod ASSERT_INSTANCE_POD (*this); /* Make sure it's POD. */ \ 91a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod } 92a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod# define _DEFINE_INSTANCE_ASSERTION0(_line, _assertion) _DEFINE_INSTANCE_ASSERTION1 (_line, _assertion) 93a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod# define DEFINE_INSTANCE_ASSERTION(_assertion) _DEFINE_INSTANCE_ASSERTION0 (__LINE__, _assertion) 94a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod 95f679635893eebc13402c5ee51a6f106eed0c76beBehdad Esfahbod/* Check that _code compiles in a method environment */ 96a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod#define _DEFINE_COMPILES_ASSERTION1(_line, _code) \ 97a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod inline void _compiles_assertion_on_line_##_line (void) const \ 98f679635893eebc13402c5ee51a6f106eed0c76beBehdad Esfahbod { _code; } 99a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod# define _DEFINE_COMPILES_ASSERTION0(_line, _code) _DEFINE_COMPILES_ASSERTION1 (_line, _code) 100a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod# define DEFINE_COMPILES_ASSERTION(_code) _DEFINE_COMPILES_ASSERTION0 (__LINE__, _code) 1010abcc3b48cfd51a22695c9e988938b2f45cb19d8Behdad Esfahbod 1020abcc3b48cfd51a22695c9e988938b2f45cb19d8Behdad Esfahbod 103e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod#define DEFINE_SIZE_STATIC(size) \ 104a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size)); \ 105e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod static const unsigned int static_size = (size); \ 106e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod static const unsigned int min_size = (size) 107e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod 108b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod/* Size signifying variable-sized array */ 109b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod#define VAR 1 110b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod 111596e471aa5053d955fb5d5b5923088c8814469b1Behdad Esfahbod#define DEFINE_SIZE_UNION(size, _member) \ 112a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod DEFINE_INSTANCE_ASSERTION (this->u._member.static_size == (size)); \ 113596e471aa5053d955fb5d5b5923088c8814469b1Behdad Esfahbod static const unsigned int min_size = (size) 114596e471aa5053d955fb5d5b5923088c8814469b1Behdad Esfahbod 115bea34c7cbb583cf7660776e95cab3171590b8427Behdad Esfahbod#define DEFINE_SIZE_MIN(size) \ 116a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod DEFINE_INSTANCE_ASSERTION (sizeof (*this) >= (size)); \ 117b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod static const unsigned int min_size = (size) 118b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod 1190eb9fc6e37935707dba2bf4b3705de2161a08cb7Behdad Esfahbod#define DEFINE_SIZE_ARRAY(size, array) \ 120a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size) + sizeof (array[0])); \ 121a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod DEFINE_COMPILES_ASSERTION ((void) array[0].static_size) \ 122e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod static const unsigned int min_size = (size) 123e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod 1240eb9fc6e37935707dba2bf4b3705de2161a08cb7Behdad Esfahbod#define DEFINE_SIZE_ARRAY2(size, array1, array2) \ 125a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size) + sizeof (this->array1[0]) + sizeof (this->array2[0])); \ 126a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod DEFINE_COMPILES_ASSERTION ((void) array1[0].static_size; (void) array2[0].static_size) \ 127e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod static const unsigned int min_size = (size) 128e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod 129e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod 130e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod 131e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod/* 132f0abcd69408a3af65207cdf8847575ade4579bd4Behdad Esfahbod * Null objects 133600e5eb80f553ea8eb862e6784133574c74ca513Behdad Esfahbod */ 134600e5eb80f553ea8eb862e6784133574c74ca513Behdad Esfahbod 1358b8358033184198ff638ee1379093717596e162dBehdad Esfahbod/* Global nul-content Null pool. Enlarge as necessary. */ 1360bb0f5d41976ae27c5c7a51cbb82144b48315a4bBehdad Esfahbod/* TODO This really should be a extern HB_INTERNAL and defined somewhere... */ 137cf5585cfa6cac6fdf627a99941299e76af5ae0f7Behdad Esfahbodstatic const void *_NullPool[64 / sizeof (void *)]; 1388b8358033184198ff638ee1379093717596e162dBehdad Esfahbod 139d2c2ca8faf62fc380d4717d286556139a62d2356Behdad Esfahbod/* Generic nul-content Null objects. */ 1408b8358033184198ff638ee1379093717596e162dBehdad Esfahbodtemplate <typename Type> 1417f97d2cd904ea999c099c73c52187c5d65aeec67Behdad Esfahbodstatic inline const Type& Null (void) { 142fd0de881f4fc004da6f36d50a91d0e62f8eb4d8cBehdad Esfahbod ASSERT_STATIC (sizeof (Type) <= sizeof (_NullPool)); 143187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbod return *CastP<Type> (_NullPool); 1449d3677899f90abdc7fb3e3d854db654a8707a84bBehdad Esfahbod} 1458b8358033184198ff638ee1379093717596e162dBehdad Esfahbod 1468b8358033184198ff638ee1379093717596e162dBehdad Esfahbod/* Specializaiton for arbitrary-content arbitrary-sized Null objects. */ 14765f46b00333e20ab8a52a4b350747507541ec1dbBehdad Esfahbod#define DEFINE_NULL_DATA(Type, data) \ 148fd0de881f4fc004da6f36d50a91d0e62f8eb4d8cBehdad Esfahbodstatic const char _Null##Type[sizeof (Type) + 1] = data; /* +1 is for nul-termination in data */ \ 1498b8358033184198ff638ee1379093717596e162dBehdad Esfahbodtemplate <> \ 1507f97d2cd904ea999c099c73c52187c5d65aeec67Behdad Esfahbodinline const Type& Null<Type> (void) { \ 151187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbod return *CastP<Type> (_Null##Type); \ 152565c80bd2960366ace2d10dd71beaaf2a80213c8Behdad Esfahbod} /* The following line really exists such that we end in a place needing semicolon */ \ 153bea34c7cbb583cf7660776e95cab3171590b8427Behdad EsfahbodASSERT_STATIC (Type::min_size + 1 <= sizeof (_Null##Type)) 1548b8358033184198ff638ee1379093717596e162dBehdad Esfahbod 1558b8358033184198ff638ee1379093717596e162dBehdad Esfahbod/* Accessor macro. */ 1569d3677899f90abdc7fb3e3d854db654a8707a84bBehdad Esfahbod#define Null(Type) Null<Type>() 1578b8358033184198ff638ee1379093717596e162dBehdad Esfahbod 1588b8358033184198ff638ee1379093717596e162dBehdad Esfahbod 159600e5eb80f553ea8eb862e6784133574c74ca513Behdad Esfahbod 160577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod/* 161577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod * Sanitize 162577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod */ 163577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod 16495e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod#ifndef HB_DEBUG_SANITIZE 16511e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod#define HB_DEBUG_SANITIZE (HB_DEBUG+0) 16695e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod#endif 16795e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod 16820e3dd5d292b65f70d2eae63b8d8713a1c889d47Behdad Esfahbod 169be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod#define TRACE_SANITIZE(this) \ 170902cc8aca0b3ff25eeee50b3a84d729e31731ef3Behdad Esfahbod hb_auto_trace_t<HB_DEBUG_SANITIZE, bool> trace \ 1712c53bd3c3ec4f81eff126c5bf84b7f2ddf2f0fefBehdad Esfahbod (&c->debug_depth, c->get_name (), this, HB_FUNC, \ 172902cc8aca0b3ff25eeee50b3a84d729e31731ef3Behdad Esfahbod ""); 173807c5b03a2251a3c29a520852639421783101b55Behdad Esfahbod 174b28815c1f6e46d38471cacbc31248ca6fda8c4d1Behdad Esfahbod 1751376fb7bf9ef07970f0ba13dc64d6a8ab8252762Behdad Esfahbodstruct hb_sanitize_context_t 176577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod{ 1772c53bd3c3ec4f81eff126c5bf84b7f2ddf2f0fefBehdad Esfahbod inline const char *get_name (void) { return "SANITIZE"; } 1782c53bd3c3ec4f81eff126c5bf84b7f2ddf2f0fefBehdad Esfahbod static const unsigned int max_debug_depth = HB_DEBUG_SANITIZE; 1792c53bd3c3ec4f81eff126c5bf84b7f2ddf2f0fefBehdad Esfahbod typedef bool return_t; 1802c53bd3c3ec4f81eff126c5bf84b7f2ddf2f0fefBehdad Esfahbod template <typename T> 1812c53bd3c3ec4f81eff126c5bf84b7f2ddf2f0fefBehdad Esfahbod inline return_t process (const T &obj) { return obj.sanitize (this); } 1822c53bd3c3ec4f81eff126c5bf84b7f2ddf2f0fefBehdad Esfahbod static return_t default_return_value (void) { return true; } 1830beb66e3a61ae8bb1fa66e54b1ff1abb2f8711e9Behdad Esfahbod bool stop_sublookup_iteration (const return_t r HB_UNUSED) const { return false; } 1842c53bd3c3ec4f81eff126c5bf84b7f2ddf2f0fefBehdad Esfahbod 18531f18abecb149f8888a72510f2660328dd6de16dBehdad Esfahbod inline void init (hb_blob_t *b) 18698daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod { 18731f18abecb149f8888a72510f2660328dd6de16dBehdad Esfahbod this->blob = hb_blob_reference (b); 1881c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod this->writable = false; 1891c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod } 1901c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod 191cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod inline void start_processing (void) 1921c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod { 1934101ca7dbbdf1438fa116fb8cad935501ac7cca8Behdad Esfahbod this->start = hb_blob_get_data (this->blob, NULL); 1944101ca7dbbdf1438fa116fb8cad935501ac7cca8Behdad Esfahbod this->end = this->start + hb_blob_get_length (this->blob); 19598daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod this->edit_count = 0; 19620e3dd5d292b65f70d2eae63b8d8713a1c889d47Behdad Esfahbod this->debug_depth = 0; 197577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod 1981e08830b4fac3a60ae52349cab6e101d389d30cdBehdad Esfahbod DEBUG_MSG_LEVEL (SANITIZE, this->blob, 0, +1, 199cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod "start [%p..%p] (%lu bytes)", 2001e08830b4fac3a60ae52349cab6e101d389d30cdBehdad Esfahbod this->start, this->end, 2011e08830b4fac3a60ae52349cab6e101d389d30cdBehdad Esfahbod (unsigned long) (this->end - this->start)); 20298daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod } 2031376fb7bf9ef07970f0ba13dc64d6a8ab8252762Behdad Esfahbod 204cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod inline void end_processing (void) 20598daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod { 2061e08830b4fac3a60ae52349cab6e101d389d30cdBehdad Esfahbod DEBUG_MSG_LEVEL (SANITIZE, this->blob, 0, -1, 207cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod "end [%p..%p] %u edit requests", 2081e08830b4fac3a60ae52349cab6e101d389d30cdBehdad Esfahbod this->start, this->end, this->edit_count); 209577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod 21098daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod hb_blob_destroy (this->blob); 21198daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod this->blob = NULL; 21298daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod this->start = this->end = NULL; 21398daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod } 2144f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod 2154ad2cc5dec6b0639da2b1846282bdd99d06d5ff1Behdad Esfahbod inline bool check_range (const void *base, unsigned int len) const 21698daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod { 217a82ef7a893b773a17f7548375de9f588dfc83abaBehdad Esfahbod const char *p = (const char *) base; 21898daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod 219902cc8aca0b3ff25eeee50b3a84d729e31731ef3Behdad Esfahbod hb_auto_trace_t<HB_DEBUG_SANITIZE, bool> trace 220902cc8aca0b3ff25eeee50b3a84d729e31731ef3Behdad Esfahbod (&this->debug_depth, "SANITIZE", this->blob, NULL, 221902cc8aca0b3ff25eeee50b3a84d729e31731ef3Behdad Esfahbod "check_range [%p..%p] (%d bytes) in [%p..%p]", 222902cc8aca0b3ff25eeee50b3a84d729e31731ef3Behdad Esfahbod p, p + len, len, 223902cc8aca0b3ff25eeee50b3a84d729e31731ef3Behdad Esfahbod this->start, this->end); 22498daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod 225cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod return TRACE_RETURN (likely (this->start <= p && p <= this->end && (unsigned int) (this->end - p) >= len)); 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; 231080a0eb7d82d7195be72c16ece6e0a3ffed636b6Behdad Esfahbod bool overflows = _hb_unsigned_int_mul_overflows (len, record_size); 23241895506cb6a41b1a833866f8822261ea449ea0bBehdad Esfahbod 233902cc8aca0b3ff25eeee50b3a84d729e31731ef3Behdad Esfahbod hb_auto_trace_t<HB_DEBUG_SANITIZE, bool> trace 234902cc8aca0b3ff25eeee50b3a84d729e31731ef3Behdad Esfahbod (&this->debug_depth, "SANITIZE", this->blob, NULL, 235902cc8aca0b3ff25eeee50b3a84d729e31731ef3Behdad Esfahbod "check_array [%p..%p] (%d*%d=%ld bytes) in [%p..%p]", 236902cc8aca0b3ff25eeee50b3a84d729e31731ef3Behdad Esfahbod p, p + (record_size * len), record_size, len, (unsigned long) record_size * len, 237902cc8aca0b3ff25eeee50b3a84d729e31731ef3Behdad Esfahbod this->start, this->end); 238fa030175ca998b00cc42cbced6e98de323ec01ecBehdad Esfahbod 239cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod return TRACE_RETURN (likely (!overflows && this->check_range (base, record_size * len))); 24098daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod } 241254933c397f1ce9796f59689a25f9fc2e58df4eaBehdad Esfahbod 242b157617644d1e38f680163889d1dc2e2f64d9ba3Behdad Esfahbod template <typename Type> 243b157617644d1e38f680163889d1dc2e2f64d9ba3Behdad Esfahbod inline bool check_struct (const Type *obj) const 244b157617644d1e38f680163889d1dc2e2f64d9ba3Behdad Esfahbod { 24554842374c2b291ef208c51ae1d853ec0403ccf84Behdad Esfahbod return likely (this->check_range (obj, obj->min_size)); 246b157617644d1e38f680163889d1dc2e2f64d9ba3Behdad Esfahbod } 247b157617644d1e38f680163889d1dc2e2f64d9ba3Behdad Esfahbod 248cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod inline bool may_edit (const void *base HB_UNUSED, unsigned int len HB_UNUSED) 24998daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod { 250a82ef7a893b773a17f7548375de9f588dfc83abaBehdad Esfahbod const char *p = (const char *) base; 25198daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod this->edit_count++; 25298daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod 253902cc8aca0b3ff25eeee50b3a84d729e31731ef3Behdad Esfahbod hb_auto_trace_t<HB_DEBUG_SANITIZE, bool> trace 254902cc8aca0b3ff25eeee50b3a84d729e31731ef3Behdad Esfahbod (&this->debug_depth, "SANITIZE", this->blob, NULL, 255902cc8aca0b3ff25eeee50b3a84d729e31731ef3Behdad Esfahbod "may_edit(%u) [%p..%p] (%d bytes) in [%p..%p] -> %s", 256902cc8aca0b3ff25eeee50b3a84d729e31731ef3Behdad Esfahbod this->edit_count, 257902cc8aca0b3ff25eeee50b3a84d729e31731ef3Behdad Esfahbod p, p + len, len, 258902cc8aca0b3ff25eeee50b3a84d729e31731ef3Behdad Esfahbod this->start, this->end); 25998daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod 260cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod return TRACE_RETURN (this->writable); 26198daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod } 26298daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod 263cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod mutable unsigned int debug_depth; 26498daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod const char *start, *end; 26598daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod bool writable; 26698daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod unsigned int edit_count; 26798daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod hb_blob_t *blob; 26898daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod}; 269815a73e4202ca17677f12e862b70ca8724cf2f57Behdad Esfahbod 270577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod 271577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod 2724e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod/* Template to sanitize an object. */ 2734e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbodtemplate <typename Type> 2744e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbodstruct Sanitizer 2754e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod{ 2764e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod static hb_blob_t *sanitize (hb_blob_t *blob) { 277d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod hb_sanitize_context_t c[1] = {{0}}; 2784e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod bool sane; 2794e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod 280d0b657379bbe63602953412d6bc944b2a0f430ebBehdad Esfahbod /* TODO is_sane() stuff */ 2814e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod 2821c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod c->init (blob); 2831c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod 2844e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod retry: 285cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod DEBUG_MSG_FUNC (SANITIZE, blob, "start"); 2864f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod 287cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod c->start_processing (); 2884e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod 289d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod if (unlikely (!c->start)) { 290cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod c->end_processing (); 29148146e5612f6d272d6962f6829c6d64a31edef89Behdad Esfahbod return blob; 29248146e5612f6d272d6962f6829c6d64a31edef89Behdad Esfahbod } 29348146e5612f6d272d6962f6829c6d64a31edef89Behdad Esfahbod 294d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod Type *t = CastP<Type> (const_cast<char *> (c->start)); 2954e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod 296d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod sane = t->sanitize (c); 2974e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod if (sane) { 298d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod if (c->edit_count) { 299cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod DEBUG_MSG_FUNC (SANITIZE, blob, "passed first round with %d edits; going for second round", c->edit_count); 300fa030175ca998b00cc42cbced6e98de323ec01ecBehdad Esfahbod 3018b5346130425c7c101f6ff2432874ba2fd372edcBehdad Esfahbod /* sanitize again to ensure no toe-stepping */ 302d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod c->edit_count = 0; 303d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod sane = t->sanitize (c); 304d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod if (c->edit_count) { 305cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod DEBUG_MSG_FUNC (SANITIZE, blob, "requested %d edits in second round; FAILLING", c->edit_count); 3064e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod sane = false; 3074e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod } 3084e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod } 3094e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod } else { 310d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod unsigned int edit_count = c->edit_count; 3111c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod if (edit_count && !c->writable) { 3121c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod c->start = hb_blob_get_data_writable (blob, NULL); 3131c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod c->end = c->start + hb_blob_get_length (blob); 3141c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod 3151c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod if (c->start) { 3161c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod c->writable = true; 3171c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod /* ok, we made it writable by relocating. try again */ 318cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod DEBUG_MSG_FUNC (SANITIZE, blob, "retry"); 3191c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod goto retry; 3201c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod } 3214e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod } 3224e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod } 3234e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod 324cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod c->end_processing (); 3254101ca7dbbdf1438fa116fb8cad935501ac7cca8Behdad Esfahbod 326cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod DEBUG_MSG_FUNC (SANITIZE, blob, sane ? "PASSED" : "FAILED"); 3274e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod if (sane) 3284e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod return blob; 3294e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod else { 3304e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod hb_blob_destroy (blob); 3314911062d5be0d937ee8f1a70cc93e05d162f45b3Behdad Esfahbod return hb_blob_get_empty (); 3324e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod } 3334e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod } 334b435ab7e29c388e3b100f729957319931625a3a8Behdad Esfahbod 335b435ab7e29c388e3b100f729957319931625a3a8Behdad Esfahbod static const Type* lock_instance (hb_blob_t *blob) { 3361c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod hb_blob_make_immutable (blob); 3371c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod const char *base = hb_blob_get_data (blob, NULL); 338b435ab7e29c388e3b100f729957319931625a3a8Behdad Esfahbod return unlikely (!base) ? &Null(Type) : CastP<Type> (base); 339b435ab7e29c388e3b100f729957319931625a3a8Behdad Esfahbod } 3404e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod}; 3414e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod 3422d15e72c75931398db5e027e660f1320bb979117Behdad Esfahbod 343f0abcd69408a3af65207cdf8847575ade4579bd4Behdad Esfahbod 344e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod/* 345e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod * Serialize 346e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod */ 347e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod 348e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod#ifndef HB_DEBUG_SERIALIZE 349e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod#define HB_DEBUG_SERIALIZE (HB_DEBUG+0) 350e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod#endif 351e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod 352e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod 353be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod#define TRACE_SERIALIZE(this) \ 354902cc8aca0b3ff25eeee50b3a84d729e31731ef3Behdad Esfahbod hb_auto_trace_t<HB_DEBUG_SERIALIZE, bool> trace \ 355902cc8aca0b3ff25eeee50b3a84d729e31731ef3Behdad Esfahbod (&c->debug_depth, "SERIALIZE", c, HB_FUNC, \ 356902cc8aca0b3ff25eeee50b3a84d729e31731ef3Behdad Esfahbod ""); 357e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod 358e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod 359e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbodstruct hb_serialize_context_t 360e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod{ 361fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod inline hb_serialize_context_t (void *start, unsigned int size) 362e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod { 363e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod this->start = (char *) start; 364e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod this->end = this->start + size; 365e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod 366e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod this->ran_out_of_room = false; 367e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod this->head = this->start; 368e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod this->debug_depth = 0; 369fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod } 370e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod 371fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod template <typename Type> 372fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod inline Type *start_serialize (void) 373fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod { 374e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod DEBUG_MSG_LEVEL (SERIALIZE, this->start, 0, +1, 375e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod "start [%p..%p] (%lu bytes)", 376e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod this->start, this->end, 377e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod (unsigned long) (this->end - this->start)); 378fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod 379fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod return start_embed<Type> (); 380e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod } 381e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod 382fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod inline void end_serialize (void) 383e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod { 384e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod DEBUG_MSG_LEVEL (SERIALIZE, this->start, 0, -1, 385fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod "end [%p..%p] serialized %d bytes; %s", 386e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod this->start, this->end, 387fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod (int) (this->head - this->start), 388e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod this->ran_out_of_room ? "RAN OUT OF ROOM" : "did not ran out of room"); 389e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod 390fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod } 391fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod 392fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod template <typename Type> 393fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod inline Type *copy (void) 394fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod { 395fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod assert (!this->ran_out_of_room); 396fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod unsigned int len = this->head - this->start; 397fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod void *p = malloc (len); 398fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod if (p) 399fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod memcpy (p, this->start, len); 400fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod return reinterpret_cast<Type *> (p); 401e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod } 402e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod 403e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod template <typename Type> 4044b312fb288faa383a2c5bd3be0428f0e58e02699Behdad Esfahbod inline Type *allocate_size (unsigned int size) 405e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod { 406fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod if (unlikely (this->ran_out_of_room || this->end - this->head < size)) { 407e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod this->ran_out_of_room = true; 408e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod return NULL; 409e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod } 4104b312fb288faa383a2c5bd3be0428f0e58e02699Behdad Esfahbod memset (this->head, 0, size); 4119f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod char *ret = this->head; 412e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod this->head += size; 413e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod return reinterpret_cast<Type *> (ret); 414e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod } 415e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod 416e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod template <typename Type> 4174b312fb288faa383a2c5bd3be0428f0e58e02699Behdad Esfahbod inline Type *allocate_min (void) 4189f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod { 4194b312fb288faa383a2c5bd3be0428f0e58e02699Behdad Esfahbod return this->allocate_size<Type> (Type::min_size); 4209f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod } 4219f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod 4229f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod template <typename Type> 423fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod inline Type *start_embed (void) 424fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod { 425fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod Type *ret = reinterpret_cast<Type *> (this->head); 426fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod return ret; 427fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod } 428fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod 429fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod template <typename Type> 4304b312fb288faa383a2c5bd3be0428f0e58e02699Behdad Esfahbod inline Type *embed (const Type &obj) 431e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod { 432bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod unsigned int size = obj.get_size (); 4334b312fb288faa383a2c5bd3be0428f0e58e02699Behdad Esfahbod Type *ret = this->allocate_size<Type> (size); 434bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod if (unlikely (!ret)) return NULL; 435bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod memcpy (ret, obj, size); 436bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod return ret; 4379f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod } 4389f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod 4399f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod template <typename Type> 4404b312fb288faa383a2c5bd3be0428f0e58e02699Behdad Esfahbod inline Type *extend_min (Type &obj) 4419f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod { 442bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod unsigned int size = obj.min_size; 443fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod assert (this->start <= (char *) &obj && (char *) &obj <= this->head && (char *) &obj + size >= this->head); 444fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod if (unlikely (!this->allocate_size<Type> (((char *) &obj) + size - this->head))) return NULL; 4459f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod return reinterpret_cast<Type *> (&obj); 4469f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod } 4479f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod 4489f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod template <typename Type> 4494b312fb288faa383a2c5bd3be0428f0e58e02699Behdad Esfahbod inline Type *extend (Type &obj) 4509f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod { 451bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod unsigned int size = obj.get_size (); 452bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod assert (this->start < (char *) &obj && (char *) &obj <= this->head && (char *) &obj + size >= this->head); 453811eefe225d20b20f1de20c6e62a0ebd6d89102aBehdad Esfahbod if (unlikely (!this->allocate_size<Type> (((char *) &obj) + size - this->head))) return NULL; 454bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod return reinterpret_cast<Type *> (&obj); 455e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod } 456e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod 457e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod inline void truncate (void *head) 458e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod { 459e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod assert (this->start < head && head <= this->head); 460e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod this->head = (char *) head; 461e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod } 462e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod 463e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod unsigned int debug_depth; 464e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod char *start, *end, *head; 465e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod bool ran_out_of_room; 466e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod}; 467e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod 468a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbodtemplate <typename Type> 469a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbodstruct Supplier 470a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod{ 471a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod inline Supplier (const Type *array, unsigned int len_) 472a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod { 473a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod head = array; 474a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod len = len_; 475a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod } 476a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod inline const Type operator [] (unsigned int i) const 477a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod { 478a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod if (unlikely (i >= len)) return Type (); 479a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod return head[i]; 480a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod } 481a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod 482fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod inline void advance (unsigned int count) 483fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod { 484a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod if (unlikely (count > len)) 485a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod count = len; 486a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod len -= count; 487a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod head += count; 488a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod } 489a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod 490a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod private: 491fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod inline Supplier (const Supplier<Type> &); /* Disallow copy */ 492fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod inline Supplier<Type>& operator= (const Supplier<Type> &); /* Disallow copy */ 493fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod 494a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod unsigned int len; 495a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod const Type *head; 496a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod}; 497a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod 498a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod 499e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod 500f0abcd69408a3af65207cdf8847575ade4579bd4Behdad Esfahbod 501b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod/* 502b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod * 503bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod * The OpenType Font File: Data Types 504b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod */ 505b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod 506b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod 507b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod/* "The following data types are used in the OpenType font file. 508b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod * All OpenType fonts use Motorola-style byte ordering (Big Endian):" */ 509b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod 5105f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod/* 5115f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod * Int types 5125f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod */ 5135f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod 5146b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod 515d7bf473ef222ab420456ff155ffaa09bacb3a394Behdad Esfahbodtemplate <typename Type, int Bytes> struct BEInt; 516e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod 517e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodtemplate <typename Type> 518d7bf473ef222ab420456ff155ffaa09bacb3a394Behdad Esfahbodstruct BEInt<Type, 2> 519e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod{ 520e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod public: 52181408cd51ce575891e79e6483be187130f864c28Behdad Esfahbod inline void set (Type i) { hb_be_uint16_put (v,i); } 5227f97d2cd904ea999c099c73c52187c5d65aeec67Behdad Esfahbod inline operator Type (void) const { return hb_be_uint16_get (v); } 523153142dac8dd9abaf164bb88af07c600c17fc3a1Behdad Esfahbod inline bool operator == (const BEInt<Type, 2>& o) const { return hb_be_uint16_eq (v, o.v); } 52401c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod inline bool operator != (const BEInt<Type, 2>& o) const { return !(*this == o); } 525e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod private: uint8_t v[2]; 526e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod}; 527e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodtemplate <typename Type> 528d7bf473ef222ab420456ff155ffaa09bacb3a394Behdad Esfahbodstruct BEInt<Type, 4> 529e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod{ 530e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod public: 53181408cd51ce575891e79e6483be187130f864c28Behdad Esfahbod inline void set (Type i) { hb_be_uint32_put (v,i); } 5327f97d2cd904ea999c099c73c52187c5d65aeec67Behdad Esfahbod inline operator Type (void) const { return hb_be_uint32_get (v); } 533153142dac8dd9abaf164bb88af07c600c17fc3a1Behdad Esfahbod inline bool operator == (const BEInt<Type, 4>& o) const { return hb_be_uint32_eq (v, o.v); } 53401c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod inline bool operator != (const BEInt<Type, 4>& o) const { return !(*this == o); } 535e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod private: uint8_t v[4]; 536e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod}; 537bd61bc13ea8ff350ada5449b2cfeb612e66ecafaBehdad Esfahbodtemplate <typename Type> 538bd61bc13ea8ff350ada5449b2cfeb612e66ecafaBehdad Esfahbodstruct BEInt<Type, 3> 539bd61bc13ea8ff350ada5449b2cfeb612e66ecafaBehdad Esfahbod{ 540bd61bc13ea8ff350ada5449b2cfeb612e66ecafaBehdad Esfahbod public: 541bd61bc13ea8ff350ada5449b2cfeb612e66ecafaBehdad Esfahbod inline void set (Type i) { hb_be_uint24_put (v,i); } 542bd61bc13ea8ff350ada5449b2cfeb612e66ecafaBehdad Esfahbod inline operator Type (void) const { return hb_be_uint24_get (v); } 543bd61bc13ea8ff350ada5449b2cfeb612e66ecafaBehdad Esfahbod inline bool operator == (const BEInt<Type, 3>& o) const { return hb_be_uint24_eq (v, o.v); } 544bd61bc13ea8ff350ada5449b2cfeb612e66ecafaBehdad Esfahbod inline bool operator != (const BEInt<Type, 3>& o) const { return !(*this == o); } 545bd61bc13ea8ff350ada5449b2cfeb612e66ecafaBehdad Esfahbod private: uint8_t v[3]; 546bd61bc13ea8ff350ada5449b2cfeb612e66ecafaBehdad Esfahbod}; 547e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod 5482467c669c2aee4de2a6621a9d06cba0262376d41Behdad Esfahbod/* Integer types in big-endian order and no alignment requirement */ 549bd61bc13ea8ff350ada5449b2cfeb612e66ecafaBehdad Esfahbodtemplate <typename Type, unsigned int Size> 550e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodstruct IntType 551e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod{ 55281408cd51ce575891e79e6483be187130f864c28Behdad Esfahbod inline void set (Type i) { v.set (i); } 55301c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod inline operator Type(void) const { return v; } 554bd61bc13ea8ff350ada5449b2cfeb612e66ecafaBehdad Esfahbod inline bool operator == (const IntType<Type,Size> &o) const { return v == o.v; } 555bd61bc13ea8ff350ada5449b2cfeb612e66ecafaBehdad Esfahbod inline bool operator != (const IntType<Type,Size> &o) const { return v != o.v; } 556bd61bc13ea8ff350ada5449b2cfeb612e66ecafaBehdad Esfahbod static inline int cmp (const IntType<Type,Size> *a, const IntType<Type,Size> *b) { return b->cmp (*a); } 557bd61bc13ea8ff350ada5449b2cfeb612e66ecafaBehdad Esfahbod inline int cmp (IntType<Type,Size> va) const { Type a = va; Type b = v; return a < b ? -1 : a == b ? 0 : +1; } 5584e573715ae5f5ed486ad66382bb44c47a86591ffBehdad Esfahbod inline int cmp (Type a) const { Type b = v; return a < b ? -1 : a == b ? 0 : +1; } 559d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod inline bool sanitize (hb_sanitize_context_t *c) { 560be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod TRACE_SANITIZE (this); 5610ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod return TRACE_RETURN (likely (c->check_struct (this))); 562e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod } 563a82ef7a893b773a17f7548375de9f588dfc83abaBehdad Esfahbod protected: 564bd61bc13ea8ff350ada5449b2cfeb612e66ecafaBehdad Esfahbod BEInt<Type, Size> v; 565569da92bc6956f42d9b2d65c784e184fb6380efeBehdad Esfahbod public: 566bd61bc13ea8ff350ada5449b2cfeb612e66ecafaBehdad Esfahbod DEFINE_SIZE_STATIC (Size); 567e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod}; 568e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod 569bd61bc13ea8ff350ada5449b2cfeb612e66ecafaBehdad Esfahbodtypedef IntType<uint16_t, 2> USHORT; /* 16-bit unsigned integer. */ 570bd61bc13ea8ff350ada5449b2cfeb612e66ecafaBehdad Esfahbodtypedef IntType<int16_t, 2> SHORT; /* 16-bit signed integer. */ 571bd61bc13ea8ff350ada5449b2cfeb612e66ecafaBehdad Esfahbodtypedef IntType<uint32_t, 4> ULONG; /* 32-bit unsigned integer. */ 572bd61bc13ea8ff350ada5449b2cfeb612e66ecafaBehdad Esfahbodtypedef IntType<int32_t, 4> LONG; /* 32-bit signed integer. */ 573bd61bc13ea8ff350ada5449b2cfeb612e66ecafaBehdad Esfahbodtypedef IntType<uint32_t, 3> UINT24; /* 24-bit unsigned integer. */ 574e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod 575ae9877dea6a1aed3566d9b87a75ede84259deacaBehdad Esfahbod/* 16-bit signed integer (SHORT) that describes a quantity in FUnits. */ 576ae9877dea6a1aed3566d9b87a75ede84259deacaBehdad Esfahbodtypedef SHORT FWORD; 577ae9877dea6a1aed3566d9b87a75ede84259deacaBehdad Esfahbod 578ae9877dea6a1aed3566d9b87a75ede84259deacaBehdad Esfahbod/* 16-bit unsigned integer (USHORT) that describes a quantity in FUnits. */ 579ae9877dea6a1aed3566d9b87a75ede84259deacaBehdad Esfahbodtypedef USHORT UFWORD; 580ae9877dea6a1aed3566d9b87a75ede84259deacaBehdad Esfahbod 581e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod/* Date represented in number of seconds since 12:00 midnight, January 1, 582e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod * 1904. The value is represented as a signed 64-bit integer. */ 583e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbodstruct LONGDATETIME 584e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod{ 585e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod inline bool sanitize (hb_sanitize_context_t *c) { 586be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod TRACE_SANITIZE (this); 5870ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod return TRACE_RETURN (likely (c->check_struct (this))); 588e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod } 589e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod private: 590e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod LONG major; 591e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod ULONG minor; 592e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod public: 593e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod DEFINE_SIZE_STATIC (8); 594e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod}; 595e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod 5966b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod/* Array of four uint8s (length = 32 bits) used to identify a script, language 5976b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod * system, feature, or baseline */ 59820cc86b3592db33731de671f008d7d222776be49Behdad Esfahbodstruct Tag : ULONG 59960d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{ 600befc022affd2386b3f46cd7d11e4262f6c8bce9fBehdad Esfahbod /* What the char* converters return is NOT nul-terminated. Print using "%.4s" */ 601a82ef7a893b773a17f7548375de9f588dfc83abaBehdad Esfahbod inline operator const char* (void) const { return reinterpret_cast<const char *> (&this->v); } 602a82ef7a893b773a17f7548375de9f588dfc83abaBehdad Esfahbod inline operator char* (void) { return reinterpret_cast<char *> (&this->v); } 603b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod public: 604b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod DEFINE_SIZE_STATIC (4); 6056b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod}; 60665f46b00333e20ab8a52a4b350747507541ec1dbBehdad EsfahbodDEFINE_NULL_DATA (Tag, " "); 6076b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod 6086b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod/* Glyph index number, same as uint16 (length = 16 bits) */ 6096ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbodtypedef USHORT GlyphID; 6106b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod 611b5db4f1e4eefa266a71a28b5496f47ff9d1a81e8Behdad Esfahbod/* Script/language-system/feature index */ 612b5db4f1e4eefa266a71a28b5496f47ff9d1a81e8Behdad Esfahbodstruct Index : USHORT { 613b5db4f1e4eefa266a71a28b5496f47ff9d1a81e8Behdad Esfahbod static const unsigned int NOT_FOUND_INDEX = 0xFFFF; 614b5db4f1e4eefa266a71a28b5496f47ff9d1a81e8Behdad Esfahbod}; 615b5db4f1e4eefa266a71a28b5496f47ff9d1a81e8Behdad EsfahbodDEFINE_NULL_DATA (Index, "\xff\xff"); 616b5db4f1e4eefa266a71a28b5496f47ff9d1a81e8Behdad Esfahbod 6171f437e6f47fb6c15761021bd2078f31778f2179cBehdad Esfahbod/* Offset to a table, same as uint16 (length = 16 bits), Null offset = 0x0000 */ 6186ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbodtypedef USHORT Offset; 6196ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbod 6206ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbod/* LongOffset to a table, same as uint32 (length = 32 bits), Null offset = 0x00000000 */ 6216ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbodtypedef ULONG LongOffset; 6226ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbod 6236b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod 6246b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod/* CheckSum */ 62560d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbodstruct CheckSum : ULONG 62660d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{ 62760d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod static uint32_t CalcTableChecksum (ULONG *Table, uint32_t Length) 62860d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod { 6296b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod uint32_t Sum = 0L; 630e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod ULONG *EndPtr = Table+((Length+3) & ~3) / ULONG::static_size; 6316b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod 6326b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod while (Table < EndPtr) 6336b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod Sum += *Table++; 6346b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod return Sum; 6356b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod } 636b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod public: 637b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod DEFINE_SIZE_STATIC (4); 6386b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod}; 6396b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod 6406b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod 6416b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod/* 6426b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod * Version Numbers 6436b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod */ 6446b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod 64587fcdcbe3644da10154688765db2d62eb9ac079aBehdad Esfahbodstruct FixedVersion 64660d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{ 6474f28fbdd804fabeec57a98fe267d892ab58b3a6dBehdad Esfahbod inline uint32_t to_int (void) const { return (major << 16) + minor; } 64896908b898476ca5d7da5f386b15be76f9e83d76eBehdad Esfahbod 649d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod inline bool sanitize (hb_sanitize_context_t *c) { 650be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod TRACE_SANITIZE (this); 6510ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod return TRACE_RETURN (c->check_struct (this)); 652cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod } 653cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod 6546ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbod USHORT major; 65587fcdcbe3644da10154688765db2d62eb9ac079aBehdad Esfahbod USHORT minor; 656b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod public: 657b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod DEFINE_SIZE_STATIC (4); 6586b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod}; 6596b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod 66092b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 66192b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 6625f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod/* 66392b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod * Template subclasses of Offset and LongOffset that do the dereferencing. 664f0abcd69408a3af65207cdf8847575ade4579bd4Behdad Esfahbod * Use: (base+offset) 6655f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod */ 6665f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod 66792b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename OffsetType, typename Type> 66892b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct GenericOffsetTo : OffsetType 66992b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod{ 67000e23fcc6fd0eee5c582251bf3de6a2703fbbd3eBehdad Esfahbod inline const Type& operator () (const void *base) const 67192b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod { 67292b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod unsigned int offset = *this; 67364d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod if (unlikely (!offset)) return Null(Type); 67409766b1ec5ec55a61edbcd7a89ed3613cc92d4cbBehdad Esfahbod return StructAtOffset<Type> (base, offset); 67592b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod } 676bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod inline Type& operator () (void *base) 677bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod { 678bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod unsigned int offset = *this; 679bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod return StructAtOffset<Type> (base, offset); 680bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod } 681bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod 682abcc5ac1fde1c493e4055dd2f27b8aade7713156Behdad Esfahbod inline Type& serialize (hb_serialize_context_t *c, void *base) 683bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod { 684fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod Type *t = c->start_embed<Type> (); 6854912030dfba740c822e200d33cbb5c6dbbeaf79eBehdad Esfahbod this->set ((char *) t - (char *) base); /* TODO(serialize) Overflow? */ 686abcc5ac1fde1c493e4055dd2f27b8aade7713156Behdad Esfahbod return *t; 687bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod } 68892b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 689d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod inline bool sanitize (hb_sanitize_context_t *c, void *base) { 690be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod TRACE_SANITIZE (this); 6910ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod if (unlikely (!c->check_struct (this))) return TRACE_RETURN (false); 69292b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod unsigned int offset = *this; 6930ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod if (unlikely (!offset)) return TRACE_RETURN (true); 69409766b1ec5ec55a61edbcd7a89ed3613cc92d4cbBehdad Esfahbod Type &obj = StructAtOffset<Type> (base, offset); 6950ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod return TRACE_RETURN (likely (obj.sanitize (c)) || neuter (c)); 69692b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod } 6974a446ac35136eff23d55f47bdd7b40095ad707abBehdad Esfahbod template <typename T> 698d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod inline bool sanitize (hb_sanitize_context_t *c, void *base, T user_data) { 699be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod TRACE_SANITIZE (this); 7000ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod if (unlikely (!c->check_struct (this))) return TRACE_RETURN (false); 70142b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod unsigned int offset = *this; 7020ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod if (unlikely (!offset)) return TRACE_RETURN (true); 70309766b1ec5ec55a61edbcd7a89ed3613cc92d4cbBehdad Esfahbod Type &obj = StructAtOffset<Type> (base, offset); 7040ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod return TRACE_RETURN (likely (obj.sanitize (c, user_data)) || neuter (c)); 705c9f14687a30866181feb57ee2736a147ec9f25a1Behdad Esfahbod } 706c9f14687a30866181feb57ee2736a147ec9f25a1Behdad Esfahbod 7079b54562d63f1a9e0e5b33d71c32bd1588759ebf1Behdad Esfahbod inline bool try_set (hb_sanitize_context_t *c, const OffsetType &v) { 7089b54562d63f1a9e0e5b33d71c32bd1588759ebf1Behdad Esfahbod if (c->may_edit (this, this->static_size)) { 7099b54562d63f1a9e0e5b33d71c32bd1588759ebf1Behdad Esfahbod this->set (v); 7109b54562d63f1a9e0e5b33d71c32bd1588759ebf1Behdad Esfahbod return true; 7119b54562d63f1a9e0e5b33d71c32bd1588759ebf1Behdad Esfahbod } 7129b54562d63f1a9e0e5b33d71c32bd1588759ebf1Behdad Esfahbod return false; 7139b54562d63f1a9e0e5b33d71c32bd1588759ebf1Behdad Esfahbod } 714c9f14687a30866181feb57ee2736a147ec9f25a1Behdad Esfahbod /* Set the offset to Null */ 715d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod inline bool neuter (hb_sanitize_context_t *c) { 716cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod if (c->may_edit (this, this->static_size)) { 717c9f14687a30866181feb57ee2736a147ec9f25a1Behdad Esfahbod this->set (0); /* 0 is Null offset */ 718c9f14687a30866181feb57ee2736a147ec9f25a1Behdad Esfahbod return true; 719c9f14687a30866181feb57ee2736a147ec9f25a1Behdad Esfahbod } 720c9f14687a30866181feb57ee2736a147ec9f25a1Behdad Esfahbod return false; 72142b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod } 72292b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod}; 72392b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Base, typename OffsetType, typename Type> 724bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbodinline const Type& operator + (const Base &base, const GenericOffsetTo<OffsetType, Type> &offset) { return offset (base); } 725bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbodtemplate <typename Base, typename OffsetType, typename Type> 726bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbodinline Type& operator + (Base &base, GenericOffsetTo<OffsetType, Type> &offset) { return offset (base); } 72792b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 7285f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbodtemplate <typename Type> 72992b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct OffsetTo : GenericOffsetTo<Offset, Type> {}; 73092b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 73192b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Type> 73292b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct LongOffsetTo : GenericOffsetTo<LongOffset, Type> {}; 733bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod 734bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod 73592b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod/* 73692b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod * Array Types 73792b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod */ 73892b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 73992b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename LenType, typename Type> 74092b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct GenericArrayOf 74160d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{ 7424f5f1c34dda1e0629bfa6d7b0ffa2e1ce003b7c7Behdad Esfahbod const Type *sub_array (unsigned int start_offset, unsigned int *pcount /* IN/OUT */) const 74348de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod { 74448de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod unsigned int count = len; 74564d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod if (unlikely (start_offset > count)) 74648de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod count = 0; 74748de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod else 74848de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod count -= start_offset; 74948de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod count = MIN (count, *pcount); 75048de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod *pcount = count; 751b961518b9611471ff7060e97686e5625974847ebBehdad Esfahbod return array + start_offset; 75248de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod } 75348de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod 75460d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod inline const Type& operator [] (unsigned int i) const 75560d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod { 75664d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod if (unlikely (i >= len)) return Null(Type); 757b961518b9611471ff7060e97686e5625974847ebBehdad Esfahbod return array[i]; 7585f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod } 7599f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod inline Type& operator [] (unsigned int i) 7609f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod { 7619f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod return array[i]; 7629f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod } 7637f97d2cd904ea999c099c73c52187c5d65aeec67Behdad Esfahbod inline unsigned int get_size (void) const 764e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod { return len.static_size + len * Type::static_size; } 765e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod 766c61be03d6df122f18eebda3b29e42c9e768d45b9Behdad Esfahbod inline bool serialize (hb_serialize_context_t *c, 7671f07e3382a1608b054cbf88b89fef74f6c485434Behdad Esfahbod unsigned int items_len) 7681f07e3382a1608b054cbf88b89fef74f6c485434Behdad Esfahbod { 769be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod TRACE_SERIALIZE (this); 7701f07e3382a1608b054cbf88b89fef74f6c485434Behdad Esfahbod if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); 7711f07e3382a1608b054cbf88b89fef74f6c485434Behdad Esfahbod len.set (items_len); /* TODO(serialize) Overflow? */ 7721f07e3382a1608b054cbf88b89fef74f6c485434Behdad Esfahbod if (unlikely (!c->extend (*this))) return TRACE_RETURN (false); 7731f07e3382a1608b054cbf88b89fef74f6c485434Behdad Esfahbod return TRACE_RETURN (true); 7741f07e3382a1608b054cbf88b89fef74f6c485434Behdad Esfahbod } 7751f07e3382a1608b054cbf88b89fef74f6c485434Behdad Esfahbod 7761f07e3382a1608b054cbf88b89fef74f6c485434Behdad Esfahbod inline bool serialize (hb_serialize_context_t *c, 777a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod Supplier<Type> &items, 778c61be03d6df122f18eebda3b29e42c9e768d45b9Behdad Esfahbod unsigned int items_len) 779c61be03d6df122f18eebda3b29e42c9e768d45b9Behdad Esfahbod { 780be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod TRACE_SERIALIZE (this); 781715e03bc21d6adaa8e1f647235843839dc47dad1Behdad Esfahbod if (unlikely (!serialize (c, items_len))) return TRACE_RETURN (false); 782715e03bc21d6adaa8e1f647235843839dc47dad1Behdad Esfahbod for (unsigned int i = 0; i < items_len; i++) 783fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod array[i] = items[i]; 784a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod items.advance (items_len); 785c61be03d6df122f18eebda3b29e42c9e768d45b9Behdad Esfahbod return TRACE_RETURN (true); 786c61be03d6df122f18eebda3b29e42c9e768d45b9Behdad Esfahbod } 787c61be03d6df122f18eebda3b29e42c9e768d45b9Behdad Esfahbod 788d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod inline bool sanitize (hb_sanitize_context_t *c) { 789be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod TRACE_SANITIZE (this); 7900ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false); 79111e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod 79240d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod /* Note: for structs that do not reference other structs, 79340d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod * we do not need to call their sanitize() as we already did 79411e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod * a bound check on the aggregate array size. We just include 79511e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod * a small unreachable expression to make sure the structs 79611e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod * pointed to do have a simple sanitize(), ie. they do not 79711e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod * reference other structs via offsets. 79840d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod */ 79911e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod (void) (false && array[0].sanitize (c)); 80011e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod 8010ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod return TRACE_RETURN (true); 80270de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod } 803d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod inline bool sanitize (hb_sanitize_context_t *c, void *base) { 804be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod TRACE_SANITIZE (this); 8050ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false); 806e6ab2c59ba2d37942ac5fcbfe61d38b7e359ac8cBehdad Esfahbod unsigned int count = len; 807e6ab2c59ba2d37942ac5fcbfe61d38b7e359ac8cBehdad Esfahbod for (unsigned int i = 0; i < count; i++) 808d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod if (unlikely (!array[i].sanitize (c, base))) 8090ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod return TRACE_RETURN (false); 8100ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod return TRACE_RETURN (true); 811e6ab2c59ba2d37942ac5fcbfe61d38b7e359ac8cBehdad Esfahbod } 8124a446ac35136eff23d55f47bdd7b40095ad707abBehdad Esfahbod template <typename T> 813d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod inline bool sanitize (hb_sanitize_context_t *c, void *base, T user_data) { 814be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod TRACE_SANITIZE (this); 8150ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false); 81642b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod unsigned int count = len; 81742b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod for (unsigned int i = 0; i < count; i++) 818d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod if (unlikely (!array[i].sanitize (c, base, user_data))) 8190ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod return TRACE_RETURN (false); 8200ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod return TRACE_RETURN (true); 82142b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod } 82270de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod 82330fa2821c277df99a14089749313dfe2b541e2d0Behdad Esfahbod private: 824d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod inline bool sanitize_shallow (hb_sanitize_context_t *c) { 825be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod TRACE_SANITIZE (this); 8260ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod return TRACE_RETURN (c->check_struct (this) && c->check_array (this, Type::static_size, len)); 82730fa2821c277df99a14089749313dfe2b541e2d0Behdad Esfahbod } 82830fa2821c277df99a14089749313dfe2b541e2d0Behdad Esfahbod 82930fa2821c277df99a14089749313dfe2b541e2d0Behdad Esfahbod public: 83092b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod LenType len; 831b961518b9611471ff7060e97686e5625974847ebBehdad Esfahbod Type array[VAR]; 832b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod public: 8330eb9fc6e37935707dba2bf4b3705de2161a08cb7Behdad Esfahbod DEFINE_SIZE_ARRAY (sizeof (LenType), array); 834e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod}; 835e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod 83692b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod/* An array with a USHORT number of elements. */ 83792b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Type> 83892b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct ArrayOf : GenericArrayOf<USHORT, Type> {}; 83992b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 84092b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod/* An array with a ULONG number of elements. */ 84192b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Type> 84292b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct LongArrayOf : GenericArrayOf<ULONG, Type> {}; 84392b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 84492b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod/* Array of Offset's */ 84592b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Type> 84692b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct OffsetArrayOf : ArrayOf<OffsetTo<Type> > {}; 84792b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 84892b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod/* Array of LongOffset's */ 84992b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Type> 85092b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct LongOffsetArrayOf : ArrayOf<LongOffsetTo<Type> > {}; 85192b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 85292b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod/* LongArray of LongOffset's */ 85392b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Type> 85492b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct LongOffsetLongArrayOf : LongArrayOf<LongOffsetTo<Type> > {}; 85592b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 85680e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod/* Array of offsets relative to the beginning of the array itself. */ 85780e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbodtemplate <typename Type> 85880e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbodstruct OffsetListOf : OffsetArrayOf<Type> 85980e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod{ 86080e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod inline const Type& operator [] (unsigned int i) const 86180e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod { 86264d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod if (unlikely (i >= this->len)) return Null(Type); 863b961518b9611471ff7060e97686e5625974847ebBehdad Esfahbod return this+this->array[i]; 86480e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod } 86580e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod 866d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod inline bool sanitize (hb_sanitize_context_t *c) { 867be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod TRACE_SANITIZE (this); 8680ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod return TRACE_RETURN (OffsetArrayOf<Type>::sanitize (c, this)); 86980e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod } 8704a446ac35136eff23d55f47bdd7b40095ad707abBehdad Esfahbod template <typename T> 871d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod inline bool sanitize (hb_sanitize_context_t *c, T user_data) { 872be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod TRACE_SANITIZE (this); 8730ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod return TRACE_RETURN (OffsetArrayOf<Type>::sanitize (c, this, user_data)); 87480e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod } 87580e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod}; 87680e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod 87780e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod 878e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod/* An array with a USHORT number of elements, 879e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod * starting at second element. */ 880e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbodtemplate <typename Type> 88160d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbodstruct HeadlessArrayOf 88260d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{ 88360d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod inline const Type& operator [] (unsigned int i) const 88460d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod { 88564d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod if (unlikely (i >= len || !i)) return Null(Type); 886b961518b9611471ff7060e97686e5625974847ebBehdad Esfahbod return array[i-1]; 887e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod } 8887f97d2cd904ea999c099c73c52187c5d65aeec67Behdad Esfahbod inline unsigned int get_size (void) const 889e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod { return len.static_size + (len ? len - 1 : 0) * Type::static_size; } 8905f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod 891a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod inline bool serialize (hb_serialize_context_t *c, 892a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod Supplier<Type> &items, 893a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod unsigned int items_len) 894a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod { 895be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod TRACE_SERIALIZE (this); 896a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); 897a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod len.set (items_len); /* TODO(serialize) Overflow? */ 898a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod if (unlikely (!items_len)) return TRACE_RETURN (true); 899fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod if (unlikely (!c->extend (*this))) return TRACE_RETURN (false); 900fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod for (unsigned int i = 0; i < items_len - 1; i++) 901fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod array[i] = items[i]; 902a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod items.advance (items_len - 1); 903a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod return TRACE_RETURN (true); 904a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod } 905a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod 906d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod inline bool sanitize_shallow (hb_sanitize_context_t *c) { 907d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod return c->check_struct (this) 908d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod && c->check_array (this, Type::static_size, len); 909e5546a4352c54311ac4a9ef138b187378155ebe1Behdad Esfahbod } 910e5546a4352c54311ac4a9ef138b187378155ebe1Behdad Esfahbod 911d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod inline bool sanitize (hb_sanitize_context_t *c) { 912be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod TRACE_SANITIZE (this); 9130ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false); 91411e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod 91540d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod /* Note: for structs that do not reference other structs, 91640d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod * we do not need to call their sanitize() as we already did 91711e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod * a bound check on the aggregate array size. We just include 91811e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod * a small unreachable expression to make sure the structs 91911e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod * pointed to do have a simple sanitize(), ie. they do not 92011e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod * reference other structs via offsets. 92140d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod */ 92211e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod (void) (false && array[0].sanitize (c)); 92311e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod 9240ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod return TRACE_RETURN (true); 92570de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod } 92670de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod 9275f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod USHORT len; 928b961518b9611471ff7060e97686e5625974847ebBehdad Esfahbod Type array[VAR]; 929ed07422c33bbb52ff4d79e65986171e3f07697d8Behdad Esfahbod public: 9300eb9fc6e37935707dba2bf4b3705de2161a08cb7Behdad Esfahbod DEFINE_SIZE_ARRAY (sizeof (USHORT), array); 9315f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod}; 9325f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod 9336b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod 934cc8a4abea68f2dba26feb5785f9e518e6853c744Behdad Esfahbod/* An array with sorted elements. Supports binary searching. */ 935cc8a4abea68f2dba26feb5785f9e518e6853c744Behdad Esfahbodtemplate <typename Type> 936cc8a4abea68f2dba26feb5785f9e518e6853c744Behdad Esfahbodstruct SortedArrayOf : ArrayOf<Type> { 937cc8a4abea68f2dba26feb5785f9e518e6853c744Behdad Esfahbod 938cc8a4abea68f2dba26feb5785f9e518e6853c744Behdad Esfahbod template <typename SearchType> 939cc8a4abea68f2dba26feb5785f9e518e6853c744Behdad Esfahbod inline int search (const SearchType &x) const { 94099159e52a3c9d5ae6c0fbdec64e7ed684fa70b61Behdad Esfahbod unsigned int count = this->len; 94199159e52a3c9d5ae6c0fbdec64e7ed684fa70b61Behdad Esfahbod /* Linear search is *much* faster for small counts. */ 94299159e52a3c9d5ae6c0fbdec64e7ed684fa70b61Behdad Esfahbod if (likely (count < 32)) { 94399159e52a3c9d5ae6c0fbdec64e7ed684fa70b61Behdad Esfahbod for (unsigned int i = 0; i < count; i++) 94499159e52a3c9d5ae6c0fbdec64e7ed684fa70b61Behdad Esfahbod if (this->array[i].cmp (x) == 0) 94599159e52a3c9d5ae6c0fbdec64e7ed684fa70b61Behdad Esfahbod return i; 94699159e52a3c9d5ae6c0fbdec64e7ed684fa70b61Behdad Esfahbod return -1; 94799159e52a3c9d5ae6c0fbdec64e7ed684fa70b61Behdad Esfahbod } else { 94899159e52a3c9d5ae6c0fbdec64e7ed684fa70b61Behdad Esfahbod struct Cmp { 94999159e52a3c9d5ae6c0fbdec64e7ed684fa70b61Behdad Esfahbod static int cmp (const SearchType *a, const Type *b) { return b->cmp (*a); } 95099159e52a3c9d5ae6c0fbdec64e7ed684fa70b61Behdad Esfahbod }; 95199159e52a3c9d5ae6c0fbdec64e7ed684fa70b61Behdad Esfahbod const Type *p = (const Type *) bsearch (&x, this->array, this->len, sizeof (this->array[0]), (hb_compare_func_t) Cmp::cmp); 95299159e52a3c9d5ae6c0fbdec64e7ed684fa70b61Behdad Esfahbod return p ? p - this->array : -1; 95399159e52a3c9d5ae6c0fbdec64e7ed684fa70b61Behdad Esfahbod } 954cc8a4abea68f2dba26feb5785f9e518e6853c744Behdad Esfahbod } 955cc8a4abea68f2dba26feb5785f9e518e6853c744Behdad Esfahbod}; 956cc8a4abea68f2dba26feb5785f9e518e6853c744Behdad Esfahbod 957cc8a4abea68f2dba26feb5785f9e518e6853c744Behdad Esfahbod 9587d52e6601f0e695690cd168a288466746cf25300Behdad Esfahbod} /* namespace OT */ 9597c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod 960acdba3f90b232fc12fcb200dca2584481b339118Behdad Esfahbod 9611e91434569a9e9535ef021ca52b60b2e2af75d19Behdad Esfahbod#endif /* HB_OPEN_TYPE_PRIVATE_HH */ 962