hb-open-type-private.hh revision 6faff8e4132197ba06f0e685b82efe35b546cf64
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 34a16ecbf0564a6e2576da22c12827f3c0719da549Behdad Esfahbod 357c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbodnamespace OT { 367c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod 37a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbod 3881822528efc63d867cb2343a8ff7af64fac1c70dBehdad Esfahbod 3981822528efc63d867cb2343a8ff7af64fac1c70dBehdad Esfahbod/* 40196598bbccff08415ff5192314cba044df258cadBehdad Esfahbod * Casts 41196598bbccff08415ff5192314cba044df258cadBehdad Esfahbod */ 42196598bbccff08415ff5192314cba044df258cadBehdad Esfahbod 43187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbod/* Cast to struct T, reference to reference */ 44a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbodtemplate<typename Type, typename TObject> 456faff8e4132197ba06f0e685b82efe35b546cf64Behdad Esfahbodstatic inline const Type& CastR(const TObject &X) 46a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbod{ return reinterpret_cast<const Type&> (X); } 47a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbodtemplate<typename Type, typename TObject> 486faff8e4132197ba06f0e685b82efe35b546cf64Behdad Esfahbodstatic inline Type& CastR(TObject &X) 49a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbod{ return reinterpret_cast<Type&> (X); } 50196598bbccff08415ff5192314cba044df258cadBehdad Esfahbod 51187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbod/* Cast to struct T, pointer to pointer */ 52187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbodtemplate<typename Type, typename TObject> 536faff8e4132197ba06f0e685b82efe35b546cf64Behdad Esfahbodstatic inline const Type* CastP(const TObject *X) 54187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbod{ return reinterpret_cast<const Type*> (X); } 55187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbodtemplate<typename Type, typename TObject> 566faff8e4132197ba06f0e685b82efe35b546cf64Behdad Esfahbodstatic inline Type* CastP(TObject *X) 57187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbod{ return reinterpret_cast<Type*> (X); } 58187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbod 5909766b1ec5ec55a61edbcd7a89ed3613cc92d4cbBehdad Esfahbod/* StructAtOffset<T>(P,Ofs) returns the struct T& that is placed at memory 6009766b1ec5ec55a61edbcd7a89ed3613cc92d4cbBehdad Esfahbod * location pointed to by P plus Ofs bytes. */ 6109766b1ec5ec55a61edbcd7a89ed3613cc92d4cbBehdad Esfahbodtemplate<typename Type> 626faff8e4132197ba06f0e685b82efe35b546cf64Behdad Esfahbodstatic inline const Type& StructAtOffset(const void *P, unsigned int offset) 63a82ef7a893b773a17f7548375de9f588dfc83abaBehdad Esfahbod{ return * reinterpret_cast<const Type*> ((const char *) P + offset); } 6409766b1ec5ec55a61edbcd7a89ed3613cc92d4cbBehdad Esfahbodtemplate<typename Type> 656faff8e4132197ba06f0e685b82efe35b546cf64Behdad Esfahbodstatic inline Type& StructAtOffset(void *P, unsigned int offset) 66a82ef7a893b773a17f7548375de9f588dfc83abaBehdad Esfahbod{ return * reinterpret_cast<Type*> ((char *) P + offset); } 6770de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod 682e2f43edf2f49f4047e28b1ce2ea95938536de9cBehdad Esfahbod/* StructAfter<T>(X) returns the struct T& that is placed after X. 6929c3f5e1b6212c775a7b911becd44ba093b7b0ebBehdad Esfahbod * Works with X of variable size also. X must implement get_size() */ 70e961c86c579fd98ee604342a9c70c4e7f8d4f220Behdad Esfahbodtemplate<typename Type, typename TObject> 716faff8e4132197ba06f0e685b82efe35b546cf64Behdad Esfahbodstatic inline const Type& StructAfter(const TObject &X) 7209766b1ec5ec55a61edbcd7a89ed3613cc92d4cbBehdad Esfahbod{ return StructAtOffset<Type>(&X, X.get_size()); } 73e961c86c579fd98ee604342a9c70c4e7f8d4f220Behdad Esfahbodtemplate<typename Type, typename TObject> 746faff8e4132197ba06f0e685b82efe35b546cf64Behdad Esfahbodstatic inline Type& StructAfter(TObject &X) 7509766b1ec5ec55a61edbcd7a89ed3613cc92d4cbBehdad Esfahbod{ return StructAtOffset<Type>(&X, X.get_size()); } 76a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbod 77e961c86c579fd98ee604342a9c70c4e7f8d4f220Behdad Esfahbod 78d3480ba37fbb5d4be75b094060f5b2f1ce98fb53Behdad Esfahbod 7970de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod/* 80e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod * Size checking 81e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod */ 82e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod 83f679635893eebc13402c5ee51a6f106eed0c76beBehdad Esfahbod/* Check _assertion in a method environment */ 84a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod#define _DEFINE_INSTANCE_ASSERTION1(_line, _assertion) \ 85a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod inline void _instance_assertion_on_line_##_line (void) const \ 86a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod { \ 87a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod ASSERT_STATIC (_assertion); \ 88a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod ASSERT_INSTANCE_POD (*this); /* Make sure it's POD. */ \ 89a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod } 90a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod# define _DEFINE_INSTANCE_ASSERTION0(_line, _assertion) _DEFINE_INSTANCE_ASSERTION1 (_line, _assertion) 91a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod# define DEFINE_INSTANCE_ASSERTION(_assertion) _DEFINE_INSTANCE_ASSERTION0 (__LINE__, _assertion) 92a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod 93f679635893eebc13402c5ee51a6f106eed0c76beBehdad Esfahbod/* Check that _code compiles in a method environment */ 94a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod#define _DEFINE_COMPILES_ASSERTION1(_line, _code) \ 95a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod inline void _compiles_assertion_on_line_##_line (void) const \ 96f679635893eebc13402c5ee51a6f106eed0c76beBehdad Esfahbod { _code; } 97a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod# define _DEFINE_COMPILES_ASSERTION0(_line, _code) _DEFINE_COMPILES_ASSERTION1 (_line, _code) 98a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod# define DEFINE_COMPILES_ASSERTION(_code) _DEFINE_COMPILES_ASSERTION0 (__LINE__, _code) 990abcc3b48cfd51a22695c9e988938b2f45cb19d8Behdad Esfahbod 1000abcc3b48cfd51a22695c9e988938b2f45cb19d8Behdad Esfahbod 101e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod#define DEFINE_SIZE_STATIC(size) \ 102a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size)); \ 103e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod static const unsigned int static_size = (size); \ 104e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod static const unsigned int min_size = (size) 105e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod 106b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod/* Size signifying variable-sized array */ 107b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod#define VAR 1 108b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod 109596e471aa5053d955fb5d5b5923088c8814469b1Behdad Esfahbod#define DEFINE_SIZE_UNION(size, _member) \ 110a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod DEFINE_INSTANCE_ASSERTION (this->u._member.static_size == (size)); \ 111596e471aa5053d955fb5d5b5923088c8814469b1Behdad Esfahbod static const unsigned int min_size = (size) 112596e471aa5053d955fb5d5b5923088c8814469b1Behdad Esfahbod 113bea34c7cbb583cf7660776e95cab3171590b8427Behdad Esfahbod#define DEFINE_SIZE_MIN(size) \ 114a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod DEFINE_INSTANCE_ASSERTION (sizeof (*this) >= (size)); \ 115b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod static const unsigned int min_size = (size) 116b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod 1170eb9fc6e37935707dba2bf4b3705de2161a08cb7Behdad Esfahbod#define DEFINE_SIZE_ARRAY(size, array) \ 118a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size) + sizeof (array[0])); \ 119a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod DEFINE_COMPILES_ASSERTION ((void) array[0].static_size) \ 120e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod static const unsigned int min_size = (size) 121e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod 1220eb9fc6e37935707dba2bf4b3705de2161a08cb7Behdad Esfahbod#define DEFINE_SIZE_ARRAY2(size, array1, array2) \ 123a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size) + sizeof (this->array1[0]) + sizeof (this->array2[0])); \ 124a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod DEFINE_COMPILES_ASSERTION ((void) array1[0].static_size; (void) array2[0].static_size) \ 125e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod static const unsigned int min_size = (size) 126e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod 127e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod 128e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod 129e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod/* 130f0abcd69408a3af65207cdf8847575ade4579bd4Behdad Esfahbod * Null objects 131600e5eb80f553ea8eb862e6784133574c74ca513Behdad Esfahbod */ 132600e5eb80f553ea8eb862e6784133574c74ca513Behdad Esfahbod 1338b8358033184198ff638ee1379093717596e162dBehdad Esfahbod/* Global nul-content Null pool. Enlarge as necessary. */ 1340bb0f5d41976ae27c5c7a51cbb82144b48315a4bBehdad Esfahbod/* TODO This really should be a extern HB_INTERNAL and defined somewhere... */ 135cf5585cfa6cac6fdf627a99941299e76af5ae0f7Behdad Esfahbodstatic const void *_NullPool[64 / sizeof (void *)]; 1368b8358033184198ff638ee1379093717596e162dBehdad Esfahbod 137d2c2ca8faf62fc380d4717d286556139a62d2356Behdad Esfahbod/* Generic nul-content Null objects. */ 1388b8358033184198ff638ee1379093717596e162dBehdad Esfahbodtemplate <typename Type> 1397f97d2cd904ea999c099c73c52187c5d65aeec67Behdad Esfahbodstatic inline const Type& Null (void) { 140fd0de881f4fc004da6f36d50a91d0e62f8eb4d8cBehdad Esfahbod ASSERT_STATIC (sizeof (Type) <= sizeof (_NullPool)); 141187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbod return *CastP<Type> (_NullPool); 1429d3677899f90abdc7fb3e3d854db654a8707a84bBehdad Esfahbod} 1438b8358033184198ff638ee1379093717596e162dBehdad Esfahbod 1448b8358033184198ff638ee1379093717596e162dBehdad Esfahbod/* Specializaiton for arbitrary-content arbitrary-sized Null objects. */ 14565f46b00333e20ab8a52a4b350747507541ec1dbBehdad Esfahbod#define DEFINE_NULL_DATA(Type, data) \ 146fd0de881f4fc004da6f36d50a91d0e62f8eb4d8cBehdad Esfahbodstatic const char _Null##Type[sizeof (Type) + 1] = data; /* +1 is for nul-termination in data */ \ 1478b8358033184198ff638ee1379093717596e162dBehdad Esfahbodtemplate <> \ 1486faff8e4132197ba06f0e685b82efe35b546cf64Behdad Esfahbod/*static*/ inline const Type& Null<Type> (void) { \ 149187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbod return *CastP<Type> (_Null##Type); \ 150565c80bd2960366ace2d10dd71beaaf2a80213c8Behdad Esfahbod} /* The following line really exists such that we end in a place needing semicolon */ \ 151bea34c7cbb583cf7660776e95cab3171590b8427Behdad EsfahbodASSERT_STATIC (Type::min_size + 1 <= sizeof (_Null##Type)) 1528b8358033184198ff638ee1379093717596e162dBehdad Esfahbod 1538b8358033184198ff638ee1379093717596e162dBehdad Esfahbod/* Accessor macro. */ 1549d3677899f90abdc7fb3e3d854db654a8707a84bBehdad Esfahbod#define Null(Type) Null<Type>() 1558b8358033184198ff638ee1379093717596e162dBehdad Esfahbod 1568b8358033184198ff638ee1379093717596e162dBehdad Esfahbod 157600e5eb80f553ea8eb862e6784133574c74ca513Behdad Esfahbod 158577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod/* 159577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod * Sanitize 160577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod */ 161577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod 16295e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod#ifndef HB_DEBUG_SANITIZE 16311e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod#define HB_DEBUG_SANITIZE (HB_DEBUG+0) 16495e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod#endif 16595e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod 16620e3dd5d292b65f70d2eae63b8d8713a1c889d47Behdad Esfahbod 167be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod#define TRACE_SANITIZE(this) \ 168902cc8aca0b3ff25eeee50b3a84d729e31731ef3Behdad Esfahbod hb_auto_trace_t<HB_DEBUG_SANITIZE, bool> trace \ 1692c53bd3c3ec4f81eff126c5bf84b7f2ddf2f0fefBehdad Esfahbod (&c->debug_depth, c->get_name (), this, HB_FUNC, \ 170902cc8aca0b3ff25eeee50b3a84d729e31731ef3Behdad Esfahbod ""); 171807c5b03a2251a3c29a520852639421783101b55Behdad Esfahbod 17207a52b62115f10caea5c2d174a4272eb9ddb2284Behdad Esfahbod/* This limits sanitizing time on really broken fonts. */ 17307a52b62115f10caea5c2d174a4272eb9ddb2284Behdad Esfahbod#ifndef HB_SANITIZE_MAX_EDITS 17407a52b62115f10caea5c2d174a4272eb9ddb2284Behdad Esfahbod#define HB_SANITIZE_MAX_EDITS 100 17507a52b62115f10caea5c2d174a4272eb9ddb2284Behdad Esfahbod#endif 176b28815c1f6e46d38471cacbc31248ca6fda8c4d1Behdad Esfahbod 1771376fb7bf9ef07970f0ba13dc64d6a8ab8252762Behdad Esfahbodstruct hb_sanitize_context_t 178577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod{ 1792c53bd3c3ec4f81eff126c5bf84b7f2ddf2f0fefBehdad Esfahbod inline const char *get_name (void) { return "SANITIZE"; } 1802c53bd3c3ec4f81eff126c5bf84b7f2ddf2f0fefBehdad Esfahbod static const unsigned int max_debug_depth = HB_DEBUG_SANITIZE; 1812c53bd3c3ec4f81eff126c5bf84b7f2ddf2f0fefBehdad Esfahbod typedef bool return_t; 1822c53bd3c3ec4f81eff126c5bf84b7f2ddf2f0fefBehdad Esfahbod template <typename T> 1839c5a9ee967120c8a968a1160c420e03620d46c24Behdad Esfahbod inline return_t dispatch (const T &obj) { return obj.sanitize (this); } 1842c53bd3c3ec4f81eff126c5bf84b7f2ddf2f0fefBehdad Esfahbod static return_t default_return_value (void) { return true; } 1850beb66e3a61ae8bb1fa66e54b1ff1abb2f8711e9Behdad Esfahbod bool stop_sublookup_iteration (const return_t r HB_UNUSED) const { return false; } 1862c53bd3c3ec4f81eff126c5bf84b7f2ddf2f0fefBehdad Esfahbod 18731f18abecb149f8888a72510f2660328dd6de16dBehdad Esfahbod inline void init (hb_blob_t *b) 18898daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod { 18931f18abecb149f8888a72510f2660328dd6de16dBehdad Esfahbod this->blob = hb_blob_reference (b); 1901c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod this->writable = false; 1911c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod } 1921c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod 193cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod inline void start_processing (void) 1941c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod { 1954101ca7dbbdf1438fa116fb8cad935501ac7cca8Behdad Esfahbod this->start = hb_blob_get_data (this->blob, NULL); 1964101ca7dbbdf1438fa116fb8cad935501ac7cca8Behdad Esfahbod this->end = this->start + hb_blob_get_length (this->blob); 19798daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod this->edit_count = 0; 19820e3dd5d292b65f70d2eae63b8d8713a1c889d47Behdad Esfahbod this->debug_depth = 0; 199577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod 2001e08830b4fac3a60ae52349cab6e101d389d30cdBehdad Esfahbod DEBUG_MSG_LEVEL (SANITIZE, this->blob, 0, +1, 201cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod "start [%p..%p] (%lu bytes)", 2021e08830b4fac3a60ae52349cab6e101d389d30cdBehdad Esfahbod this->start, this->end, 2031e08830b4fac3a60ae52349cab6e101d389d30cdBehdad Esfahbod (unsigned long) (this->end - this->start)); 20498daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod } 2051376fb7bf9ef07970f0ba13dc64d6a8ab8252762Behdad Esfahbod 206cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod inline void end_processing (void) 20798daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod { 2081e08830b4fac3a60ae52349cab6e101d389d30cdBehdad Esfahbod DEBUG_MSG_LEVEL (SANITIZE, this->blob, 0, -1, 209cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod "end [%p..%p] %u edit requests", 2101e08830b4fac3a60ae52349cab6e101d389d30cdBehdad Esfahbod this->start, this->end, this->edit_count); 211577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod 21298daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod hb_blob_destroy (this->blob); 21398daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod this->blob = NULL; 21498daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod this->start = this->end = NULL; 21598daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod } 2164f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod 2174ad2cc5dec6b0639da2b1846282bdd99d06d5ff1Behdad Esfahbod inline bool check_range (const void *base, unsigned int len) const 21898daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod { 219a82ef7a893b773a17f7548375de9f588dfc83abaBehdad Esfahbod const char *p = (const char *) base; 22098daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod 221902cc8aca0b3ff25eeee50b3a84d729e31731ef3Behdad Esfahbod hb_auto_trace_t<HB_DEBUG_SANITIZE, bool> trace 222902cc8aca0b3ff25eeee50b3a84d729e31731ef3Behdad Esfahbod (&this->debug_depth, "SANITIZE", this->blob, NULL, 223902cc8aca0b3ff25eeee50b3a84d729e31731ef3Behdad Esfahbod "check_range [%p..%p] (%d bytes) in [%p..%p]", 224902cc8aca0b3ff25eeee50b3a84d729e31731ef3Behdad Esfahbod p, p + len, len, 225902cc8aca0b3ff25eeee50b3a84d729e31731ef3Behdad Esfahbod this->start, this->end); 22698daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod 227cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod return TRACE_RETURN (likely (this->start <= p && p <= this->end && (unsigned int) (this->end - p) >= len)); 22898daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod } 229577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod 2301cd1e117d060d38e314618b627d7663cb01ed584Behdad Esfahbod inline bool check_array (const void *base, unsigned int record_size, unsigned int len) const 23198daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod { 232a82ef7a893b773a17f7548375de9f588dfc83abaBehdad Esfahbod const char *p = (const char *) base; 233080a0eb7d82d7195be72c16ece6e0a3ffed636b6Behdad Esfahbod bool overflows = _hb_unsigned_int_mul_overflows (len, record_size); 23441895506cb6a41b1a833866f8822261ea449ea0bBehdad Esfahbod 235902cc8aca0b3ff25eeee50b3a84d729e31731ef3Behdad Esfahbod hb_auto_trace_t<HB_DEBUG_SANITIZE, bool> trace 236902cc8aca0b3ff25eeee50b3a84d729e31731ef3Behdad Esfahbod (&this->debug_depth, "SANITIZE", this->blob, NULL, 237902cc8aca0b3ff25eeee50b3a84d729e31731ef3Behdad Esfahbod "check_array [%p..%p] (%d*%d=%ld bytes) in [%p..%p]", 238902cc8aca0b3ff25eeee50b3a84d729e31731ef3Behdad Esfahbod p, p + (record_size * len), record_size, len, (unsigned long) record_size * len, 239902cc8aca0b3ff25eeee50b3a84d729e31731ef3Behdad Esfahbod this->start, this->end); 240fa030175ca998b00cc42cbced6e98de323ec01ecBehdad Esfahbod 241cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod return TRACE_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 250cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod inline bool may_edit (const void *base HB_UNUSED, unsigned int len HB_UNUSED) 25198daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod { 25207a52b62115f10caea5c2d174a4272eb9ddb2284Behdad Esfahbod if (this->edit_count >= HB_SANITIZE_MAX_EDITS) 25307a52b62115f10caea5c2d174a4272eb9ddb2284Behdad Esfahbod return false; 25407a52b62115f10caea5c2d174a4272eb9ddb2284Behdad Esfahbod 255a82ef7a893b773a17f7548375de9f588dfc83abaBehdad Esfahbod const char *p = (const char *) base; 25698daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod this->edit_count++; 25798daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod 258902cc8aca0b3ff25eeee50b3a84d729e31731ef3Behdad Esfahbod hb_auto_trace_t<HB_DEBUG_SANITIZE, bool> trace 259902cc8aca0b3ff25eeee50b3a84d729e31731ef3Behdad Esfahbod (&this->debug_depth, "SANITIZE", this->blob, NULL, 260902cc8aca0b3ff25eeee50b3a84d729e31731ef3Behdad Esfahbod "may_edit(%u) [%p..%p] (%d bytes) in [%p..%p] -> %s", 261902cc8aca0b3ff25eeee50b3a84d729e31731ef3Behdad Esfahbod this->edit_count, 262902cc8aca0b3ff25eeee50b3a84d729e31731ef3Behdad Esfahbod p, p + len, len, 263e77b4425746ac9eb407ca4e742d962f1955971b4Behdad Esfahbod this->start, this->end, 264e77b4425746ac9eb407ca4e742d962f1955971b4Behdad Esfahbod this->writable ? "GRANTED" : "DENIED"); 26598daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod 266cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod return TRACE_RETURN (this->writable); 26798daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod } 26898daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod 269cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod mutable unsigned int debug_depth; 27098daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod const char *start, *end; 27198daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod bool writable; 27298daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod unsigned int edit_count; 27398daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod hb_blob_t *blob; 27498daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod}; 275815a73e4202ca17677f12e862b70ca8724cf2f57Behdad Esfahbod 276577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod 277577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod 2784e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod/* Template to sanitize an object. */ 2794e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbodtemplate <typename Type> 2804e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbodstruct Sanitizer 2814e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod{ 2824e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod static hb_blob_t *sanitize (hb_blob_t *blob) { 283d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod hb_sanitize_context_t c[1] = {{0}}; 2844e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod bool sane; 2854e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod 286d0b657379bbe63602953412d6bc944b2a0f430ebBehdad Esfahbod /* TODO is_sane() stuff */ 2874e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod 2881c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod c->init (blob); 2891c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod 2904e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod retry: 291cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod DEBUG_MSG_FUNC (SANITIZE, blob, "start"); 2924f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod 293cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod c->start_processing (); 2944e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod 295d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod if (unlikely (!c->start)) { 296cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod c->end_processing (); 29748146e5612f6d272d6962f6829c6d64a31edef89Behdad Esfahbod return blob; 29848146e5612f6d272d6962f6829c6d64a31edef89Behdad Esfahbod } 29948146e5612f6d272d6962f6829c6d64a31edef89Behdad Esfahbod 300d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod Type *t = CastP<Type> (const_cast<char *> (c->start)); 3014e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod 302d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod sane = t->sanitize (c); 3034e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod if (sane) { 304d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod if (c->edit_count) { 305cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod DEBUG_MSG_FUNC (SANITIZE, blob, "passed first round with %d edits; going for second round", c->edit_count); 306fa030175ca998b00cc42cbced6e98de323ec01ecBehdad Esfahbod 3078b5346130425c7c101f6ff2432874ba2fd372edcBehdad Esfahbod /* sanitize again to ensure no toe-stepping */ 308d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod c->edit_count = 0; 309d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod sane = t->sanitize (c); 310d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod if (c->edit_count) { 311cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod DEBUG_MSG_FUNC (SANITIZE, blob, "requested %d edits in second round; FAILLING", c->edit_count); 3124e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod sane = false; 3134e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod } 3144e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod } 3154e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod } else { 316d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod unsigned int edit_count = c->edit_count; 3171c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod if (edit_count && !c->writable) { 3181c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod c->start = hb_blob_get_data_writable (blob, NULL); 3191c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod c->end = c->start + hb_blob_get_length (blob); 3201c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod 3211c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod if (c->start) { 3221c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod c->writable = true; 3231c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod /* ok, we made it writable by relocating. try again */ 324cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod DEBUG_MSG_FUNC (SANITIZE, blob, "retry"); 3251c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod goto retry; 3261c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod } 3274e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod } 3284e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod } 3294e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod 330cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod c->end_processing (); 3314101ca7dbbdf1438fa116fb8cad935501ac7cca8Behdad Esfahbod 332cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod DEBUG_MSG_FUNC (SANITIZE, blob, sane ? "PASSED" : "FAILED"); 3334e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod if (sane) 3344e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod return blob; 3354e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod else { 3364e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod hb_blob_destroy (blob); 3374911062d5be0d937ee8f1a70cc93e05d162f45b3Behdad Esfahbod return hb_blob_get_empty (); 3384e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod } 3394e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod } 340b435ab7e29c388e3b100f729957319931625a3a8Behdad Esfahbod 341b435ab7e29c388e3b100f729957319931625a3a8Behdad Esfahbod static const Type* lock_instance (hb_blob_t *blob) { 3421c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod hb_blob_make_immutable (blob); 3431c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod const char *base = hb_blob_get_data (blob, NULL); 344b435ab7e29c388e3b100f729957319931625a3a8Behdad Esfahbod return unlikely (!base) ? &Null(Type) : CastP<Type> (base); 345b435ab7e29c388e3b100f729957319931625a3a8Behdad Esfahbod } 3464e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod}; 3474e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod 3482d15e72c75931398db5e027e660f1320bb979117Behdad Esfahbod 349f0abcd69408a3af65207cdf8847575ade4579bd4Behdad Esfahbod 350e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod/* 351e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod * Serialize 352e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod */ 353e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod 354e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod#ifndef HB_DEBUG_SERIALIZE 355e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod#define HB_DEBUG_SERIALIZE (HB_DEBUG+0) 356e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod#endif 357e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod 358e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod 359be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod#define TRACE_SERIALIZE(this) \ 360902cc8aca0b3ff25eeee50b3a84d729e31731ef3Behdad Esfahbod hb_auto_trace_t<HB_DEBUG_SERIALIZE, bool> trace \ 361902cc8aca0b3ff25eeee50b3a84d729e31731ef3Behdad Esfahbod (&c->debug_depth, "SERIALIZE", c, HB_FUNC, \ 362902cc8aca0b3ff25eeee50b3a84d729e31731ef3Behdad Esfahbod ""); 363e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod 364e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod 365e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbodstruct hb_serialize_context_t 366e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod{ 367fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod inline hb_serialize_context_t (void *start, unsigned int size) 368e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod { 369e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod this->start = (char *) start; 370e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod this->end = this->start + size; 371e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod 372e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod this->ran_out_of_room = false; 373e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod this->head = this->start; 374e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod this->debug_depth = 0; 375fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod } 376e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod 377fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod template <typename Type> 378fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod inline Type *start_serialize (void) 379fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod { 380e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod DEBUG_MSG_LEVEL (SERIALIZE, this->start, 0, +1, 381e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod "start [%p..%p] (%lu bytes)", 382e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod this->start, this->end, 383e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod (unsigned long) (this->end - this->start)); 384fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod 385fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod return start_embed<Type> (); 386e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod } 387e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod 388fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod inline void end_serialize (void) 389e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod { 390e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod DEBUG_MSG_LEVEL (SERIALIZE, this->start, 0, -1, 391fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod "end [%p..%p] serialized %d bytes; %s", 392e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod this->start, this->end, 393fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod (int) (this->head - this->start), 394e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod this->ran_out_of_room ? "RAN OUT OF ROOM" : "did not ran out of room"); 395e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod 396fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod } 397fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod 398fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod template <typename Type> 399fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod inline Type *copy (void) 400fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod { 401fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod assert (!this->ran_out_of_room); 402fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod unsigned int len = this->head - this->start; 403fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod void *p = malloc (len); 404fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod if (p) 405fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod memcpy (p, this->start, len); 406fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod return reinterpret_cast<Type *> (p); 407e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod } 408e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod 409e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod template <typename Type> 4104b312fb288faa383a2c5bd3be0428f0e58e02699Behdad Esfahbod inline Type *allocate_size (unsigned int size) 411e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod { 41205d5d3cd63ba2fadfdb62190dd24ef80ee3df40cBehdad Esfahbod if (unlikely (this->ran_out_of_room || this->end - this->head < ptrdiff_t (size))) { 413e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod this->ran_out_of_room = true; 414e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod return NULL; 415e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod } 4164b312fb288faa383a2c5bd3be0428f0e58e02699Behdad Esfahbod memset (this->head, 0, size); 4179f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod char *ret = this->head; 418e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod this->head += size; 419e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod return reinterpret_cast<Type *> (ret); 420e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod } 421e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod 422e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod template <typename Type> 4234b312fb288faa383a2c5bd3be0428f0e58e02699Behdad Esfahbod inline Type *allocate_min (void) 4249f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod { 4254b312fb288faa383a2c5bd3be0428f0e58e02699Behdad Esfahbod return this->allocate_size<Type> (Type::min_size); 4269f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod } 4279f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod 4289f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod template <typename Type> 429fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod inline Type *start_embed (void) 430fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod { 431fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod Type *ret = reinterpret_cast<Type *> (this->head); 432fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod return ret; 433fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod } 434fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod 435fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod template <typename Type> 4364b312fb288faa383a2c5bd3be0428f0e58e02699Behdad Esfahbod inline Type *embed (const Type &obj) 437e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod { 438bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod unsigned int size = obj.get_size (); 4394b312fb288faa383a2c5bd3be0428f0e58e02699Behdad Esfahbod Type *ret = this->allocate_size<Type> (size); 440bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod if (unlikely (!ret)) return NULL; 441bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod memcpy (ret, obj, size); 442bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod return ret; 4439f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod } 4449f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod 4459f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod template <typename Type> 4464b312fb288faa383a2c5bd3be0428f0e58e02699Behdad Esfahbod inline Type *extend_min (Type &obj) 4479f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod { 448bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod unsigned int size = obj.min_size; 449fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod assert (this->start <= (char *) &obj && (char *) &obj <= this->head && (char *) &obj + size >= this->head); 450fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod if (unlikely (!this->allocate_size<Type> (((char *) &obj) + size - this->head))) return NULL; 4519f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod return reinterpret_cast<Type *> (&obj); 4529f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod } 4539f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod 4549f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod template <typename Type> 4554b312fb288faa383a2c5bd3be0428f0e58e02699Behdad Esfahbod inline Type *extend (Type &obj) 4569f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod { 457bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod unsigned int size = obj.get_size (); 458bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod assert (this->start < (char *) &obj && (char *) &obj <= this->head && (char *) &obj + size >= this->head); 459811eefe225d20b20f1de20c6e62a0ebd6d89102aBehdad Esfahbod if (unlikely (!this->allocate_size<Type> (((char *) &obj) + size - this->head))) return NULL; 460bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod return reinterpret_cast<Type *> (&obj); 461e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod } 462e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod 463e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod inline void truncate (void *head) 464e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod { 465e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod assert (this->start < head && head <= this->head); 466e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod this->head = (char *) head; 467e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod } 468e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod 469e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod unsigned int debug_depth; 470e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod char *start, *end, *head; 471e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod bool ran_out_of_room; 472e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod}; 473e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod 474a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbodtemplate <typename Type> 475a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbodstruct Supplier 476a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod{ 477a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod inline Supplier (const Type *array, unsigned int len_) 478a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod { 479a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod head = array; 480a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod len = len_; 481a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod } 482a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod inline const Type operator [] (unsigned int i) const 483a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod { 484a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod if (unlikely (i >= len)) return Type (); 485a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod return head[i]; 486a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod } 487a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod 488fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod inline void advance (unsigned int count) 489fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod { 490a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod if (unlikely (count > len)) 491a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod count = len; 492a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod len -= count; 493a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod head += count; 494a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod } 495a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod 496a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod private: 497fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod inline Supplier (const Supplier<Type> &); /* Disallow copy */ 498fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod inline Supplier<Type>& operator= (const Supplier<Type> &); /* Disallow copy */ 499fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod 500a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod unsigned int len; 501a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod const Type *head; 502a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod}; 503a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod 504a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod 505e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod 506f0abcd69408a3af65207cdf8847575ade4579bd4Behdad Esfahbod 507b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod/* 508b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod * 509bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod * The OpenType Font File: Data Types 510b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod */ 511b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod 512b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod 513b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod/* "The following data types are used in the OpenType font file. 514b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod * All OpenType fonts use Motorola-style byte ordering (Big Endian):" */ 515b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod 5165f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod/* 5175f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod * Int types 5185f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod */ 5195f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod 5206b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod 521d7bf473ef222ab420456ff155ffaa09bacb3a394Behdad Esfahbodtemplate <typename Type, int Bytes> struct BEInt; 522e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod 523e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodtemplate <typename Type> 524d7bf473ef222ab420456ff155ffaa09bacb3a394Behdad Esfahbodstruct BEInt<Type, 2> 525e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod{ 526e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod public: 52781408cd51ce575891e79e6483be187130f864c28Behdad Esfahbod inline void set (Type i) { hb_be_uint16_put (v,i); } 5287f97d2cd904ea999c099c73c52187c5d65aeec67Behdad Esfahbod inline operator Type (void) const { return hb_be_uint16_get (v); } 529153142dac8dd9abaf164bb88af07c600c17fc3a1Behdad Esfahbod inline bool operator == (const BEInt<Type, 2>& o) const { return hb_be_uint16_eq (v, o.v); } 53001c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod inline bool operator != (const BEInt<Type, 2>& o) const { return !(*this == o); } 531e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod private: uint8_t v[2]; 532e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod}; 533e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodtemplate <typename Type> 534d7bf473ef222ab420456ff155ffaa09bacb3a394Behdad Esfahbodstruct BEInt<Type, 4> 535e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod{ 536e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod public: 53781408cd51ce575891e79e6483be187130f864c28Behdad Esfahbod inline void set (Type i) { hb_be_uint32_put (v,i); } 5387f97d2cd904ea999c099c73c52187c5d65aeec67Behdad Esfahbod inline operator Type (void) const { return hb_be_uint32_get (v); } 539153142dac8dd9abaf164bb88af07c600c17fc3a1Behdad Esfahbod inline bool operator == (const BEInt<Type, 4>& o) const { return hb_be_uint32_eq (v, o.v); } 54001c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod inline bool operator != (const BEInt<Type, 4>& o) const { return !(*this == o); } 541e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod private: uint8_t v[4]; 542e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod}; 543bd61bc13ea8ff350ada5449b2cfeb612e66ecafaBehdad Esfahbodtemplate <typename Type> 544bd61bc13ea8ff350ada5449b2cfeb612e66ecafaBehdad Esfahbodstruct BEInt<Type, 3> 545bd61bc13ea8ff350ada5449b2cfeb612e66ecafaBehdad Esfahbod{ 546bd61bc13ea8ff350ada5449b2cfeb612e66ecafaBehdad Esfahbod public: 547bd61bc13ea8ff350ada5449b2cfeb612e66ecafaBehdad Esfahbod inline void set (Type i) { hb_be_uint24_put (v,i); } 548bd61bc13ea8ff350ada5449b2cfeb612e66ecafaBehdad Esfahbod inline operator Type (void) const { return hb_be_uint24_get (v); } 549bd61bc13ea8ff350ada5449b2cfeb612e66ecafaBehdad Esfahbod inline bool operator == (const BEInt<Type, 3>& o) const { return hb_be_uint24_eq (v, o.v); } 550bd61bc13ea8ff350ada5449b2cfeb612e66ecafaBehdad Esfahbod inline bool operator != (const BEInt<Type, 3>& o) const { return !(*this == o); } 551bd61bc13ea8ff350ada5449b2cfeb612e66ecafaBehdad Esfahbod private: uint8_t v[3]; 552bd61bc13ea8ff350ada5449b2cfeb612e66ecafaBehdad Esfahbod}; 553e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod 5542467c669c2aee4de2a6621a9d06cba0262376d41Behdad Esfahbod/* Integer types in big-endian order and no alignment requirement */ 555bd61bc13ea8ff350ada5449b2cfeb612e66ecafaBehdad Esfahbodtemplate <typename Type, unsigned int Size> 556e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodstruct IntType 557e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod{ 55881408cd51ce575891e79e6483be187130f864c28Behdad Esfahbod inline void set (Type i) { v.set (i); } 55901c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod inline operator Type(void) const { return v; } 560bd61bc13ea8ff350ada5449b2cfeb612e66ecafaBehdad Esfahbod inline bool operator == (const IntType<Type,Size> &o) const { return v == o.v; } 561bd61bc13ea8ff350ada5449b2cfeb612e66ecafaBehdad Esfahbod inline bool operator != (const IntType<Type,Size> &o) const { return v != o.v; } 562bd61bc13ea8ff350ada5449b2cfeb612e66ecafaBehdad Esfahbod static inline int cmp (const IntType<Type,Size> *a, const IntType<Type,Size> *b) { return b->cmp (*a); } 563bd61bc13ea8ff350ada5449b2cfeb612e66ecafaBehdad Esfahbod inline int cmp (IntType<Type,Size> va) const { Type a = va; Type b = v; return a < b ? -1 : a == b ? 0 : +1; } 5644e573715ae5f5ed486ad66382bb44c47a86591ffBehdad Esfahbod inline int cmp (Type a) const { Type b = v; return a < b ? -1 : a == b ? 0 : +1; } 565d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod inline bool sanitize (hb_sanitize_context_t *c) { 566be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod TRACE_SANITIZE (this); 5670ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod return TRACE_RETURN (likely (c->check_struct (this))); 568e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod } 569a82ef7a893b773a17f7548375de9f588dfc83abaBehdad Esfahbod protected: 570bd61bc13ea8ff350ada5449b2cfeb612e66ecafaBehdad Esfahbod BEInt<Type, Size> v; 571569da92bc6956f42d9b2d65c784e184fb6380efeBehdad Esfahbod public: 572bd61bc13ea8ff350ada5449b2cfeb612e66ecafaBehdad Esfahbod DEFINE_SIZE_STATIC (Size); 573e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod}; 574e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod 575bd61bc13ea8ff350ada5449b2cfeb612e66ecafaBehdad Esfahbodtypedef IntType<uint16_t, 2> USHORT; /* 16-bit unsigned integer. */ 576bd61bc13ea8ff350ada5449b2cfeb612e66ecafaBehdad Esfahbodtypedef IntType<int16_t, 2> SHORT; /* 16-bit signed integer. */ 577bd61bc13ea8ff350ada5449b2cfeb612e66ecafaBehdad Esfahbodtypedef IntType<uint32_t, 4> ULONG; /* 32-bit unsigned integer. */ 578bd61bc13ea8ff350ada5449b2cfeb612e66ecafaBehdad Esfahbodtypedef IntType<int32_t, 4> LONG; /* 32-bit signed integer. */ 579bd61bc13ea8ff350ada5449b2cfeb612e66ecafaBehdad Esfahbodtypedef IntType<uint32_t, 3> UINT24; /* 24-bit unsigned integer. */ 580e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod 581ae9877dea6a1aed3566d9b87a75ede84259deacaBehdad Esfahbod/* 16-bit signed integer (SHORT) that describes a quantity in FUnits. */ 582ae9877dea6a1aed3566d9b87a75ede84259deacaBehdad Esfahbodtypedef SHORT FWORD; 583ae9877dea6a1aed3566d9b87a75ede84259deacaBehdad Esfahbod 584ae9877dea6a1aed3566d9b87a75ede84259deacaBehdad Esfahbod/* 16-bit unsigned integer (USHORT) that describes a quantity in FUnits. */ 585ae9877dea6a1aed3566d9b87a75ede84259deacaBehdad Esfahbodtypedef USHORT UFWORD; 586ae9877dea6a1aed3566d9b87a75ede84259deacaBehdad Esfahbod 587e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod/* Date represented in number of seconds since 12:00 midnight, January 1, 588e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod * 1904. The value is represented as a signed 64-bit integer. */ 589e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbodstruct LONGDATETIME 590e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod{ 591e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod inline bool sanitize (hb_sanitize_context_t *c) { 592be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod TRACE_SANITIZE (this); 5930ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod return TRACE_RETURN (likely (c->check_struct (this))); 594e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod } 5956775da3a7c07db6c032cf429dc199d471948db56Behdad Esfahbod protected: 596e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod LONG major; 597e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod ULONG minor; 598e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod public: 599e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod DEFINE_SIZE_STATIC (8); 600e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod}; 601e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod 6026b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod/* Array of four uint8s (length = 32 bits) used to identify a script, language 6036b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod * system, feature, or baseline */ 60420cc86b3592db33731de671f008d7d222776be49Behdad Esfahbodstruct Tag : ULONG 60560d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{ 606befc022affd2386b3f46cd7d11e4262f6c8bce9fBehdad Esfahbod /* What the char* converters return is NOT nul-terminated. Print using "%.4s" */ 607a82ef7a893b773a17f7548375de9f588dfc83abaBehdad Esfahbod inline operator const char* (void) const { return reinterpret_cast<const char *> (&this->v); } 608a82ef7a893b773a17f7548375de9f588dfc83abaBehdad Esfahbod inline operator char* (void) { return reinterpret_cast<char *> (&this->v); } 609b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod public: 610b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod DEFINE_SIZE_STATIC (4); 6116b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod}; 61265f46b00333e20ab8a52a4b350747507541ec1dbBehdad EsfahbodDEFINE_NULL_DATA (Tag, " "); 6136b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod 6146b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod/* Glyph index number, same as uint16 (length = 16 bits) */ 6156ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbodtypedef USHORT GlyphID; 6166b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod 617b5db4f1e4eefa266a71a28b5496f47ff9d1a81e8Behdad Esfahbod/* Script/language-system/feature index */ 618b5db4f1e4eefa266a71a28b5496f47ff9d1a81e8Behdad Esfahbodstruct Index : USHORT { 619b5db4f1e4eefa266a71a28b5496f47ff9d1a81e8Behdad Esfahbod static const unsigned int NOT_FOUND_INDEX = 0xFFFF; 620b5db4f1e4eefa266a71a28b5496f47ff9d1a81e8Behdad Esfahbod}; 621b5db4f1e4eefa266a71a28b5496f47ff9d1a81e8Behdad EsfahbodDEFINE_NULL_DATA (Index, "\xff\xff"); 622b5db4f1e4eefa266a71a28b5496f47ff9d1a81e8Behdad Esfahbod 6231f437e6f47fb6c15761021bd2078f31778f2179cBehdad Esfahbod/* Offset to a table, same as uint16 (length = 16 bits), Null offset = 0x0000 */ 624e95e031b5682809488cc965883e15404cb9cfb6aBehdad Esfahbodstruct Offset : USHORT 625e95e031b5682809488cc965883e15404cb9cfb6aBehdad Esfahbod{ 626e95e031b5682809488cc965883e15404cb9cfb6aBehdad Esfahbod inline bool is_null (void) const { return 0 == *this; } 627e95e031b5682809488cc965883e15404cb9cfb6aBehdad Esfahbod public: 628e95e031b5682809488cc965883e15404cb9cfb6aBehdad Esfahbod DEFINE_SIZE_STATIC (2); 629e95e031b5682809488cc965883e15404cb9cfb6aBehdad Esfahbod}; 6306ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbod 6316ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbod/* LongOffset to a table, same as uint32 (length = 32 bits), Null offset = 0x00000000 */ 632e95e031b5682809488cc965883e15404cb9cfb6aBehdad Esfahbodstruct LongOffset : ULONG 633e95e031b5682809488cc965883e15404cb9cfb6aBehdad Esfahbod{ 634e95e031b5682809488cc965883e15404cb9cfb6aBehdad Esfahbod inline bool is_null (void) const { return 0 == *this; } 635e95e031b5682809488cc965883e15404cb9cfb6aBehdad Esfahbod public: 636e95e031b5682809488cc965883e15404cb9cfb6aBehdad Esfahbod DEFINE_SIZE_STATIC (4); 637e95e031b5682809488cc965883e15404cb9cfb6aBehdad Esfahbod}; 6386ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbod 6396b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod 6406b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod/* CheckSum */ 64160d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbodstruct CheckSum : ULONG 64260d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{ 64305bad3b8c25a89bc0f20f99f9215e492f48f03feBehdad Esfahbod /* This is reference implementation from the spec. */ 64405bad3b8c25a89bc0f20f99f9215e492f48f03feBehdad Esfahbod static inline uint32_t CalcTableChecksum (const ULONG *Table, uint32_t Length) 64560d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod { 6466b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod uint32_t Sum = 0L; 64705bad3b8c25a89bc0f20f99f9215e492f48f03feBehdad Esfahbod const ULONG *EndPtr = Table+((Length+3) & ~3) / ULONG::static_size; 6486b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod 6496b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod while (Table < EndPtr) 6506b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod Sum += *Table++; 6516b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod return Sum; 6526b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod } 65305bad3b8c25a89bc0f20f99f9215e492f48f03feBehdad Esfahbod 65405bad3b8c25a89bc0f20f99f9215e492f48f03feBehdad Esfahbod /* Note: data should be 4byte aligned and have 4byte padding at the end. */ 65505bad3b8c25a89bc0f20f99f9215e492f48f03feBehdad Esfahbod inline void set_for_data (const void *data, unsigned int length) 65605bad3b8c25a89bc0f20f99f9215e492f48f03feBehdad Esfahbod { set (CalcTableChecksum ((const ULONG *) data, length)); } 65705bad3b8c25a89bc0f20f99f9215e492f48f03feBehdad Esfahbod 658b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod public: 659b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod DEFINE_SIZE_STATIC (4); 6606b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod}; 6616b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod 6626b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod 6636b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod/* 6646b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod * Version Numbers 6656b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod */ 6666b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod 66787fcdcbe3644da10154688765db2d62eb9ac079aBehdad Esfahbodstruct FixedVersion 66860d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{ 6694f28fbdd804fabeec57a98fe267d892ab58b3a6dBehdad Esfahbod inline uint32_t to_int (void) const { return (major << 16) + minor; } 67096908b898476ca5d7da5f386b15be76f9e83d76eBehdad Esfahbod 671d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod inline bool sanitize (hb_sanitize_context_t *c) { 672be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod TRACE_SANITIZE (this); 6730ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod return TRACE_RETURN (c->check_struct (this)); 674cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod } 675cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod 6766ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbod USHORT major; 67787fcdcbe3644da10154688765db2d62eb9ac079aBehdad Esfahbod USHORT minor; 678b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod public: 679b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod DEFINE_SIZE_STATIC (4); 6806b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod}; 6816b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod 68292b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 68392b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 6845f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod/* 68592b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod * Template subclasses of Offset and LongOffset that do the dereferencing. 686f0abcd69408a3af65207cdf8847575ade4579bd4Behdad Esfahbod * Use: (base+offset) 6875f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod */ 6885f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod 68992b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename OffsetType, typename Type> 69092b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct GenericOffsetTo : OffsetType 69192b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod{ 69200e23fcc6fd0eee5c582251bf3de6a2703fbbd3eBehdad Esfahbod inline const Type& operator () (const void *base) const 69392b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod { 69492b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod unsigned int offset = *this; 69564d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod if (unlikely (!offset)) return Null(Type); 69609766b1ec5ec55a61edbcd7a89ed3613cc92d4cbBehdad Esfahbod return StructAtOffset<Type> (base, offset); 69792b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod } 698bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod 699abcc5ac1fde1c493e4055dd2f27b8aade7713156Behdad Esfahbod inline Type& serialize (hb_serialize_context_t *c, void *base) 700bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod { 701fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod Type *t = c->start_embed<Type> (); 7024912030dfba740c822e200d33cbb5c6dbbeaf79eBehdad Esfahbod this->set ((char *) t - (char *) base); /* TODO(serialize) Overflow? */ 703abcc5ac1fde1c493e4055dd2f27b8aade7713156Behdad Esfahbod return *t; 704bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod } 70592b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 706d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod inline bool sanitize (hb_sanitize_context_t *c, void *base) { 707be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod TRACE_SANITIZE (this); 7080ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod if (unlikely (!c->check_struct (this))) return TRACE_RETURN (false); 70992b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod unsigned int offset = *this; 7100ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod if (unlikely (!offset)) return TRACE_RETURN (true); 71109766b1ec5ec55a61edbcd7a89ed3613cc92d4cbBehdad Esfahbod Type &obj = StructAtOffset<Type> (base, offset); 7120ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod return TRACE_RETURN (likely (obj.sanitize (c)) || neuter (c)); 71392b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod } 7144a446ac35136eff23d55f47bdd7b40095ad707abBehdad Esfahbod template <typename T> 715d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod inline bool sanitize (hb_sanitize_context_t *c, void *base, T user_data) { 716be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod TRACE_SANITIZE (this); 7170ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod if (unlikely (!c->check_struct (this))) return TRACE_RETURN (false); 71842b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod unsigned int offset = *this; 7190ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod if (unlikely (!offset)) return TRACE_RETURN (true); 72009766b1ec5ec55a61edbcd7a89ed3613cc92d4cbBehdad Esfahbod Type &obj = StructAtOffset<Type> (base, offset); 7210ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod return TRACE_RETURN (likely (obj.sanitize (c, user_data)) || neuter (c)); 722c9f14687a30866181feb57ee2736a147ec9f25a1Behdad Esfahbod } 723c9f14687a30866181feb57ee2736a147ec9f25a1Behdad Esfahbod 7249b54562d63f1a9e0e5b33d71c32bd1588759ebf1Behdad Esfahbod inline bool try_set (hb_sanitize_context_t *c, const OffsetType &v) { 7259b54562d63f1a9e0e5b33d71c32bd1588759ebf1Behdad Esfahbod if (c->may_edit (this, this->static_size)) { 7269b54562d63f1a9e0e5b33d71c32bd1588759ebf1Behdad Esfahbod this->set (v); 7279b54562d63f1a9e0e5b33d71c32bd1588759ebf1Behdad Esfahbod return true; 7289b54562d63f1a9e0e5b33d71c32bd1588759ebf1Behdad Esfahbod } 7299b54562d63f1a9e0e5b33d71c32bd1588759ebf1Behdad Esfahbod return false; 7309b54562d63f1a9e0e5b33d71c32bd1588759ebf1Behdad Esfahbod } 731c9f14687a30866181feb57ee2736a147ec9f25a1Behdad Esfahbod /* Set the offset to Null */ 732d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod inline bool neuter (hb_sanitize_context_t *c) { 733cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod if (c->may_edit (this, this->static_size)) { 734c9f14687a30866181feb57ee2736a147ec9f25a1Behdad Esfahbod this->set (0); /* 0 is Null offset */ 735c9f14687a30866181feb57ee2736a147ec9f25a1Behdad Esfahbod return true; 736c9f14687a30866181feb57ee2736a147ec9f25a1Behdad Esfahbod } 737c9f14687a30866181feb57ee2736a147ec9f25a1Behdad Esfahbod return false; 73842b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod } 73992b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod}; 74092b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Base, typename OffsetType, typename Type> 7416faff8e4132197ba06f0e685b82efe35b546cf64Behdad Esfahbodstatic inline const Type& operator + (const Base &base, const GenericOffsetTo<OffsetType, Type> &offset) { return offset (base); } 742bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbodtemplate <typename Base, typename OffsetType, typename Type> 7436faff8e4132197ba06f0e685b82efe35b546cf64Behdad Esfahbodstatic inline Type& operator + (Base &base, GenericOffsetTo<OffsetType, Type> &offset) { return offset (base); } 74492b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 7455f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbodtemplate <typename Type> 74692b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct OffsetTo : GenericOffsetTo<Offset, Type> {}; 74792b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 74892b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Type> 74992b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct LongOffsetTo : GenericOffsetTo<LongOffset, Type> {}; 750bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod 751bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod 75292b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod/* 75392b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod * Array Types 75492b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod */ 75592b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 75692b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename LenType, typename Type> 75792b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct GenericArrayOf 75860d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{ 7594f5f1c34dda1e0629bfa6d7b0ffa2e1ce003b7c7Behdad Esfahbod const Type *sub_array (unsigned int start_offset, unsigned int *pcount /* IN/OUT */) const 76048de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod { 76148de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod unsigned int count = len; 76264d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod if (unlikely (start_offset > count)) 76348de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod count = 0; 76448de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod else 76548de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod count -= start_offset; 76648de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod count = MIN (count, *pcount); 76748de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod *pcount = count; 768b961518b9611471ff7060e97686e5625974847ebBehdad Esfahbod return array + start_offset; 76948de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod } 77048de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod 77160d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod inline const Type& operator [] (unsigned int i) const 77260d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod { 77364d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod if (unlikely (i >= len)) return Null(Type); 774b961518b9611471ff7060e97686e5625974847ebBehdad Esfahbod return array[i]; 7755f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod } 7769f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod inline Type& operator [] (unsigned int i) 7779f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod { 7789f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod return array[i]; 7799f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod } 7807f97d2cd904ea999c099c73c52187c5d65aeec67Behdad Esfahbod inline unsigned int get_size (void) const 781e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod { return len.static_size + len * Type::static_size; } 782e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod 783c61be03d6df122f18eebda3b29e42c9e768d45b9Behdad Esfahbod inline bool serialize (hb_serialize_context_t *c, 7841f07e3382a1608b054cbf88b89fef74f6c485434Behdad Esfahbod unsigned int items_len) 7851f07e3382a1608b054cbf88b89fef74f6c485434Behdad Esfahbod { 786be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod TRACE_SERIALIZE (this); 7871f07e3382a1608b054cbf88b89fef74f6c485434Behdad Esfahbod if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); 7881f07e3382a1608b054cbf88b89fef74f6c485434Behdad Esfahbod len.set (items_len); /* TODO(serialize) Overflow? */ 7891f07e3382a1608b054cbf88b89fef74f6c485434Behdad Esfahbod if (unlikely (!c->extend (*this))) return TRACE_RETURN (false); 7901f07e3382a1608b054cbf88b89fef74f6c485434Behdad Esfahbod return TRACE_RETURN (true); 7911f07e3382a1608b054cbf88b89fef74f6c485434Behdad Esfahbod } 7921f07e3382a1608b054cbf88b89fef74f6c485434Behdad Esfahbod 7931f07e3382a1608b054cbf88b89fef74f6c485434Behdad Esfahbod inline bool serialize (hb_serialize_context_t *c, 794a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod Supplier<Type> &items, 795c61be03d6df122f18eebda3b29e42c9e768d45b9Behdad Esfahbod unsigned int items_len) 796c61be03d6df122f18eebda3b29e42c9e768d45b9Behdad Esfahbod { 797be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod TRACE_SERIALIZE (this); 798715e03bc21d6adaa8e1f647235843839dc47dad1Behdad Esfahbod if (unlikely (!serialize (c, items_len))) return TRACE_RETURN (false); 799715e03bc21d6adaa8e1f647235843839dc47dad1Behdad Esfahbod for (unsigned int i = 0; i < items_len; i++) 800fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod array[i] = items[i]; 801a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod items.advance (items_len); 802c61be03d6df122f18eebda3b29e42c9e768d45b9Behdad Esfahbod return TRACE_RETURN (true); 803c61be03d6df122f18eebda3b29e42c9e768d45b9Behdad Esfahbod } 804c61be03d6df122f18eebda3b29e42c9e768d45b9Behdad Esfahbod 805d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod inline bool sanitize (hb_sanitize_context_t *c) { 806be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod TRACE_SANITIZE (this); 8070ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false); 80811e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod 80940d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod /* Note: for structs that do not reference other structs, 81040d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod * we do not need to call their sanitize() as we already did 81111e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod * a bound check on the aggregate array size. We just include 81211e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod * a small unreachable expression to make sure the structs 81311e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod * pointed to do have a simple sanitize(), ie. they do not 81411e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod * reference other structs via offsets. 81540d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod */ 81611e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod (void) (false && array[0].sanitize (c)); 81711e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod 8180ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod return TRACE_RETURN (true); 81970de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod } 820d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod inline bool sanitize (hb_sanitize_context_t *c, void *base) { 821be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod TRACE_SANITIZE (this); 8220ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false); 823e6ab2c59ba2d37942ac5fcbfe61d38b7e359ac8cBehdad Esfahbod unsigned int count = len; 824e6ab2c59ba2d37942ac5fcbfe61d38b7e359ac8cBehdad Esfahbod for (unsigned int i = 0; i < count; i++) 825d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod if (unlikely (!array[i].sanitize (c, base))) 8260ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod return TRACE_RETURN (false); 8270ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod return TRACE_RETURN (true); 828e6ab2c59ba2d37942ac5fcbfe61d38b7e359ac8cBehdad Esfahbod } 8294a446ac35136eff23d55f47bdd7b40095ad707abBehdad Esfahbod template <typename T> 830d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod inline bool sanitize (hb_sanitize_context_t *c, void *base, T user_data) { 831be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod TRACE_SANITIZE (this); 8320ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false); 83342b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod unsigned int count = len; 83442b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod for (unsigned int i = 0; i < count; i++) 835d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod if (unlikely (!array[i].sanitize (c, base, user_data))) 8360ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod return TRACE_RETURN (false); 8370ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod return TRACE_RETURN (true); 83842b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod } 83970de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod 84030fa2821c277df99a14089749313dfe2b541e2d0Behdad Esfahbod private: 841d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod inline bool sanitize_shallow (hb_sanitize_context_t *c) { 842be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod TRACE_SANITIZE (this); 8430ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod return TRACE_RETURN (c->check_struct (this) && c->check_array (this, Type::static_size, len)); 84430fa2821c277df99a14089749313dfe2b541e2d0Behdad Esfahbod } 84530fa2821c277df99a14089749313dfe2b541e2d0Behdad Esfahbod 84630fa2821c277df99a14089749313dfe2b541e2d0Behdad Esfahbod public: 84792b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod LenType len; 848b961518b9611471ff7060e97686e5625974847ebBehdad Esfahbod Type array[VAR]; 849b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod public: 8500eb9fc6e37935707dba2bf4b3705de2161a08cb7Behdad Esfahbod DEFINE_SIZE_ARRAY (sizeof (LenType), array); 851e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod}; 852e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod 85392b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod/* An array with a USHORT number of elements. */ 85492b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Type> 85592b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct ArrayOf : GenericArrayOf<USHORT, Type> {}; 85692b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 85792b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod/* An array with a ULONG number of elements. */ 85892b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Type> 85992b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct LongArrayOf : GenericArrayOf<ULONG, Type> {}; 86092b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 86192b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod/* Array of Offset's */ 86292b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Type> 86392b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct OffsetArrayOf : ArrayOf<OffsetTo<Type> > {}; 86492b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 86592b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod/* Array of LongOffset's */ 86692b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Type> 86792b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct LongOffsetArrayOf : ArrayOf<LongOffsetTo<Type> > {}; 86892b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 86992b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod/* LongArray of LongOffset's */ 87092b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Type> 87192b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct LongOffsetLongArrayOf : LongArrayOf<LongOffsetTo<Type> > {}; 87292b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 87380e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod/* Array of offsets relative to the beginning of the array itself. */ 87480e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbodtemplate <typename Type> 87580e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbodstruct OffsetListOf : OffsetArrayOf<Type> 87680e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod{ 87780e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod inline const Type& operator [] (unsigned int i) const 87880e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod { 87964d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod if (unlikely (i >= this->len)) return Null(Type); 880b961518b9611471ff7060e97686e5625974847ebBehdad Esfahbod return this+this->array[i]; 88180e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod } 88280e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod 883d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod inline bool sanitize (hb_sanitize_context_t *c) { 884be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod TRACE_SANITIZE (this); 8850ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod return TRACE_RETURN (OffsetArrayOf<Type>::sanitize (c, this)); 88680e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod } 8874a446ac35136eff23d55f47bdd7b40095ad707abBehdad Esfahbod template <typename T> 888d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod inline bool sanitize (hb_sanitize_context_t *c, T user_data) { 889be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod TRACE_SANITIZE (this); 8900ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod return TRACE_RETURN (OffsetArrayOf<Type>::sanitize (c, this, user_data)); 89180e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod } 89280e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod}; 89380e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod 89480e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod 895e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod/* An array with a USHORT number of elements, 896e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod * starting at second element. */ 897e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbodtemplate <typename Type> 89860d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbodstruct HeadlessArrayOf 89960d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{ 90060d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod inline const Type& operator [] (unsigned int i) const 90160d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod { 90264d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod if (unlikely (i >= len || !i)) return Null(Type); 903b961518b9611471ff7060e97686e5625974847ebBehdad Esfahbod return array[i-1]; 904e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod } 9057f97d2cd904ea999c099c73c52187c5d65aeec67Behdad Esfahbod inline unsigned int get_size (void) const 906e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod { return len.static_size + (len ? len - 1 : 0) * Type::static_size; } 9075f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod 908a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod inline bool serialize (hb_serialize_context_t *c, 909a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod Supplier<Type> &items, 910a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod unsigned int items_len) 911a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod { 912be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod TRACE_SERIALIZE (this); 913a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); 914a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod len.set (items_len); /* TODO(serialize) Overflow? */ 915a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod if (unlikely (!items_len)) return TRACE_RETURN (true); 916fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod if (unlikely (!c->extend (*this))) return TRACE_RETURN (false); 917fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod for (unsigned int i = 0; i < items_len - 1; i++) 918fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod array[i] = items[i]; 919a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod items.advance (items_len - 1); 920a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod return TRACE_RETURN (true); 921a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod } 922a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod 923d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod inline bool sanitize_shallow (hb_sanitize_context_t *c) { 924d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod return c->check_struct (this) 925d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod && c->check_array (this, Type::static_size, len); 926e5546a4352c54311ac4a9ef138b187378155ebe1Behdad Esfahbod } 927e5546a4352c54311ac4a9ef138b187378155ebe1Behdad Esfahbod 928d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod inline bool sanitize (hb_sanitize_context_t *c) { 929be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod TRACE_SANITIZE (this); 9300ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false); 93111e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod 93240d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod /* Note: for structs that do not reference other structs, 93340d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod * we do not need to call their sanitize() as we already did 93411e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod * a bound check on the aggregate array size. We just include 93511e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod * a small unreachable expression to make sure the structs 93611e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod * pointed to do have a simple sanitize(), ie. they do not 93711e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod * reference other structs via offsets. 93840d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod */ 93911e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod (void) (false && array[0].sanitize (c)); 94011e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod 9410ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod return TRACE_RETURN (true); 94270de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod } 94370de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod 9445f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod USHORT len; 945b961518b9611471ff7060e97686e5625974847ebBehdad Esfahbod Type array[VAR]; 946ed07422c33bbb52ff4d79e65986171e3f07697d8Behdad Esfahbod public: 9470eb9fc6e37935707dba2bf4b3705de2161a08cb7Behdad Esfahbod DEFINE_SIZE_ARRAY (sizeof (USHORT), array); 9485f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod}; 9495f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod 9506b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod 951cc8a4abea68f2dba26feb5785f9e518e6853c744Behdad Esfahbod/* An array with sorted elements. Supports binary searching. */ 952cc8a4abea68f2dba26feb5785f9e518e6853c744Behdad Esfahbodtemplate <typename Type> 953cc8a4abea68f2dba26feb5785f9e518e6853c744Behdad Esfahbodstruct SortedArrayOf : ArrayOf<Type> { 954cc8a4abea68f2dba26feb5785f9e518e6853c744Behdad Esfahbod 955cc8a4abea68f2dba26feb5785f9e518e6853c744Behdad Esfahbod template <typename SearchType> 9568659c636087e433f56da458351e8b4d85fdb347cBehdad Esfahbod inline int search (const SearchType &x) const 9578659c636087e433f56da458351e8b4d85fdb347cBehdad Esfahbod { 9588659c636087e433f56da458351e8b4d85fdb347cBehdad Esfahbod /* Hand-coded bsearch here since this is in the hot inner loop. */ 9598659c636087e433f56da458351e8b4d85fdb347cBehdad Esfahbod int min = 0, max = (int) this->len - 1; 9608659c636087e433f56da458351e8b4d85fdb347cBehdad Esfahbod while (min <= max) 9618659c636087e433f56da458351e8b4d85fdb347cBehdad Esfahbod { 9628659c636087e433f56da458351e8b4d85fdb347cBehdad Esfahbod int mid = (min + max) / 2; 9638659c636087e433f56da458351e8b4d85fdb347cBehdad Esfahbod int c = this->array[mid].cmp (x); 9648659c636087e433f56da458351e8b4d85fdb347cBehdad Esfahbod if (c < 0) 9658659c636087e433f56da458351e8b4d85fdb347cBehdad Esfahbod max = mid - 1; 9668659c636087e433f56da458351e8b4d85fdb347cBehdad Esfahbod else if (c > 0) 9678659c636087e433f56da458351e8b4d85fdb347cBehdad Esfahbod min = mid + 1; 9688659c636087e433f56da458351e8b4d85fdb347cBehdad Esfahbod else 9698659c636087e433f56da458351e8b4d85fdb347cBehdad Esfahbod return mid; 97099159e52a3c9d5ae6c0fbdec64e7ed684fa70b61Behdad Esfahbod } 9718659c636087e433f56da458351e8b4d85fdb347cBehdad Esfahbod return -1; 972cc8a4abea68f2dba26feb5785f9e518e6853c744Behdad Esfahbod } 973cc8a4abea68f2dba26feb5785f9e518e6853c744Behdad Esfahbod}; 974cc8a4abea68f2dba26feb5785f9e518e6853c744Behdad Esfahbod 975cc8a4abea68f2dba26feb5785f9e518e6853c744Behdad Esfahbod 9767d52e6601f0e695690cd168a288466746cf25300Behdad Esfahbod} /* namespace OT */ 9777c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod 978acdba3f90b232fc12fcb200dca2584481b339118Behdad Esfahbod 9791e91434569a9e9535ef021ca52b60b2e2af75d19Behdad Esfahbod#endif /* HB_OPEN_TYPE_PRIVATE_HH */ 980