hb-open-type-private.hh revision bc5be24014371ceb811b9ffd37062ede63d87bb1
164aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod/* 22409d5f8d7dd8b535ce5ea29e933f7db27d33793Behdad Esfahbod * Copyright © 2007,2008,2009,2010 Red Hat, Inc. 30ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod * Copyright © 2012 Google, Inc. 464aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * 5c755cb3e3ac55156d0d2ec05adea7a650b97cc41Behdad Esfahbod * This is part of HarfBuzz, a text shaping library. 664aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * 764aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * Permission is hereby granted, without written agreement and without 864aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * license or royalty fees, to use, copy, modify, and distribute this 964aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * software and its documentation for any purpose, provided that the 1064aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * above copyright notice and the following two paragraphs appear in 1164aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * all copies of this software. 1264aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * 1364aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR 1464aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 1564aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN 1664aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 1764aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * DAMAGE. 1864aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * 1964aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, 2064aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 2164aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS 2264aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO 2364aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 2464aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * 2564aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * Red Hat Author(s): Behdad Esfahbod 260ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod * Google Author(s): Behdad Esfahbod 2764aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod */ 2864aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod 290f0cd9d361f1bb614aa3fd4616160d027062370eBehdad Esfahbod#ifndef HB_OPEN_TYPE_PRIVATE_HH 300f0cd9d361f1bb614aa3fd4616160d027062370eBehdad Esfahbod#define HB_OPEN_TYPE_PRIVATE_HH 3112c4568c680ea2b9b98a16a8b7402ca185c90ef6Behdad Esfahbod 32c57d454accff66e5f2c58006e8fb40bc020b6182Behdad Esfahbod#include "hb-private.hh" 3312c4568c680ea2b9b98a16a8b7402ca185c90ef6Behdad Esfahbod 3470de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod#include "hb-blob.h" 3570de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod 36a16ecbf0564a6e2576da22c12827f3c0719da549Behdad Esfahbod 377c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbodnamespace OT { 387c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod 39a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbod 40196598bbccff08415ff5192314cba044df258cadBehdad Esfahbod/* 41196598bbccff08415ff5192314cba044df258cadBehdad Esfahbod * Casts 42196598bbccff08415ff5192314cba044df258cadBehdad Esfahbod */ 43196598bbccff08415ff5192314cba044df258cadBehdad Esfahbod 44187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbod/* Cast to struct T, reference to reference */ 45a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbodtemplate<typename Type, typename TObject> 46187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbodinline const Type& CastR(const TObject &X) 47a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbod{ return reinterpret_cast<const Type&> (X); } 48a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbodtemplate<typename Type, typename TObject> 49187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbodinline Type& CastR(TObject &X) 50a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbod{ return reinterpret_cast<Type&> (X); } 51196598bbccff08415ff5192314cba044df258cadBehdad Esfahbod 52187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbod/* Cast to struct T, pointer to pointer */ 53187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbodtemplate<typename Type, typename TObject> 54187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbodinline const Type* CastP(const TObject *X) 55187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbod{ return reinterpret_cast<const Type*> (X); } 56187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbodtemplate<typename Type, typename TObject> 57187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbodinline Type* CastP(TObject *X) 58187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbod{ return reinterpret_cast<Type*> (X); } 59187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbod 6009766b1ec5ec55a61edbcd7a89ed3613cc92d4cbBehdad Esfahbod/* StructAtOffset<T>(P,Ofs) returns the struct T& that is placed at memory 6109766b1ec5ec55a61edbcd7a89ed3613cc92d4cbBehdad Esfahbod * location pointed to by P plus Ofs bytes. */ 6209766b1ec5ec55a61edbcd7a89ed3613cc92d4cbBehdad Esfahbodtemplate<typename Type> 6309766b1ec5ec55a61edbcd7a89ed3613cc92d4cbBehdad Esfahbodinline const Type& StructAtOffset(const void *P, unsigned int offset) 64a82ef7a893b773a17f7548375de9f588dfc83abaBehdad Esfahbod{ return * reinterpret_cast<const Type*> ((const char *) P + offset); } 6509766b1ec5ec55a61edbcd7a89ed3613cc92d4cbBehdad Esfahbodtemplate<typename Type> 6609766b1ec5ec55a61edbcd7a89ed3613cc92d4cbBehdad Esfahbodinline Type& StructAtOffset(void *P, unsigned int offset) 67a82ef7a893b773a17f7548375de9f588dfc83abaBehdad Esfahbod{ return * reinterpret_cast<Type*> ((char *) P + offset); } 6870de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod 692e2f43edf2f49f4047e28b1ce2ea95938536de9cBehdad Esfahbod/* StructAfter<T>(X) returns the struct T& that is placed after X. 7029c3f5e1b6212c775a7b911becd44ba093b7b0ebBehdad Esfahbod * Works with X of variable size also. X must implement get_size() */ 71e961c86c579fd98ee604342a9c70c4e7f8d4f220Behdad Esfahbodtemplate<typename Type, typename TObject> 72e961c86c579fd98ee604342a9c70c4e7f8d4f220Behdad Esfahbodinline const Type& StructAfter(const TObject &X) 7309766b1ec5ec55a61edbcd7a89ed3613cc92d4cbBehdad Esfahbod{ return StructAtOffset<Type>(&X, X.get_size()); } 74e961c86c579fd98ee604342a9c70c4e7f8d4f220Behdad Esfahbodtemplate<typename Type, typename TObject> 75e961c86c579fd98ee604342a9c70c4e7f8d4f220Behdad Esfahbodinline Type& StructAfter(TObject &X) 7609766b1ec5ec55a61edbcd7a89ed3613cc92d4cbBehdad Esfahbod{ return StructAtOffset<Type>(&X, X.get_size()); } 77a3263aa773ad7a914496792466c69047048b093cBehdad Esfahbod 78e961c86c579fd98ee604342a9c70c4e7f8d4f220Behdad Esfahbod 79d3480ba37fbb5d4be75b094060f5b2f1ce98fb53Behdad Esfahbod 8070de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod/* 81e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod * Size checking 82e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod */ 83e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod 84f679635893eebc13402c5ee51a6f106eed0c76beBehdad Esfahbod/* Check _assertion in a method environment */ 85a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod#define _DEFINE_INSTANCE_ASSERTION1(_line, _assertion) \ 86a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod inline void _instance_assertion_on_line_##_line (void) const \ 87a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod { \ 88a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod ASSERT_STATIC (_assertion); \ 89a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod ASSERT_INSTANCE_POD (*this); /* Make sure it's POD. */ \ 90a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod } 91a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod# define _DEFINE_INSTANCE_ASSERTION0(_line, _assertion) _DEFINE_INSTANCE_ASSERTION1 (_line, _assertion) 92a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod# define DEFINE_INSTANCE_ASSERTION(_assertion) _DEFINE_INSTANCE_ASSERTION0 (__LINE__, _assertion) 93a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod 94f679635893eebc13402c5ee51a6f106eed0c76beBehdad Esfahbod/* Check that _code compiles in a method environment */ 95a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod#define _DEFINE_COMPILES_ASSERTION1(_line, _code) \ 96a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod inline void _compiles_assertion_on_line_##_line (void) const \ 97f679635893eebc13402c5ee51a6f106eed0c76beBehdad Esfahbod { _code; } 98a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod# define _DEFINE_COMPILES_ASSERTION0(_line, _code) _DEFINE_COMPILES_ASSERTION1 (_line, _code) 99a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod# define DEFINE_COMPILES_ASSERTION(_code) _DEFINE_COMPILES_ASSERTION0 (__LINE__, _code) 1000abcc3b48cfd51a22695c9e988938b2f45cb19d8Behdad Esfahbod 1010abcc3b48cfd51a22695c9e988938b2f45cb19d8Behdad Esfahbod 102e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod#define DEFINE_SIZE_STATIC(size) \ 103a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size)); \ 104e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod static const unsigned int static_size = (size); \ 105e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod static const unsigned int min_size = (size) 106e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod 107b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod/* Size signifying variable-sized array */ 108b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod#define VAR 1 109b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod 110596e471aa5053d955fb5d5b5923088c8814469b1Behdad Esfahbod#define DEFINE_SIZE_UNION(size, _member) \ 111a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod DEFINE_INSTANCE_ASSERTION (this->u._member.static_size == (size)); \ 112596e471aa5053d955fb5d5b5923088c8814469b1Behdad Esfahbod static const unsigned int min_size = (size) 113596e471aa5053d955fb5d5b5923088c8814469b1Behdad Esfahbod 114bea34c7cbb583cf7660776e95cab3171590b8427Behdad Esfahbod#define DEFINE_SIZE_MIN(size) \ 115a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod DEFINE_INSTANCE_ASSERTION (sizeof (*this) >= (size)); \ 116b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod static const unsigned int min_size = (size) 117b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod 1180eb9fc6e37935707dba2bf4b3705de2161a08cb7Behdad Esfahbod#define DEFINE_SIZE_ARRAY(size, array) \ 119a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size) + sizeof (array[0])); \ 120a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod DEFINE_COMPILES_ASSERTION ((void) array[0].static_size) \ 121e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod static const unsigned int min_size = (size) 122e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod 1230eb9fc6e37935707dba2bf4b3705de2161a08cb7Behdad Esfahbod#define DEFINE_SIZE_ARRAY2(size, array1, array2) \ 124a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size) + sizeof (this->array1[0]) + sizeof (this->array2[0])); \ 125a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod DEFINE_COMPILES_ASSERTION ((void) array1[0].static_size; (void) array2[0].static_size) \ 126e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod static const unsigned int min_size = (size) 127e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod 128e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod 129e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod 130e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod/* 131f0abcd69408a3af65207cdf8847575ade4579bd4Behdad Esfahbod * Null objects 132600e5eb80f553ea8eb862e6784133574c74ca513Behdad Esfahbod */ 133600e5eb80f553ea8eb862e6784133574c74ca513Behdad Esfahbod 1348b8358033184198ff638ee1379093717596e162dBehdad Esfahbod/* Global nul-content Null pool. Enlarge as necessary. */ 1350bb0f5d41976ae27c5c7a51cbb82144b48315a4bBehdad Esfahbod/* TODO This really should be a extern HB_INTERNAL and defined somewhere... */ 136cf5585cfa6cac6fdf627a99941299e76af5ae0f7Behdad Esfahbodstatic const void *_NullPool[64 / sizeof (void *)]; 1378b8358033184198ff638ee1379093717596e162dBehdad Esfahbod 138d2c2ca8faf62fc380d4717d286556139a62d2356Behdad Esfahbod/* Generic nul-content Null objects. */ 1398b8358033184198ff638ee1379093717596e162dBehdad Esfahbodtemplate <typename Type> 1407f97d2cd904ea999c099c73c52187c5d65aeec67Behdad Esfahbodstatic inline const Type& Null (void) { 141ed07422c33bbb52ff4d79e65986171e3f07697d8Behdad Esfahbod ASSERT_STATIC (Type::min_size <= sizeof (_NullPool)); 142187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbod return *CastP<Type> (_NullPool); 1439d3677899f90abdc7fb3e3d854db654a8707a84bBehdad Esfahbod} 1448b8358033184198ff638ee1379093717596e162dBehdad Esfahbod 1458b8358033184198ff638ee1379093717596e162dBehdad Esfahbod/* Specializaiton for arbitrary-content arbitrary-sized Null objects. */ 14665f46b00333e20ab8a52a4b350747507541ec1dbBehdad Esfahbod#define DEFINE_NULL_DATA(Type, data) \ 14765f46b00333e20ab8a52a4b350747507541ec1dbBehdad Esfahbodstatic const char _Null##Type[Type::min_size + 1] = data; /* +1 is for nul-termination in data */ \ 1488b8358033184198ff638ee1379093717596e162dBehdad Esfahbodtemplate <> \ 1497f97d2cd904ea999c099c73c52187c5d65aeec67Behdad Esfahbodinline const Type& Null<Type> (void) { \ 150187454c595559ce48d072fee6bccb51f3de283d4Behdad Esfahbod return *CastP<Type> (_Null##Type); \ 151565c80bd2960366ace2d10dd71beaaf2a80213c8Behdad Esfahbod} /* The following line really exists such that we end in a place needing semicolon */ \ 152bea34c7cbb583cf7660776e95cab3171590b8427Behdad EsfahbodASSERT_STATIC (Type::min_size + 1 <= sizeof (_Null##Type)) 1538b8358033184198ff638ee1379093717596e162dBehdad Esfahbod 1548b8358033184198ff638ee1379093717596e162dBehdad Esfahbod/* Accessor macro. */ 1559d3677899f90abdc7fb3e3d854db654a8707a84bBehdad Esfahbod#define Null(Type) Null<Type>() 1568b8358033184198ff638ee1379093717596e162dBehdad Esfahbod 1578b8358033184198ff638ee1379093717596e162dBehdad Esfahbod 158600e5eb80f553ea8eb862e6784133574c74ca513Behdad Esfahbod 159577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod/* 160577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod * Sanitize 161577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod */ 162577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod 16395e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod#ifndef HB_DEBUG_SANITIZE 16411e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod#define HB_DEBUG_SANITIZE (HB_DEBUG+0) 16595e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod#endif 16695e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod 16720e3dd5d292b65f70d2eae63b8d8713a1c889d47Behdad Esfahbod 168bc200457430c083914a64bf4b056153506749610Behdad Esfahbod#define TRACE_SANITIZE() \ 1690ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod hb_auto_trace_t<HB_DEBUG_SANITIZE> trace (&c->debug_depth, "SANITIZE", this, HB_FUNC, ""); 170807c5b03a2251a3c29a520852639421783101b55Behdad Esfahbod 171b28815c1f6e46d38471cacbc31248ca6fda8c4d1Behdad Esfahbod 1721376fb7bf9ef07970f0ba13dc64d6a8ab8252762Behdad Esfahbodstruct hb_sanitize_context_t 173577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod{ 17431f18abecb149f8888a72510f2660328dd6de16dBehdad Esfahbod inline void init (hb_blob_t *b) 17598daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod { 17631f18abecb149f8888a72510f2660328dd6de16dBehdad Esfahbod this->blob = hb_blob_reference (b); 1771c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod this->writable = false; 1781c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod } 1791c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod 180cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod inline void start_processing (void) 1811c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod { 1824101ca7dbbdf1438fa116fb8cad935501ac7cca8Behdad Esfahbod this->start = hb_blob_get_data (this->blob, NULL); 1834101ca7dbbdf1438fa116fb8cad935501ac7cca8Behdad Esfahbod this->end = this->start + hb_blob_get_length (this->blob); 18498daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod this->edit_count = 0; 18520e3dd5d292b65f70d2eae63b8d8713a1c889d47Behdad Esfahbod this->debug_depth = 0; 186577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod 1871e08830b4fac3a60ae52349cab6e101d389d30cdBehdad Esfahbod DEBUG_MSG_LEVEL (SANITIZE, this->blob, 0, +1, 188cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod "start [%p..%p] (%lu bytes)", 1891e08830b4fac3a60ae52349cab6e101d389d30cdBehdad Esfahbod this->start, this->end, 1901e08830b4fac3a60ae52349cab6e101d389d30cdBehdad Esfahbod (unsigned long) (this->end - this->start)); 19198daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod } 1921376fb7bf9ef07970f0ba13dc64d6a8ab8252762Behdad Esfahbod 193cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod inline void end_processing (void) 19498daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod { 1951e08830b4fac3a60ae52349cab6e101d389d30cdBehdad Esfahbod DEBUG_MSG_LEVEL (SANITIZE, this->blob, 0, -1, 196cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod "end [%p..%p] %u edit requests", 1971e08830b4fac3a60ae52349cab6e101d389d30cdBehdad Esfahbod this->start, this->end, this->edit_count); 198577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod 19998daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod hb_blob_destroy (this->blob); 20098daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod this->blob = NULL; 20198daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod this->start = this->end = NULL; 20298daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod } 2034f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod 2044ad2cc5dec6b0639da2b1846282bdd99d06d5ff1Behdad Esfahbod inline bool check_range (const void *base, unsigned int len) const 20598daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod { 206a82ef7a893b773a17f7548375de9f588dfc83abaBehdad Esfahbod const char *p = (const char *) base; 20798daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod 208cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod hb_auto_trace_t<HB_DEBUG_SANITIZE> trace (&this->debug_depth, "SANITIZE", this->blob, NULL, 209cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod "check_range [%p..%p] (%d bytes) in [%p..%p]", 210cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod p, p + len, len, 211cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod this->start, this->end); 21298daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod 213cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod return TRACE_RETURN (likely (this->start <= p && p <= this->end && (unsigned int) (this->end - p) >= len)); 21498daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod } 215577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod 2161cd1e117d060d38e314618b627d7663cb01ed584Behdad Esfahbod inline bool check_array (const void *base, unsigned int record_size, unsigned int len) const 21798daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod { 218a82ef7a893b773a17f7548375de9f588dfc83abaBehdad Esfahbod const char *p = (const char *) base; 219080a0eb7d82d7195be72c16ece6e0a3ffed636b6Behdad Esfahbod bool overflows = _hb_unsigned_int_mul_overflows (len, record_size); 22041895506cb6a41b1a833866f8822261ea449ea0bBehdad Esfahbod 221cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod hb_auto_trace_t<HB_DEBUG_SANITIZE> trace (&this->debug_depth, "SANITIZE", this->blob, NULL, 222cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod "check_array [%p..%p] (%d*%d=%ld bytes) in [%p..%p]", 223cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod p, p + (record_size * len), record_size, len, (unsigned long) record_size * len, 224cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod this->start, this->end); 225fa030175ca998b00cc42cbced6e98de323ec01ecBehdad Esfahbod 226cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod return TRACE_RETURN (likely (!overflows && this->check_range (base, record_size * len))); 22798daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod } 228254933c397f1ce9796f59689a25f9fc2e58df4eaBehdad Esfahbod 229b157617644d1e38f680163889d1dc2e2f64d9ba3Behdad Esfahbod template <typename Type> 230b157617644d1e38f680163889d1dc2e2f64d9ba3Behdad Esfahbod inline bool check_struct (const Type *obj) const 231b157617644d1e38f680163889d1dc2e2f64d9ba3Behdad Esfahbod { 23254842374c2b291ef208c51ae1d853ec0403ccf84Behdad Esfahbod return likely (this->check_range (obj, obj->min_size)); 233b157617644d1e38f680163889d1dc2e2f64d9ba3Behdad Esfahbod } 234b157617644d1e38f680163889d1dc2e2f64d9ba3Behdad Esfahbod 235cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod inline bool may_edit (const void *base HB_UNUSED, unsigned int len HB_UNUSED) 23698daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod { 237a82ef7a893b773a17f7548375de9f588dfc83abaBehdad Esfahbod const char *p = (const char *) base; 23898daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod this->edit_count++; 23998daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod 240cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod hb_auto_trace_t<HB_DEBUG_SANITIZE> trace (&this->debug_depth, "SANITIZE", this->blob, NULL, 241cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod "may_edit(%u) [%p..%p] (%d bytes) in [%p..%p] -> %s", 242cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod this->edit_count, 243cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod p, p + len, len, 244cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod this->start, this->end); 24598daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod 246cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod return TRACE_RETURN (this->writable); 24798daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod } 24898daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod 249cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod mutable unsigned int debug_depth; 25098daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod const char *start, *end; 25198daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod bool writable; 25298daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod unsigned int edit_count; 25398daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod hb_blob_t *blob; 25498daaf183d6dbf2b68959da608cd9876ba55d7aaBehdad Esfahbod}; 255815a73e4202ca17677f12e862b70ca8724cf2f57Behdad Esfahbod 256577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod 257577c1116493d785d3455626612f97dabb383abf0Behdad Esfahbod 2584e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod/* Template to sanitize an object. */ 2594e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbodtemplate <typename Type> 2604e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbodstruct Sanitizer 2614e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod{ 2624e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod static hb_blob_t *sanitize (hb_blob_t *blob) { 263d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod hb_sanitize_context_t c[1] = {{0}}; 2644e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod bool sane; 2654e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod 266d0b657379bbe63602953412d6bc944b2a0f430ebBehdad Esfahbod /* TODO is_sane() stuff */ 2674e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod 2681c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod c->init (blob); 2691c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod 2704e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod retry: 271cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod DEBUG_MSG_FUNC (SANITIZE, blob, "start"); 2724f3ad9115a4161fc23fa559c26082440196217ecBehdad Esfahbod 273cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod c->start_processing (); 2744e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod 275d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod if (unlikely (!c->start)) { 276cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod c->end_processing (); 27748146e5612f6d272d6962f6829c6d64a31edef89Behdad Esfahbod return blob; 27848146e5612f6d272d6962f6829c6d64a31edef89Behdad Esfahbod } 27948146e5612f6d272d6962f6829c6d64a31edef89Behdad Esfahbod 280d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod Type *t = CastP<Type> (const_cast<char *> (c->start)); 2814e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod 282d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod sane = t->sanitize (c); 2834e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod if (sane) { 284d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod if (c->edit_count) { 285cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod DEBUG_MSG_FUNC (SANITIZE, blob, "passed first round with %d edits; going for second round", c->edit_count); 286fa030175ca998b00cc42cbced6e98de323ec01ecBehdad Esfahbod 2878b5346130425c7c101f6ff2432874ba2fd372edcBehdad Esfahbod /* sanitize again to ensure no toe-stepping */ 288d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod c->edit_count = 0; 289d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod sane = t->sanitize (c); 290d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod if (c->edit_count) { 291cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod DEBUG_MSG_FUNC (SANITIZE, blob, "requested %d edits in second round; FAILLING", c->edit_count); 2924e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod sane = false; 2934e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod } 2944e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod } 2954e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod } else { 296d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod unsigned int edit_count = c->edit_count; 2971c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod if (edit_count && !c->writable) { 2981c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod c->start = hb_blob_get_data_writable (blob, NULL); 2991c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod c->end = c->start + hb_blob_get_length (blob); 3001c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod 3011c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod if (c->start) { 3021c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod c->writable = true; 3031c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod /* ok, we made it writable by relocating. try again */ 304cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod DEBUG_MSG_FUNC (SANITIZE, blob, "retry"); 3051c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod goto retry; 3061c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod } 3074e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod } 3084e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod } 3094e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod 310cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod c->end_processing (); 3114101ca7dbbdf1438fa116fb8cad935501ac7cca8Behdad Esfahbod 312cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod DEBUG_MSG_FUNC (SANITIZE, blob, sane ? "PASSED" : "FAILED"); 3134e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod if (sane) 3144e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod return blob; 3154e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod else { 3164e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod hb_blob_destroy (blob); 3174911062d5be0d937ee8f1a70cc93e05d162f45b3Behdad Esfahbod return hb_blob_get_empty (); 3184e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod } 3194e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod } 320b435ab7e29c388e3b100f729957319931625a3a8Behdad Esfahbod 321b435ab7e29c388e3b100f729957319931625a3a8Behdad Esfahbod static const Type* lock_instance (hb_blob_t *blob) { 3221c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod hb_blob_make_immutable (blob); 3231c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod const char *base = hb_blob_get_data (blob, NULL); 324b435ab7e29c388e3b100f729957319931625a3a8Behdad Esfahbod return unlikely (!base) ? &Null(Type) : CastP<Type> (base); 325b435ab7e29c388e3b100f729957319931625a3a8Behdad Esfahbod } 3264e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod}; 3274e8a0602bb0b3cbf7f26cc38790e37cdec7b0b37Behdad Esfahbod 3282d15e72c75931398db5e027e660f1320bb979117Behdad Esfahbod 329f0abcd69408a3af65207cdf8847575ade4579bd4Behdad Esfahbod 330e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod/* 331e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod * Serialize 332e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod */ 333e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod 334e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod#ifndef HB_DEBUG_SERIALIZE 335e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod#define HB_DEBUG_SERIALIZE (HB_DEBUG+0) 336e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod#endif 337e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod 338e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod 339e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod#define TRACE_SERIALIZE() \ 3409f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod hb_auto_trace_t<HB_DEBUG_SERIALIZE> trace (&c->debug_depth, "SERIALIZE", c, HB_FUNC, ""); 341e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod 342e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod 343e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbodstruct hb_serialize_context_t 344e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod{ 345e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod inline void init (void *start, unsigned int size) 346e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod { 347e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod this->start = (char *) start; 348e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod this->end = this->start + size; 349e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod } 350e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod 351e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod inline void start_processing (void) 352e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod { 353e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod this->ran_out_of_room = false; 354e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod this->head = this->start; 355e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod this->debug_depth = 0; 356e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod 357e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod DEBUG_MSG_LEVEL (SERIALIZE, this->start, 0, +1, 358e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod "start [%p..%p] (%lu bytes)", 359e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod this->start, this->end, 360e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod (unsigned long) (this->end - this->start)); 361e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod } 362e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod 363e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod inline void end_processing (void) 364e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod { 365e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod DEBUG_MSG_LEVEL (SERIALIZE, this->start, 0, -1, 366e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod "end [%p..%p] %s", 367e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod this->start, this->end, 368e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod this->ran_out_of_room ? "RAN OUT OF ROOM" : "did not ran out of room"); 369e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod 370e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod this->start = this->end = this->head = NULL; 371e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod } 372e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod 373e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod template <typename Type> 374bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod inline Type *allocate_size (unsigned int size, unsigned int alignment = 1) 375e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod { 376bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod unsigned int padding = alignment < 2 ? 0 : (alignment - (this->head - this->start) % alignment) % alignment; 377e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod if (unlikely (this->ran_out_of_room || this->end - this->head > padding + size)) { 378e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod this->ran_out_of_room = true; 379e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod return NULL; 380e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod } 381bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod memset (this->head, 0, padding + size); 382e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod this->head += padding; 3839f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod char *ret = this->head; 384e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod this->head += size; 385e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod return reinterpret_cast<Type *> (ret); 386e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod } 387e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod 388e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod template <typename Type> 3899f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod inline Type *allocate_min (unsigned int alignment = 2) 3909f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod { 391bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod return this->allocate_size<Type> (Type::min_size, alignment); 3929f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod } 3939f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod 3949f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod template <typename Type> 395e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod inline Type *embed (const Type &obj, unsigned int alignment = 2) 396e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod { 397bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod unsigned int size = obj.get_size (); 398bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod Type *ret = this->allocate_size<Type> (size, alignment); 399bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod if (unlikely (!ret)) return NULL; 400bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod memcpy (ret, obj, size); 401bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod return ret; 4029f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod } 4039f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod 4049f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod template <typename Type> 405bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod inline Type *extend_min (Type &obj, unsigned int alignment = 2) 4069f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod { 407bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod unsigned int size = obj.min_size; 4089f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod assert (this->start < (char *) &obj && (char *) &obj <= this->head && (char *) &obj + size >= this->head); 409bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod this->allocate_size<Type> (((char *) &obj) + size - this->head, alignment); 4109f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod return reinterpret_cast<Type *> (&obj); 4119f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod } 4129f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod 4139f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod template <typename Type> 414bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod inline Type *extend (Type &obj, unsigned int alignment = 2) 4159f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod { 416bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod unsigned int size = obj.get_size (); 417bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod assert (this->start < (char *) &obj && (char *) &obj <= this->head && (char *) &obj + size >= this->head); 418bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod this->allocate_size<Type> (((char *) &obj) + size - this->head, alignment); 419bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod return reinterpret_cast<Type *> (&obj); 420e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod } 421e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod 422e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod inline void truncate (void *head) 423e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod { 424e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod assert (this->start < head && head <= this->head); 425e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod this->head = (char *) head; 426e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod } 427e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod 428e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod unsigned int debug_depth; 429e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod char *start, *end, *head; 430e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod bool ran_out_of_room; 431e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod}; 432e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod 433e901b954c6ec44ac3ae7fb3c326e6e7a40718e4bBehdad Esfahbod 434f0abcd69408a3af65207cdf8847575ade4579bd4Behdad Esfahbod 435b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod/* 436b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod * 437bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod * The OpenType Font File: Data Types 438b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod */ 439b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod 440b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod 441b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod/* "The following data types are used in the OpenType font file. 442b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod * All OpenType fonts use Motorola-style byte ordering (Big Endian):" */ 443b6e62bc5db76ae342177b2b646c37f45eccad975Behdad Esfahbod 4445f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod/* 4455f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod * Int types 4465f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod */ 4475f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod 4486b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod 449d7bf473ef222ab420456ff155ffaa09bacb3a394Behdad Esfahbodtemplate <typename Type, int Bytes> struct BEInt; 450e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod 451e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodtemplate <typename Type> 452d7bf473ef222ab420456ff155ffaa09bacb3a394Behdad Esfahbodstruct BEInt<Type, 2> 453e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod{ 454e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod public: 45581408cd51ce575891e79e6483be187130f864c28Behdad Esfahbod inline void set (Type i) { hb_be_uint16_put (v,i); } 4567f97d2cd904ea999c099c73c52187c5d65aeec67Behdad Esfahbod inline operator Type (void) const { return hb_be_uint16_get (v); } 457153142dac8dd9abaf164bb88af07c600c17fc3a1Behdad Esfahbod inline bool operator == (const BEInt<Type, 2>& o) const { return hb_be_uint16_eq (v, o.v); } 45801c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod inline bool operator != (const BEInt<Type, 2>& o) const { return !(*this == o); } 459e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod private: uint8_t v[2]; 460e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod}; 461e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodtemplate <typename Type> 462d7bf473ef222ab420456ff155ffaa09bacb3a394Behdad Esfahbodstruct BEInt<Type, 4> 463e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod{ 464e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod public: 46581408cd51ce575891e79e6483be187130f864c28Behdad Esfahbod inline void set (Type i) { hb_be_uint32_put (v,i); } 4667f97d2cd904ea999c099c73c52187c5d65aeec67Behdad Esfahbod inline operator Type (void) const { return hb_be_uint32_get (v); } 467153142dac8dd9abaf164bb88af07c600c17fc3a1Behdad Esfahbod inline bool operator == (const BEInt<Type, 4>& o) const { return hb_be_uint32_eq (v, o.v); } 46801c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod inline bool operator != (const BEInt<Type, 4>& o) const { return !(*this == o); } 469e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod private: uint8_t v[4]; 470e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod}; 471e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod 4722467c669c2aee4de2a6621a9d06cba0262376d41Behdad Esfahbod/* Integer types in big-endian order and no alignment requirement */ 473e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodtemplate <typename Type> 474e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodstruct IntType 475e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod{ 47681408cd51ce575891e79e6483be187130f864c28Behdad Esfahbod inline void set (Type i) { v.set (i); } 47701c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod inline operator Type(void) const { return v; } 47801c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod inline bool operator == (const IntType<Type> &o) const { return v == o.v; } 47901c01618e98283611628cd54d5ba4bf122f24cd9Behdad Esfahbod inline bool operator != (const IntType<Type> &o) const { return v != o.v; } 4804e573715ae5f5ed486ad66382bb44c47a86591ffBehdad Esfahbod inline int cmp (Type a) const { Type b = v; return a < b ? -1 : a == b ? 0 : +1; } 481d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod inline bool sanitize (hb_sanitize_context_t *c) { 482e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod TRACE_SANITIZE (); 4830ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod return TRACE_RETURN (likely (c->check_struct (this))); 484e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod } 485a82ef7a893b773a17f7548375de9f588dfc83abaBehdad Esfahbod protected: 486569da92bc6956f42d9b2d65c784e184fb6380efeBehdad Esfahbod BEInt<Type, sizeof (Type)> v; 487569da92bc6956f42d9b2d65c784e184fb6380efeBehdad Esfahbod public: 488e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod DEFINE_SIZE_STATIC (sizeof (Type)); 489e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod}; 490e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod 491e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodtypedef IntType<uint16_t> USHORT; /* 16-bit unsigned integer. */ 492e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodtypedef IntType<int16_t> SHORT; /* 16-bit signed integer. */ 493e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodtypedef IntType<uint32_t> ULONG; /* 32-bit unsigned integer. */ 494e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbodtypedef IntType<int32_t> LONG; /* 32-bit signed integer. */ 495e032ed9f75d4a0f365649a25706871bbb5ae6651Behdad Esfahbod 496ae9877dea6a1aed3566d9b87a75ede84259deacaBehdad Esfahbod/* 16-bit signed integer (SHORT) that describes a quantity in FUnits. */ 497ae9877dea6a1aed3566d9b87a75ede84259deacaBehdad Esfahbodtypedef SHORT FWORD; 498ae9877dea6a1aed3566d9b87a75ede84259deacaBehdad Esfahbod 499ae9877dea6a1aed3566d9b87a75ede84259deacaBehdad Esfahbod/* 16-bit unsigned integer (USHORT) that describes a quantity in FUnits. */ 500ae9877dea6a1aed3566d9b87a75ede84259deacaBehdad Esfahbodtypedef USHORT UFWORD; 501ae9877dea6a1aed3566d9b87a75ede84259deacaBehdad Esfahbod 502e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod/* Date represented in number of seconds since 12:00 midnight, January 1, 503e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod * 1904. The value is represented as a signed 64-bit integer. */ 504e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbodstruct LONGDATETIME 505e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod{ 506e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod inline bool sanitize (hb_sanitize_context_t *c) { 507e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod TRACE_SANITIZE (); 5080ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod return TRACE_RETURN (likely (c->check_struct (this))); 509e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod } 510e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod private: 511e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod LONG major; 512e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod ULONG minor; 513e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod public: 514e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod DEFINE_SIZE_STATIC (8); 515e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod}; 516e29caf3f943b2b6f4997f469f7274252c82f465eBehdad Esfahbod 5176b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod/* Array of four uint8s (length = 32 bits) used to identify a script, language 5186b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod * system, feature, or baseline */ 51920cc86b3592db33731de671f008d7d222776be49Behdad Esfahbodstruct Tag : ULONG 52060d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{ 521befc022affd2386b3f46cd7d11e4262f6c8bce9fBehdad Esfahbod /* What the char* converters return is NOT nul-terminated. Print using "%.4s" */ 522a82ef7a893b773a17f7548375de9f588dfc83abaBehdad Esfahbod inline operator const char* (void) const { return reinterpret_cast<const char *> (&this->v); } 523a82ef7a893b773a17f7548375de9f588dfc83abaBehdad Esfahbod inline operator char* (void) { return reinterpret_cast<char *> (&this->v); } 524b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod public: 525b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod DEFINE_SIZE_STATIC (4); 5266b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod}; 52765f46b00333e20ab8a52a4b350747507541ec1dbBehdad EsfahbodDEFINE_NULL_DATA (Tag, " "); 5286b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod 5296b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod/* Glyph index number, same as uint16 (length = 16 bits) */ 5306ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbodtypedef USHORT GlyphID; 5316b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod 532b5db4f1e4eefa266a71a28b5496f47ff9d1a81e8Behdad Esfahbod/* Script/language-system/feature index */ 533b5db4f1e4eefa266a71a28b5496f47ff9d1a81e8Behdad Esfahbodstruct Index : USHORT { 534b5db4f1e4eefa266a71a28b5496f47ff9d1a81e8Behdad Esfahbod static const unsigned int NOT_FOUND_INDEX = 0xFFFF; 535b5db4f1e4eefa266a71a28b5496f47ff9d1a81e8Behdad Esfahbod}; 536b5db4f1e4eefa266a71a28b5496f47ff9d1a81e8Behdad EsfahbodDEFINE_NULL_DATA (Index, "\xff\xff"); 537b5db4f1e4eefa266a71a28b5496f47ff9d1a81e8Behdad Esfahbod 5381f437e6f47fb6c15761021bd2078f31778f2179cBehdad Esfahbod/* Offset to a table, same as uint16 (length = 16 bits), Null offset = 0x0000 */ 5396ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbodtypedef USHORT Offset; 5406ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbod 5416ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbod/* LongOffset to a table, same as uint32 (length = 32 bits), Null offset = 0x00000000 */ 5426ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbodtypedef ULONG LongOffset; 5436ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbod 5446b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod 5456b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod/* CheckSum */ 54660d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbodstruct CheckSum : ULONG 54760d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{ 54860d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod static uint32_t CalcTableChecksum (ULONG *Table, uint32_t Length) 54960d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod { 5506b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod uint32_t Sum = 0L; 551e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod ULONG *EndPtr = Table+((Length+3) & ~3) / ULONG::static_size; 5526b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod 5536b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod while (Table < EndPtr) 5546b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod Sum += *Table++; 5556b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod return Sum; 5566b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod } 557b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod public: 558b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod DEFINE_SIZE_STATIC (4); 5596b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod}; 5606b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod 5616b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod 5626b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod/* 5636b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod * Version Numbers 5646b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod */ 5656b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod 56687fcdcbe3644da10154688765db2d62eb9ac079aBehdad Esfahbodstruct FixedVersion 56760d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{ 5684f28fbdd804fabeec57a98fe267d892ab58b3a6dBehdad Esfahbod inline uint32_t to_int (void) const { return (major << 16) + minor; } 56996908b898476ca5d7da5f386b15be76f9e83d76eBehdad Esfahbod 570d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod inline bool sanitize (hb_sanitize_context_t *c) { 5713e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod TRACE_SANITIZE (); 5720ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod return TRACE_RETURN (c->check_struct (this)); 573cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod } 574cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod 5756ad8d5f3c7028147b371137ae4bca6aae66b3489Behdad Esfahbod USHORT major; 57687fcdcbe3644da10154688765db2d62eb9ac079aBehdad Esfahbod USHORT minor; 577b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod public: 578b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod DEFINE_SIZE_STATIC (4); 5796b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod}; 5806b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod 58192b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 58292b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 5835f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod/* 58492b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod * Template subclasses of Offset and LongOffset that do the dereferencing. 585f0abcd69408a3af65207cdf8847575ade4579bd4Behdad Esfahbod * Use: (base+offset) 5865f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod */ 5875f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod 58892b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename OffsetType, typename Type> 58992b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct GenericOffsetTo : OffsetType 59092b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod{ 59100e23fcc6fd0eee5c582251bf3de6a2703fbbd3eBehdad Esfahbod inline const Type& operator () (const void *base) const 59292b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod { 59392b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod unsigned int offset = *this; 59464d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod if (unlikely (!offset)) return Null(Type); 59509766b1ec5ec55a61edbcd7a89ed3613cc92d4cbBehdad Esfahbod return StructAtOffset<Type> (base, offset); 59692b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod } 597bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod inline Type& operator () (void *base) 598bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod { 599bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod unsigned int offset = *this; 600bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod return StructAtOffset<Type> (base, offset); 601bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod } 602bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod 603bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod inline void set_offset (void *base, void *obj) 604bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod { 605bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod this->set ((char *) obj - (char *) base); 606bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbod } 60792b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 608d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod inline bool sanitize (hb_sanitize_context_t *c, void *base) { 6093e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod TRACE_SANITIZE (); 6100ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod if (unlikely (!c->check_struct (this))) return TRACE_RETURN (false); 61192b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod unsigned int offset = *this; 6120ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod if (unlikely (!offset)) return TRACE_RETURN (true); 61309766b1ec5ec55a61edbcd7a89ed3613cc92d4cbBehdad Esfahbod Type &obj = StructAtOffset<Type> (base, offset); 6140ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod return TRACE_RETURN (likely (obj.sanitize (c)) || neuter (c)); 61592b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod } 6164a446ac35136eff23d55f47bdd7b40095ad707abBehdad Esfahbod template <typename T> 617d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod inline bool sanitize (hb_sanitize_context_t *c, void *base, T user_data) { 6183e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod TRACE_SANITIZE (); 6190ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod if (unlikely (!c->check_struct (this))) return TRACE_RETURN (false); 62042b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod unsigned int offset = *this; 6210ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod if (unlikely (!offset)) return TRACE_RETURN (true); 62209766b1ec5ec55a61edbcd7a89ed3613cc92d4cbBehdad Esfahbod Type &obj = StructAtOffset<Type> (base, offset); 6230ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod return TRACE_RETURN (likely (obj.sanitize (c, user_data)) || neuter (c)); 624c9f14687a30866181feb57ee2736a147ec9f25a1Behdad Esfahbod } 625c9f14687a30866181feb57ee2736a147ec9f25a1Behdad Esfahbod 626c9f14687a30866181feb57ee2736a147ec9f25a1Behdad Esfahbod private: 627c9f14687a30866181feb57ee2736a147ec9f25a1Behdad Esfahbod /* Set the offset to Null */ 628d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod inline bool neuter (hb_sanitize_context_t *c) { 629cf26e88a5ab477295479f5b9450c2019b6430eaaBehdad Esfahbod if (c->may_edit (this, this->static_size)) { 630c9f14687a30866181feb57ee2736a147ec9f25a1Behdad Esfahbod this->set (0); /* 0 is Null offset */ 631c9f14687a30866181feb57ee2736a147ec9f25a1Behdad Esfahbod return true; 632c9f14687a30866181feb57ee2736a147ec9f25a1Behdad Esfahbod } 633c9f14687a30866181feb57ee2736a147ec9f25a1Behdad Esfahbod return false; 63442b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod } 63592b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod}; 63692b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Base, typename OffsetType, typename Type> 637bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbodinline const Type& operator + (const Base &base, const GenericOffsetTo<OffsetType, Type> &offset) { return offset (base); } 638bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbodtemplate <typename Base, typename OffsetType, typename Type> 639bc5be24014371ceb811b9ffd37062ede63d87bb1Behdad Esfahbodinline Type& operator + (Base &base, GenericOffsetTo<OffsetType, Type> &offset) { return offset (base); } 64092b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 6415f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbodtemplate <typename Type> 64292b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct OffsetTo : GenericOffsetTo<Offset, Type> {}; 64392b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 64492b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Type> 64592b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct LongOffsetTo : GenericOffsetTo<LongOffset, Type> {}; 646bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod 647bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod 64892b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod/* 64992b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod * Array Types 65092b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod */ 65192b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 65292b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename LenType, typename Type> 65392b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct GenericArrayOf 65460d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{ 6554f5f1c34dda1e0629bfa6d7b0ffa2e1ce003b7c7Behdad Esfahbod const Type *sub_array (unsigned int start_offset, unsigned int *pcount /* IN/OUT */) const 65648de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod { 65748de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod unsigned int count = len; 65864d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod if (unlikely (start_offset > count)) 65948de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod count = 0; 66048de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod else 66148de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod count -= start_offset; 66248de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod count = MIN (count, *pcount); 66348de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod *pcount = count; 664b961518b9611471ff7060e97686e5625974847ebBehdad Esfahbod return array + start_offset; 66548de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod } 66648de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod 66760d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod inline const Type& operator [] (unsigned int i) const 66860d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod { 66964d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod if (unlikely (i >= len)) return Null(Type); 670b961518b9611471ff7060e97686e5625974847ebBehdad Esfahbod return array[i]; 6715f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod } 6729f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod inline Type& operator [] (unsigned int i) 6739f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod { 6749f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod return array[i]; 6759f2348de58f0f85593027378169bc03c4dd64e59Behdad Esfahbod } 6767f97d2cd904ea999c099c73c52187c5d65aeec67Behdad Esfahbod inline unsigned int get_size (void) const 677e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod { return len.static_size + len * Type::static_size; } 678e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod 679d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod inline bool sanitize (hb_sanitize_context_t *c) { 6803e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod TRACE_SANITIZE (); 6810ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false); 68211e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod 68340d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod /* Note: for structs that do not reference other structs, 68440d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod * we do not need to call their sanitize() as we already did 68511e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod * a bound check on the aggregate array size. We just include 68611e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod * a small unreachable expression to make sure the structs 68711e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod * pointed to do have a simple sanitize(), ie. they do not 68811e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod * reference other structs via offsets. 68940d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod */ 69011e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod (void) (false && array[0].sanitize (c)); 69111e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod 6920ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod return TRACE_RETURN (true); 69370de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod } 694d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod inline bool sanitize (hb_sanitize_context_t *c, void *base) { 6953e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod TRACE_SANITIZE (); 6960ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false); 697e6ab2c59ba2d37942ac5fcbfe61d38b7e359ac8cBehdad Esfahbod unsigned int count = len; 698e6ab2c59ba2d37942ac5fcbfe61d38b7e359ac8cBehdad Esfahbod for (unsigned int i = 0; i < count; i++) 699d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod if (unlikely (!array[i].sanitize (c, base))) 7000ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod return TRACE_RETURN (false); 7010ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod return TRACE_RETURN (true); 702e6ab2c59ba2d37942ac5fcbfe61d38b7e359ac8cBehdad Esfahbod } 7034a446ac35136eff23d55f47bdd7b40095ad707abBehdad Esfahbod template <typename T> 704d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod inline bool sanitize (hb_sanitize_context_t *c, void *base, T user_data) { 7053e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod TRACE_SANITIZE (); 7060ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false); 70742b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod unsigned int count = len; 70842b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod for (unsigned int i = 0; i < count; i++) 709d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod if (unlikely (!array[i].sanitize (c, base, user_data))) 7100ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod return TRACE_RETURN (false); 7110ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod return TRACE_RETURN (true); 71242b778f89e0818fe06910ce04e2203485823da09Behdad Esfahbod } 71370de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod 71430fa2821c277df99a14089749313dfe2b541e2d0Behdad Esfahbod private: 715d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod inline bool sanitize_shallow (hb_sanitize_context_t *c) { 71630fa2821c277df99a14089749313dfe2b541e2d0Behdad Esfahbod TRACE_SANITIZE (); 7170ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod return TRACE_RETURN (c->check_struct (this) && c->check_array (this, Type::static_size, len)); 71830fa2821c277df99a14089749313dfe2b541e2d0Behdad Esfahbod } 71930fa2821c277df99a14089749313dfe2b541e2d0Behdad Esfahbod 72030fa2821c277df99a14089749313dfe2b541e2d0Behdad Esfahbod public: 72192b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod LenType len; 722b961518b9611471ff7060e97686e5625974847ebBehdad Esfahbod Type array[VAR]; 723b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod public: 7240eb9fc6e37935707dba2bf4b3705de2161a08cb7Behdad Esfahbod DEFINE_SIZE_ARRAY (sizeof (LenType), array); 725e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod}; 726e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod 72792b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod/* An array with a USHORT number of elements. */ 72892b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Type> 72992b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct ArrayOf : GenericArrayOf<USHORT, Type> {}; 73092b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 73192b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod/* An array with a ULONG number of elements. */ 73292b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Type> 73392b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct LongArrayOf : GenericArrayOf<ULONG, Type> {}; 73492b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 73592b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod/* Array of Offset's */ 73692b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Type> 73792b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct OffsetArrayOf : ArrayOf<OffsetTo<Type> > {}; 73892b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 73992b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod/* Array of LongOffset's */ 74092b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Type> 74192b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct LongOffsetArrayOf : ArrayOf<LongOffsetTo<Type> > {}; 74292b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 74392b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod/* LongArray of LongOffset's */ 74492b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodtemplate <typename Type> 74592b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbodstruct LongOffsetLongArrayOf : LongArrayOf<LongOffsetTo<Type> > {}; 74692b5dd8e71e1bdeaa6e86a53f167683a3f5f4289Behdad Esfahbod 74780e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod/* Array of offsets relative to the beginning of the array itself. */ 74880e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbodtemplate <typename Type> 74980e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbodstruct OffsetListOf : OffsetArrayOf<Type> 75080e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod{ 75180e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod inline const Type& operator [] (unsigned int i) const 75280e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod { 75364d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod if (unlikely (i >= this->len)) return Null(Type); 754b961518b9611471ff7060e97686e5625974847ebBehdad Esfahbod return this+this->array[i]; 75580e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod } 75680e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod 757d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod inline bool sanitize (hb_sanitize_context_t *c) { 7583e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod TRACE_SANITIZE (); 7590ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod return TRACE_RETURN (OffsetArrayOf<Type>::sanitize (c, this)); 76080e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod } 7614a446ac35136eff23d55f47bdd7b40095ad707abBehdad Esfahbod template <typename T> 762d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod inline bool sanitize (hb_sanitize_context_t *c, T user_data) { 7633e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod TRACE_SANITIZE (); 7640ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod return TRACE_RETURN (OffsetArrayOf<Type>::sanitize (c, this, user_data)); 76580e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod } 76680e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod}; 76780e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod 76880e2aa2e1bfa2c8ecedcfa4cce8cadeb15792ac3Behdad Esfahbod 769e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod/* An array with a USHORT number of elements, 770e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod * starting at second element. */ 771e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbodtemplate <typename Type> 77260d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbodstruct HeadlessArrayOf 77360d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{ 77460d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod inline const Type& operator [] (unsigned int i) const 77560d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod { 77664d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod if (unlikely (i >= len || !i)) return Null(Type); 777b961518b9611471ff7060e97686e5625974847ebBehdad Esfahbod return array[i-1]; 778e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod } 7797f97d2cd904ea999c099c73c52187c5d65aeec67Behdad Esfahbod inline unsigned int get_size (void) const 780e45d3f86f9a5f3d29ca35a282de7f98e702878f9Behdad Esfahbod { return len.static_size + (len ? len - 1 : 0) * Type::static_size; } 7815f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod 782d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod inline bool sanitize_shallow (hb_sanitize_context_t *c) { 783d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod return c->check_struct (this) 784d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod && c->check_array (this, Type::static_size, len); 785e5546a4352c54311ac4a9ef138b187378155ebe1Behdad Esfahbod } 786e5546a4352c54311ac4a9ef138b187378155ebe1Behdad Esfahbod 787d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod inline bool sanitize (hb_sanitize_context_t *c) { 7883e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod TRACE_SANITIZE (); 7890ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false); 79011e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod 79140d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod /* Note: for structs that do not reference other structs, 79240d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod * we do not need to call their sanitize() as we already did 79311e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod * a bound check on the aggregate array size. We just include 79411e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod * a small unreachable expression to make sure the structs 79511e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod * pointed to do have a simple sanitize(), ie. they do not 79611e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod * reference other structs via offsets. 79740d73bc68dd828cf68f90fde0f9499a6ce9fbb19Behdad Esfahbod */ 79811e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod (void) (false && array[0].sanitize (c)); 79911e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod 8000ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod return TRACE_RETURN (true); 80170de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod } 80270de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod 8035f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod USHORT len; 804b961518b9611471ff7060e97686e5625974847ebBehdad Esfahbod Type array[VAR]; 805ed07422c33bbb52ff4d79e65986171e3f07697d8Behdad Esfahbod public: 8060eb9fc6e37935707dba2bf4b3705de2161a08cb7Behdad Esfahbod DEFINE_SIZE_ARRAY (sizeof (USHORT), array); 8075f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod}; 8085f810363acc3ad3cba631a68620e3d37e54c95c4Behdad Esfahbod 8096b4ce01da121e12e1c78ad7eaedf469f35f3568dBehdad Esfahbod 810cc8a4abea68f2dba26feb5785f9e518e6853c744Behdad Esfahbod/* An array with sorted elements. Supports binary searching. */ 811cc8a4abea68f2dba26feb5785f9e518e6853c744Behdad Esfahbodtemplate <typename Type> 812cc8a4abea68f2dba26feb5785f9e518e6853c744Behdad Esfahbodstruct SortedArrayOf : ArrayOf<Type> { 813cc8a4abea68f2dba26feb5785f9e518e6853c744Behdad Esfahbod 814cc8a4abea68f2dba26feb5785f9e518e6853c744Behdad Esfahbod template <typename SearchType> 815cc8a4abea68f2dba26feb5785f9e518e6853c744Behdad Esfahbod inline int search (const SearchType &x) const { 81699159e52a3c9d5ae6c0fbdec64e7ed684fa70b61Behdad Esfahbod unsigned int count = this->len; 81799159e52a3c9d5ae6c0fbdec64e7ed684fa70b61Behdad Esfahbod /* Linear search is *much* faster for small counts. */ 81899159e52a3c9d5ae6c0fbdec64e7ed684fa70b61Behdad Esfahbod if (likely (count < 32)) { 81999159e52a3c9d5ae6c0fbdec64e7ed684fa70b61Behdad Esfahbod for (unsigned int i = 0; i < count; i++) 82099159e52a3c9d5ae6c0fbdec64e7ed684fa70b61Behdad Esfahbod if (this->array[i].cmp (x) == 0) 82199159e52a3c9d5ae6c0fbdec64e7ed684fa70b61Behdad Esfahbod return i; 82299159e52a3c9d5ae6c0fbdec64e7ed684fa70b61Behdad Esfahbod return -1; 82399159e52a3c9d5ae6c0fbdec64e7ed684fa70b61Behdad Esfahbod } else { 82499159e52a3c9d5ae6c0fbdec64e7ed684fa70b61Behdad Esfahbod struct Cmp { 82599159e52a3c9d5ae6c0fbdec64e7ed684fa70b61Behdad Esfahbod static int cmp (const SearchType *a, const Type *b) { return b->cmp (*a); } 82699159e52a3c9d5ae6c0fbdec64e7ed684fa70b61Behdad Esfahbod }; 82799159e52a3c9d5ae6c0fbdec64e7ed684fa70b61Behdad Esfahbod const Type *p = (const Type *) bsearch (&x, this->array, this->len, sizeof (this->array[0]), (hb_compare_func_t) Cmp::cmp); 82899159e52a3c9d5ae6c0fbdec64e7ed684fa70b61Behdad Esfahbod return p ? p - this->array : -1; 82999159e52a3c9d5ae6c0fbdec64e7ed684fa70b61Behdad Esfahbod } 830cc8a4abea68f2dba26feb5785f9e518e6853c744Behdad Esfahbod } 831cc8a4abea68f2dba26feb5785f9e518e6853c744Behdad Esfahbod}; 832cc8a4abea68f2dba26feb5785f9e518e6853c744Behdad Esfahbod 833cc8a4abea68f2dba26feb5785f9e518e6853c744Behdad Esfahbod 8347c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod} // namespace OT 8357c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod 836acdba3f90b232fc12fcb200dca2584481b339118Behdad Esfahbod 8371e91434569a9e9535ef021ca52b60b2e2af75d19Behdad Esfahbod#endif /* HB_OPEN_TYPE_PRIVATE_HH */ 838