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