1 /*
   2  * Copyright © 2007,2008,2009,2010  Red Hat, Inc.
   3  * Copyright © 2012  Google, Inc.
   4  *
   5  *  This is part of HarfBuzz, a text shaping library.
   6  *
   7  * Permission is hereby granted, without written agreement and without
   8  * license or royalty fees, to use, copy, modify, and distribute this
   9  * software and its documentation for any purpose, provided that the
  10  * above copyright notice and the following two paragraphs appear in
  11  * all copies of this software.
  12  *
  13  * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
  14  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
  15  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
  16  * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
  17  * DAMAGE.
  18  *
  19  * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
  20  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  21  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
  22  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
  23  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  24  *
  25  * Red Hat Author(s): Behdad Esfahbod
  26  * Google Author(s): Behdad Esfahbod
  27  */
  28 
  29 #ifndef HB_OPEN_TYPE_PRIVATE_HH
  30 #define HB_OPEN_TYPE_PRIVATE_HH
  31 
  32 #include "hb-private.hh"
  33 
  34 
  35 namespace OT {
  36 
  37 
  38 
  39 /*
  40  * Casts
  41  */
  42 
  43 /* Cast to struct T, reference to reference */
  44 template<typename Type, typename TObject>
  45 static inline const Type& CastR(const TObject &X)
  46 { return reinterpret_cast<const Type&> (X); }
  47 template<typename Type, typename TObject>
  48 static inline Type& CastR(TObject &X)
  49 { return reinterpret_cast<Type&> (X); }
  50 
  51 /* Cast to struct T, pointer to pointer */
  52 template<typename Type, typename TObject>
  53 static inline const Type* CastP(const TObject *X)
  54 { return reinterpret_cast<const Type*> (X); }
  55 template<typename Type, typename TObject>
  56 static inline Type* CastP(TObject *X)
  57 { return reinterpret_cast<Type*> (X); }
  58 
  59 /* StructAtOffset<T>(P,Ofs) returns the struct T& that is placed at memory
  60  * location pointed to by P plus Ofs bytes. */
  61 template<typename Type>
  62 static inline const Type& StructAtOffset(const void *P, unsigned int offset)
  63 { return * reinterpret_cast<const Type*> ((const char *) P + offset); }
  64 template<typename Type>
  65 static inline Type& StructAtOffset(void *P, unsigned int offset)
  66 { return * reinterpret_cast<Type*> ((char *) P + offset); }
  67 
  68 /* StructAfter<T>(X) returns the struct T& that is placed after X.
  69  * Works with X of variable size also.  X must implement get_size() */
  70 template<typename Type, typename TObject>
  71 static inline const Type& StructAfter(const TObject &X)
  72 { return StructAtOffset<Type>(&X, X.get_size()); }
  73 template<typename Type, typename TObject>
  74 static inline Type& StructAfter(TObject &X)
  75 { return StructAtOffset<Type>(&X, X.get_size()); }
  76 
  77 
  78 
  79 /*
  80  * Size checking
  81  */
  82 
  83 /* Check _assertion in a method environment */
  84 #define _DEFINE_INSTANCE_ASSERTION1(_line, _assertion) \
  85   inline void _instance_assertion_on_line_##_line (void) const \
  86   { \
  87     ASSERT_STATIC (_assertion); \
  88     ASSERT_INSTANCE_POD (*this); /* Make sure it's POD. */ \
  89   }
  90 # define _DEFINE_INSTANCE_ASSERTION0(_line, _assertion) _DEFINE_INSTANCE_ASSERTION1 (_line, _assertion)
  91 # define DEFINE_INSTANCE_ASSERTION(_assertion) _DEFINE_INSTANCE_ASSERTION0 (__LINE__, _assertion)
  92 
  93 /* Check that _code compiles in a method environment */
  94 #define _DEFINE_COMPILES_ASSERTION1(_line, _code) \
  95   inline void _compiles_assertion_on_line_##_line (void) const \
  96   { _code; }
  97 # define _DEFINE_COMPILES_ASSERTION0(_line, _code) _DEFINE_COMPILES_ASSERTION1 (_line, _code)
  98 # define DEFINE_COMPILES_ASSERTION(_code) _DEFINE_COMPILES_ASSERTION0 (__LINE__, _code)
  99 
 100 
 101 #define DEFINE_SIZE_STATIC(size) \
 102   DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size)); \
 103   static const unsigned int static_size = (size); \
 104   static const unsigned int min_size = (size)
 105 
 106 /* Size signifying variable-sized array */
 107 #define VAR 1
 108 
 109 #define DEFINE_SIZE_UNION(size, _member) \
 110   DEFINE_INSTANCE_ASSERTION (this->u._member.static_size == (size)); \
 111   static const unsigned int min_size = (size)
 112 
 113 #define DEFINE_SIZE_MIN(size) \
 114   DEFINE_INSTANCE_ASSERTION (sizeof (*this) >= (size)); \
 115   static const unsigned int min_size = (size)
 116 
 117 #define DEFINE_SIZE_ARRAY(size, array) \
 118   DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size) + sizeof (array[0])); \
 119   DEFINE_COMPILES_ASSERTION ((void) array[0].static_size) \
 120   static const unsigned int min_size = (size)
 121 
 122 #define DEFINE_SIZE_ARRAY2(size, array1, array2) \
 123   DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size) + sizeof (this->array1[0]) + sizeof (this->array2[0])); \
 124   DEFINE_COMPILES_ASSERTION ((void) array1[0].static_size; (void) array2[0].static_size) \
 125   static const unsigned int min_size = (size)
 126 
 127 
 128 
 129 /*
 130  * Null objects
 131  */
 132 
 133 /* Global nul-content Null pool.  Enlarge as necessary. */
 134 /* TODO This really should be a extern HB_INTERNAL and defined somewhere... */
 135 static const void *_NullPool[(256+8) / sizeof (void *)];
 136 
 137 /* Generic nul-content Null objects. */
 138 template <typename Type>
 139 static inline const Type& Null (void) {
 140   ASSERT_STATIC (sizeof (Type) <= sizeof (_NullPool));
 141   return *CastP<Type> (_NullPool);
 142 }
 143 
 144 /* Specializaiton for arbitrary-content arbitrary-sized Null objects. */
 145 #define DEFINE_NULL_DATA(Type, data) \
 146 static const char _Null##Type[sizeof (Type) + 1] = data; /* +1 is for nul-termination in data */ \
 147 template <> \
 148 /*static*/ inline const Type& Null<Type> (void) { \
 149   return *CastP<Type> (_Null##Type); \
 150 } /* The following line really exists such that we end in a place needing semicolon */ \
 151 ASSERT_STATIC (Type::min_size + 1 <= sizeof (_Null##Type))
 152 
 153 /* Accessor macro. */
 154 #define Null(Type) Null<Type>()
 155 
 156 
 157 /*
 158  * Dispatch
 159  */
 160 
 161 template <typename Context, typename Return, unsigned int MaxDebugDepth>
 162 struct hb_dispatch_context_t
 163 {
 164   static const unsigned int max_debug_depth = MaxDebugDepth;
 165   typedef Return return_t;
 166   template <typename T, typename F>
 167   inline bool may_dispatch (const T *obj, const F *format) { return true; }
 168   static return_t no_dispatch_return_value (void) { return Context::default_return_value (); }
 169 };
 170 
 171 
 172 /*
 173  * Sanitize
 174  */
 175 
 176 #ifndef HB_DEBUG_SANITIZE
 177 #define HB_DEBUG_SANITIZE (HB_DEBUG+0)
 178 #endif
 179 
 180 
 181 #define TRACE_SANITIZE(this) \
 182         hb_auto_trace_t<HB_DEBUG_SANITIZE, bool> trace \
 183         (&c->debug_depth, c->get_name (), this, HB_FUNC, \
 184          "");
 185 
 186 /* This limits sanitizing time on really broken fonts. */
 187 #ifndef HB_SANITIZE_MAX_EDITS
 188 #define HB_SANITIZE_MAX_EDITS 100
 189 #endif
 190 
 191 struct hb_sanitize_context_t :
 192        hb_dispatch_context_t<hb_sanitize_context_t, bool, HB_DEBUG_SANITIZE>
 193 {
 194   inline hb_sanitize_context_t (void) :
 195         debug_depth (0),
 196         start (NULL), end (NULL),
 197         writable (false), edit_count (0),
 198         blob (NULL) {}
 199 
 200   inline const char *get_name (void) { return "SANITIZE"; }
 201   template <typename T, typename F>
 202   inline bool may_dispatch (const T *obj, const F *format)
 203   { return format->sanitize (this); }
 204   template <typename T>
 205   inline return_t dispatch (const T &obj) { return obj.sanitize (this); }
 206   static return_t default_return_value (void) { return true; }
 207   static return_t no_dispatch_return_value (void) { return false; }
 208   bool stop_sublookup_iteration (const return_t r) const { return !r; }
 209 
 210   inline void init (hb_blob_t *b)
 211   {
 212     this->blob = hb_blob_reference (b);
 213     this->writable = false;
 214   }
 215 
 216   inline void start_processing (void)
 217   {
 218     this->start = hb_blob_get_data (this->blob, NULL);
 219     this->end = this->start + hb_blob_get_length (this->blob);
 220     assert (this->start <= this->end); /* Must not overflow. */
 221     this->edit_count = 0;
 222     this->debug_depth = 0;
 223 
 224     DEBUG_MSG_LEVEL (SANITIZE, start, 0, +1,
 225                      "start [%p..%p] (%lu bytes)",
 226                      this->start, this->end,
 227                      (unsigned long) (this->end - this->start));
 228   }
 229 
 230   inline void end_processing (void)
 231   {
 232     DEBUG_MSG_LEVEL (SANITIZE, this->start, 0, -1,
 233                      "end [%p..%p] %u edit requests",
 234                      this->start, this->end, this->edit_count);
 235 
 236     hb_blob_destroy (this->blob);
 237     this->blob = NULL;
 238     this->start = this->end = NULL;
 239   }
 240 
 241   inline bool check_range (const void *base, unsigned int len) const
 242   {
 243     const char *p = (const char *) base;
 244     bool ok = this->start <= p && p <= this->end && (unsigned int) (this->end - p) >= len;
 245 
 246     DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0,
 247        "check_range [%p..%p] (%d bytes) in [%p..%p] -> %s",
 248        p, p + len, len,
 249        this->start, this->end,
 250        ok ? "OK" : "OUT-OF-RANGE");
 251 
 252     return likely (ok);
 253   }
 254 
 255   inline bool check_array (const void *base, unsigned int record_size, unsigned int len) const
 256   {
 257     const char *p = (const char *) base;
 258     bool overflows = _hb_unsigned_int_mul_overflows (len, record_size);
 259     unsigned int array_size = record_size * len;
 260     bool ok = !overflows && this->check_range (base, array_size);
 261 
 262     DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0,
 263        "check_array [%p..%p] (%d*%d=%d bytes) in [%p..%p] -> %s",
 264        p, p + (record_size * len), record_size, len, (unsigned int) array_size,
 265        this->start, this->end,
 266        overflows ? "OVERFLOWS" : ok ? "OK" : "OUT-OF-RANGE");
 267 
 268     return likely (ok);
 269   }
 270 
 271   template <typename Type>
 272   inline bool check_struct (const Type *obj) const
 273   {
 274     return likely (this->check_range (obj, obj->min_size));
 275   }
 276 
 277   inline bool may_edit (const void *base HB_UNUSED, unsigned int len HB_UNUSED)
 278   {
 279     if (this->edit_count >= HB_SANITIZE_MAX_EDITS)
 280       return false;
 281 
 282     const char *p = (const char *) base;
 283     this->edit_count++;
 284 
 285     DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0,
 286        "may_edit(%u) [%p..%p] (%d bytes) in [%p..%p] -> %s",
 287        this->edit_count,
 288        p, p + len, len,
 289        this->start, this->end,
 290        this->writable ? "GRANTED" : "DENIED");
 291 
 292     return this->writable;
 293   }
 294 
 295   template <typename Type, typename ValueType>
 296   inline bool try_set (const Type *obj, const ValueType &v) {
 297     if (this->may_edit (obj, obj->static_size)) {
 298       const_cast<Type *> (obj)->set (v);
 299       return true;
 300     }
 301     return false;
 302   }
 303 
 304   mutable unsigned int debug_depth;
 305   const char *start, *end;
 306   bool writable;
 307   unsigned int edit_count;
 308   hb_blob_t *blob;
 309 };
 310 
 311 
 312 
 313 /* Template to sanitize an object. */
 314 template <typename Type>
 315 struct Sanitizer
 316 {
 317   static hb_blob_t *sanitize (hb_blob_t *blob) {
 318     hb_sanitize_context_t c[1];
 319     bool sane;
 320 
 321     /* TODO is_sane() stuff */
 322 
 323     c->init (blob);
 324 
 325   retry:
 326     DEBUG_MSG_FUNC (SANITIZE, c->start, "start");
 327 
 328     c->start_processing ();
 329 
 330     if (unlikely (!c->start)) {
 331       c->end_processing ();
 332       return blob;
 333     }
 334 
 335     Type *t = CastP<Type> (const_cast<char *> (c->start));
 336 
 337     sane = t->sanitize (c);
 338     if (sane) {
 339       if (c->edit_count) {
 340         DEBUG_MSG_FUNC (SANITIZE, c->start, "passed first round with %d edits; going for second round", c->edit_count);
 341 
 342         /* sanitize again to ensure no toe-stepping */
 343         c->edit_count = 0;
 344         sane = t->sanitize (c);
 345         if (c->edit_count) {
 346           DEBUG_MSG_FUNC (SANITIZE, c->start, "requested %d edits in second round; FAILLING", c->edit_count);
 347           sane = false;
 348         }
 349       }
 350     } else {
 351       unsigned int edit_count = c->edit_count;
 352       if (edit_count && !c->writable) {
 353         c->start = hb_blob_get_data_writable (blob, NULL);
 354         c->end = c->start + hb_blob_get_length (blob);
 355 
 356         if (c->start) {
 357           c->writable = true;
 358           /* ok, we made it writable by relocating.  try again */
 359           DEBUG_MSG_FUNC (SANITIZE, c->start, "retry");
 360           goto retry;
 361         }
 362       }
 363     }
 364 
 365     c->end_processing ();
 366 
 367     DEBUG_MSG_FUNC (SANITIZE, c->start, sane ? "PASSED" : "FAILED");
 368     if (sane)
 369       return blob;
 370     else {
 371       hb_blob_destroy (blob);
 372       return hb_blob_get_empty ();
 373     }
 374   }
 375 
 376   static const Type* lock_instance (hb_blob_t *blob) {
 377     hb_blob_make_immutable (blob);
 378     const char *base = hb_blob_get_data (blob, NULL);
 379     return unlikely (!base) ? &Null(Type) : CastP<Type> (base);
 380   }
 381 };
 382 
 383 
 384 
 385 /*
 386  * Serialize
 387  */
 388 
 389 #ifndef HB_DEBUG_SERIALIZE
 390 #define HB_DEBUG_SERIALIZE (HB_DEBUG+0)
 391 #endif
 392 
 393 
 394 #define TRACE_SERIALIZE(this) \
 395         hb_auto_trace_t<HB_DEBUG_SERIALIZE, bool> trace \
 396         (&c->debug_depth, "SERIALIZE", c, HB_FUNC, \
 397          "");
 398 
 399 
 400 struct hb_serialize_context_t
 401 {
 402   inline hb_serialize_context_t (void *start, unsigned int size)
 403   {
 404     this->start = (char *) start;
 405     this->end = this->start + size;
 406 
 407     this->ran_out_of_room = false;
 408     this->head = this->start;
 409     this->debug_depth = 0;
 410   }
 411 
 412   template <typename Type>
 413   inline Type *start_serialize (void)
 414   {
 415     DEBUG_MSG_LEVEL (SERIALIZE, this->start, 0, +1,
 416                      "start [%p..%p] (%lu bytes)",
 417                      this->start, this->end,
 418                      (unsigned long) (this->end - this->start));
 419 
 420     return start_embed<Type> ();
 421   }
 422 
 423   inline void end_serialize (void)
 424   {
 425     DEBUG_MSG_LEVEL (SERIALIZE, this->start, 0, -1,
 426                      "end [%p..%p] serialized %d bytes; %s",
 427                      this->start, this->end,
 428                      (int) (this->head - this->start),
 429                      this->ran_out_of_room ? "RAN OUT OF ROOM" : "did not ran out of room");
 430 
 431   }
 432 
 433   template <typename Type>
 434   inline Type *copy (void)
 435   {
 436     assert (!this->ran_out_of_room);
 437     unsigned int len = this->head - this->start;
 438     void *p = malloc (len);
 439     if (p)
 440       memcpy (p, this->start, len);
 441     return reinterpret_cast<Type *> (p);
 442   }
 443 
 444   template <typename Type>
 445   inline Type *allocate_size (unsigned int size)
 446   {
 447     if (unlikely (this->ran_out_of_room || this->end - this->head < ptrdiff_t (size))) {
 448       this->ran_out_of_room = true;
 449       return NULL;
 450     }
 451     memset (this->head, 0, size);
 452     char *ret = this->head;
 453     this->head += size;
 454     return reinterpret_cast<Type *> (ret);
 455   }
 456 
 457   template <typename Type>
 458   inline Type *allocate_min (void)
 459   {
 460     return this->allocate_size<Type> (Type::min_size);
 461   }
 462 
 463   template <typename Type>
 464   inline Type *start_embed (void)
 465   {
 466     Type *ret = reinterpret_cast<Type *> (this->head);
 467     return ret;
 468   }
 469 
 470   template <typename Type>
 471   inline Type *embed (const Type &obj)
 472   {
 473     unsigned int size = obj.get_size ();
 474     Type *ret = this->allocate_size<Type> (size);
 475     if (unlikely (!ret)) return NULL;
 476     memcpy (ret, obj, size);
 477     return ret;
 478   }
 479 
 480   template <typename Type>
 481   inline Type *extend_min (Type &obj)
 482   {
 483     unsigned int size = obj.min_size;
 484     assert (this->start <= (char *) &obj && (char *) &obj <= this->head && (char *) &obj + size >= this->head);
 485     if (unlikely (!this->allocate_size<Type> (((char *) &obj) + size - this->head))) return NULL;
 486     return reinterpret_cast<Type *> (&obj);
 487   }
 488 
 489   template <typename Type>
 490   inline Type *extend (Type &obj)
 491   {
 492     unsigned int size = obj.get_size ();
 493     assert (this->start < (char *) &obj && (char *) &obj <= this->head && (char *) &obj + size >= this->head);
 494     if (unlikely (!this->allocate_size<Type> (((char *) &obj) + size - this->head))) return NULL;
 495     return reinterpret_cast<Type *> (&obj);
 496   }
 497 
 498   inline void truncate (void *head)
 499   {
 500     assert (this->start < head && head <= this->head);
 501     this->head = (char *) head;
 502   }
 503 
 504   unsigned int debug_depth;
 505   char *start, *end, *head;
 506   bool ran_out_of_room;
 507 };
 508 
 509 template <typename Type>
 510 struct Supplier
 511 {
 512   inline Supplier (const Type *array, unsigned int len_)
 513   {
 514     head = array;
 515     len = len_;
 516   }
 517   inline const Type operator [] (unsigned int i) const
 518   {
 519     if (unlikely (i >= len)) return Type ();
 520     return head[i];
 521   }
 522 
 523   inline void advance (unsigned int count)
 524   {
 525     if (unlikely (count > len))
 526       count = len;
 527     len -= count;
 528     head += count;
 529   }
 530 
 531   private:
 532   inline Supplier (const Supplier<Type> &); /* Disallow copy */
 533   inline Supplier<Type>& operator= (const Supplier<Type> &); /* Disallow copy */
 534 
 535   unsigned int len;
 536   const Type *head;
 537 };
 538 
 539 
 540 
 541 
 542 /*
 543  *
 544  * The OpenType Font File: Data Types
 545  */
 546 
 547 
 548 /* "The following data types are used in the OpenType font file.
 549  *  All OpenType fonts use Motorola-style byte ordering (Big Endian):" */
 550 
 551 /*
 552  * Int types
 553  */
 554 
 555 
 556 template <typename Type, int Bytes> struct BEInt;
 557 
 558 template <typename Type>
 559 struct BEInt<Type, 1>
 560 {
 561   public:
 562   inline void set (Type V)
 563   {
 564     v = V;
 565   }
 566   inline operator Type (void) const
 567   {
 568     return v;
 569   }
 570   private: uint8_t v;
 571 };
 572 template <typename Type>
 573 struct BEInt<Type, 2>
 574 {
 575   public:
 576   inline void set (Type V)
 577   {
 578     v[0] = (V >>  8) & 0xFF;
 579     v[1] = (V      ) & 0xFF;
 580   }
 581   inline operator Type (void) const
 582   {
 583     return (v[0] <<  8)
 584          + (v[1]      );
 585   }
 586   private: uint8_t v[2];
 587 };
 588 template <typename Type>
 589 struct BEInt<Type, 3>
 590 {
 591   public:
 592   inline void set (Type V)
 593   {
 594     v[0] = (V >> 16) & 0xFF;
 595     v[1] = (V >>  8) & 0xFF;
 596     v[2] = (V      ) & 0xFF;
 597   }
 598   inline operator Type (void) const
 599   {
 600     return (v[0] << 16)
 601          + (v[1] <<  8)
 602          + (v[2]      );
 603   }
 604   private: uint8_t v[3];
 605 };
 606 template <typename Type>
 607 struct BEInt<Type, 4>
 608 {
 609   public:
 610   inline void set (Type V)
 611   {
 612     v[0] = (V >> 24) & 0xFF;
 613     v[1] = (V >> 16) & 0xFF;
 614     v[2] = (V >>  8) & 0xFF;
 615     v[3] = (V      ) & 0xFF;
 616   }
 617   inline operator Type (void) const
 618   {
 619     return (v[0] << 24)
 620          + (v[1] << 16)
 621          + (v[2] <<  8)
 622          + (v[3]      );
 623   }
 624   private: uint8_t v[4];
 625 };
 626 
 627 /* Integer types in big-endian order and no alignment requirement */
 628 template <typename Type, unsigned int Size>
 629 struct IntType
 630 {
 631   inline void set (Type i) { v.set (i); }
 632   inline operator Type(void) const { return v; }
 633   inline bool operator == (const IntType<Type,Size> &o) const { return (Type) v == (Type) o.v; }
 634   inline bool operator != (const IntType<Type,Size> &o) const { return !(*this == o); }
 635   static inline int cmp (const IntType<Type,Size> *a, const IntType<Type,Size> *b) { return b->cmp (*a); }
 636   inline int cmp (Type a) const
 637   {
 638     Type b = v;
 639     if (sizeof (Type) < sizeof (int))
 640       return (int) a - (int) b;
 641     else
 642       return a < b ? -1 : a == b ? 0 : +1;
 643   }
 644   inline bool sanitize (hb_sanitize_context_t *c) const
 645   {
 646     TRACE_SANITIZE (this);
 647     return_trace (likely (c->check_struct (this)));
 648   }
 649   protected:
 650   BEInt<Type, Size> v;
 651   public:
 652   DEFINE_SIZE_STATIC (Size);
 653 };
 654 
 655 typedef IntType<uint8_t , 1> BYTE;      /* 8-bit unsigned integer. */
 656 typedef IntType<uint16_t, 2> USHORT;    /* 16-bit unsigned integer. */
 657 typedef IntType<int16_t,  2> SHORT;     /* 16-bit signed integer. */
 658 typedef IntType<uint32_t, 4> ULONG;     /* 32-bit unsigned integer. */
 659 typedef IntType<int32_t,  4> LONG;      /* 32-bit signed integer. */
 660 typedef IntType<uint32_t, 3> UINT24;    /* 24-bit unsigned integer. */
 661 
 662 /* 16-bit signed integer (SHORT) that describes a quantity in FUnits. */
 663 typedef SHORT FWORD;
 664 
 665 /* 16-bit unsigned integer (USHORT) that describes a quantity in FUnits. */
 666 typedef USHORT UFWORD;
 667 
 668 /* Date represented in number of seconds since 12:00 midnight, January 1,
 669  * 1904. The value is represented as a signed 64-bit integer. */
 670 struct LONGDATETIME
 671 {
 672   inline bool sanitize (hb_sanitize_context_t *c) const
 673   {
 674     TRACE_SANITIZE (this);
 675     return_trace (likely (c->check_struct (this)));
 676   }
 677   protected:
 678   LONG major;
 679   ULONG minor;
 680   public:
 681   DEFINE_SIZE_STATIC (8);
 682 };
 683 
 684 /* Array of four uint8s (length = 32 bits) used to identify a script, language
 685  * system, feature, or baseline */
 686 struct Tag : ULONG
 687 {
 688   /* What the char* converters return is NOT nul-terminated.  Print using "%.4s" */
 689   inline operator const char* (void) const { return reinterpret_cast<const char *> (&this->v); }
 690   inline operator char* (void) { return reinterpret_cast<char *> (&this->v); }
 691   public:
 692   DEFINE_SIZE_STATIC (4);
 693 };
 694 DEFINE_NULL_DATA (Tag, "    ");
 695 
 696 /* Glyph index number, same as uint16 (length = 16 bits) */
 697 struct GlyphID : USHORT {
 698   static inline int cmp (const GlyphID *a, const GlyphID *b) { return b->USHORT::cmp (*a); }
 699   inline int cmp (hb_codepoint_t a) const { return (int) a - (int) *this; }
 700 };
 701 
 702 /* Script/language-system/feature index */
 703 struct Index : USHORT {
 704   static const unsigned int NOT_FOUND_INDEX = 0xFFFFu;
 705 };
 706 DEFINE_NULL_DATA (Index, "\xff\xff");
 707 
 708 /* Offset, Null offset = 0 */
 709 template <typename Type=USHORT>
 710 struct Offset : Type
 711 {
 712   inline bool is_null (void) const { return 0 == *this; }
 713   public:
 714   DEFINE_SIZE_STATIC (sizeof(Type));
 715 };
 716 
 717 
 718 /* CheckSum */
 719 struct CheckSum : ULONG
 720 {
 721   /* This is reference implementation from the spec. */
 722   static inline uint32_t CalcTableChecksum (const ULONG *Table, uint32_t Length)
 723   {
 724     uint32_t Sum = 0L;
 725     const ULONG *EndPtr = Table+((Length+3) & ~3) / ULONG::static_size;
 726 
 727     while (Table < EndPtr)
 728       Sum += *Table++;
 729     return Sum;
 730   }
 731 
 732   /* Note: data should be 4byte aligned and have 4byte padding at the end. */
 733   inline void set_for_data (const void *data, unsigned int length)
 734   { set (CalcTableChecksum ((const ULONG *) data, length)); }
 735 
 736   public:
 737   DEFINE_SIZE_STATIC (4);
 738 };
 739 
 740 
 741 /*
 742  * Version Numbers
 743  */
 744 
 745 struct FixedVersion
 746 {
 747   inline uint32_t to_int (void) const { return (major << 16) + minor; }
 748 
 749   inline bool sanitize (hb_sanitize_context_t *c) const
 750   {
 751     TRACE_SANITIZE (this);
 752     return_trace (c->check_struct (this));
 753   }
 754 
 755   USHORT major;
 756   USHORT minor;
 757   public:
 758   DEFINE_SIZE_STATIC (4);
 759 };
 760 
 761 
 762 
 763 /*
 764  * Template subclasses of Offset that do the dereferencing.
 765  * Use: (base+offset)
 766  */
 767 
 768 template <typename Type, typename OffsetType=USHORT>
 769 struct OffsetTo : Offset<OffsetType>
 770 {
 771   inline const Type& operator () (const void *base) const
 772   {
 773     unsigned int offset = *this;
 774     if (unlikely (!offset)) return Null(Type);
 775     return StructAtOffset<Type> (base, offset);
 776   }
 777 
 778   inline Type& serialize (hb_serialize_context_t *c, const void *base)
 779   {
 780     Type *t = c->start_embed<Type> ();
 781     this->set ((char *) t - (char *) base); /* TODO(serialize) Overflow? */
 782     return *t;
 783   }
 784 
 785   inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
 786   {
 787     TRACE_SANITIZE (this);
 788     if (unlikely (!c->check_struct (this))) return_trace (false);
 789     unsigned int offset = *this;
 790     if (unlikely (!offset)) return_trace (true);
 791     const Type &obj = StructAtOffset<Type> (base, offset);
 792     return_trace (likely (obj.sanitize (c)) || neuter (c));
 793   }
 794   template <typename T>
 795   inline bool sanitize (hb_sanitize_context_t *c, const void *base, T user_data) const
 796   {
 797     TRACE_SANITIZE (this);
 798     if (unlikely (!c->check_struct (this))) return_trace (false);
 799     unsigned int offset = *this;
 800     if (unlikely (!offset)) return_trace (true);
 801     const Type &obj = StructAtOffset<Type> (base, offset);
 802     return_trace (likely (obj.sanitize (c, user_data)) || neuter (c));
 803   }
 804 
 805   /* Set the offset to Null */
 806   inline bool neuter (hb_sanitize_context_t *c) const {
 807     return c->try_set (this, 0);
 808   }
 809   DEFINE_SIZE_STATIC (sizeof(OffsetType));
 810 };
 811 template <typename Base, typename OffsetType, typename Type>
 812 static inline const Type& operator + (const Base &base, const OffsetTo<Type, OffsetType> &offset) { return offset (base); }
 813 template <typename Base, typename OffsetType, typename Type>
 814 static inline Type& operator + (Base &base, OffsetTo<Type, OffsetType> &offset) { return offset (base); }
 815 
 816 
 817 /*
 818  * Array Types
 819  */
 820 
 821 /* An array with a number of elements. */
 822 template <typename Type, typename LenType=USHORT>
 823 struct ArrayOf
 824 {
 825   const Type *sub_array (unsigned int start_offset, unsigned int *pcount /* IN/OUT */) const
 826   {
 827     unsigned int count = len;
 828     if (unlikely (start_offset > count))
 829       count = 0;
 830     else
 831       count -= start_offset;
 832     count = MIN (count, *pcount);
 833     *pcount = count;
 834     return array + start_offset;
 835   }
 836 
 837   inline const Type& operator [] (unsigned int i) const
 838   {
 839     if (unlikely (i >= len)) return Null(Type);
 840     return array[i];
 841   }
 842   inline Type& operator [] (unsigned int i)
 843   {
 844     return array[i];
 845   }
 846   inline unsigned int get_size (void) const
 847   { return len.static_size + len * Type::static_size; }
 848 
 849   inline bool serialize (hb_serialize_context_t *c,
 850                          unsigned int items_len)
 851   {
 852     TRACE_SERIALIZE (this);
 853     if (unlikely (!c->extend_min (*this))) return_trace (false);
 854     len.set (items_len); /* TODO(serialize) Overflow? */
 855     if (unlikely (!c->extend (*this))) return_trace (false);
 856     return_trace (true);
 857   }
 858 
 859   inline bool serialize (hb_serialize_context_t *c,
 860                          Supplier<Type> &items,
 861                          unsigned int items_len)
 862   {
 863     TRACE_SERIALIZE (this);
 864     if (unlikely (!serialize (c, items_len))) return_trace (false);
 865     for (unsigned int i = 0; i < items_len; i++)
 866       array[i] = items[i];
 867     items.advance (items_len);
 868     return_trace (true);
 869   }
 870 
 871   inline bool sanitize (hb_sanitize_context_t *c) const
 872   {
 873     TRACE_SANITIZE (this);
 874     if (unlikely (!sanitize_shallow (c))) return_trace (false);
 875 
 876     /* Note: for structs that do not reference other structs,
 877      * we do not need to call their sanitize() as we already did
 878      * a bound check on the aggregate array size.  We just include
 879      * a small unreachable expression to make sure the structs
 880      * pointed to do have a simple sanitize(), ie. they do not
 881      * reference other structs via offsets.
 882      */
 883     (void) (false && array[0].sanitize (c));
 884 
 885     return_trace (true);
 886   }
 887   inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
 888   {
 889     TRACE_SANITIZE (this);
 890     if (unlikely (!sanitize_shallow (c))) return_trace (false);
 891     unsigned int count = len;
 892     for (unsigned int i = 0; i < count; i++)
 893       if (unlikely (!array[i].sanitize (c, base)))
 894         return_trace (false);
 895     return_trace (true);
 896   }
 897   template <typename T>
 898   inline bool sanitize (hb_sanitize_context_t *c, const void *base, T user_data) const
 899   {
 900     TRACE_SANITIZE (this);
 901     if (unlikely (!sanitize_shallow (c))) return_trace (false);
 902     unsigned int count = len;
 903     for (unsigned int i = 0; i < count; i++)
 904       if (unlikely (!array[i].sanitize (c, base, user_data)))
 905         return_trace (false);
 906     return_trace (true);
 907   }
 908 
 909   template <typename SearchType>
 910   inline int lsearch (const SearchType &x) const
 911   {
 912     unsigned int count = len;
 913     for (unsigned int i = 0; i < count; i++)
 914       if (!this->array[i].cmp (x))
 915         return i;
 916     return -1;
 917   }
 918 
 919   private:
 920   inline bool sanitize_shallow (hb_sanitize_context_t *c) const
 921   {
 922     TRACE_SANITIZE (this);
 923     return_trace (c->check_struct (this) && c->check_array (array, Type::static_size, len));
 924   }
 925 
 926   public:
 927   LenType len;
 928   Type array[VAR];
 929   public:
 930   DEFINE_SIZE_ARRAY (sizeof (LenType), array);
 931 };
 932 
 933 /* Array of Offset's */
 934 template <typename Type>
 935 struct OffsetArrayOf : ArrayOf<OffsetTo<Type> > {};
 936 
 937 /* Array of offsets relative to the beginning of the array itself. */
 938 template <typename Type>
 939 struct OffsetListOf : OffsetArrayOf<Type>
 940 {
 941   inline const Type& operator [] (unsigned int i) const
 942   {
 943     if (unlikely (i >= this->len)) return Null(Type);
 944     return this+this->array[i];
 945   }
 946 
 947   inline bool sanitize (hb_sanitize_context_t *c) const
 948   {
 949     TRACE_SANITIZE (this);
 950     return_trace (OffsetArrayOf<Type>::sanitize (c, this));
 951   }
 952   template <typename T>
 953   inline bool sanitize (hb_sanitize_context_t *c, T user_data) const
 954   {
 955     TRACE_SANITIZE (this);
 956     return_trace (OffsetArrayOf<Type>::sanitize (c, this, user_data));
 957   }
 958 };
 959 
 960 
 961 /* An array starting at second element. */
 962 template <typename Type, typename LenType=USHORT>
 963 struct HeadlessArrayOf
 964 {
 965   inline const Type& operator [] (unsigned int i) const
 966   {
 967     if (unlikely (i >= len || !i)) return Null(Type);
 968     return array[i-1];
 969   }
 970   inline unsigned int get_size (void) const
 971   { return len.static_size + (len ? len - 1 : 0) * Type::static_size; }
 972 
 973   inline bool serialize (hb_serialize_context_t *c,
 974                          Supplier<Type> &items,
 975                          unsigned int items_len)
 976   {
 977     TRACE_SERIALIZE (this);
 978     if (unlikely (!c->extend_min (*this))) return_trace (false);
 979     len.set (items_len); /* TODO(serialize) Overflow? */
 980     if (unlikely (!items_len)) return_trace (true);
 981     if (unlikely (!c->extend (*this))) return_trace (false);
 982     for (unsigned int i = 0; i < items_len - 1; i++)
 983       array[i] = items[i];
 984     items.advance (items_len - 1);
 985     return_trace (true);
 986   }
 987 
 988   inline bool sanitize_shallow (hb_sanitize_context_t *c) const
 989   {
 990     return c->check_struct (this)
 991         && c->check_array (this, Type::static_size, len);
 992   }
 993 
 994   inline bool sanitize (hb_sanitize_context_t *c) const
 995   {
 996     TRACE_SANITIZE (this);
 997     if (unlikely (!sanitize_shallow (c))) return_trace (false);
 998 
 999     /* Note: for structs that do not reference other structs,
1000      * we do not need to call their sanitize() as we already did
1001      * a bound check on the aggregate array size.  We just include
1002      * a small unreachable expression to make sure the structs
1003      * pointed to do have a simple sanitize(), ie. they do not
1004      * reference other structs via offsets.
1005      */
1006     (void) (false && array[0].sanitize (c));
1007 
1008     return_trace (true);
1009   }
1010 
1011   LenType len;
1012   Type array[VAR];
1013   public:
1014   DEFINE_SIZE_ARRAY (sizeof (LenType), array);
1015 };
1016 
1017 
1018 /* An array with sorted elements.  Supports binary searching. */
1019 template <typename Type, typename LenType=USHORT>
1020 struct SortedArrayOf : ArrayOf<Type, LenType>
1021 {
1022   template <typename SearchType>
1023   inline int bsearch (const SearchType &x) const
1024   {
1025     /* Hand-coded bsearch here since this is in the hot inner loop. */
1026     int min = 0, max = (int) this->len - 1;
1027     while (min <= max)
1028     {
1029       int mid = (min + max) / 2;
1030       int c = this->array[mid].cmp (x);
1031       if (c < 0)
1032         max = mid - 1;
1033       else if (c > 0)
1034         min = mid + 1;
1035       else
1036         return mid;
1037     }
1038     return -1;
1039   }
1040 };
1041 
1042 
1043 } /* namespace OT */
1044 
1045 
1046 #endif /* HB_OPEN_TYPE_PRIVATE_HH */