hb-open-type-private.hh revision 5821806d5e7f356e8fa4b058a389a808ea183019
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright © 2007,2008,2009,2010  Red Hat, Inc.
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright © 2012  Google, Inc.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  This is part of HarfBuzz, a text shaping library.
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Permission is hereby granted, without written agreement and without
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * license or royalty fees, to use, copy, modify, and distribute this
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * software and its documentation for any purpose, provided that the
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * above copyright notice and the following two paragraphs appear in
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * all copies of this software.
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * DAMAGE.
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Red Hat Author(s): Behdad Esfahbod
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Google Author(s): Behdad Esfahbod
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef HB_OPEN_TYPE_PRIVATE_HH
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define HB_OPEN_TYPE_PRIVATE_HH
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "hb-private.hh"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "hb-blob.h"
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace OT {
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Casts
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Cast to struct T, reference to reference */
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename Type, typename TObject>
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline const Type& CastR(const TObject &X)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ return reinterpret_cast<const Type&> (X); }
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename Type, typename TObject>
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Type& CastR(TObject &X)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ return reinterpret_cast<Type&> (X); }
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Cast to struct T, pointer to pointer */
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename Type, typename TObject>
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline const Type* CastP(const TObject *X)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ return reinterpret_cast<const Type*> (X); }
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename Type, typename TObject>
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Type* CastP(TObject *X)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ return reinterpret_cast<Type*> (X); }
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* StructAtOffset<T>(P,Ofs) returns the struct T& that is placed at memory
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * location pointed to by P plus Ofs bytes. */
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename Type>
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline const Type& StructAtOffset(const void *P, unsigned int offset)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ return * reinterpret_cast<const Type*> ((const char *) P + offset); }
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename Type>
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Type& StructAtOffset(void *P, unsigned int offset)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ return * reinterpret_cast<Type*> ((char *) P + offset); }
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* StructAfter<T>(X) returns the struct T& that is placed after X.
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Works with X of variable size also.  X must implement get_size() */
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename Type, typename TObject>
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline const Type& StructAfter(const TObject &X)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ return StructAtOffset<Type>(&X, X.get_size()); }
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename Type, typename TObject>
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Type& StructAfter(TObject &X)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ return StructAtOffset<Type>(&X, X.get_size()); }
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Size checking
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Check _assertion in a method environment */
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define _DEFINE_INSTANCE_ASSERTION1(_line, _assertion) \
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void _instance_assertion_on_line_##_line (void) const \
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { \
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_STATIC (_assertion); \
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_INSTANCE_POD (*this); /* Make sure it's POD. */ \
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define _DEFINE_INSTANCE_ASSERTION0(_line, _assertion) _DEFINE_INSTANCE_ASSERTION1 (_line, _assertion)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define DEFINE_INSTANCE_ASSERTION(_assertion) _DEFINE_INSTANCE_ASSERTION0 (__LINE__, _assertion)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Check that _code compiles in a method environment */
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define _DEFINE_COMPILES_ASSERTION1(_line, _code) \
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void _compiles_assertion_on_line_##_line (void) const \
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { _code; }
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define _DEFINE_COMPILES_ASSERTION0(_line, _code) _DEFINE_COMPILES_ASSERTION1 (_line, _code)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define DEFINE_COMPILES_ASSERTION(_code) _DEFINE_COMPILES_ASSERTION0 (__LINE__, _code)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define DEFINE_SIZE_STATIC(size) \
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size)); \
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const unsigned int static_size = (size); \
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const unsigned int min_size = (size)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Size signifying variable-sized array */
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define VAR 1
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define DEFINE_SIZE_UNION(size, _member) \
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_INSTANCE_ASSERTION (this->u._member.static_size == (size)); \
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const unsigned int min_size = (size)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define DEFINE_SIZE_MIN(size) \
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_INSTANCE_ASSERTION (sizeof (*this) >= (size)); \
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const unsigned int min_size = (size)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define DEFINE_SIZE_ARRAY(size, array) \
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size) + sizeof (array[0])); \
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_COMPILES_ASSERTION ((void) array[0].static_size) \
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const unsigned int min_size = (size)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define DEFINE_SIZE_ARRAY2(size, array1, array2) \
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size) + sizeof (this->array1[0]) + sizeof (this->array2[0])); \
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_COMPILES_ASSERTION ((void) array1[0].static_size; (void) array2[0].static_size) \
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const unsigned int min_size = (size)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Null objects
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Global nul-content Null pool.  Enlarge as necessary. */
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* TODO This really should be a extern HB_INTERNAL and defined somewhere... */
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const void *_NullPool[64 / sizeof (void *)];
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Generic nul-content Null objects. */
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename Type>
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline const Type& Null (void) {
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_STATIC (Type::min_size <= sizeof (_NullPool));
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return *CastP<Type> (_NullPool);
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Specializaiton for arbitrary-content arbitrary-sized Null objects. */
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define DEFINE_NULL_DATA(Type, data) \
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const char _Null##Type[Type::min_size + 1] = data; /* +1 is for nul-termination in data */ \
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <> \
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline const Type& Null<Type> (void) { \
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return *CastP<Type> (_Null##Type); \
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} /* The following line really exists such that we end in a place needing semicolon */ \
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ASSERT_STATIC (Type::min_size + 1 <= sizeof (_Null##Type))
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Accessor macro. */
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define Null(Type) Null<Type>()
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Sanitize
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef HB_DEBUG_SANITIZE
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define HB_DEBUG_SANITIZE (HB_DEBUG+0)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TRACE_SANITIZE() \
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	hb_auto_trace_t<HB_DEBUG_SANITIZE> trace (&c->debug_depth, "SANITIZE", this, HB_FUNC, "");
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct hb_sanitize_context_t
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void init (hb_blob_t *b)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this->blob = hb_blob_reference (b);
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this->writable = false;
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void start_processing (void)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this->start = hb_blob_get_data (this->blob, NULL);
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this->end = this->start + hb_blob_get_length (this->blob);
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this->edit_count = 0;
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this->debug_depth = 0;
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DEBUG_MSG_LEVEL (SANITIZE, this->blob, 0, +1,
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     "start [%p..%p] (%lu bytes)",
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     this->start, this->end,
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     (unsigned long) (this->end - this->start));
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void end_processing (void)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DEBUG_MSG_LEVEL (SANITIZE, this->blob, 0, -1,
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     "end [%p..%p] %u edit requests",
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     this->start, this->end, this->edit_count);
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    hb_blob_destroy (this->blob);
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this->blob = NULL;
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this->start = this->end = NULL;
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool check_range (const void *base, unsigned int len) const
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char *p = (const char *) base;
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    hb_auto_trace_t<HB_DEBUG_SANITIZE> trace (&this->debug_depth, "SANITIZE", this->blob, NULL,
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					      "check_range [%p..%p] (%d bytes) in [%p..%p]",
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					      p, p + len, len,
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					      this->start, this->end);
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (likely (this->start <= p && p <= this->end && (unsigned int) (this->end - p) >= len));
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool check_array (const void *base, unsigned int record_size, unsigned int len) const
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char *p = (const char *) base;
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool overflows = _hb_unsigned_int_mul_overflows (len, record_size);
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    hb_auto_trace_t<HB_DEBUG_SANITIZE> trace (&this->debug_depth, "SANITIZE", this->blob, NULL,
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					      "check_array [%p..%p] (%d*%d=%ld bytes) in [%p..%p]",
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					      p, p + (record_size * len), record_size, len, (unsigned long) record_size * len,
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					      this->start, this->end);
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (likely (!overflows && this->check_range (base, record_size * len)));
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename Type>
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool check_struct (const Type *obj) const
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return likely (this->check_range (obj, obj->min_size));
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool may_edit (const void *base HB_UNUSED, unsigned int len HB_UNUSED)
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char *p = (const char *) base;
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this->edit_count++;
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    hb_auto_trace_t<HB_DEBUG_SANITIZE> trace (&this->debug_depth, "SANITIZE", this->blob, NULL,
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					      "may_edit(%u) [%p..%p] (%d bytes) in [%p..%p] -> %s",
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					      this->edit_count,
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					      p, p + len, len,
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					      this->start, this->end);
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (this->writable);
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mutable unsigned int debug_depth;
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char *start, *end;
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool writable;
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int edit_count;
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hb_blob_t *blob;
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Template to sanitize an object. */
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename Type>
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct Sanitizer
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static hb_blob_t *sanitize (hb_blob_t *blob) {
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    hb_sanitize_context_t c[1] = {{0}};
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool sane;
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* TODO is_sane() stuff */
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    c->init (blob);
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  retry:
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DEBUG_MSG_FUNC (SANITIZE, blob, "start");
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    c->start_processing ();
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!c->start)) {
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      c->end_processing ();
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return blob;
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Type *t = CastP<Type> (const_cast<char *> (c->start));
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sane = t->sanitize (c);
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (sane) {
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (c->edit_count) {
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	DEBUG_MSG_FUNC (SANITIZE, blob, "passed first round with %d edits; going for second round", c->edit_count);
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        /* sanitize again to ensure no toe-stepping */
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        c->edit_count = 0;
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	sane = t->sanitize (c);
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (c->edit_count) {
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	  DEBUG_MSG_FUNC (SANITIZE, blob, "requested %d edits in second round; FAILLING", c->edit_count);
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	  sane = false;
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      unsigned int edit_count = c->edit_count;
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (edit_count && !c->writable) {
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        c->start = hb_blob_get_data_writable (blob, NULL);
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	c->end = c->start + hb_blob_get_length (blob);
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (c->start) {
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	  c->writable = true;
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	  /* ok, we made it writable by relocating.  try again */
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	  DEBUG_MSG_FUNC (SANITIZE, blob, "retry");
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	  goto retry;
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    c->end_processing ();
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DEBUG_MSG_FUNC (SANITIZE, blob, sane ? "PASSED" : "FAILED");
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (sane)
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return blob;
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else {
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      hb_blob_destroy (blob);
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return hb_blob_get_empty ();
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const Type* lock_instance (hb_blob_t *blob) {
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    hb_blob_make_immutable (blob);
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char *base = hb_blob_get_data (blob, NULL);
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return unlikely (!base) ? &Null(Type) : CastP<Type> (base);
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Serialize
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef HB_DEBUG_SERIALIZE
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define HB_DEBUG_SERIALIZE (HB_DEBUG+0)
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TRACE_SERIALIZE() \
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	hb_auto_trace_t<HB_DEBUG_SERIALIZE> trace (&c->debug_depth, "SERIALIZE", c, HB_FUNC, "");
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct hb_serialize_context_t
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline hb_serialize_context_t (void *start, unsigned int size)
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this->start = (char *) start;
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this->end = this->start + size;
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this->ran_out_of_room = false;
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this->head = this->start;
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this->debug_depth = 0;
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename Type>
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline Type *start_serialize (void)
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DEBUG_MSG_LEVEL (SERIALIZE, this->start, 0, +1,
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     "start [%p..%p] (%lu bytes)",
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     this->start, this->end,
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     (unsigned long) (this->end - this->start));
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return start_embed<Type> ();
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void end_serialize (void)
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DEBUG_MSG_LEVEL (SERIALIZE, this->start, 0, -1,
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     "end [%p..%p] serialized %d bytes; %s",
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     this->start, this->end,
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     (int) (this->head - this->start),
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     this->ran_out_of_room ? "RAN OUT OF ROOM" : "did not ran out of room");
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename Type>
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline Type *copy (void)
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert (!this->ran_out_of_room);
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int len = this->head - this->start;
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void *p = malloc (len);
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (p)
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      memcpy (p, this->start, len);
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return reinterpret_cast<Type *> (p);
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename Type>
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline Type *allocate_size (unsigned int size)
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (this->ran_out_of_room || this->end - this->head < size)) {
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      this->ran_out_of_room = true;
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return NULL;
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memset (this->head, 0, size);
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    char *ret = this->head;
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this->head += size;
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return reinterpret_cast<Type *> (ret);
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename Type>
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline Type *allocate_min (void)
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return this->allocate_size<Type> (Type::min_size);
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename Type>
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline Type *start_embed (void)
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Type *ret = reinterpret_cast<Type *> (this->head);
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ret;
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename Type>
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline Type *embed (const Type &obj)
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int size = obj.get_size ();
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Type *ret = this->allocate_size<Type> (size);
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!ret)) return NULL;
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memcpy (ret, obj, size);
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ret;
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename Type>
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline Type *extend_min (Type &obj)
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int size = obj.min_size;
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert (this->start <= (char *) &obj && (char *) &obj <= this->head && (char *) &obj + size >= this->head);
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!this->allocate_size<Type> (((char *) &obj) + size - this->head))) return NULL;
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return reinterpret_cast<Type *> (&obj);
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename Type>
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline Type *extend (Type &obj)
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int size = obj.get_size ();
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert (this->start < (char *) &obj && (char *) &obj <= this->head && (char *) &obj + size >= this->head);
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!this->allocate_size<Type> (((char *) &obj) + size - this->head))) return NULL;
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return reinterpret_cast<Type *> (&obj);
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void truncate (void *head)
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert (this->start < head && head <= this->head);
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this->head = (char *) head;
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int debug_depth;
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char *start, *end, *head;
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ran_out_of_room;
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename Type>
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct Supplier
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline Supplier (const Type *array, unsigned int len_)
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    head = array;
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    len = len_;
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline const Type operator [] (unsigned int i) const
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (i >= len)) return Type ();
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return head[i];
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void advance (unsigned int count)
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (count > len))
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      count = len;
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    len -= count;
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    head += count;
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  private:
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline Supplier (const Supplier<Type> &); /* Disallow copy */
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline Supplier<Type>& operator= (const Supplier<Type> &); /* Disallow copy */
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int len;
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const Type *head;
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The OpenType Font File: Data Types
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* "The following data types are used in the OpenType font file.
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  All OpenType fonts use Motorola-style byte ordering (Big Endian):" */
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Int types
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename Type, int Bytes> struct BEInt;
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename Type>
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct BEInt<Type, 2>
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void set (Type i) { hb_be_uint16_put (v,i); }
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline operator Type (void) const { return hb_be_uint16_get (v); }
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool operator == (const BEInt<Type, 2>& o) const { return hb_be_uint16_eq (v, o.v); }
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool operator != (const BEInt<Type, 2>& o) const { return !(*this == o); }
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  private: uint8_t v[2];
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename Type>
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct BEInt<Type, 4>
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void set (Type i) { hb_be_uint32_put (v,i); }
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline operator Type (void) const { return hb_be_uint32_get (v); }
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool operator == (const BEInt<Type, 4>& o) const { return hb_be_uint32_eq (v, o.v); }
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool operator != (const BEInt<Type, 4>& o) const { return !(*this == o); }
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  private: uint8_t v[4];
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Integer types in big-endian order and no alignment requirement */
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename Type>
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct IntType
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void set (Type i) { v.set (i); }
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline operator Type(void) const { return v; }
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool operator == (const IntType<Type> &o) const { return v == o.v; }
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool operator != (const IntType<Type> &o) const { return v != o.v; }
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static inline int cmp (const IntType<Type> *a, const IntType<Type> *b) { return b->cmp (*a); }
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline int cmp (IntType<Type> va) const { Type a = va; Type b = v; return a < b ? -1 : a == b ? 0 : +1; }
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline int cmp (Type a) const { Type b = v; return a < b ? -1 : a == b ? 0 : +1; }
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c) {
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TRACE_SANITIZE ();
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (likely (c->check_struct (this)));
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  protected:
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BEInt<Type, sizeof (Type)> v;
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_SIZE_STATIC (sizeof (Type));
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef IntType<uint16_t> USHORT;	/* 16-bit unsigned integer. */
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef IntType<int16_t>  SHORT;	/* 16-bit signed integer. */
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef IntType<uint32_t> ULONG;	/* 32-bit unsigned integer. */
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef IntType<int32_t>  LONG;		/* 32-bit signed integer. */
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 16-bit signed integer (SHORT) that describes a quantity in FUnits. */
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef SHORT FWORD;
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 16-bit unsigned integer (USHORT) that describes a quantity in FUnits. */
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef USHORT UFWORD;
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Date represented in number of seconds since 12:00 midnight, January 1,
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 1904. The value is represented as a signed 64-bit integer. */
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct LONGDATETIME
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c) {
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TRACE_SANITIZE ();
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (likely (c->check_struct (this)));
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  private:
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LONG major;
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ULONG minor;
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_SIZE_STATIC (8);
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Array of four uint8s (length = 32 bits) used to identify a script, language
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * system, feature, or baseline */
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct Tag : ULONG
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* What the char* converters return is NOT nul-terminated.  Print using "%.4s" */
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline operator const char* (void) const { return reinterpret_cast<const char *> (&this->v); }
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline operator char* (void) { return reinterpret_cast<char *> (&this->v); }
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_SIZE_STATIC (4);
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DEFINE_NULL_DATA (Tag, "    ");
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Glyph index number, same as uint16 (length = 16 bits) */
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef USHORT GlyphID;
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Script/language-system/feature index */
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct Index : USHORT {
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const unsigned int NOT_FOUND_INDEX = 0xFFFF;
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DEFINE_NULL_DATA (Index, "\xff\xff");
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Offset to a table, same as uint16 (length = 16 bits), Null offset = 0x0000 */
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef USHORT Offset;
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* LongOffset to a table, same as uint32 (length = 32 bits), Null offset = 0x00000000 */
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef ULONG LongOffset;
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* CheckSum */
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct CheckSum : ULONG
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static uint32_t CalcTableChecksum (ULONG *Table, uint32_t Length)
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32_t Sum = 0L;
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ULONG *EndPtr = Table+((Length+3) & ~3) / ULONG::static_size;
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (Table < EndPtr)
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Sum += *Table++;
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return Sum;
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_SIZE_STATIC (4);
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Version Numbers
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct FixedVersion
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline uint32_t to_int (void) const { return (major << 16) + minor; }
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c) {
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TRACE_SANITIZE ();
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (c->check_struct (this));
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  USHORT major;
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  USHORT minor;
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_SIZE_STATIC (4);
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Template subclasses of Offset and LongOffset that do the dereferencing.
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Use: (base+offset)
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename OffsetType, typename Type>
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct GenericOffsetTo : OffsetType
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline const Type& operator () (const void *base) const
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int offset = *this;
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!offset)) return Null(Type);
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return StructAtOffset<Type> (base, offset);
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline Type& operator () (void *base)
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int offset = *this;
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return StructAtOffset<Type> (base, offset);
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline Type& serialize (hb_serialize_context_t *c, void *base)
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Type *t = c->start_embed<Type> ();
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this->set ((char *) t - (char *) base); /* TODO(serialize) Overflow? */
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return *t;
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c, void *base) {
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TRACE_SANITIZE ();
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!c->check_struct (this))) return TRACE_RETURN (false);
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int offset = *this;
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!offset)) return TRACE_RETURN (true);
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Type &obj = StructAtOffset<Type> (base, offset);
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (likely (obj.sanitize (c)) || neuter (c));
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename T>
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c, void *base, T user_data) {
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TRACE_SANITIZE ();
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!c->check_struct (this))) return TRACE_RETURN (false);
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int offset = *this;
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!offset)) return TRACE_RETURN (true);
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Type &obj = StructAtOffset<Type> (base, offset);
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (likely (obj.sanitize (c, user_data)) || neuter (c));
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  private:
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Set the offset to Null */
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool neuter (hb_sanitize_context_t *c) {
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (c->may_edit (this, this->static_size)) {
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      this->set (0); /* 0 is Null offset */
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename Base, typename OffsetType, typename Type>
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline const Type& operator + (const Base &base, const GenericOffsetTo<OffsetType, Type> &offset) { return offset (base); }
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename Base, typename OffsetType, typename Type>
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Type& operator + (Base &base, GenericOffsetTo<OffsetType, Type> &offset) { return offset (base); }
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename Type>
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct OffsetTo : GenericOffsetTo<Offset, Type> {};
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename Type>
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct LongOffsetTo : GenericOffsetTo<LongOffset, Type> {};
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Array Types
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename LenType, typename Type>
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct GenericArrayOf
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const Type *sub_array (unsigned int start_offset, unsigned int *pcount /* IN/OUT */) const
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int count = len;
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (start_offset > count))
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      count = 0;
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      count -= start_offset;
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    count = MIN (count, *pcount);
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *pcount = count;
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return array + start_offset;
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline const Type& operator [] (unsigned int i) const
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (i >= len)) return Null(Type);
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return array[i];
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline Type& operator [] (unsigned int i)
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return array[i];
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline unsigned int get_size (void) const
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { return len.static_size + len * Type::static_size; }
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool serialize (hb_serialize_context_t *c,
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			 unsigned int items_len)
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TRACE_SERIALIZE ();
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    len.set (items_len); /* TODO(serialize) Overflow? */
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!c->extend (*this))) return TRACE_RETURN (false);
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (true);
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool serialize (hb_serialize_context_t *c,
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			 Supplier<Type> &items,
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			 unsigned int items_len)
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TRACE_SERIALIZE ();
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!serialize (c, items_len))) return TRACE_RETURN (false);
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int i = 0; i < items_len; i++)
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      array[i] = items[i];
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    items.advance (items_len);
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (true);
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c) {
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TRACE_SANITIZE ();
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false);
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Note: for structs that do not reference other structs,
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * we do not need to call their sanitize() as we already did
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * a bound check on the aggregate array size.  We just include
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * a small unreachable expression to make sure the structs
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * pointed to do have a simple sanitize(), ie. they do not
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * reference other structs via offsets.
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (void) (false && array[0].sanitize (c));
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (true);
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c, void *base) {
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TRACE_SANITIZE ();
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false);
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int count = len;
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int i = 0; i < count; i++)
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (unlikely (!array[i].sanitize (c, base)))
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return TRACE_RETURN (false);
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (true);
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename T>
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c, void *base, T user_data) {
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TRACE_SANITIZE ();
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false);
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int count = len;
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int i = 0; i < count; i++)
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (unlikely (!array[i].sanitize (c, base, user_data)))
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return TRACE_RETURN (false);
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (true);
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  private:
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize_shallow (hb_sanitize_context_t *c) {
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TRACE_SANITIZE ();
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (c->check_struct (this) && c->check_array (this, Type::static_size, len));
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LenType len;
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Type array[VAR];
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_SIZE_ARRAY (sizeof (LenType), array);
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* An array with a USHORT number of elements. */
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename Type>
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct ArrayOf : GenericArrayOf<USHORT, Type> {};
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* An array with a ULONG number of elements. */
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename Type>
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct LongArrayOf : GenericArrayOf<ULONG, Type> {};
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Array of Offset's */
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename Type>
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct OffsetArrayOf : ArrayOf<OffsetTo<Type> > {};
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Array of LongOffset's */
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename Type>
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct LongOffsetArrayOf : ArrayOf<LongOffsetTo<Type> > {};
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* LongArray of LongOffset's */
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename Type>
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct LongOffsetLongArrayOf : LongArrayOf<LongOffsetTo<Type> > {};
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Array of offsets relative to the beginning of the array itself. */
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename Type>
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct OffsetListOf : OffsetArrayOf<Type>
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline const Type& operator [] (unsigned int i) const
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (i >= this->len)) return Null(Type);
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return this+this->array[i];
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c) {
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TRACE_SANITIZE ();
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (OffsetArrayOf<Type>::sanitize (c, this));
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename T>
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c, T user_data) {
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TRACE_SANITIZE ();
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (OffsetArrayOf<Type>::sanitize (c, this, user_data));
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* An array with a USHORT number of elements,
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * starting at second element. */
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename Type>
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct HeadlessArrayOf
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline const Type& operator [] (unsigned int i) const
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (i >= len || !i)) return Null(Type);
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return array[i-1];
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline unsigned int get_size (void) const
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { return len.static_size + (len ? len - 1 : 0) * Type::static_size; }
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool serialize (hb_serialize_context_t *c,
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			 Supplier<Type> &items,
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			 unsigned int items_len)
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TRACE_SERIALIZE ();
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    len.set (items_len); /* TODO(serialize) Overflow? */
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!items_len)) return TRACE_RETURN (true);
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!c->extend (*this))) return TRACE_RETURN (false);
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int i = 0; i < items_len - 1; i++)
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      array[i] = items[i];
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    items.advance (items_len - 1);
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (true);
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize_shallow (hb_sanitize_context_t *c) {
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return c->check_struct (this)
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	&& c->check_array (this, Type::static_size, len);
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c) {
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TRACE_SANITIZE ();
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false);
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Note: for structs that do not reference other structs,
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * we do not need to call their sanitize() as we already did
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * a bound check on the aggregate array size.  We just include
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * a small unreachable expression to make sure the structs
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * pointed to do have a simple sanitize(), ie. they do not
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * reference other structs via offsets.
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (void) (false && array[0].sanitize (c));
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (true);
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  USHORT len;
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Type array[VAR];
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_SIZE_ARRAY (sizeof (USHORT), array);
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* An array with sorted elements.  Supports binary searching. */
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename Type>
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct SortedArrayOf : ArrayOf<Type> {
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename SearchType>
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline int search (const SearchType &x) const {
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int count = this->len;
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Linear search is *much* faster for small counts. */
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (likely (count < 32)) {
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (unsigned int i = 0; i < count; i++)
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (this->array[i].cmp (x) == 0)
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	  return i;
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return -1;
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      struct Cmp {
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	static int cmp (const SearchType *a, const Type *b) { return b->cmp (*a); }
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      };
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const Type *p = (const Type *) bsearch (&x, this->array, this->len, sizeof (this->array[0]), (hb_compare_func_t) Cmp::cmp);
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return p ? p - this->array : -1;
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace OT
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* HB_OPEN_TYPE_PRIVATE_HH */
929