hb-open-type-private.hh revision f2477e01787aa58f445919b809d89e252beef54f
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)
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Casts
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Cast to struct T, reference to reference */
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename Type, typename TObject>
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline const Type& CastR(const TObject &X)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ return reinterpret_cast<const Type&> (X); }
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename Type, typename TObject>
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Type& CastR(TObject &X)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ return reinterpret_cast<Type&> (X); }
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Cast to struct T, pointer to pointer */
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename Type, typename TObject>
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline const Type* CastP(const TObject *X)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ return reinterpret_cast<const Type*> (X); }
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename Type, typename TObject>
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Type* CastP(TObject *X)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ return reinterpret_cast<Type*> (X); }
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* StructAtOffset<T>(P,Ofs) returns the struct T& that is placed at memory
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * location pointed to by P plus Ofs bytes. */
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename Type>
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline const Type& StructAtOffset(const void *P, unsigned int offset)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ return * reinterpret_cast<const Type*> ((const char *) P + offset); }
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename Type>
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Type& StructAtOffset(void *P, unsigned int offset)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ return * reinterpret_cast<Type*> ((char *) P + offset); }
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* StructAfter<T>(X) returns the struct T& that is placed after X.
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Works with X of variable size also.  X must implement get_size() */
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename Type, typename TObject>
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline const Type& StructAfter(const TObject &X)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ return StructAtOffset<Type>(&X, X.get_size()); }
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename Type, typename TObject>
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Type& StructAfter(TObject &X)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ return StructAtOffset<Type>(&X, X.get_size()); }
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Size checking
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Check _assertion in a method environment */
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define _DEFINE_INSTANCE_ASSERTION1(_line, _assertion) \
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void _instance_assertion_on_line_##_line (void) const \
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { \
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_STATIC (_assertion); \
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_INSTANCE_POD (*this); /* Make sure it's POD. */ \
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define _DEFINE_INSTANCE_ASSERTION0(_line, _assertion) _DEFINE_INSTANCE_ASSERTION1 (_line, _assertion)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define DEFINE_INSTANCE_ASSERTION(_assertion) _DEFINE_INSTANCE_ASSERTION0 (__LINE__, _assertion)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Check that _code compiles in a method environment */
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define _DEFINE_COMPILES_ASSERTION1(_line, _code) \
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void _compiles_assertion_on_line_##_line (void) const \
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { _code; }
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define _DEFINE_COMPILES_ASSERTION0(_line, _code) _DEFINE_COMPILES_ASSERTION1 (_line, _code)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define DEFINE_COMPILES_ASSERTION(_code) _DEFINE_COMPILES_ASSERTION0 (__LINE__, _code)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define DEFINE_SIZE_STATIC(size) \
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size)); \
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const unsigned int static_size = (size); \
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const unsigned int min_size = (size)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Size signifying variable-sized array */
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define VAR 1
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define DEFINE_SIZE_UNION(size, _member) \
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_INSTANCE_ASSERTION (this->u._member.static_size == (size)); \
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const unsigned int min_size = (size)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define DEFINE_SIZE_MIN(size) \
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_INSTANCE_ASSERTION (sizeof (*this) >= (size)); \
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const unsigned int min_size = (size)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define DEFINE_SIZE_ARRAY(size, array) \
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size) + sizeof (array[0])); \
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_COMPILES_ASSERTION ((void) array[0].static_size) \
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const unsigned int min_size = (size)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define DEFINE_SIZE_ARRAY2(size, array1, array2) \
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size) + sizeof (this->array1[0]) + sizeof (this->array2[0])); \
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_COMPILES_ASSERTION ((void) array1[0].static_size; (void) array2[0].static_size) \
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const unsigned int min_size = (size)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Null objects
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Global nul-content Null pool.  Enlarge as necessary. */
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* TODO This really should be a extern HB_INTERNAL and defined somewhere... */
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const void *_NullPool[64 / sizeof (void *)];
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Generic nul-content Null objects. */
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename Type>
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline const Type& Null (void) {
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_STATIC (sizeof (Type) <= sizeof (_NullPool));
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return *CastP<Type> (_NullPool);
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Specializaiton for arbitrary-content arbitrary-sized Null objects. */
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define DEFINE_NULL_DATA(Type, data) \
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static const char _Null##Type[sizeof (Type) + 1] = data; /* +1 is for nul-termination in data */ \
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <> \
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline const Type& Null<Type> (void) { \
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return *CastP<Type> (_Null##Type); \
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} /* The following line really exists such that we end in a place needing semicolon */ \
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ASSERT_STATIC (Type::min_size + 1 <= sizeof (_Null##Type))
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Accessor macro. */
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define Null(Type) Null<Type>()
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Sanitize
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef HB_DEBUG_SANITIZE
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define HB_DEBUG_SANITIZE (HB_DEBUG+0)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define TRACE_SANITIZE(this) \
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	hb_auto_trace_t<HB_DEBUG_SANITIZE, bool> trace \
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	(&c->debug_depth, c->get_name (), this, HB_FUNC, \
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	 "");
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/* This limits sanitizing time on really broken fonts. */
175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#ifndef HB_SANITIZE_MAX_EDITS
176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#define HB_SANITIZE_MAX_EDITS 100
177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct hb_sanitize_context_t
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline const char *get_name (void) { return "SANITIZE"; }
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static const unsigned int max_debug_depth = HB_DEBUG_SANITIZE;
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  typedef bool return_t;
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  template <typename T>
185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  inline return_t dispatch (const T &obj) { return obj.sanitize (this); }
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static return_t default_return_value (void) { return true; }
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool stop_sublookup_iteration (const return_t r HB_UNUSED) const { return false; }
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void init (hb_blob_t *b)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this->blob = hb_blob_reference (b);
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this->writable = false;
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void start_processing (void)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this->start = hb_blob_get_data (this->blob, NULL);
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this->end = this->start + hb_blob_get_length (this->blob);
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this->edit_count = 0;
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this->debug_depth = 0;
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DEBUG_MSG_LEVEL (SANITIZE, this->blob, 0, +1,
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     "start [%p..%p] (%lu bytes)",
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     this->start, this->end,
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     (unsigned long) (this->end - this->start));
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void end_processing (void)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DEBUG_MSG_LEVEL (SANITIZE, this->blob, 0, -1,
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     "end [%p..%p] %u edit requests",
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     this->start, this->end, this->edit_count);
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    hb_blob_destroy (this->blob);
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this->blob = NULL;
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this->start = this->end = NULL;
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool check_range (const void *base, unsigned int len) const
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char *p = (const char *) base;
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    hb_auto_trace_t<HB_DEBUG_SANITIZE, bool> trace
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      (&this->debug_depth, "SANITIZE", this->blob, NULL,
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       "check_range [%p..%p] (%d bytes) in [%p..%p]",
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       p, p + len, len,
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       this->start, this->end);
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (likely (this->start <= p && p <= this->end && (unsigned int) (this->end - p) >= len));
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool check_array (const void *base, unsigned int record_size, unsigned int len) const
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char *p = (const char *) base;
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool overflows = _hb_unsigned_int_mul_overflows (len, record_size);
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    hb_auto_trace_t<HB_DEBUG_SANITIZE, bool> trace
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      (&this->debug_depth, "SANITIZE", this->blob, NULL,
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       "check_array [%p..%p] (%d*%d=%ld bytes) in [%p..%p]",
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       p, p + (record_size * len), record_size, len, (unsigned long) record_size * len,
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       this->start, this->end);
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (likely (!overflows && this->check_range (base, record_size * len)));
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename Type>
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool check_struct (const Type *obj) const
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return likely (this->check_range (obj, obj->min_size));
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool may_edit (const void *base HB_UNUSED, unsigned int len HB_UNUSED)
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
254c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (this->edit_count >= HB_SANITIZE_MAX_EDITS)
255c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return false;
256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char *p = (const char *) base;
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this->edit_count++;
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    hb_auto_trace_t<HB_DEBUG_SANITIZE, bool> trace
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      (&this->debug_depth, "SANITIZE", this->blob, NULL,
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       "may_edit(%u) [%p..%p] (%d bytes) in [%p..%p] -> %s",
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       this->edit_count,
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       p, p + len, len,
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       this->start, this->end,
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       this->writable ? "GRANTED" : "DENIED");
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (this->writable);
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mutable unsigned int debug_depth;
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char *start, *end;
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool writable;
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int edit_count;
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hb_blob_t *blob;
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Template to sanitize an object. */
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename Type>
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct Sanitizer
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static hb_blob_t *sanitize (hb_blob_t *blob) {
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    hb_sanitize_context_t c[1] = {{0}};
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool sane;
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* TODO is_sane() stuff */
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    c->init (blob);
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  retry:
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DEBUG_MSG_FUNC (SANITIZE, blob, "start");
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    c->start_processing ();
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!c->start)) {
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      c->end_processing ();
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return blob;
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Type *t = CastP<Type> (const_cast<char *> (c->start));
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sane = t->sanitize (c);
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (sane) {
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (c->edit_count) {
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	DEBUG_MSG_FUNC (SANITIZE, blob, "passed first round with %d edits; going for second round", c->edit_count);
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        /* sanitize again to ensure no toe-stepping */
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        c->edit_count = 0;
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	sane = t->sanitize (c);
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (c->edit_count) {
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	  DEBUG_MSG_FUNC (SANITIZE, blob, "requested %d edits in second round; FAILLING", c->edit_count);
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	  sane = false;
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      unsigned int edit_count = c->edit_count;
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (edit_count && !c->writable) {
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        c->start = hb_blob_get_data_writable (blob, NULL);
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	c->end = c->start + hb_blob_get_length (blob);
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (c->start) {
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	  c->writable = true;
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	  /* ok, we made it writable by relocating.  try again */
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	  DEBUG_MSG_FUNC (SANITIZE, blob, "retry");
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	  goto retry;
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    c->end_processing ();
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DEBUG_MSG_FUNC (SANITIZE, blob, sane ? "PASSED" : "FAILED");
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (sane)
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return blob;
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else {
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      hb_blob_destroy (blob);
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return hb_blob_get_empty ();
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const Type* lock_instance (hb_blob_t *blob) {
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    hb_blob_make_immutable (blob);
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char *base = hb_blob_get_data (blob, NULL);
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return unlikely (!base) ? &Null(Type) : CastP<Type> (base);
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Serialize
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef HB_DEBUG_SERIALIZE
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define HB_DEBUG_SERIALIZE (HB_DEBUG+0)
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define TRACE_SERIALIZE(this) \
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	hb_auto_trace_t<HB_DEBUG_SERIALIZE, bool> trace \
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	(&c->debug_depth, "SERIALIZE", c, HB_FUNC, \
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	 "");
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct hb_serialize_context_t
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline hb_serialize_context_t (void *start, unsigned int size)
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this->start = (char *) start;
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this->end = this->start + size;
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this->ran_out_of_room = false;
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this->head = this->start;
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this->debug_depth = 0;
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename Type>
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline Type *start_serialize (void)
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DEBUG_MSG_LEVEL (SERIALIZE, this->start, 0, +1,
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     "start [%p..%p] (%lu bytes)",
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     this->start, this->end,
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     (unsigned long) (this->end - this->start));
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return start_embed<Type> ();
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void end_serialize (void)
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DEBUG_MSG_LEVEL (SERIALIZE, this->start, 0, -1,
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     "end [%p..%p] serialized %d bytes; %s",
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     this->start, this->end,
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     (int) (this->head - this->start),
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     this->ran_out_of_room ? "RAN OUT OF ROOM" : "did not ran out of room");
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename Type>
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline Type *copy (void)
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert (!this->ran_out_of_room);
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int len = this->head - this->start;
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void *p = malloc (len);
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (p)
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      memcpy (p, this->start, len);
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return reinterpret_cast<Type *> (p);
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename Type>
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline Type *allocate_size (unsigned int size)
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
414c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (unlikely (this->ran_out_of_room || this->end - this->head < ptrdiff_t (size))) {
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      this->ran_out_of_room = true;
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return NULL;
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memset (this->head, 0, size);
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    char *ret = this->head;
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this->head += size;
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return reinterpret_cast<Type *> (ret);
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename Type>
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline Type *allocate_min (void)
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return this->allocate_size<Type> (Type::min_size);
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename Type>
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline Type *start_embed (void)
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Type *ret = reinterpret_cast<Type *> (this->head);
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ret;
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename Type>
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline Type *embed (const Type &obj)
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int size = obj.get_size ();
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Type *ret = this->allocate_size<Type> (size);
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!ret)) return NULL;
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memcpy (ret, obj, size);
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ret;
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename Type>
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline Type *extend_min (Type &obj)
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int size = obj.min_size;
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert (this->start <= (char *) &obj && (char *) &obj <= this->head && (char *) &obj + size >= this->head);
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!this->allocate_size<Type> (((char *) &obj) + size - this->head))) return NULL;
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return reinterpret_cast<Type *> (&obj);
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename Type>
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline Type *extend (Type &obj)
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int size = obj.get_size ();
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert (this->start < (char *) &obj && (char *) &obj <= this->head && (char *) &obj + size >= this->head);
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!this->allocate_size<Type> (((char *) &obj) + size - this->head))) return NULL;
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return reinterpret_cast<Type *> (&obj);
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void truncate (void *head)
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert (this->start < head && head <= this->head);
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this->head = (char *) head;
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int debug_depth;
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char *start, *end, *head;
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ran_out_of_room;
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename Type>
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct Supplier
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline Supplier (const Type *array, unsigned int len_)
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    head = array;
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    len = len_;
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline const Type operator [] (unsigned int i) const
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (i >= len)) return Type ();
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return head[i];
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void advance (unsigned int count)
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (count > len))
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      count = len;
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    len -= count;
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    head += count;
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  private:
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline Supplier (const Supplier<Type> &); /* Disallow copy */
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline Supplier<Type>& operator= (const Supplier<Type> &); /* Disallow copy */
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int len;
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const Type *head;
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The OpenType Font File: Data Types
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* "The following data types are used in the OpenType font file.
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  All OpenType fonts use Motorola-style byte ordering (Big Endian):" */
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Int types
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename Type, int Bytes> struct BEInt;
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename Type>
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct BEInt<Type, 2>
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void set (Type i) { hb_be_uint16_put (v,i); }
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline operator Type (void) const { return hb_be_uint16_get (v); }
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool operator == (const BEInt<Type, 2>& o) const { return hb_be_uint16_eq (v, o.v); }
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool operator != (const BEInt<Type, 2>& o) const { return !(*this == o); }
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  private: uint8_t v[2];
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename Type>
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct BEInt<Type, 4>
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void set (Type i) { hb_be_uint32_put (v,i); }
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline operator Type (void) const { return hb_be_uint32_get (v); }
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool operator == (const BEInt<Type, 4>& o) const { return hb_be_uint32_eq (v, o.v); }
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool operator != (const BEInt<Type, 4>& o) const { return !(*this == o); }
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  private: uint8_t v[4];
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
5452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)template <typename Type>
5462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct BEInt<Type, 3>
5472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
5482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  public:
5492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline void set (Type i) { hb_be_uint24_put (v,i); }
5502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline operator Type (void) const { return hb_be_uint24_get (v); }
5512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline bool operator == (const BEInt<Type, 3>& o) const { return hb_be_uint24_eq (v, o.v); }
5522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline bool operator != (const BEInt<Type, 3>& o) const { return !(*this == o); }
5532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  private: uint8_t v[3];
5542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Integer types in big-endian order and no alignment requirement */
5572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)template <typename Type, unsigned int Size>
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct IntType
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void set (Type i) { v.set (i); }
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline operator Type(void) const { return v; }
5622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline bool operator == (const IntType<Type,Size> &o) const { return v == o.v; }
5632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline bool operator != (const IntType<Type,Size> &o) const { return v != o.v; }
5642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static inline int cmp (const IntType<Type,Size> *a, const IntType<Type,Size> *b) { return b->cmp (*a); }
5652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline int cmp (IntType<Type,Size> va) const { Type a = va; Type b = v; return a < b ? -1 : a == b ? 0 : +1; }
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline int cmp (Type a) const { Type b = v; return a < b ? -1 : a == b ? 0 : +1; }
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c) {
5682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (likely (c->check_struct (this)));
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  protected:
5722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  BEInt<Type, Size> v;
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
5742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DEFINE_SIZE_STATIC (Size);
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)typedef IntType<uint16_t, 2> USHORT;	/* 16-bit unsigned integer. */
5782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)typedef IntType<int16_t,  2> SHORT;	/* 16-bit signed integer. */
5792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)typedef IntType<uint32_t, 4> ULONG;	/* 32-bit unsigned integer. */
5802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)typedef IntType<int32_t,  4> LONG;	/* 32-bit signed integer. */
5812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)typedef IntType<uint32_t, 3> UINT24;	/* 24-bit unsigned integer. */
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 16-bit signed integer (SHORT) that describes a quantity in FUnits. */
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef SHORT FWORD;
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 16-bit unsigned integer (USHORT) that describes a quantity in FUnits. */
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef USHORT UFWORD;
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Date represented in number of seconds since 12:00 midnight, January 1,
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 1904. The value is represented as a signed 64-bit integer. */
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct LONGDATETIME
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c) {
5942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (likely (c->check_struct (this)));
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  private:
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LONG major;
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ULONG minor;
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_SIZE_STATIC (8);
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Array of four uint8s (length = 32 bits) used to identify a script, language
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * system, feature, or baseline */
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct Tag : ULONG
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* What the char* converters return is NOT nul-terminated.  Print using "%.4s" */
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline operator const char* (void) const { return reinterpret_cast<const char *> (&this->v); }
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline operator char* (void) { return reinterpret_cast<char *> (&this->v); }
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_SIZE_STATIC (4);
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DEFINE_NULL_DATA (Tag, "    ");
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Glyph index number, same as uint16 (length = 16 bits) */
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef USHORT GlyphID;
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Script/language-system/feature index */
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct Index : USHORT {
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const unsigned int NOT_FOUND_INDEX = 0xFFFF;
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DEFINE_NULL_DATA (Index, "\xff\xff");
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Offset to a table, same as uint16 (length = 16 bits), Null offset = 0x0000 */
626c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)struct Offset : USHORT
627c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles){
628c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  inline bool is_null (void) const { return 0 == *this; }
629c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  public:
630c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DEFINE_SIZE_STATIC (2);
631c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* LongOffset to a table, same as uint32 (length = 32 bits), Null offset = 0x00000000 */
634c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)struct LongOffset : ULONG
635c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles){
636c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  inline bool is_null (void) const { return 0 == *this; }
637c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  public:
638c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DEFINE_SIZE_STATIC (4);
639c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* CheckSum */
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct CheckSum : ULONG
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
645f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  /* This is reference implementation from the spec. */
646f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  static inline uint32_t CalcTableChecksum (const ULONG *Table, uint32_t Length)
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32_t Sum = 0L;
649f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const ULONG *EndPtr = Table+((Length+3) & ~3) / ULONG::static_size;
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (Table < EndPtr)
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Sum += *Table++;
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return Sum;
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
655f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
656f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  /* Note: data should be 4byte aligned and have 4byte padding at the end. */
657f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  inline void set_for_data (const void *data, unsigned int length)
658f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  { set (CalcTableChecksum ((const ULONG *) data, length)); }
659f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_SIZE_STATIC (4);
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Version Numbers
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct FixedVersion
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline uint32_t to_int (void) const { return (major << 16) + minor; }
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c) {
6742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (c->check_struct (this));
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  USHORT major;
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  USHORT minor;
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_SIZE_STATIC (4);
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Template subclasses of Offset and LongOffset that do the dereferencing.
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Use: (base+offset)
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename OffsetType, typename Type>
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct GenericOffsetTo : OffsetType
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline const Type& operator () (const void *base) const
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int offset = *this;
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!offset)) return Null(Type);
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return StructAtOffset<Type> (base, offset);
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline Type& serialize (hb_serialize_context_t *c, void *base)
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Type *t = c->start_embed<Type> ();
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this->set ((char *) t - (char *) base); /* TODO(serialize) Overflow? */
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return *t;
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c, void *base) {
7092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!c->check_struct (this))) return TRACE_RETURN (false);
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int offset = *this;
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!offset)) return TRACE_RETURN (true);
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Type &obj = StructAtOffset<Type> (base, offset);
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (likely (obj.sanitize (c)) || neuter (c));
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename T>
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c, void *base, T user_data) {
7182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!c->check_struct (this))) return TRACE_RETURN (false);
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int offset = *this;
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!offset)) return TRACE_RETURN (true);
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Type &obj = StructAtOffset<Type> (base, offset);
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (likely (obj.sanitize (c, user_data)) || neuter (c));
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline bool try_set (hb_sanitize_context_t *c, const OffsetType &v) {
7272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (c->may_edit (this, this->static_size)) {
7282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      this->set (v);
7292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return true;
7302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
7312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
7322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Set the offset to Null */
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool neuter (hb_sanitize_context_t *c) {
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (c->may_edit (this, this->static_size)) {
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      this->set (0); /* 0 is Null offset */
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename Base, typename OffsetType, typename Type>
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline const Type& operator + (const Base &base, const GenericOffsetTo<OffsetType, Type> &offset) { return offset (base); }
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename Base, typename OffsetType, typename Type>
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Type& operator + (Base &base, GenericOffsetTo<OffsetType, Type> &offset) { return offset (base); }
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename Type>
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct OffsetTo : GenericOffsetTo<Offset, Type> {};
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename Type>
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct LongOffsetTo : GenericOffsetTo<LongOffset, Type> {};
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Array Types
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename LenType, typename Type>
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct GenericArrayOf
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const Type *sub_array (unsigned int start_offset, unsigned int *pcount /* IN/OUT */) const
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int count = len;
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (start_offset > count))
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      count = 0;
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      count -= start_offset;
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    count = MIN (count, *pcount);
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *pcount = count;
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return array + start_offset;
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline const Type& operator [] (unsigned int i) const
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (i >= len)) return Null(Type);
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return array[i];
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline Type& operator [] (unsigned int i)
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return array[i];
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline unsigned int get_size (void) const
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { return len.static_size + len * Type::static_size; }
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool serialize (hb_serialize_context_t *c,
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			 unsigned int items_len)
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
7882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SERIALIZE (this);
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    len.set (items_len); /* TODO(serialize) Overflow? */
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!c->extend (*this))) return TRACE_RETURN (false);
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (true);
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool serialize (hb_serialize_context_t *c,
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			 Supplier<Type> &items,
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			 unsigned int items_len)
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
7992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SERIALIZE (this);
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!serialize (c, items_len))) return TRACE_RETURN (false);
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int i = 0; i < items_len; i++)
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      array[i] = items[i];
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    items.advance (items_len);
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (true);
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c) {
8082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false);
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Note: for structs that do not reference other structs,
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * we do not need to call their sanitize() as we already did
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * a bound check on the aggregate array size.  We just include
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * a small unreachable expression to make sure the structs
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * pointed to do have a simple sanitize(), ie. they do not
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * reference other structs via offsets.
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (void) (false && array[0].sanitize (c));
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (true);
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c, void *base) {
8232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false);
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int count = len;
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int i = 0; i < count; i++)
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (unlikely (!array[i].sanitize (c, base)))
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return TRACE_RETURN (false);
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (true);
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename T>
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c, void *base, T user_data) {
8332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false);
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int count = len;
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int i = 0; i < count; i++)
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (unlikely (!array[i].sanitize (c, base, user_data)))
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return TRACE_RETURN (false);
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (true);
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  private:
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize_shallow (hb_sanitize_context_t *c) {
8442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (c->check_struct (this) && c->check_array (this, Type::static_size, len));
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LenType len;
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Type array[VAR];
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_SIZE_ARRAY (sizeof (LenType), array);
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* An array with a USHORT number of elements. */
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename Type>
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct ArrayOf : GenericArrayOf<USHORT, Type> {};
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* An array with a ULONG number of elements. */
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename Type>
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct LongArrayOf : GenericArrayOf<ULONG, Type> {};
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Array of Offset's */
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename Type>
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct OffsetArrayOf : ArrayOf<OffsetTo<Type> > {};
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Array of LongOffset's */
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename Type>
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct LongOffsetArrayOf : ArrayOf<LongOffsetTo<Type> > {};
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* LongArray of LongOffset's */
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename Type>
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct LongOffsetLongArrayOf : LongArrayOf<LongOffsetTo<Type> > {};
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Array of offsets relative to the beginning of the array itself. */
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename Type>
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct OffsetListOf : OffsetArrayOf<Type>
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline const Type& operator [] (unsigned int i) const
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (i >= this->len)) return Null(Type);
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return this+this->array[i];
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c) {
8862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (OffsetArrayOf<Type>::sanitize (c, this));
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename T>
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c, T user_data) {
8912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (OffsetArrayOf<Type>::sanitize (c, this, user_data));
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* An array with a USHORT number of elements,
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * starting at second element. */
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename Type>
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct HeadlessArrayOf
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline const Type& operator [] (unsigned int i) const
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (i >= len || !i)) return Null(Type);
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return array[i-1];
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline unsigned int get_size (void) const
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { return len.static_size + (len ? len - 1 : 0) * Type::static_size; }
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool serialize (hb_serialize_context_t *c,
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			 Supplier<Type> &items,
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			 unsigned int items_len)
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
9142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SERIALIZE (this);
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    len.set (items_len); /* TODO(serialize) Overflow? */
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!items_len)) return TRACE_RETURN (true);
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!c->extend (*this))) return TRACE_RETURN (false);
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int i = 0; i < items_len - 1; i++)
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      array[i] = items[i];
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    items.advance (items_len - 1);
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (true);
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize_shallow (hb_sanitize_context_t *c) {
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return c->check_struct (this)
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	&& c->check_array (this, Type::static_size, len);
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c) {
9312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false);
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Note: for structs that do not reference other structs,
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * we do not need to call their sanitize() as we already did
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * a bound check on the aggregate array size.  We just include
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * a small unreachable expression to make sure the structs
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * pointed to do have a simple sanitize(), ie. they do not
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * reference other structs via offsets.
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (void) (false && array[0].sanitize (c));
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (true);
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  USHORT len;
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Type array[VAR];
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_SIZE_ARRAY (sizeof (USHORT), array);
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* An array with sorted elements.  Supports binary searching. */
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename Type>
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct SortedArrayOf : ArrayOf<Type> {
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename SearchType>
9587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  inline int search (const SearchType &x) const
9597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  {
9607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    /* Hand-coded bsearch here since this is in the hot inner loop. */
9617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    int min = 0, max = (int) this->len - 1;
9627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    while (min <= max)
9637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    {
9647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      int mid = (min + max) / 2;
9657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      int c = this->array[mid].cmp (x);
9667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      if (c < 0)
9677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        max = mid - 1;
9687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      else if (c > 0)
9697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        min = mid + 1;
9707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      else
9717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        return mid;
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return -1;
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} /* namespace OT */
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* HB_OPEN_TYPE_PRIVATE_HH */
982