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)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace OT {
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Casts
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Cast to struct T, reference to reference */
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename Type, typename TObject>
455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static inline const Type& CastR(const TObject &X)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ return reinterpret_cast<const Type&> (X); }
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename Type, typename TObject>
485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static inline Type& CastR(TObject &X)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ return reinterpret_cast<Type&> (X); }
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Cast to struct T, pointer to pointer */
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename Type, typename TObject>
535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static inline const Type* CastP(const TObject *X)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ return reinterpret_cast<const Type*> (X); }
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename Type, typename TObject>
565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static inline Type* CastP(TObject *X)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ return reinterpret_cast<Type*> (X); }
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* StructAtOffset<T>(P,Ofs) returns the struct T& that is placed at memory
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * location pointed to by P plus Ofs bytes. */
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename Type>
625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static inline const Type& StructAtOffset(const void *P, unsigned int offset)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ return * reinterpret_cast<const Type*> ((const char *) P + offset); }
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename Type>
655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static inline Type& StructAtOffset(void *P, unsigned int offset)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ return * reinterpret_cast<Type*> ((char *) P + offset); }
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* StructAfter<T>(X) returns the struct T& that is placed after X.
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Works with X of variable size also.  X must implement get_size() */
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename Type, typename TObject>
715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static inline const Type& StructAfter(const TObject &X)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ return StructAtOffset<Type>(&X, X.get_size()); }
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename Type, typename TObject>
745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static inline Type& StructAfter(TObject &X)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ return StructAtOffset<Type>(&X, X.get_size()); }
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Size checking
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Check _assertion in a method environment */
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define _DEFINE_INSTANCE_ASSERTION1(_line, _assertion) \
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void _instance_assertion_on_line_##_line (void) const \
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { \
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_STATIC (_assertion); \
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_INSTANCE_POD (*this); /* Make sure it's POD. */ \
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define _DEFINE_INSTANCE_ASSERTION0(_line, _assertion) _DEFINE_INSTANCE_ASSERTION1 (_line, _assertion)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define DEFINE_INSTANCE_ASSERTION(_assertion) _DEFINE_INSTANCE_ASSERTION0 (__LINE__, _assertion)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Check that _code compiles in a method environment */
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define _DEFINE_COMPILES_ASSERTION1(_line, _code) \
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void _compiles_assertion_on_line_##_line (void) const \
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { _code; }
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define _DEFINE_COMPILES_ASSERTION0(_line, _code) _DEFINE_COMPILES_ASSERTION1 (_line, _code)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define DEFINE_COMPILES_ASSERTION(_code) _DEFINE_COMPILES_ASSERTION0 (__LINE__, _code)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define DEFINE_SIZE_STATIC(size) \
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size)); \
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const unsigned int static_size = (size); \
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const unsigned int min_size = (size)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Size signifying variable-sized array */
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define VAR 1
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define DEFINE_SIZE_UNION(size, _member) \
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_INSTANCE_ASSERTION (this->u._member.static_size == (size)); \
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const unsigned int min_size = (size)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define DEFINE_SIZE_MIN(size) \
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_INSTANCE_ASSERTION (sizeof (*this) >= (size)); \
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const unsigned int min_size = (size)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define DEFINE_SIZE_ARRAY(size, array) \
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size) + sizeof (array[0])); \
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_COMPILES_ASSERTION ((void) array[0].static_size) \
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const unsigned int min_size = (size)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define DEFINE_SIZE_ARRAY2(size, array1, array2) \
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size) + sizeof (this->array1[0]) + sizeof (this->array2[0])); \
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_COMPILES_ASSERTION ((void) array1[0].static_size; (void) array2[0].static_size) \
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const unsigned int min_size = (size)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Null objects
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Global nul-content Null pool.  Enlarge as necessary. */
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* TODO This really should be a extern HB_INTERNAL and defined somewhere... */
1355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static const void *_NullPool[(256+8) / sizeof (void *)];
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Generic nul-content Null objects. */
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename Type>
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline const Type& Null (void) {
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_STATIC (sizeof (Type) <= sizeof (_NullPool));
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return *CastP<Type> (_NullPool);
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Specializaiton for arbitrary-content arbitrary-sized Null objects. */
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define DEFINE_NULL_DATA(Type, data) \
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static const char _Null##Type[sizeof (Type) + 1] = data; /* +1 is for nul-termination in data */ \
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <> \
1485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)/*static*/ inline const Type& Null<Type> (void) { \
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return *CastP<Type> (_Null##Type); \
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} /* The following line really exists such that we end in a place needing semicolon */ \
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ASSERT_STATIC (Type::min_size + 1 <= sizeof (_Null##Type))
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Accessor macro. */
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define Null(Type) Null<Type>()
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Sanitize
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef HB_DEBUG_SANITIZE
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define HB_DEBUG_SANITIZE (HB_DEBUG+0)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define TRACE_SANITIZE(this) \
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	hb_auto_trace_t<HB_DEBUG_SANITIZE, bool> trace \
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	(&c->debug_depth, c->get_name (), this, HB_FUNC, \
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	 "");
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/* This limits sanitizing time on really broken fonts. */
173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#ifndef HB_SANITIZE_MAX_EDITS
174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#define HB_SANITIZE_MAX_EDITS 100
175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct hb_sanitize_context_t
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline const char *get_name (void) { return "SANITIZE"; }
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static const unsigned int max_debug_depth = HB_DEBUG_SANITIZE;
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  typedef bool return_t;
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  template <typename T>
183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  inline return_t dispatch (const T &obj) { return obj.sanitize (this); }
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static return_t default_return_value (void) { return true; }
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool stop_sublookup_iteration (const return_t r HB_UNUSED) const { return false; }
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void init (hb_blob_t *b)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this->blob = hb_blob_reference (b);
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this->writable = false;
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void start_processing (void)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this->start = hb_blob_get_data (this->blob, NULL);
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this->end = this->start + hb_blob_get_length (this->blob);
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this->edit_count = 0;
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this->debug_depth = 0;
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DEBUG_MSG_LEVEL (SANITIZE, this->blob, 0, +1,
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     "start [%p..%p] (%lu bytes)",
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     this->start, this->end,
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     (unsigned long) (this->end - this->start));
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void end_processing (void)
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DEBUG_MSG_LEVEL (SANITIZE, this->blob, 0, -1,
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     "end [%p..%p] %u edit requests",
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     this->start, this->end, this->edit_count);
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    hb_blob_destroy (this->blob);
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this->blob = NULL;
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this->start = this->end = NULL;
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool check_range (const void *base, unsigned int len) const
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char *p = (const char *) base;
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    hb_auto_trace_t<HB_DEBUG_SANITIZE, bool> trace
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      (&this->debug_depth, "SANITIZE", this->blob, NULL,
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       "check_range [%p..%p] (%d bytes) in [%p..%p]",
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       p, p + len, len,
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       this->start, this->end);
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (likely (this->start <= p && p <= this->end && (unsigned int) (this->end - p) >= len));
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool check_array (const void *base, unsigned int record_size, unsigned int len) const
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char *p = (const char *) base;
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool overflows = _hb_unsigned_int_mul_overflows (len, record_size);
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    hb_auto_trace_t<HB_DEBUG_SANITIZE, bool> trace
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      (&this->debug_depth, "SANITIZE", this->blob, NULL,
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       "check_array [%p..%p] (%d*%d=%ld bytes) in [%p..%p]",
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       p, p + (record_size * len), record_size, len, (unsigned long) record_size * len,
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       this->start, this->end);
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (likely (!overflows && this->check_range (base, record_size * len)));
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename Type>
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool check_struct (const Type *obj) const
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return likely (this->check_range (obj, obj->min_size));
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool may_edit (const void *base HB_UNUSED, unsigned int len HB_UNUSED)
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (this->edit_count >= HB_SANITIZE_MAX_EDITS)
253c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return false;
254c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char *p = (const char *) base;
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this->edit_count++;
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    hb_auto_trace_t<HB_DEBUG_SANITIZE, bool> trace
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      (&this->debug_depth, "SANITIZE", this->blob, NULL,
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       "may_edit(%u) [%p..%p] (%d bytes) in [%p..%p] -> %s",
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       this->edit_count,
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       p, p + len, len,
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       this->start, this->end,
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       this->writable ? "GRANTED" : "DENIED");
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (this->writable);
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  template <typename Type, typename ValueType>
2705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  inline bool try_set (Type *obj, const ValueType &v) {
2715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (this->may_edit (obj, obj->static_size)) {
2725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      obj->set (v);
2735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      return true;
2745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
2755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return false;
2765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
2775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mutable unsigned int debug_depth;
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char *start, *end;
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool writable;
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int edit_count;
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hb_blob_t *blob;
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Template to sanitize an object. */
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename Type>
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct Sanitizer
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static hb_blob_t *sanitize (hb_blob_t *blob) {
29203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    hb_sanitize_context_t c[1] = {{0, NULL, NULL, false, 0, NULL}};
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool sane;
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* TODO is_sane() stuff */
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    c->init (blob);
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  retry:
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DEBUG_MSG_FUNC (SANITIZE, blob, "start");
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    c->start_processing ();
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!c->start)) {
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      c->end_processing ();
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return blob;
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Type *t = CastP<Type> (const_cast<char *> (c->start));
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sane = t->sanitize (c);
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (sane) {
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (c->edit_count) {
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	DEBUG_MSG_FUNC (SANITIZE, blob, "passed first round with %d edits; going for second round", c->edit_count);
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        /* sanitize again to ensure no toe-stepping */
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        c->edit_count = 0;
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	sane = t->sanitize (c);
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (c->edit_count) {
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	  DEBUG_MSG_FUNC (SANITIZE, blob, "requested %d edits in second round; FAILLING", c->edit_count);
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	  sane = false;
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      unsigned int edit_count = c->edit_count;
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (edit_count && !c->writable) {
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        c->start = hb_blob_get_data_writable (blob, NULL);
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	c->end = c->start + hb_blob_get_length (blob);
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (c->start) {
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	  c->writable = true;
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	  /* ok, we made it writable by relocating.  try again */
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	  DEBUG_MSG_FUNC (SANITIZE, blob, "retry");
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	  goto retry;
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    c->end_processing ();
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DEBUG_MSG_FUNC (SANITIZE, blob, sane ? "PASSED" : "FAILED");
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (sane)
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return blob;
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else {
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      hb_blob_destroy (blob);
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return hb_blob_get_empty ();
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const Type* lock_instance (hb_blob_t *blob) {
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    hb_blob_make_immutable (blob);
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char *base = hb_blob_get_data (blob, NULL);
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return unlikely (!base) ? &Null(Type) : CastP<Type> (base);
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Serialize
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef HB_DEBUG_SERIALIZE
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define HB_DEBUG_SERIALIZE (HB_DEBUG+0)
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define TRACE_SERIALIZE(this) \
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	hb_auto_trace_t<HB_DEBUG_SERIALIZE, bool> trace \
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	(&c->debug_depth, "SERIALIZE", c, HB_FUNC, \
3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	 "");
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct hb_serialize_context_t
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline hb_serialize_context_t (void *start, unsigned int size)
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this->start = (char *) start;
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this->end = this->start + size;
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this->ran_out_of_room = false;
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this->head = this->start;
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this->debug_depth = 0;
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename Type>
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline Type *start_serialize (void)
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DEBUG_MSG_LEVEL (SERIALIZE, this->start, 0, +1,
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     "start [%p..%p] (%lu bytes)",
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     this->start, this->end,
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     (unsigned long) (this->end - this->start));
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return start_embed<Type> ();
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void end_serialize (void)
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DEBUG_MSG_LEVEL (SERIALIZE, this->start, 0, -1,
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     "end [%p..%p] serialized %d bytes; %s",
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     this->start, this->end,
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     (int) (this->head - this->start),
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     this->ran_out_of_room ? "RAN OUT OF ROOM" : "did not ran out of room");
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename Type>
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline Type *copy (void)
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert (!this->ran_out_of_room);
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int len = this->head - this->start;
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void *p = malloc (len);
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (p)
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      memcpy (p, this->start, len);
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return reinterpret_cast<Type *> (p);
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename Type>
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline Type *allocate_size (unsigned int size)
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
421c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (unlikely (this->ran_out_of_room || this->end - this->head < ptrdiff_t (size))) {
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      this->ran_out_of_room = true;
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return NULL;
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memset (this->head, 0, size);
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    char *ret = this->head;
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this->head += size;
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return reinterpret_cast<Type *> (ret);
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename Type>
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline Type *allocate_min (void)
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return this->allocate_size<Type> (Type::min_size);
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename Type>
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline Type *start_embed (void)
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Type *ret = reinterpret_cast<Type *> (this->head);
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ret;
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename Type>
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline Type *embed (const Type &obj)
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int size = obj.get_size ();
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Type *ret = this->allocate_size<Type> (size);
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!ret)) return NULL;
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memcpy (ret, obj, size);
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ret;
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename Type>
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline Type *extend_min (Type &obj)
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int size = obj.min_size;
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert (this->start <= (char *) &obj && (char *) &obj <= this->head && (char *) &obj + size >= this->head);
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!this->allocate_size<Type> (((char *) &obj) + size - this->head))) return NULL;
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return reinterpret_cast<Type *> (&obj);
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename Type>
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline Type *extend (Type &obj)
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int size = obj.get_size ();
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert (this->start < (char *) &obj && (char *) &obj <= this->head && (char *) &obj + size >= this->head);
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!this->allocate_size<Type> (((char *) &obj) + size - this->head))) return NULL;
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return reinterpret_cast<Type *> (&obj);
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void truncate (void *head)
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert (this->start < head && head <= this->head);
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this->head = (char *) head;
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int debug_depth;
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char *start, *end, *head;
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ran_out_of_room;
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename Type>
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct Supplier
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline Supplier (const Type *array, unsigned int len_)
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    head = array;
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    len = len_;
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline const Type operator [] (unsigned int i) const
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (i >= len)) return Type ();
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return head[i];
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void advance (unsigned int count)
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (count > len))
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      count = len;
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    len -= count;
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    head += count;
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  private:
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline Supplier (const Supplier<Type> &); /* Disallow copy */
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline Supplier<Type>& operator= (const Supplier<Type> &); /* Disallow copy */
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int len;
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const Type *head;
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The OpenType Font File: Data Types
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* "The following data types are used in the OpenType font file.
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  All OpenType fonts use Motorola-style byte ordering (Big Endian):" */
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Int types
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename Type, int Bytes> struct BEInt;
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename Type>
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct BEInt<Type, 2>
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void set (Type i) { hb_be_uint16_put (v,i); }
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline operator Type (void) const { return hb_be_uint16_get (v); }
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool operator == (const BEInt<Type, 2>& o) const { return hb_be_uint16_eq (v, o.v); }
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool operator != (const BEInt<Type, 2>& o) const { return !(*this == o); }
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  private: uint8_t v[2];
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename Type>
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct BEInt<Type, 4>
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void set (Type i) { hb_be_uint32_put (v,i); }
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline operator Type (void) const { return hb_be_uint32_get (v); }
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool operator == (const BEInt<Type, 4>& o) const { return hb_be_uint32_eq (v, o.v); }
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool operator != (const BEInt<Type, 4>& o) const { return !(*this == o); }
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  private: uint8_t v[4];
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
5522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)template <typename Type>
5532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct BEInt<Type, 3>
5542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
5552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  public:
5562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline void set (Type i) { hb_be_uint24_put (v,i); }
5572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline operator Type (void) const { return hb_be_uint24_get (v); }
5582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline bool operator == (const BEInt<Type, 3>& o) const { return hb_be_uint24_eq (v, o.v); }
5592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline bool operator != (const BEInt<Type, 3>& o) const { return !(*this == o); }
5602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  private: uint8_t v[3];
5612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Integer types in big-endian order and no alignment requirement */
5642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)template <typename Type, unsigned int Size>
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct IntType
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void set (Type i) { v.set (i); }
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline operator Type(void) const { return v; }
5692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline bool operator == (const IntType<Type,Size> &o) const { return v == o.v; }
5702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline bool operator != (const IntType<Type,Size> &o) const { return v != o.v; }
5712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static inline int cmp (const IntType<Type,Size> *a, const IntType<Type,Size> *b) { return b->cmp (*a); }
5722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline int cmp (IntType<Type,Size> va) const { Type a = va; Type b = v; return a < b ? -1 : a == b ? 0 : +1; }
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline int cmp (Type a) const { Type b = v; return a < b ? -1 : a == b ? 0 : +1; }
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c) {
5752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (likely (c->check_struct (this)));
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  protected:
5792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  BEInt<Type, Size> v;
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
5812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DEFINE_SIZE_STATIC (Size);
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)typedef		uint8_t	     BYTE;	/* 8-bit unsigned integer. */
5852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)typedef IntType<uint16_t, 2> USHORT;	/* 16-bit unsigned integer. */
5862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)typedef IntType<int16_t,  2> SHORT;	/* 16-bit signed integer. */
5872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)typedef IntType<uint32_t, 4> ULONG;	/* 32-bit unsigned integer. */
5882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)typedef IntType<int32_t,  4> LONG;	/* 32-bit signed integer. */
5892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)typedef IntType<uint32_t, 3> UINT24;	/* 24-bit unsigned integer. */
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 16-bit signed integer (SHORT) that describes a quantity in FUnits. */
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef SHORT FWORD;
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 16-bit unsigned integer (USHORT) that describes a quantity in FUnits. */
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef USHORT UFWORD;
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Date represented in number of seconds since 12:00 midnight, January 1,
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 1904. The value is represented as a signed 64-bit integer. */
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct LONGDATETIME
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c) {
6022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (likely (c->check_struct (this)));
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
60523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  protected:
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LONG major;
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ULONG minor;
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_SIZE_STATIC (8);
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Array of four uint8s (length = 32 bits) used to identify a script, language
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * system, feature, or baseline */
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct Tag : ULONG
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* What the char* converters return is NOT nul-terminated.  Print using "%.4s" */
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline operator const char* (void) const { return reinterpret_cast<const char *> (&this->v); }
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline operator char* (void) { return reinterpret_cast<char *> (&this->v); }
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_SIZE_STATIC (4);
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DEFINE_NULL_DATA (Tag, "    ");
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Glyph index number, same as uint16 (length = 16 bits) */
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef USHORT GlyphID;
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Script/language-system/feature index */
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct Index : USHORT {
6295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  static const unsigned int NOT_FOUND_INDEX = 0xFFFFu;
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DEFINE_NULL_DATA (Index, "\xff\xff");
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)/* Offset, Null offset = 0 */
6345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)template <typename Type=USHORT>
6355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)struct Offset : Type
636c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles){
637c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  inline bool is_null (void) const { return 0 == *this; }
638c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  public:
6395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DEFINE_SIZE_STATIC (sizeof(Type));
640c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* CheckSum */
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct CheckSum : ULONG
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
646f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  /* This is reference implementation from the spec. */
647f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  static inline uint32_t CalcTableChecksum (const ULONG *Table, uint32_t Length)
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32_t Sum = 0L;
650f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const ULONG *EndPtr = Table+((Length+3) & ~3) / ULONG::static_size;
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (Table < EndPtr)
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Sum += *Table++;
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return Sum;
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
656f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
657f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  /* Note: data should be 4byte aligned and have 4byte padding at the end. */
658f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  inline void set_for_data (const void *data, unsigned int length)
659f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  { set (CalcTableChecksum ((const ULONG *) data, length)); }
660f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_SIZE_STATIC (4);
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Version Numbers
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct FixedVersion
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline uint32_t to_int (void) const { return (major << 16) + minor; }
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c) {
6752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (c->check_struct (this));
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  USHORT major;
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  USHORT minor;
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_SIZE_STATIC (4);
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
6885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * Template subclasses of Offset that do the dereferencing.
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Use: (base+offset)
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)template <typename Type, typename OffsetType=USHORT>
6935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)struct OffsetTo : Offset<OffsetType>
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline const Type& operator () (const void *base) const
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int offset = *this;
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!offset)) return Null(Type);
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return StructAtOffset<Type> (base, offset);
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline Type& serialize (hb_serialize_context_t *c, void *base)
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Type *t = c->start_embed<Type> ();
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this->set ((char *) t - (char *) base); /* TODO(serialize) Overflow? */
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return *t;
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c, void *base) {
7102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!c->check_struct (this))) return TRACE_RETURN (false);
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int offset = *this;
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!offset)) return TRACE_RETURN (true);
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Type &obj = StructAtOffset<Type> (base, offset);
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (likely (obj.sanitize (c)) || neuter (c));
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename T>
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c, void *base, T user_data) {
7192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!c->check_struct (this))) return TRACE_RETURN (false);
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int offset = *this;
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!offset)) return TRACE_RETURN (true);
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Type &obj = StructAtOffset<Type> (base, offset);
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (likely (obj.sanitize (c, user_data)) || neuter (c));
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Set the offset to Null */
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool neuter (hb_sanitize_context_t *c) {
7295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return c->try_set (this, 0);
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DEFINE_SIZE_STATIC (sizeof(OffsetType));
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename Base, typename OffsetType, typename Type>
7345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static inline const Type& operator + (const Base &base, const OffsetTo<Type, OffsetType> &offset) { return offset (base); }
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename Base, typename OffsetType, typename Type>
7365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static inline Type& operator + (Base &base, OffsetTo<Type, OffsetType> &offset) { return offset (base); }
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Array Types
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)/* An array with a number of elements. */
7445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)template <typename Type, typename LenType=USHORT>
7455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)struct ArrayOf
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const Type *sub_array (unsigned int start_offset, unsigned int *pcount /* IN/OUT */) const
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int count = len;
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (start_offset > count))
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      count = 0;
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      count -= start_offset;
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    count = MIN (count, *pcount);
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *pcount = count;
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return array + start_offset;
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline const Type& operator [] (unsigned int i) const
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (i >= len)) return Null(Type);
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return array[i];
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline Type& operator [] (unsigned int i)
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return array[i];
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline unsigned int get_size (void) const
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { return len.static_size + len * Type::static_size; }
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool serialize (hb_serialize_context_t *c,
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			 unsigned int items_len)
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
7742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SERIALIZE (this);
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    len.set (items_len); /* TODO(serialize) Overflow? */
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!c->extend (*this))) return TRACE_RETURN (false);
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (true);
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool serialize (hb_serialize_context_t *c,
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			 Supplier<Type> &items,
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			 unsigned int items_len)
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
7852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SERIALIZE (this);
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!serialize (c, items_len))) return TRACE_RETURN (false);
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int i = 0; i < items_len; i++)
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      array[i] = items[i];
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    items.advance (items_len);
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (true);
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c) {
7942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false);
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Note: for structs that do not reference other structs,
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * we do not need to call their sanitize() as we already did
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * a bound check on the aggregate array size.  We just include
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * a small unreachable expression to make sure the structs
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * pointed to do have a simple sanitize(), ie. they do not
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * reference other structs via offsets.
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (void) (false && array[0].sanitize (c));
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (true);
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c, void *base) {
8092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false);
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int count = len;
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int i = 0; i < count; i++)
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (unlikely (!array[i].sanitize (c, base)))
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return TRACE_RETURN (false);
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (true);
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename T>
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c, void *base, T user_data) {
8192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false);
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int count = len;
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int i = 0; i < count; i++)
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (unlikely (!array[i].sanitize (c, base, user_data)))
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return TRACE_RETURN (false);
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (true);
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  template <typename SearchType>
8295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  inline int lsearch (const SearchType &x) const
8305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  {
8315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    unsigned int count = len;
8325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    for (unsigned int i = 0; i < count; i++)
8335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      if (!this->array[i].cmp (x))
8345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return i;
8355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return -1;
8365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
8375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  private:
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize_shallow (hb_sanitize_context_t *c) {
8402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (c->check_struct (this) && c->check_array (this, Type::static_size, len));
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LenType len;
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Type array[VAR];
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_SIZE_ARRAY (sizeof (LenType), array);
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Array of Offset's */
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename Type>
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct OffsetArrayOf : ArrayOf<OffsetTo<Type> > {};
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Array of offsets relative to the beginning of the array itself. */
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename Type>
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct OffsetListOf : OffsetArrayOf<Type>
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline const Type& operator [] (unsigned int i) const
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (i >= this->len)) return Null(Type);
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return this+this->array[i];
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c) {
8662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (OffsetArrayOf<Type>::sanitize (c, this));
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename T>
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c, T user_data) {
8712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (OffsetArrayOf<Type>::sanitize (c, this, user_data));
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)/* An array starting at second element. */
8785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)template <typename Type, typename LenType=USHORT>
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct HeadlessArrayOf
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline const Type& operator [] (unsigned int i) const
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (i >= len || !i)) return Null(Type);
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return array[i-1];
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline unsigned int get_size (void) const
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { return len.static_size + (len ? len - 1 : 0) * Type::static_size; }
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool serialize (hb_serialize_context_t *c,
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			 Supplier<Type> &items,
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			 unsigned int items_len)
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
8932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SERIALIZE (this);
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    len.set (items_len); /* TODO(serialize) Overflow? */
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!items_len)) return TRACE_RETURN (true);
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!c->extend (*this))) return TRACE_RETURN (false);
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int i = 0; i < items_len - 1; i++)
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      array[i] = items[i];
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    items.advance (items_len - 1);
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (true);
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize_shallow (hb_sanitize_context_t *c) {
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return c->check_struct (this)
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	&& c->check_array (this, Type::static_size, len);
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c) {
9102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false);
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Note: for structs that do not reference other structs,
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * we do not need to call their sanitize() as we already did
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * a bound check on the aggregate array size.  We just include
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * a small unreachable expression to make sure the structs
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * pointed to do have a simple sanitize(), ie. they do not
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * reference other structs via offsets.
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (void) (false && array[0].sanitize (c));
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (true);
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  LenType len;
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Type array[VAR];
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
9285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DEFINE_SIZE_ARRAY (sizeof (LenType), array);
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* An array with sorted elements.  Supports binary searching. */
9335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)template <typename Type, typename LenType=USHORT>
9345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)struct SortedArrayOf : ArrayOf<Type, LenType>
9355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles){
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename SearchType>
9375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  inline int bsearch (const SearchType &x) const
9387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  {
9397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    /* Hand-coded bsearch here since this is in the hot inner loop. */
9407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    int min = 0, max = (int) this->len - 1;
9417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    while (min <= max)
9427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    {
9437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      int mid = (min + max) / 2;
9447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      int c = this->array[mid].cmp (x);
9457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      if (c < 0)
9467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        max = mid - 1;
9477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      else if (c > 0)
9487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        min = mid + 1;
9497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      else
9507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        return mid;
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return -1;
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} /* namespace OT */
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* HB_OPEN_TYPE_PRIVATE_HH */
961