LCOV - code coverage report
Current view: directory - gfx/harfbuzz/src - hb-open-type-private.hh (source / functions) Found Hit Coverage
Test: app.info Lines: 190 0 0.0 %
Date: 2012-06-02 Functions: 649 0 0.0 %

       1                 : /*
       2                 :  * Copyright © 2007,2008,2009,2010  Red Hat, Inc.
       3                 :  *
       4                 :  *  This is part of HarfBuzz, a text shaping library.
       5                 :  *
       6                 :  * Permission is hereby granted, without written agreement and without
       7                 :  * license or royalty fees, to use, copy, modify, and distribute this
       8                 :  * software and its documentation for any purpose, provided that the
       9                 :  * above copyright notice and the following two paragraphs appear in
      10                 :  * all copies of this software.
      11                 :  *
      12                 :  * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
      13                 :  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
      14                 :  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
      15                 :  * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
      16                 :  * DAMAGE.
      17                 :  *
      18                 :  * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
      19                 :  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
      20                 :  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
      21                 :  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
      22                 :  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
      23                 :  *
      24                 :  * Red Hat Author(s): Behdad Esfahbod
      25                 :  */
      26                 : 
      27                 : #ifndef HB_OPEN_TYPE_PRIVATE_HH
      28                 : #define HB_OPEN_TYPE_PRIVATE_HH
      29                 : 
      30                 : #include "hb-private.hh"
      31                 : 
      32                 : #include "hb-blob.h"
      33                 : 
      34                 : 
      35                 : 
      36                 : /*
      37                 :  * Casts
      38                 :  */
      39                 : 
      40                 : /* Cast to struct T, reference to reference */
      41                 : template<typename Type, typename TObject>
      42               0 : inline const Type& CastR(const TObject &X)
      43               0 : { return reinterpret_cast<const Type&> (X); }
      44                 : template<typename Type, typename TObject>
      45               0 : inline Type& CastR(TObject &X)
      46               0 : { return reinterpret_cast<Type&> (X); }
      47                 : 
      48                 : /* Cast to struct T, pointer to pointer */
      49                 : template<typename Type, typename TObject>
      50               0 : inline const Type* CastP(const TObject *X)
      51               0 : { return reinterpret_cast<const Type*> (X); }
      52                 : template<typename Type, typename TObject>
      53               0 : inline Type* CastP(TObject *X)
      54               0 : { return reinterpret_cast<Type*> (X); }
      55                 : 
      56                 : /* StructAtOffset<T>(P,Ofs) returns the struct T& that is placed at memory
      57                 :  * location pointed to by P plus Ofs bytes. */
      58                 : template<typename Type>
      59               0 : inline const Type& StructAtOffset(const void *P, unsigned int offset)
      60               0 : { return * reinterpret_cast<const Type*> ((const char *) P + offset); }
      61                 : template<typename Type>
      62               0 : inline Type& StructAtOffset(void *P, unsigned int offset)
      63               0 : { return * reinterpret_cast<Type*> ((char *) P + offset); }
      64                 : 
      65                 : /* StructAfter<T>(X) returns the struct T& that is placed after X.
      66                 :  * Works with X of variable size also.  X must implement get_size() */
      67                 : template<typename Type, typename TObject>
      68               0 : inline const Type& StructAfter(const TObject &X)
      69               0 : { return StructAtOffset<Type>(&X, X.get_size()); }
      70                 : template<typename Type, typename TObject>
      71               0 : inline Type& StructAfter(TObject &X)
      72               0 : { return StructAtOffset<Type>(&X, X.get_size()); }
      73                 : 
      74                 : 
      75                 : 
      76                 : /*
      77                 :  * Size checking
      78                 :  */
      79                 : 
      80                 : /* Check _assertion in a method environment */
      81                 : #define _DEFINE_SIZE_ASSERTION(_assertion) \
      82                 :   inline void _size_assertion (void) const \
      83                 :   { ASSERT_STATIC (_assertion); }
      84                 : /* Check that _code compiles in a method environment */
      85                 : #define _DEFINE_COMPILES_ASSERTION(_code) \
      86                 :   inline void _compiles_assertion (void) const \
      87                 :   { _code; }
      88                 : 
      89                 : 
      90                 : #define DEFINE_SIZE_STATIC(size) \
      91                 :   _DEFINE_SIZE_ASSERTION (sizeof (*this) == (size)); \
      92                 :   static const unsigned int static_size = (size); \
      93                 :   static const unsigned int min_size = (size)
      94                 : 
      95                 : /* Size signifying variable-sized array */
      96                 : #define VAR 1
      97                 : 
      98                 : #define DEFINE_SIZE_UNION(size, _member) \
      99                 :   _DEFINE_SIZE_ASSERTION (this->u._member.static_size == (size)); \
     100                 :   static const unsigned int min_size = (size)
     101                 : 
     102                 : #define DEFINE_SIZE_MIN(size) \
     103                 :   _DEFINE_SIZE_ASSERTION (sizeof (*this) >= (size)); \
     104                 :   static const unsigned int min_size = (size)
     105                 : 
     106                 : #define DEFINE_SIZE_ARRAY(size, array) \
     107                 :   _DEFINE_SIZE_ASSERTION (sizeof (*this) == (size) + sizeof (array[0])); \
     108                 :   _DEFINE_COMPILES_ASSERTION ((void) array[0].static_size) \
     109                 :   static const unsigned int min_size = (size)
     110                 : 
     111                 : #define DEFINE_SIZE_ARRAY2(size, array1, array2) \
     112                 :   _DEFINE_SIZE_ASSERTION (sizeof (*this) == (size) + sizeof (this->array1[0]) + sizeof (this->array2[0])); \
     113                 :   _DEFINE_COMPILES_ASSERTION ((void) array1[0].static_size; (void) array2[0].static_size) \
     114                 :   static const unsigned int min_size = (size)
     115                 : 
     116                 : 
     117                 : 
     118                 : /*
     119                 :  * Null objects
     120                 :  */
     121                 : 
     122                 : /* Global nul-content Null pool.  Enlarge as necessary. */
     123                 : static const void *_NullPool[64 / sizeof (void *)];
     124                 : 
     125                 : /* Generic nul-content Null objects. */
     126                 : template <typename Type>
     127               0 : static inline const Type& Null (void) {
     128                 :   ASSERT_STATIC (Type::min_size <= sizeof (_NullPool));
     129               0 :   return *CastP<Type> (_NullPool);
     130                 : }
     131                 : 
     132                 : /* Specializaiton for arbitrary-content arbitrary-sized Null objects. */
     133                 : #define DEFINE_NULL_DATA(Type, data) \
     134                 : static const char _Null##Type[Type::min_size + 1] = data; /* +1 is for nul-termination in data */ \
     135                 : template <> \
     136                 : inline const Type& Null<Type> (void) { \
     137                 :   return *CastP<Type> (_Null##Type); \
     138                 : } /* The following line really exists such that we end in a place needing semicolon */ \
     139                 : ASSERT_STATIC (Type::min_size + 1 <= sizeof (_Null##Type))
     140                 : 
     141                 : /* Accessor macro. */
     142                 : #define Null(Type) Null<Type>()
     143                 : 
     144                 : 
     145                 : 
     146                 : /*
     147                 :  * Sanitize
     148                 :  */
     149                 : 
     150                 : #ifndef HB_DEBUG_SANITIZE
     151                 : #define HB_DEBUG_SANITIZE (HB_DEBUG+0)
     152                 : #endif
     153                 : 
     154                 : 
     155                 : #define TRACE_SANITIZE() \
     156                 :         hb_auto_trace_t<HB_DEBUG_SANITIZE> trace (&c->debug_depth, "SANITIZE", this, NULL, HB_FUNC);
     157                 : 
     158                 : 
     159                 : struct hb_sanitize_context_t
     160                 : {
     161               0 :   inline void init (hb_blob_t *b)
     162                 :   {
     163               0 :     this->blob = hb_blob_reference (b);
     164               0 :     this->writable = false;
     165               0 :   }
     166                 : 
     167               0 :   inline void setup (void)
     168                 :   {
     169               0 :     this->start = hb_blob_get_data (this->blob, NULL);
     170               0 :     this->end = this->start + hb_blob_get_length (this->blob);
     171               0 :     this->edit_count = 0;
     172               0 :     this->debug_depth = 0;
     173                 : 
     174                 :     DEBUG_MSG (SANITIZE, this->blob,
     175                 :                "init [%p..%p] (%lu bytes)",
     176                 :                this->start, this->end,
     177               0 :                (unsigned long) (this->end - this->start));
     178               0 :   }
     179                 : 
     180               0 :   inline void finish (void)
     181                 :   {
     182                 :     DEBUG_MSG (SANITIZE, this->blob,
     183                 :                "fini [%p..%p] %u edit requests",
     184               0 :                this->start, this->end, this->edit_count);
     185                 : 
     186               0 :     hb_blob_destroy (this->blob);
     187               0 :     this->blob = NULL;
     188               0 :     this->start = this->end = NULL;
     189               0 :   }
     190                 : 
     191               0 :   inline bool check_range (const void *base, unsigned int len) const
     192                 :   {
     193               0 :     const char *p = (const char *) base;
     194                 :     bool ret = this->start <= p &&
     195                 :                p <= this->end &&
     196               0 :                (unsigned int) (this->end - p) >= len;
     197                 : 
     198                 :     DEBUG_MSG_LEVEL (SANITIZE, this->blob, this->debug_depth,
     199                 :                      "%-*d-> range [%p..%p] (%d bytes) in [%p..%p] -> %s",
     200                 :                      this->debug_depth, this->debug_depth,
     201                 :                      p, p + len, len,
     202                 :                      this->start, this->end,
     203               0 :                      ret ? "pass" : "FAIL");
     204                 : 
     205               0 :     return likely (ret);
     206                 :   }
     207                 : 
     208               0 :   inline bool check_array (const void *base, unsigned int record_size, unsigned int len) const
     209                 :   {
     210               0 :     const char *p = (const char *) base;
     211               0 :     bool overflows = _hb_unsigned_int_mul_overflows (len, record_size);
     212                 : 
     213                 :     DEBUG_MSG_LEVEL (SANITIZE, this->blob, this->debug_depth,
     214                 :                      "%-*d-> array [%p..%p] (%d*%d=%ld bytes) in [%p..%p] -> %s",
     215                 :                      this->debug_depth, this->debug_depth,
     216                 :                      p, p + (record_size * len), record_size, len, (unsigned long) record_size * len,
     217                 :                      this->start, this->end,
     218               0 :                      !overflows ? "does not overflow" : "OVERFLOWS FAIL");
     219                 : 
     220               0 :     return likely (!overflows && this->check_range (base, record_size * len));
     221                 :   }
     222                 : 
     223                 :   template <typename Type>
     224               0 :   inline bool check_struct (const Type *obj) const
     225                 :   {
     226               0 :     return likely (this->check_range (obj, obj->min_size));
     227                 :   }
     228                 : 
     229               0 :   inline bool can_edit (const void *base HB_UNUSED, unsigned int len HB_UNUSED)
     230                 :   {
     231               0 :     const char *p = (const char *) base;
     232               0 :     this->edit_count++;
     233                 : 
     234                 :     DEBUG_MSG_LEVEL (SANITIZE, this->blob, this->debug_depth,
     235                 :                      "%-*d-> edit(%u) [%p..%p] (%d bytes) in [%p..%p] -> %s",
     236                 :                      this->debug_depth, this->debug_depth,
     237                 :                      this->edit_count,
     238                 :                      p, p + len, len,
     239                 :                      this->start, this->end,
     240               0 :                      this->writable ? "granted" : "REJECTED");
     241                 : 
     242               0 :     return this->writable;
     243                 :   }
     244                 : 
     245                 :   unsigned int debug_depth;
     246                 :   const char *start, *end;
     247                 :   bool writable;
     248                 :   unsigned int edit_count;
     249                 :   hb_blob_t *blob;
     250                 : };
     251                 : 
     252                 : 
     253                 : 
     254                 : /* Template to sanitize an object. */
     255                 : template <typename Type>
     256                 : struct Sanitizer
     257                 : {
     258               0 :   static hb_blob_t *sanitize (hb_blob_t *blob) {
     259               0 :     hb_sanitize_context_t c[1] = {{0}};
     260                 :     bool sane;
     261                 : 
     262                 :     /* TODO is_sane() stuff */
     263                 : 
     264               0 :     c->init (blob);
     265                 : 
     266                 :   retry:
     267               0 :     DEBUG_MSG_FUNC (SANITIZE, blob, "start");
     268                 : 
     269               0 :     c->setup ();
     270                 : 
     271               0 :     if (unlikely (!c->start)) {
     272               0 :       c->finish ();
     273               0 :       return blob;
     274                 :     }
     275                 : 
     276               0 :     Type *t = CastP<Type> (const_cast<char *> (c->start));
     277                 : 
     278               0 :     sane = t->sanitize (c);
     279               0 :     if (sane) {
     280               0 :       if (c->edit_count) {
     281               0 :         DEBUG_MSG_FUNC (SANITIZE, blob, "passed first round with %d edits; going for second round", c->edit_count);
     282                 : 
     283                 :         /* sanitize again to ensure no toe-stepping */
     284               0 :         c->edit_count = 0;
     285               0 :         sane = t->sanitize (c);
     286               0 :         if (c->edit_count) {
     287               0 :           DEBUG_MSG_FUNC (SANITIZE, blob, "requested %d edits in second round; FAILLING", c->edit_count);
     288               0 :           sane = false;
     289                 :         }
     290                 :       }
     291                 :     } else {
     292               0 :       unsigned int edit_count = c->edit_count;
     293               0 :       if (edit_count && !c->writable) {
     294               0 :         c->start = hb_blob_get_data_writable (blob, NULL);
     295               0 :         c->end = c->start + hb_blob_get_length (blob);
     296                 : 
     297               0 :         if (c->start) {
     298               0 :           c->writable = true;
     299                 :           /* ok, we made it writable by relocating.  try again */
     300               0 :           DEBUG_MSG_FUNC (SANITIZE, blob, "retry");
     301               0 :           goto retry;
     302                 :         }
     303                 :       }
     304                 :     }
     305                 : 
     306               0 :     c->finish ();
     307                 : 
     308               0 :     DEBUG_MSG_FUNC (SANITIZE, blob, sane ? "PASSED" : "FAILED");
     309               0 :     if (sane)
     310               0 :       return blob;
     311                 :     else {
     312               0 :       hb_blob_destroy (blob);
     313               0 :       return hb_blob_get_empty ();
     314                 :     }
     315                 :   }
     316                 : 
     317               0 :   static const Type* lock_instance (hb_blob_t *blob) {
     318               0 :     hb_blob_make_immutable (blob);
     319               0 :     const char *base = hb_blob_get_data (blob, NULL);
     320               0 :     return unlikely (!base) ? &Null(Type) : CastP<Type> (base);
     321                 :   }
     322                 : };
     323                 : 
     324                 : 
     325                 : 
     326                 : 
     327                 : /*
     328                 :  *
     329                 :  * The OpenType Font File: Data Types
     330                 :  */
     331                 : 
     332                 : 
     333                 : /* "The following data types are used in the OpenType font file.
     334                 :  *  All OpenType fonts use Motorola-style byte ordering (Big Endian):" */
     335                 : 
     336                 : /*
     337                 :  * Int types
     338                 :  */
     339                 : 
     340                 : 
     341                 : template <typename Type, int Bytes> struct BEInt;
     342                 : 
     343                 : /* LONGTERMTODO: On machines allowing unaligned access, we can make the
     344                 :  * following tighter by using byteswap instructions on ints directly. */
     345                 : template <typename Type>
     346                 : struct BEInt<Type, 2>
     347                 : {
     348                 :   public:
     349               0 :   inline void set (Type i) { hb_be_uint16_put (v,i); }
     350               0 :   inline operator Type (void) const { return hb_be_uint16_get (v); }
     351                 :   inline bool operator == (const BEInt<Type, 2>& o) const { return hb_be_uint16_eq (v, o.v); }
     352                 :   inline bool operator != (const BEInt<Type, 2>& o) const { return !(*this == o); }
     353                 :   private: uint8_t v[2];
     354                 : };
     355                 : template <typename Type>
     356                 : struct BEInt<Type, 4>
     357                 : {
     358                 :   public:
     359               0 :   inline void set (Type i) { hb_be_uint32_put (v,i); }
     360               0 :   inline operator Type (void) const { return hb_be_uint32_get (v); }
     361               0 :   inline bool operator == (const BEInt<Type, 4>& o) const { return hb_be_uint32_eq (v, o.v); }
     362                 :   inline bool operator != (const BEInt<Type, 4>& o) const { return !(*this == o); }
     363                 :   private: uint8_t v[4];
     364                 : };
     365                 : 
     366                 : /* Integer types in big-endian order and no alignment requirement */
     367                 : template <typename Type>
     368                 : struct IntType
     369                 : {
     370               0 :   inline void set (Type i) { v.set (i); }
     371               0 :   inline operator Type(void) const { return v; }
     372               0 :   inline bool operator == (const IntType<Type> &o) const { return v == o.v; }
     373                 :   inline bool operator != (const IntType<Type> &o) const { return v != o.v; }
     374               0 :   inline int cmp (Type a) const { Type b = v; return a < b ? -1 : a == b ? 0 : +1; }
     375               0 :   inline bool sanitize (hb_sanitize_context_t *c) {
     376               0 :     TRACE_SANITIZE ();
     377               0 :     return likely (c->check_struct (this));
     378                 :   }
     379                 :   protected:
     380                 :   BEInt<Type, sizeof (Type)> v;
     381                 :   public:
     382                 :   DEFINE_SIZE_STATIC (sizeof (Type));
     383                 : };
     384                 : 
     385                 : /* Typedef these to avoid clash with windows.h */
     386                 : #define USHORT  HB_USHORT
     387                 : #define SHORT   HB_SHORT
     388                 : #define ULONG   HB_ULONG
     389                 : #define LONG    HB_LONG
     390                 : typedef IntType<uint16_t> USHORT; /* 16-bit unsigned integer. */
     391                 : typedef IntType<int16_t>  SHORT;  /* 16-bit signed integer. */
     392                 : typedef IntType<uint32_t> ULONG;  /* 32-bit unsigned integer. */
     393                 : typedef IntType<int32_t>  LONG;           /* 32-bit signed integer. */
     394                 : 
     395                 : /* 16-bit signed integer (SHORT) that describes a quantity in FUnits. */
     396                 : typedef SHORT FWORD;
     397                 : 
     398                 : /* 16-bit unsigned integer (USHORT) that describes a quantity in FUnits. */
     399                 : typedef USHORT UFWORD;
     400                 : 
     401                 : /* Date represented in number of seconds since 12:00 midnight, January 1,
     402                 :  * 1904. The value is represented as a signed 64-bit integer. */
     403                 : struct LONGDATETIME
     404                 : {
     405                 :   inline bool sanitize (hb_sanitize_context_t *c) {
     406                 :     TRACE_SANITIZE ();
     407                 :     return likely (c->check_struct (this));
     408                 :   }
     409                 :   private:
     410                 :   LONG major;
     411                 :   ULONG minor;
     412                 :   public:
     413                 :   DEFINE_SIZE_STATIC (8);
     414                 : };
     415                 : 
     416                 : /* Array of four uint8s (length = 32 bits) used to identify a script, language
     417                 :  * system, feature, or baseline */
     418                 : struct Tag : ULONG
     419                 : {
     420                 :   /* What the char* converters return is NOT nul-terminated.  Print using "%.4s" */
     421                 :   inline operator const char* (void) const { return reinterpret_cast<const char *> (&this->v); }
     422                 :   inline operator char* (void) { return reinterpret_cast<char *> (&this->v); }
     423                 :   public:
     424                 :   DEFINE_SIZE_STATIC (4);
     425                 : };
     426               0 : DEFINE_NULL_DATA (Tag, "    ");
     427                 : 
     428                 : /* Glyph index number, same as uint16 (length = 16 bits) */
     429                 : typedef USHORT GlyphID;
     430                 : 
     431                 : /* Script/language-system/feature index */
     432                 : struct Index : USHORT {
     433                 :   static const unsigned int NOT_FOUND_INDEX = 0xFFFF;
     434                 : };
     435               0 : DEFINE_NULL_DATA (Index, "\xff\xff");
     436                 : 
     437                 : /* Offset to a table, same as uint16 (length = 16 bits), Null offset = 0x0000 */
     438                 : typedef USHORT Offset;
     439                 : 
     440                 : /* LongOffset to a table, same as uint32 (length = 32 bits), Null offset = 0x00000000 */
     441                 : typedef ULONG LongOffset;
     442                 : 
     443                 : 
     444                 : /* CheckSum */
     445                 : struct CheckSum : ULONG
     446                 : {
     447                 :   static uint32_t CalcTableChecksum (ULONG *Table, uint32_t Length)
     448                 :   {
     449                 :     uint32_t Sum = 0L;
     450                 :     ULONG *EndPtr = Table+((Length+3) & ~3) / ULONG::static_size;
     451                 : 
     452                 :     while (Table < EndPtr)
     453                 :       Sum += *Table++;
     454                 :     return Sum;
     455                 :   }
     456                 :   public:
     457                 :   DEFINE_SIZE_STATIC (4);
     458                 : };
     459                 : 
     460                 : 
     461                 : /*
     462                 :  * Version Numbers
     463                 :  */
     464                 : 
     465                 : struct FixedVersion
     466                 : {
     467               0 :   inline uint32_t to_int (void) const { return (major << 16) + minor; }
     468                 : 
     469               0 :   inline bool sanitize (hb_sanitize_context_t *c) {
     470               0 :     TRACE_SANITIZE ();
     471               0 :     return c->check_struct (this);
     472                 :   }
     473                 : 
     474                 :   USHORT major;
     475                 :   USHORT minor;
     476                 :   public:
     477                 :   DEFINE_SIZE_STATIC (4);
     478                 : };
     479                 : 
     480                 : 
     481                 : 
     482                 : /*
     483                 :  * Template subclasses of Offset and LongOffset that do the dereferencing.
     484                 :  * Use: (base+offset)
     485                 :  */
     486                 : 
     487                 : template <typename OffsetType, typename Type>
     488                 : struct GenericOffsetTo : OffsetType
     489                 : {
     490               0 :   inline const Type& operator () (const void *base) const
     491                 :   {
     492               0 :     unsigned int offset = *this;
     493               0 :     if (unlikely (!offset)) return Null(Type);
     494               0 :     return StructAtOffset<Type> (base, offset);
     495                 :   }
     496                 : 
     497               0 :   inline bool sanitize (hb_sanitize_context_t *c, void *base) {
     498               0 :     TRACE_SANITIZE ();
     499               0 :     if (unlikely (!c->check_struct (this))) return false;
     500               0 :     unsigned int offset = *this;
     501               0 :     if (unlikely (!offset)) return true;
     502               0 :     Type &obj = StructAtOffset<Type> (base, offset);
     503               0 :     return likely (obj.sanitize (c)) || neuter (c);
     504                 :   }
     505                 :   template <typename T>
     506               0 :   inline bool sanitize (hb_sanitize_context_t *c, void *base, T user_data) {
     507               0 :     TRACE_SANITIZE ();
     508               0 :     if (unlikely (!c->check_struct (this))) return false;
     509               0 :     unsigned int offset = *this;
     510               0 :     if (unlikely (!offset)) return true;
     511               0 :     Type &obj = StructAtOffset<Type> (base, offset);
     512               0 :     return likely (obj.sanitize (c, user_data)) || neuter (c);
     513                 :   }
     514                 : 
     515                 :   private:
     516                 :   /* Set the offset to Null */
     517               0 :   inline bool neuter (hb_sanitize_context_t *c) {
     518               0 :     if (c->can_edit (this, this->static_size)) {
     519               0 :       this->set (0); /* 0 is Null offset */
     520               0 :       return true;
     521                 :     }
     522               0 :     return false;
     523                 :   }
     524                 : };
     525                 : template <typename Base, typename OffsetType, typename Type>
     526               0 : inline const Type& operator + (const Base &base, GenericOffsetTo<OffsetType, Type> offset) { return offset (base); }
     527                 : 
     528                 : template <typename Type>
     529                 : struct OffsetTo : GenericOffsetTo<Offset, Type> {};
     530                 : 
     531                 : template <typename Type>
     532                 : struct LongOffsetTo : GenericOffsetTo<LongOffset, Type> {};
     533                 : 
     534                 : 
     535                 : /*
     536                 :  * Array Types
     537                 :  */
     538                 : 
     539                 : template <typename LenType, typename Type>
     540                 : struct GenericArrayOf
     541                 : {
     542               0 :   const Type *sub_array (unsigned int start_offset, unsigned int *pcount /* IN/OUT */) const
     543                 :   {
     544               0 :     unsigned int count = len;
     545               0 :     if (unlikely (start_offset > count))
     546               0 :       count = 0;
     547                 :     else
     548               0 :       count -= start_offset;
     549               0 :     count = MIN (count, *pcount);
     550               0 :     *pcount = count;
     551               0 :     return array + start_offset;
     552                 :   }
     553                 : 
     554               0 :   inline const Type& operator [] (unsigned int i) const
     555                 :   {
     556               0 :     if (unlikely (i >= len)) return Null(Type);
     557               0 :     return array[i];
     558                 :   }
     559               0 :   inline unsigned int get_size (void) const
     560               0 :   { return len.static_size + len * Type::static_size; }
     561                 : 
     562               0 :   inline bool sanitize (hb_sanitize_context_t *c) {
     563               0 :     TRACE_SANITIZE ();
     564               0 :     if (unlikely (!sanitize_shallow (c))) return false;
     565                 : 
     566                 :     /* Note: for structs that do not reference other structs,
     567                 :      * we do not need to call their sanitize() as we already did
     568                 :      * a bound check on the aggregate array size.  We just include
     569                 :      * a small unreachable expression to make sure the structs
     570                 :      * pointed to do have a simple sanitize(), ie. they do not
     571                 :      * reference other structs via offsets.
     572                 :      */
     573                 :     (void) (false && array[0].sanitize (c));
     574                 : 
     575               0 :     return true;
     576                 :   }
     577               0 :   inline bool sanitize (hb_sanitize_context_t *c, void *base) {
     578               0 :     TRACE_SANITIZE ();
     579               0 :     if (unlikely (!sanitize_shallow (c))) return false;
     580               0 :     unsigned int count = len;
     581               0 :     for (unsigned int i = 0; i < count; i++)
     582               0 :       if (unlikely (!array[i].sanitize (c, base)))
     583               0 :         return false;
     584               0 :     return true;
     585                 :   }
     586                 :   template <typename T>
     587               0 :   inline bool sanitize (hb_sanitize_context_t *c, void *base, T user_data) {
     588               0 :     TRACE_SANITIZE ();
     589               0 :     if (unlikely (!sanitize_shallow (c))) return false;
     590               0 :     unsigned int count = len;
     591               0 :     for (unsigned int i = 0; i < count; i++)
     592               0 :       if (unlikely (!array[i].sanitize (c, base, user_data)))
     593               0 :         return false;
     594               0 :     return true;
     595                 :   }
     596                 : 
     597                 :   private:
     598               0 :   inline bool sanitize_shallow (hb_sanitize_context_t *c) {
     599               0 :     TRACE_SANITIZE ();
     600                 :     return c->check_struct (this)
     601               0 :         && c->check_array (this, Type::static_size, len);
     602                 :   }
     603                 : 
     604                 :   public:
     605                 :   LenType len;
     606                 :   Type array[VAR];
     607                 :   public:
     608                 :   DEFINE_SIZE_ARRAY (sizeof (LenType), array);
     609                 : };
     610                 : 
     611                 : /* An array with a USHORT number of elements. */
     612                 : template <typename Type>
     613                 : struct ArrayOf : GenericArrayOf<USHORT, Type> {};
     614                 : 
     615                 : /* An array with a ULONG number of elements. */
     616                 : template <typename Type>
     617                 : struct LongArrayOf : GenericArrayOf<ULONG, Type> {};
     618                 : 
     619                 : /* Array of Offset's */
     620                 : template <typename Type>
     621                 : struct OffsetArrayOf : ArrayOf<OffsetTo<Type> > {};
     622                 : 
     623                 : /* Array of LongOffset's */
     624                 : template <typename Type>
     625                 : struct LongOffsetArrayOf : ArrayOf<LongOffsetTo<Type> > {};
     626                 : 
     627                 : /* LongArray of LongOffset's */
     628                 : template <typename Type>
     629                 : struct LongOffsetLongArrayOf : LongArrayOf<LongOffsetTo<Type> > {};
     630                 : 
     631                 : /* Array of offsets relative to the beginning of the array itself. */
     632                 : template <typename Type>
     633                 : struct OffsetListOf : OffsetArrayOf<Type>
     634                 : {
     635               0 :   inline const Type& operator [] (unsigned int i) const
     636                 :   {
     637               0 :     if (unlikely (i >= this->len)) return Null(Type);
     638               0 :     return this+this->array[i];
     639                 :   }
     640                 : 
     641               0 :   inline bool sanitize (hb_sanitize_context_t *c) {
     642               0 :     TRACE_SANITIZE ();
     643               0 :     return OffsetArrayOf<Type>::sanitize (c, this);
     644                 :   }
     645                 :   template <typename T>
     646               0 :   inline bool sanitize (hb_sanitize_context_t *c, T user_data) {
     647               0 :     TRACE_SANITIZE ();
     648               0 :     return OffsetArrayOf<Type>::sanitize (c, this, user_data);
     649                 :   }
     650                 : };
     651                 : 
     652                 : 
     653                 : /* An array with a USHORT number of elements,
     654                 :  * starting at second element. */
     655                 : template <typename Type>
     656                 : struct HeadlessArrayOf
     657                 : {
     658               0 :   inline const Type& operator [] (unsigned int i) const
     659                 :   {
     660               0 :     if (unlikely (i >= len || !i)) return Null(Type);
     661               0 :     return array[i-1];
     662                 :   }
     663               0 :   inline unsigned int get_size (void) const
     664               0 :   { return len.static_size + (len ? len - 1 : 0) * Type::static_size; }
     665                 : 
     666               0 :   inline bool sanitize_shallow (hb_sanitize_context_t *c) {
     667                 :     return c->check_struct (this)
     668               0 :         && c->check_array (this, Type::static_size, len);
     669                 :   }
     670                 : 
     671               0 :   inline bool sanitize (hb_sanitize_context_t *c) {
     672               0 :     TRACE_SANITIZE ();
     673               0 :     if (unlikely (!sanitize_shallow (c))) return false;
     674                 : 
     675                 :     /* Note: for structs that do not reference other structs,
     676                 :      * we do not need to call their sanitize() as we already did
     677                 :      * a bound check on the aggregate array size.  We just include
     678                 :      * a small unreachable expression to make sure the structs
     679                 :      * pointed to do have a simple sanitize(), ie. they do not
     680                 :      * reference other structs via offsets.
     681                 :      */
     682                 :     (void) (false && array[0].sanitize (c));
     683                 : 
     684               0 :     return true;
     685                 :   }
     686                 : 
     687                 :   USHORT len;
     688                 :   Type array[VAR];
     689                 :   public:
     690                 :   DEFINE_SIZE_ARRAY (sizeof (USHORT), array);
     691                 : };
     692                 : 
     693                 : 
     694                 : /* An array with sorted elements.  Supports binary searching. */
     695                 : template <typename Type>
     696                 : struct SortedArrayOf : ArrayOf<Type> {
     697                 : 
     698                 :   template <typename SearchType>
     699               0 :   inline int search (const SearchType &x) const {
     700                 :     struct Cmp {
     701               0 :       static int cmp (const SearchType *a, const Type *b) { return b->cmp (*a); }
     702                 :     };
     703               0 :     const Type *p = (const Type *) bsearch (&x, this->array, this->len, sizeof (this->array[0]), (hb_compare_func_t) Cmp::cmp);
     704               0 :     return p ? p - this->array : -1;
     705                 :   }
     706                 : };
     707                 : 
     708                 : 
     709                 : 
     710                 : #endif /* HB_OPEN_TYPE_PRIVATE_HH */

Generated by: LCOV version 1.7