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... */ 135b7878cd58ea9a67236e1e0228c35b5b03ec4ff9cBehdad Esfahbodstatic const void *_NullPool[(256+8) / 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 26951f563579b94e1ee23ced9bbcc7dd3341535ce72Behdad Esfahbod template <typename Type, typename ValueType> 27051f563579b94e1ee23ced9bbcc7dd3341535ce72Behdad Esfahbod inline bool try_set (Type *obj, const ValueType &v) { 27151f563579b94e1ee23ced9bbcc7dd3341535ce72Behdad Esfahbod if (this->may_edit (obj, obj->static_size)) { 27251f563579b94e1ee23ced9bbcc7dd3341535ce72Behdad Esfahbod obj->set (v); 27351f563579b94e1ee23ced9bbcc7dd3341535ce72Behdad Esfahbod return true; 27451f563579b94e1ee23ced9bbcc7dd3341535ce72Behdad Esfahbod } 27551f563579b94e1ee23ced9bbcc7dd3341535ce72Behdad Esfahbod return false; 27651f563579b94e1ee23ced9bbcc7dd3341535ce72Behdad Esfahbod } 27751f563579b94e1ee23ced9bbcc7dd3341535ce72Behdad Esfahbod 278cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod mutable unsigned int debug_depth; 27998daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod const char *start, *end; 28098daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod bool writable; 28198daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod unsigned int edit_count; 28298daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod hb_blob_t *blob; 28398daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod}; 284815a73e4202ca17677f12e862b70ca8724cf2f57Behdad Esfahbod 285577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod 286577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod 2874e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod/* Template to sanitize an object. */ 2884e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbodtemplate <typename Type> 2894e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbodstruct Sanitizer 2904e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod{ 2914e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod static hb_blob_t *sanitize (hb_blob_t *blob) { 2927e8c38954649c0bf2e6051d84ca08dce090ec169Behdad Esfahbod hb_sanitize_context_t c[1] = {{0, NULL, NULL, false, 0, NULL}}; 2934e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod bool sane; 2944e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod 295d0b657379bbe63602953412d6bc944b2a0f430ebBehdad Esfahbod /* TODO is_sane() stuff */ 2964e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod 2971c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod c->init (blob); 2981c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod 2994e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod retry: 300cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod DEBUG_MSG_FUNC (SANITIZE, blob, "start"); 3014f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod 302cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod c->start_processing (); 3034e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod 304d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod if (unlikely (!c->start)) { 305cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod c->end_processing (); 30648146e5612f6d272d6962f6829c6d64a31edef89Behdad Esfahbod return blob; 30748146e5612f6d272d6962f6829c6d64a31edef89Behdad Esfahbod } 30848146e5612f6d272d6962f6829c6d64a31edef89Behdad Esfahbod 309d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod Type *t = CastP<Type> (const_cast<char *> (c->start)); 3104e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod 311d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod sane = t->sanitize (c); 3124e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod if (sane) { 313d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod if (c->edit_count) { 314cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod DEBUG_MSG_FUNC (SANITIZE, blob, "passed first round with %d edits; going for second round", c->edit_count); 315fa030175ca998b00cc42cbced6e98de323ec01ecBehdad Esfahbod 3168b5346130425c7c101f6ff2432874ba2fd372edcBehdad Esfahbod /* sanitize again to ensure no toe-stepping */ 317d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod c->edit_count = 0; 318d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod sane = t->sanitize (c); 319d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod if (c->edit_count) { 320cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod DEBUG_MSG_FUNC (SANITIZE, blob, "requested %d edits in second round; FAILLING", c->edit_count); 3214e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod sane = false; 3224e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod } 3234e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod } 3244e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod } else { 325d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod unsigned int edit_count = c->edit_count; 3261c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod if (edit_count && !c->writable) { 3271c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod c->start = hb_blob_get_data_writable (blob, NULL); 3281c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod c->end = c->start + hb_blob_get_length (blob); 3291c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod 3301c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod if (c->start) { 3311c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod c->writable = true; 3321c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod /* ok, we made it writable by relocating. try again */ 333cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod DEBUG_MSG_FUNC (SANITIZE, blob, "retry"); 3341c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod goto retry; 3351c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod } 3364e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod } 3374e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod } 3384e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod 339cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod c->end_processing (); 3404101ca7dbbdf1438fa116fb8cad935501ac7cca8Behdad Esfahbod 341cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod DEBUG_MSG_FUNC (SANITIZE, blob, sane ? "PASSED" : "FAILED"); 3424e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod if (sane) 3434e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod return blob; 3444e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod else { 3454e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod hb_blob_destroy (blob); 3464911062d5be0d937ee8f1a70cc93e05d162f45b3Behdad Esfahbod return hb_blob_get_empty (); 3474e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod } 3484e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod } 349b435ab7e29c388e3b100f729957319931625a3a8Behdad Esfahbod 350b435ab7e29c388e3b100f729957319931625a3a8Behdad Esfahbod static const Type* lock_instance (hb_blob_t *blob) { 3511c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod hb_blob_make_immutable (blob); 3521c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod const char *base = hb_blob_get_data (blob, NULL); 353b435ab7e29c388e3b100f729957319931625a3a8Behdad Esfahbod return unlikely (!base) ? &Null(Type) : CastP<Type> (base); 354b435ab7e29c388e3b100f729957319931625a3a8Behdad Esfahbod } 3554e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod}; 3564e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod 3572d15e72c75931398db5e027e660f1320bb979117Behdad Esfahbod 358f0abcd69408a3af65207cdf8847575ade4579bd4Behdad Esfahbod 359e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod/* 360e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod * Serialize 361e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod */ 362e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod 363e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod#ifndef HB_DEBUG_SERIALIZE 364e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod#define HB_DEBUG_SERIALIZE (HB_DEBUG+0) 365e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod#endif 366e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod 367e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod 368be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod#define TRACE_SERIALIZE(this) \ 369902cc8aca0b3ff25eeee50b3a84d729e31731ef3Behdad Esfahbod hb_auto_trace_t<HB_DEBUG_SERIALIZE, bool> trace \ 370902cc8aca0b3ff25eeee50b3a84d729e31731ef3Behdad Esfahbod (&c->debug_depth, "SERIALIZE", c, HB_FUNC, \ 371902cc8aca0b3ff25eeee50b3a84d729e31731ef3Behdad Esfahbod ""); 372e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod 373e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod 374e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbodstruct hb_serialize_context_t 375e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod{ 376fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod inline hb_serialize_context_t (void *start, unsigned int size) 377e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod { 378e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod this->start = (char *) start; 379e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod this->end = this->start + size; 380e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod 381e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod this->ran_out_of_room = false; 382e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod this->head = this->start; 383e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod this->debug_depth = 0; 384fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod } 385e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod 386fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod template <typename Type> 387fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod inline Type *start_serialize (void) 388fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod { 389e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod DEBUG_MSG_LEVEL (SERIALIZE, this->start, 0, +1, 390e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod "start [%p..%p] (%lu bytes)", 391e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod this->start, this->end, 392e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod (unsigned long) (this->end - this->start)); 393fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod 394fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod return start_embed<Type> (); 395e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod } 396e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod 397fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod inline void end_serialize (void) 398e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod { 399e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod DEBUG_MSG_LEVEL (SERIALIZE, this->start, 0, -1, 400fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod "end [%p..%p] serialized %d bytes; %s", 401e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod this->start, this->end, 402fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod (int) (this->head - this->start), 403e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod this->ran_out_of_room ? "RAN OUT OF ROOM" : "did not ran out of room"); 404e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod 405fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod } 406fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod 407fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod template <typename Type> 408fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod inline Type *copy (void) 409fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod { 410fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod assert (!this->ran_out_of_room); 411fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod unsigned int len = this->head - this->start; 412fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod void *p = malloc (len); 413fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod if (p) 414fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod memcpy (p, this->start, len); 415fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod return reinterpret_cast<Type *> (p); 416e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod } 417e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod 418e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod template <typename Type> 4194b312fb288faa383a2c5bd3be0428f0e58e02699Behdad Esfahbod inline Type *allocate_size (unsigned int size) 420e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod { 42105d5d3cd63ba2fadfdb62190dd24ef80ee3df40cBehdad Esfahbod if (unlikely (this->ran_out_of_room || this->end - this->head < ptrdiff_t (size))) { 422e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod this->ran_out_of_room = true; 423e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod return NULL; 424e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod } 4254b312fb288faa383a2c5bd3be0428f0e58e02699Behdad Esfahbod memset (this->head, 0, size); 4269f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod char *ret = this->head; 427e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod this->head += size; 428e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod return reinterpret_cast<Type *> (ret); 429e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod } 430e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod 431e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod template <typename Type> 4324b312fb288faa383a2c5bd3be0428f0e58e02699Behdad Esfahbod inline Type *allocate_min (void) 4339f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod { 4344b312fb288faa383a2c5bd3be0428f0e58e02699Behdad Esfahbod return this->allocate_size<Type> (Type::min_size); 4359f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod } 4369f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod 4379f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod template <typename Type> 438fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod inline Type *start_embed (void) 439fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod { 440fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod Type *ret = reinterpret_cast<Type *> (this->head); 441fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod return ret; 442fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod } 443fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod 444fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod template <typename Type> 4454b312fb288faa383a2c5bd3be0428f0e58e02699Behdad Esfahbod inline Type *embed (const Type &obj) 446e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod { 447bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod unsigned int size = obj.get_size (); 4484b312fb288faa383a2c5bd3be0428f0e58e02699Behdad Esfahbod Type *ret = this->allocate_size<Type> (size); 449bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod if (unlikely (!ret)) return NULL; 450bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod memcpy (ret, obj, size); 451bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod return ret; 4529f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod } 4539f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod 4549f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod template <typename Type> 4554b312fb288faa383a2c5bd3be0428f0e58e02699Behdad Esfahbod inline Type *extend_min (Type &obj) 4569f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod { 457bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod unsigned int size = obj.min_size; 458fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod assert (this->start <= (char *) &obj && (char *) &obj <= this->head && (char *) &obj + size >= this->head); 459fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod if (unlikely (!this->allocate_size<Type> (((char *) &obj) + size - this->head))) return NULL; 4609f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod return reinterpret_cast<Type *> (&obj); 4619f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod } 4629f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod 4639f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod template <typename Type> 4644b312fb288faa383a2c5bd3be0428f0e58e02699Behdad Esfahbod inline Type *extend (Type &obj) 4659f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod { 466bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod unsigned int size = obj.get_size (); 467bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod assert (this->start < (char *) &obj && (char *) &obj <= this->head && (char *) &obj + size >= this->head); 468811eefe225d20b20f1de20c6e62a0ebd6d89102aBehdad Esfahbod if (unlikely (!this->allocate_size<Type> (((char *) &obj) + size - this->head))) return NULL; 469bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod return reinterpret_cast<Type *> (&obj); 470e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod } 471e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod 472e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod inline void truncate (void *head) 473e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod { 474e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod assert (this->start < head && head <= this->head); 475e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod this->head = (char *) head; 476e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod } 477e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod 478e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod unsigned int debug_depth; 479e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod char *start, *end, *head; 480e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod bool ran_out_of_room; 481e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod}; 482e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod 483a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbodtemplate <typename Type> 484a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbodstruct Supplier 485a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod{ 486a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod inline Supplier (const Type *array, unsigned int len_) 487a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod { 488a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod head = array; 489a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod len = len_; 490a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod } 491a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod inline const Type operator [] (unsigned int i) const 492a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod { 493a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod if (unlikely (i >= len)) return Type (); 494a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod return head[i]; 495a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod } 496a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod 497fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod inline void advance (unsigned int count) 498fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod { 499a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod if (unlikely (count > len)) 500a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod count = len; 501a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod len -= count; 502a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod head += count; 503a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod } 504a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod 505a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod private: 506fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod inline Supplier (const Supplier<Type> &); /* Disallow copy */ 507fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod inline Supplier<Type>& operator= (const Supplier<Type> &); /* Disallow copy */ 508fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod 509a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod unsigned int len; 510a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod const Type *head; 511a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod}; 512a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod 513a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod 514e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod 515f0abcd69408a3af65207cdf8847575ade4579bd4Behdad Esfahbod 516b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod/* 517b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod * 518bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod * The OpenType Font File: Data Types 519b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod */ 520b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod 521b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod 522b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod/* "The following data types are used in the OpenType font file. 523b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod * All OpenType fonts use Motorola-style byte ordering (Big Endian):" */ 524b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod 5255f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod/* 5265f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod * Int types 5275f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod */ 5285f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod 5296b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod 530d7bf473ef222ab420456ff155ffaa09bacb3a394Behdad Esfahbodtemplate <typename Type, int Bytes> struct BEInt; 531e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod 532e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodtemplate <typename Type> 533d7bf473ef222ab420456ff155ffaa09bacb3a394Behdad Esfahbodstruct BEInt<Type, 2> 534e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod{ 535e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod public: 53681408cd51ce575891e79e6483be187130f864c28Behdad Esfahbod inline void set (Type i) { hb_be_uint16_put (v,i); } 5377f97d2cd904ea999c099c73c52187c5d65aeec67Behdad Esfahbod inline operator Type (void) const { return hb_be_uint16_get (v); } 538153142dac8dd9abaf164bb88af07c600c17fc3a1Behdad Esfahbod inline bool operator == (const BEInt<Type, 2>& o) const { return hb_be_uint16_eq (v, o.v); } 53901c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod inline bool operator != (const BEInt<Type, 2>& o) const { return !(*this == o); } 540e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod private: uint8_t v[2]; 541e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod}; 542e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodtemplate <typename Type> 543d7bf473ef222ab420456ff155ffaa09bacb3a394Behdad Esfahbodstruct BEInt<Type, 4> 544e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod{ 545e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod public: 54681408cd51ce575891e79e6483be187130f864c28Behdad Esfahbod inline void set (Type i) { hb_be_uint32_put (v,i); } 5477f97d2cd904ea999c099c73c52187c5d65aeec67Behdad Esfahbod inline operator Type (void) const { return hb_be_uint32_get (v); } 548153142dac8dd9abaf164bb88af07c600c17fc3a1Behdad Esfahbod inline bool operator == (const BEInt<Type, 4>& o) const { return hb_be_uint32_eq (v, o.v); } 54901c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod inline bool operator != (const BEInt<Type, 4>& o) const { return !(*this == o); } 550e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod private: uint8_t v[4]; 551e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod}; 552bd61bc13ea8ff350ada5449b2cfeb612e66ecafaBehdad Esfahbodtemplate <typename Type> 553bd61bc13ea8ff350ada5449b2cfeb612e66ecafaBehdad Esfahbodstruct BEInt<Type, 3> 554bd61bc13ea8ff350ada5449b2cfeb612e66ecafaBehdad Esfahbod{ 555bd61bc13ea8ff350ada5449b2cfeb612e66ecafaBehdad Esfahbod public: 556bd61bc13ea8ff350ada5449b2cfeb612e66ecafaBehdad Esfahbod inline void set (Type i) { hb_be_uint24_put (v,i); } 557bd61bc13ea8ff350ada5449b2cfeb612e66ecafaBehdad Esfahbod inline operator Type (void) const { return hb_be_uint24_get (v); } 558bd61bc13ea8ff350ada5449b2cfeb612e66ecafaBehdad Esfahbod inline bool operator == (const BEInt<Type, 3>& o) const { return hb_be_uint24_eq (v, o.v); } 559bd61bc13ea8ff350ada5449b2cfeb612e66ecafaBehdad Esfahbod inline bool operator != (const BEInt<Type, 3>& o) const { return !(*this == o); } 560bd61bc13ea8ff350ada5449b2cfeb612e66ecafaBehdad Esfahbod private: uint8_t v[3]; 561bd61bc13ea8ff350ada5449b2cfeb612e66ecafaBehdad Esfahbod}; 562e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod 5632467c669c2aee4de2a6621a9d06cba0262376d41Behdad Esfahbod/* Integer types in big-endian order and no alignment requirement */ 564bd61bc13ea8ff350ada5449b2cfeb612e66ecafaBehdad Esfahbodtemplate <typename Type, unsigned int Size> 565e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodstruct IntType 566e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod{ 56781408cd51ce575891e79e6483be187130f864c28Behdad Esfahbod inline void set (Type i) { v.set (i); } 56801c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod inline operator Type(void) const { return v; } 569bd61bc13ea8ff350ada5449b2cfeb612e66ecafaBehdad Esfahbod inline bool operator == (const IntType<Type,Size> &o) const { return v == o.v; } 570bd61bc13ea8ff350ada5449b2cfeb612e66ecafaBehdad Esfahbod inline bool operator != (const IntType<Type,Size> &o) const { return v != o.v; } 571bd61bc13ea8ff350ada5449b2cfeb612e66ecafaBehdad Esfahbod static inline int cmp (const IntType<Type,Size> *a, const IntType<Type,Size> *b) { return b->cmp (*a); } 572bd61bc13ea8ff350ada5449b2cfeb612e66ecafaBehdad Esfahbod inline int cmp (IntType<Type,Size> va) const { Type a = va; Type b = v; return a < b ? -1 : a == b ? 0 : +1; } 5734e573715ae5f5ed486ad66382bb44c47a86591ffBehdad Esfahbod inline int cmp (Type a) const { Type b = v; return a < b ? -1 : a == b ? 0 : +1; } 574d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod inline bool sanitize (hb_sanitize_context_t *c) { 575be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod TRACE_SANITIZE (this); 5760ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod return TRACE_RETURN (likely (c->check_struct (this))); 577e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod } 578a82ef7a893b773a17f7548375de9f588dfc83abaBehdad Esfahbod protected: 579bd61bc13ea8ff350ada5449b2cfeb612e66ecafaBehdad Esfahbod BEInt<Type, Size> v; 580569da92bc6956f42d9b2d65c784e184fb6380efeBehdad Esfahbod public: 581bd61bc13ea8ff350ada5449b2cfeb612e66ecafaBehdad Esfahbod DEFINE_SIZE_STATIC (Size); 582e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod}; 583e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod 584b7878cd58ea9a67236e1e0228c35b5b03ec4ff9cBehdad Esfahbodtypedef uint8_t BYTE; /* 8-bit unsigned integer. */ 585bd61bc13ea8ff350ada5449b2cfeb612e66ecafaBehdad Esfahbodtypedef IntType<uint16_t, 2> USHORT; /* 16-bit unsigned integer. */ 586bd61bc13ea8ff350ada5449b2cfeb612e66ecafaBehdad Esfahbodtypedef IntType<int16_t, 2> SHORT; /* 16-bit signed integer. */ 587bd61bc13ea8ff350ada5449b2cfeb612e66ecafaBehdad Esfahbodtypedef IntType<uint32_t, 4> ULONG; /* 32-bit unsigned integer. */ 588bd61bc13ea8ff350ada5449b2cfeb612e66ecafaBehdad Esfahbodtypedef IntType<int32_t, 4> LONG; /* 32-bit signed integer. */ 589bd61bc13ea8ff350ada5449b2cfeb612e66ecafaBehdad Esfahbodtypedef IntType<uint32_t, 3> UINT24; /* 24-bit unsigned integer. */ 590e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod 591ae9877dea6a1aed3566d9b87a75ede84259deacaBehdad Esfahbod/* 16-bit signed integer (SHORT) that describes a quantity in FUnits. */ 592ae9877dea6a1aed3566d9b87a75ede84259deacaBehdad Esfahbodtypedef SHORT FWORD; 593ae9877dea6a1aed3566d9b87a75ede84259deacaBehdad Esfahbod 594ae9877dea6a1aed3566d9b87a75ede84259deacaBehdad Esfahbod/* 16-bit unsigned integer (USHORT) that describes a quantity in FUnits. */ 595ae9877dea6a1aed3566d9b87a75ede84259deacaBehdad Esfahbodtypedef USHORT UFWORD; 596ae9877dea6a1aed3566d9b87a75ede84259deacaBehdad Esfahbod 597e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod/* Date represented in number of seconds since 12:00 midnight, January 1, 598e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod * 1904. The value is represented as a signed 64-bit integer. */ 599e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbodstruct LONGDATETIME 600e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod{ 601e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod inline bool sanitize (hb_sanitize_context_t *c) { 602be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod TRACE_SANITIZE (this); 6030ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod return TRACE_RETURN (likely (c->check_struct (this))); 604e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod } 6056775da3a7c07db6c032cf429dc199d471948db56Behdad Esfahbod protected: 606e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod LONG major; 607e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod ULONG minor; 608e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod public: 609e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod DEFINE_SIZE_STATIC (8); 610e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod}; 611e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod 6126b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod/* Array of four uint8s (length = 32 bits) used to identify a script, language 6136b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod * system, feature, or baseline */ 61420cc86b3592db33731de671f008d7d222776be49Behdad Esfahbodstruct Tag : ULONG 61560d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{ 616befc022affd2386b3f46cd7d11e4262f6c8bce9fBehdad Esfahbod /* What the char* converters return is NOT nul-terminated. Print using "%.4s" */ 617a82ef7a893b773a17f7548375de9f588dfc83abaBehdad Esfahbod inline operator const char* (void) const { return reinterpret_cast<const char *> (&this->v); } 618a82ef7a893b773a17f7548375de9f588dfc83abaBehdad Esfahbod inline operator char* (void) { return reinterpret_cast<char *> (&this->v); } 619b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod public: 620b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod DEFINE_SIZE_STATIC (4); 6216b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod}; 62265f46b00333e20ab8a52a4b350747507541ec1dbBehdad EsfahbodDEFINE_NULL_DATA (Tag, " "); 6236b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod 6246b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod/* Glyph index number, same as uint16 (length = 16 bits) */ 6256ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbodtypedef USHORT GlyphID; 6266b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod 627b5db4f1e4eefa266a71a28b5496f47ff9d1a81e8Behdad Esfahbod/* Script/language-system/feature index */ 628b5db4f1e4eefa266a71a28b5496f47ff9d1a81e8Behdad Esfahbodstruct Index : USHORT { 6297627100f428ac0ec8509d961d368d2d25d8f0b6eBehdad Esfahbod static const unsigned int NOT_FOUND_INDEX = 0xFFFFu; 630b5db4f1e4eefa266a71a28b5496f47ff9d1a81e8Behdad Esfahbod}; 631b5db4f1e4eefa266a71a28b5496f47ff9d1a81e8Behdad EsfahbodDEFINE_NULL_DATA (Index, "\xff\xff"); 632b5db4f1e4eefa266a71a28b5496f47ff9d1a81e8Behdad Esfahbod 63399d281712390fd54e523b2f0580d10445457ec2fBehdad Esfahbod/* Offset, Null offset = 0 */ 63499d281712390fd54e523b2f0580d10445457ec2fBehdad Esfahbodtemplate <typename Type=USHORT> 63599d281712390fd54e523b2f0580d10445457ec2fBehdad Esfahbodstruct Offset : Type 636e95e031b5682809488cc965883e15404cb9cfb6aBehdad Esfahbod{ 637e95e031b5682809488cc965883e15404cb9cfb6aBehdad Esfahbod inline bool is_null (void) const { return 0 == *this; } 638e95e031b5682809488cc965883e15404cb9cfb6aBehdad Esfahbod public: 6390394ec1bfbd7806cbe9fc809b34f96f8d12ffbf2Behdad Esfahbod DEFINE_SIZE_STATIC (sizeof(Type)); 640e95e031b5682809488cc965883e15404cb9cfb6aBehdad Esfahbod}; 6416ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbod 6426b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod 6436b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod/* CheckSum */ 64460d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbodstruct CheckSum : ULONG 64560d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{ 64605bad3b8c25a89bc0f20f99f9215e492f48f03feBehdad Esfahbod /* This is reference implementation from the spec. */ 64705bad3b8c25a89bc0f20f99f9215e492f48f03feBehdad Esfahbod static inline uint32_t CalcTableChecksum (const ULONG *Table, uint32_t Length) 64860d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod { 6496b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod uint32_t Sum = 0L; 65005bad3b8c25a89bc0f20f99f9215e492f48f03feBehdad Esfahbod const ULONG *EndPtr = Table+((Length+3) & ~3) / ULONG::static_size; 6516b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod 6526b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod while (Table < EndPtr) 6536b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod Sum += *Table++; 6546b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod return Sum; 6556b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod } 65605bad3b8c25a89bc0f20f99f9215e492f48f03feBehdad Esfahbod 65705bad3b8c25a89bc0f20f99f9215e492f48f03feBehdad Esfahbod /* Note: data should be 4byte aligned and have 4byte padding at the end. */ 65805bad3b8c25a89bc0f20f99f9215e492f48f03feBehdad Esfahbod inline void set_for_data (const void *data, unsigned int length) 65905bad3b8c25a89bc0f20f99f9215e492f48f03feBehdad Esfahbod { set (CalcTableChecksum ((const ULONG *) data, length)); } 66005bad3b8c25a89bc0f20f99f9215e492f48f03feBehdad Esfahbod 661b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod public: 662b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod DEFINE_SIZE_STATIC (4); 6636b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod}; 6646b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod 6656b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod 6666b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod/* 6676b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod * Version Numbers 6686b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod */ 6696b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod 67087fcdcbe3644da10154688765db2d62eb9ac079aBehdad Esfahbodstruct FixedVersion 67160d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{ 6724f28fbdd804fabeec57a98fe267d892ab58b3a6dBehdad Esfahbod inline uint32_t to_int (void) const { return (major << 16) + minor; } 67396908b898476ca5d7da5f386b15be76f9e83d76eBehdad Esfahbod 674d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod inline bool sanitize (hb_sanitize_context_t *c) { 675be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod TRACE_SANITIZE (this); 6760ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod return TRACE_RETURN (c->check_struct (this)); 677cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod } 678cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod 6796ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbod USHORT major; 68087fcdcbe3644da10154688765db2d62eb9ac079aBehdad Esfahbod USHORT minor; 681b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod public: 682b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod DEFINE_SIZE_STATIC (4); 6836b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod}; 6846b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod 68592b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 68692b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 6875f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod/* 68899d281712390fd54e523b2f0580d10445457ec2fBehdad Esfahbod * Template subclasses of Offset that do the dereferencing. 689f0abcd69408a3af65207cdf8847575ade4579bd4Behdad Esfahbod * Use: (base+offset) 6905f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod */ 6915f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod 6929da552dcc5b89b3bbbe5a55fb7c543222382e12aBehdad Esfahbodtemplate <typename Type, typename OffsetType=USHORT> 69399d281712390fd54e523b2f0580d10445457ec2fBehdad Esfahbodstruct OffsetTo : Offset<OffsetType> 69492b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod{ 69500e23fcc6fd0eee5c582251bf3de6a2703fbbd3eBehdad Esfahbod inline const Type& operator () (const void *base) const 69692b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod { 69792b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod unsigned int offset = *this; 69864d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod if (unlikely (!offset)) return Null(Type); 69909766b1ec5ec55a61edbcd7a89ed3613cc92d4cbBehdad Esfahbod return StructAtOffset<Type> (base, offset); 70092b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod } 701bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod 702abcc5ac1fde1c493e4055dd2f27b8aade7713156Behdad Esfahbod inline Type& serialize (hb_serialize_context_t *c, void *base) 703bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod { 704fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod Type *t = c->start_embed<Type> (); 7054912030dfba740c822e200d33cbb5c6dbbeaf79eBehdad Esfahbod this->set ((char *) t - (char *) base); /* TODO(serialize) Overflow? */ 706abcc5ac1fde1c493e4055dd2f27b8aade7713156Behdad Esfahbod return *t; 707bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod } 70892b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 709d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod inline bool sanitize (hb_sanitize_context_t *c, void *base) { 710be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod TRACE_SANITIZE (this); 7110ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod if (unlikely (!c->check_struct (this))) return TRACE_RETURN (false); 71292b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod unsigned int offset = *this; 7130ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod if (unlikely (!offset)) return TRACE_RETURN (true); 71409766b1ec5ec55a61edbcd7a89ed3613cc92d4cbBehdad Esfahbod Type &obj = StructAtOffset<Type> (base, offset); 7150ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod return TRACE_RETURN (likely (obj.sanitize (c)) || neuter (c)); 71692b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod } 7174a446ac35136eff23d55f47bdd7b40095ad707abBehdad Esfahbod template <typename T> 718d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod inline bool sanitize (hb_sanitize_context_t *c, void *base, T user_data) { 719be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod TRACE_SANITIZE (this); 7200ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod if (unlikely (!c->check_struct (this))) return TRACE_RETURN (false); 72142b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod unsigned int offset = *this; 7220ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod if (unlikely (!offset)) return TRACE_RETURN (true); 72309766b1ec5ec55a61edbcd7a89ed3613cc92d4cbBehdad Esfahbod Type &obj = StructAtOffset<Type> (base, offset); 7240ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod return TRACE_RETURN (likely (obj.sanitize (c, user_data)) || neuter (c)); 725c9f14687a30866181feb57ee2736a147ec9f25a1Behdad Esfahbod } 726c9f14687a30866181feb57ee2736a147ec9f25a1Behdad Esfahbod 727c9f14687a30866181feb57ee2736a147ec9f25a1Behdad Esfahbod /* Set the offset to Null */ 728d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod inline bool neuter (hb_sanitize_context_t *c) { 72951f563579b94e1ee23ced9bbcc7dd3341535ce72Behdad Esfahbod return c->try_set (this, 0); 73042b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod } 731586b60622c33878f9ca4826b4ef07369d32bf039Behdad Esfahbod DEFINE_SIZE_STATIC (sizeof(OffsetType)); 73292b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod}; 73392b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Base, typename OffsetType, typename Type> 7340d1b3419a7bbfd18ab8fed1abd3a41dec11e8d97Behdad Esfahbodstatic inline const Type& operator + (const Base &base, const OffsetTo<Type, OffsetType> &offset) { return offset (base); } 735bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbodtemplate <typename Base, typename OffsetType, typename Type> 7360d1b3419a7bbfd18ab8fed1abd3a41dec11e8d97Behdad Esfahbodstatic inline Type& operator + (Base &base, OffsetTo<Type, OffsetType> &offset) { return offset (base); } 73792b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 738bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod 73992b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod/* 74092b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod * Array Types 74192b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod */ 74292b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 7439da552dcc5b89b3bbbe5a55fb7c543222382e12aBehdad Esfahbod/* An array with a number of elements. */ 7449da552dcc5b89b3bbbe5a55fb7c543222382e12aBehdad Esfahbodtemplate <typename Type, typename LenType=USHORT> 7459da552dcc5b89b3bbbe5a55fb7c543222382e12aBehdad Esfahbodstruct ArrayOf 74660d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{ 7474f5f1c34dda1e0629bfa6d7b0ffa2e1ce003b7c7Behdad Esfahbod const Type *sub_array (unsigned int start_offset, unsigned int *pcount /* IN/OUT */) const 74848de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod { 74948de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod unsigned int count = len; 75064d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod if (unlikely (start_offset > count)) 75148de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod count = 0; 75248de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod else 75348de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod count -= start_offset; 75448de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod count = MIN (count, *pcount); 75548de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod *pcount = count; 756b961518b9611471ff7060e97686e5625974847ebBehdad Esfahbod return array + start_offset; 75748de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod } 75848de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod 75960d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod inline const Type& operator [] (unsigned int i) const 76060d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod { 76164d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod if (unlikely (i >= len)) return Null(Type); 762b961518b9611471ff7060e97686e5625974847ebBehdad Esfahbod return array[i]; 7635f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod } 7649f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod inline Type& operator [] (unsigned int i) 7659f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod { 7669f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod return array[i]; 7679f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod } 7687f97d2cd904ea999c099c73c52187c5d65aeec67Behdad Esfahbod inline unsigned int get_size (void) const 769e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod { return len.static_size + len * Type::static_size; } 770e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod 771c61be03d6df122f18eebda3b29e42c9e768d45b9Behdad Esfahbod inline bool serialize (hb_serialize_context_t *c, 7721f07e3382a1608b054cbf88b89fef74f6c485434Behdad Esfahbod unsigned int items_len) 7731f07e3382a1608b054cbf88b89fef74f6c485434Behdad Esfahbod { 774be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod TRACE_SERIALIZE (this); 7751f07e3382a1608b054cbf88b89fef74f6c485434Behdad Esfahbod if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); 7761f07e3382a1608b054cbf88b89fef74f6c485434Behdad Esfahbod len.set (items_len); /* TODO(serialize) Overflow? */ 7771f07e3382a1608b054cbf88b89fef74f6c485434Behdad Esfahbod if (unlikely (!c->extend (*this))) return TRACE_RETURN (false); 7781f07e3382a1608b054cbf88b89fef74f6c485434Behdad Esfahbod return TRACE_RETURN (true); 7791f07e3382a1608b054cbf88b89fef74f6c485434Behdad Esfahbod } 7801f07e3382a1608b054cbf88b89fef74f6c485434Behdad Esfahbod 7811f07e3382a1608b054cbf88b89fef74f6c485434Behdad Esfahbod inline bool serialize (hb_serialize_context_t *c, 782a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod Supplier<Type> &items, 783c61be03d6df122f18eebda3b29e42c9e768d45b9Behdad Esfahbod unsigned int items_len) 784c61be03d6df122f18eebda3b29e42c9e768d45b9Behdad Esfahbod { 785be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod TRACE_SERIALIZE (this); 786715e03bc21d6adaa8e1f647235843839dc47dad1Behdad Esfahbod if (unlikely (!serialize (c, items_len))) return TRACE_RETURN (false); 787715e03bc21d6adaa8e1f647235843839dc47dad1Behdad Esfahbod for (unsigned int i = 0; i < items_len; i++) 788fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod array[i] = items[i]; 789a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod items.advance (items_len); 790c61be03d6df122f18eebda3b29e42c9e768d45b9Behdad Esfahbod return TRACE_RETURN (true); 791c61be03d6df122f18eebda3b29e42c9e768d45b9Behdad Esfahbod } 792c61be03d6df122f18eebda3b29e42c9e768d45b9Behdad Esfahbod 793d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod inline bool sanitize (hb_sanitize_context_t *c) { 794be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod TRACE_SANITIZE (this); 7950ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false); 79611e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod 79740d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod /* Note: for structs that do not reference other structs, 79840d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod * we do not need to call their sanitize() as we already did 79911e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod * a bound check on the aggregate array size. We just include 80011e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod * a small unreachable expression to make sure the structs 80111e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod * pointed to do have a simple sanitize(), ie. they do not 80211e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod * reference other structs via offsets. 80340d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod */ 80411e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod (void) (false && array[0].sanitize (c)); 80511e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod 8060ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod return TRACE_RETURN (true); 80770de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod } 808d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod inline bool sanitize (hb_sanitize_context_t *c, void *base) { 809be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod TRACE_SANITIZE (this); 8100ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false); 811e6ab2c59ba2d37942ac5fcbfe61d38b7e359ac8cBehdad Esfahbod unsigned int count = len; 812e6ab2c59ba2d37942ac5fcbfe61d38b7e359ac8cBehdad Esfahbod for (unsigned int i = 0; i < count; i++) 813d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod if (unlikely (!array[i].sanitize (c, base))) 8140ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod return TRACE_RETURN (false); 8150ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod return TRACE_RETURN (true); 816e6ab2c59ba2d37942ac5fcbfe61d38b7e359ac8cBehdad Esfahbod } 8174a446ac35136eff23d55f47bdd7b40095ad707abBehdad Esfahbod template <typename T> 818d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod inline bool sanitize (hb_sanitize_context_t *c, void *base, T user_data) { 819be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod TRACE_SANITIZE (this); 8200ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false); 82142b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod unsigned int count = len; 82242b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod for (unsigned int i = 0; i < count; i++) 823d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod if (unlikely (!array[i].sanitize (c, base, user_data))) 8240ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod return TRACE_RETURN (false); 8250ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod return TRACE_RETURN (true); 82642b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod } 82770de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod 828c7074b8798048324cb8850c55908ce77fc33d11eBehdad Esfahbod template <typename SearchType> 829df554af99db390e42d378983bb3fcf583477a1d7Behdad Esfahbod inline int lsearch (const SearchType &x) const 830c7074b8798048324cb8850c55908ce77fc33d11eBehdad Esfahbod { 831c7074b8798048324cb8850c55908ce77fc33d11eBehdad Esfahbod unsigned int count = len; 832c7074b8798048324cb8850c55908ce77fc33d11eBehdad Esfahbod for (unsigned int i = 0; i < count; i++) 833c7074b8798048324cb8850c55908ce77fc33d11eBehdad Esfahbod if (!this->array[i].cmp (x)) 834c7074b8798048324cb8850c55908ce77fc33d11eBehdad Esfahbod return i; 835c7074b8798048324cb8850c55908ce77fc33d11eBehdad Esfahbod return -1; 836c7074b8798048324cb8850c55908ce77fc33d11eBehdad Esfahbod } 837c7074b8798048324cb8850c55908ce77fc33d11eBehdad Esfahbod 83830fa2821c277df99a14089749313dfe2b541e2d0Behdad Esfahbod private: 839d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod inline bool sanitize_shallow (hb_sanitize_context_t *c) { 840be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod TRACE_SANITIZE (this); 8410ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod return TRACE_RETURN (c->check_struct (this) && c->check_array (this, Type::static_size, len)); 84230fa2821c277df99a14089749313dfe2b541e2d0Behdad Esfahbod } 84330fa2821c277df99a14089749313dfe2b541e2d0Behdad Esfahbod 84430fa2821c277df99a14089749313dfe2b541e2d0Behdad Esfahbod public: 84592b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod LenType len; 846b961518b9611471ff7060e97686e5625974847ebBehdad Esfahbod Type array[VAR]; 847b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod public: 8480eb9fc6e37935707dba2bf4b3705de2161a08cb7Behdad Esfahbod DEFINE_SIZE_ARRAY (sizeof (LenType), array); 849e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod}; 850e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod 85192b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod/* Array of Offset's */ 85292b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Type> 85392b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct OffsetArrayOf : ArrayOf<OffsetTo<Type> > {}; 85492b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 85580e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod/* Array of offsets relative to the beginning of the array itself. */ 85680e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbodtemplate <typename Type> 85780e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbodstruct OffsetListOf : OffsetArrayOf<Type> 85880e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod{ 85980e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod inline const Type& operator [] (unsigned int i) const 86080e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod { 86164d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod if (unlikely (i >= this->len)) return Null(Type); 862b961518b9611471ff7060e97686e5625974847ebBehdad Esfahbod return this+this->array[i]; 86380e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod } 86480e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod 865d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod inline bool sanitize (hb_sanitize_context_t *c) { 866be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod TRACE_SANITIZE (this); 8670ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod return TRACE_RETURN (OffsetArrayOf<Type>::sanitize (c, this)); 86880e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod } 8694a446ac35136eff23d55f47bdd7b40095ad707abBehdad Esfahbod template <typename T> 870d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod inline bool sanitize (hb_sanitize_context_t *c, T user_data) { 871be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod TRACE_SANITIZE (this); 8720ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod return TRACE_RETURN (OffsetArrayOf<Type>::sanitize (c, this, user_data)); 87380e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod } 87480e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod}; 87580e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod 87680e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod 87751d9ba09bc78188ec87218aef5232e80568c1712Behdad Esfahbod/* An array starting at second element. */ 87851d9ba09bc78188ec87218aef5232e80568c1712Behdad Esfahbodtemplate <typename Type, typename LenType=USHORT> 87960d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbodstruct HeadlessArrayOf 88060d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{ 88160d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod inline const Type& operator [] (unsigned int i) const 88260d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod { 88364d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod if (unlikely (i >= len || !i)) return Null(Type); 884b961518b9611471ff7060e97686e5625974847ebBehdad Esfahbod return array[i-1]; 885e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod } 8867f97d2cd904ea999c099c73c52187c5d65aeec67Behdad Esfahbod inline unsigned int get_size (void) const 887e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod { return len.static_size + (len ? len - 1 : 0) * Type::static_size; } 8885f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod 889a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod inline bool serialize (hb_serialize_context_t *c, 890a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod Supplier<Type> &items, 891a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod unsigned int items_len) 892a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod { 893be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod TRACE_SERIALIZE (this); 894a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false); 895a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod len.set (items_len); /* TODO(serialize) Overflow? */ 896a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod if (unlikely (!items_len)) return TRACE_RETURN (true); 897fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod if (unlikely (!c->extend (*this))) return TRACE_RETURN (false); 898fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod for (unsigned int i = 0; i < items_len - 1; i++) 899fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod array[i] = items[i]; 900a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod items.advance (items_len - 1); 901a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod return TRACE_RETURN (true); 902a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod } 903a930c68e9c50aade78c1eb0eef075c9c117e4ef6Behdad Esfahbod 904d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod inline bool sanitize_shallow (hb_sanitize_context_t *c) { 905d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod return c->check_struct (this) 906d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod && c->check_array (this, Type::static_size, len); 907e5546a4352c54311ac4a9ef138b187378155ebe1Behdad Esfahbod } 908e5546a4352c54311ac4a9ef138b187378155ebe1Behdad Esfahbod 909d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod inline bool sanitize (hb_sanitize_context_t *c) { 910be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod TRACE_SANITIZE (this); 9110ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false); 91211e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod 91340d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod /* Note: for structs that do not reference other structs, 91440d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod * we do not need to call their sanitize() as we already did 91511e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod * a bound check on the aggregate array size. We just include 91611e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod * a small unreachable expression to make sure the structs 91711e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod * pointed to do have a simple sanitize(), ie. they do not 91811e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod * reference other structs via offsets. 91940d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod */ 92011e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod (void) (false && array[0].sanitize (c)); 92111e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod 9220ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod return TRACE_RETURN (true); 92370de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod } 92470de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod 92551d9ba09bc78188ec87218aef5232e80568c1712Behdad Esfahbod LenType len; 926b961518b9611471ff7060e97686e5625974847ebBehdad Esfahbod Type array[VAR]; 927ed07422c33bbb52ff4d79e65986171e3f07697d8Behdad Esfahbod public: 92851d9ba09bc78188ec87218aef5232e80568c1712Behdad Esfahbod DEFINE_SIZE_ARRAY (sizeof (LenType), array); 9295f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod}; 9305f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod 9316b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod 932cc8a4abea68f2dba26feb5785f9e518e6853c744Behdad Esfahbod/* An array with sorted elements. Supports binary searching. */ 9339da552dcc5b89b3bbbe5a55fb7c543222382e12aBehdad Esfahbodtemplate <typename Type, typename LenType=USHORT> 9349da552dcc5b89b3bbbe5a55fb7c543222382e12aBehdad Esfahbodstruct SortedArrayOf : ArrayOf<Type, LenType> 93540a479797add42fa42b78d4267920ef75bfb6b9aBehdad Esfahbod{ 936cc8a4abea68f2dba26feb5785f9e518e6853c744Behdad Esfahbod template <typename SearchType> 937df554af99db390e42d378983bb3fcf583477a1d7Behdad Esfahbod inline int bsearch (const SearchType &x) const 9388659c636087e433f56da458351e8b4d85fdb347cBehdad Esfahbod { 9398659c636087e433f56da458351e8b4d85fdb347cBehdad Esfahbod /* Hand-coded bsearch here since this is in the hot inner loop. */ 9408659c636087e433f56da458351e8b4d85fdb347cBehdad Esfahbod int min = 0, max = (int) this->len - 1; 9418659c636087e433f56da458351e8b4d85fdb347cBehdad Esfahbod while (min <= max) 9428659c636087e433f56da458351e8b4d85fdb347cBehdad Esfahbod { 9438659c636087e433f56da458351e8b4d85fdb347cBehdad Esfahbod int mid = (min + max) / 2; 9448659c636087e433f56da458351e8b4d85fdb347cBehdad Esfahbod int c = this->array[mid].cmp (x); 9458659c636087e433f56da458351e8b4d85fdb347cBehdad Esfahbod if (c < 0) 9468659c636087e433f56da458351e8b4d85fdb347cBehdad Esfahbod max = mid - 1; 9478659c636087e433f56da458351e8b4d85fdb347cBehdad Esfahbod else if (c > 0) 9488659c636087e433f56da458351e8b4d85fdb347cBehdad Esfahbod min = mid + 1; 9498659c636087e433f56da458351e8b4d85fdb347cBehdad Esfahbod else 9508659c636087e433f56da458351e8b4d85fdb347cBehdad Esfahbod return mid; 95199159e52a3c9d5ae6c0fbdec64e7ed684fa70b61Behdad Esfahbod } 9528659c636087e433f56da458351e8b4d85fdb347cBehdad Esfahbod return -1; 953cc8a4abea68f2dba26feb5785f9e518e6853c744Behdad Esfahbod } 954cc8a4abea68f2dba26feb5785f9e518e6853c744Behdad Esfahbod}; 955cc8a4abea68f2dba26feb5785f9e518e6853c744Behdad Esfahbod 956cc8a4abea68f2dba26feb5785f9e518e6853c744Behdad Esfahbod 9577d52e6601f0e695690cd168a288466746cf25300Behdad Esfahbod} /* namespace OT */ 9587c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod 959acdba3f90b232fc12fcb200dca2584481b339118Behdad Esfahbod 9601e91434569a9e9535ef021ca52b60b2e2af75d19Behdad Esfahbod#endif /* HB_OPEN_TYPE_PRIVATE_HH */ 961