Imported Upstream version 2.3.1
[platform/upstream/harfbuzz.git] / src / hb-open-type.hh
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_HH
30 #define HB_OPEN_TYPE_HH
31
32 #include "hb.hh"
33 #include "hb-blob.hh"
34 #include "hb-face.hh"
35 #include "hb-machinery.hh"
36 #include "hb-subset.hh"
37
38
39 namespace OT {
40
41
42 /*
43  *
44  * The OpenType Font File: Data Types
45  */
46
47
48 /* "The following data types are used in the OpenType font file.
49  *  All OpenType fonts use Motorola-style byte ordering (Big Endian):" */
50
51 /*
52  * Int types
53  */
54
55 template <bool is_signed> struct hb_signedness_int;
56 template <> struct hb_signedness_int<false> { typedef unsigned int value; };
57 template <> struct hb_signedness_int<true>  { typedef   signed int value; };
58
59 /* Integer types in big-endian order and no alignment requirement */
60 template <typename Type, unsigned int Size>
61 struct IntType
62 {
63   typedef Type type;
64   typedef typename hb_signedness_int<hb_is_signed<Type>::value>::value wide_type;
65
66   void set (wide_type i) { v.set (i); }
67   operator wide_type () const { return v; }
68   bool operator == (const IntType<Type,Size> &o) const { return (Type) v == (Type) o.v; }
69   bool operator != (const IntType<Type,Size> &o) const { return !(*this == o); }
70   static int cmp (const IntType<Type,Size> *a, const IntType<Type,Size> *b) { return b->cmp (*a); }
71   template <typename Type2>
72   int cmp (Type2 a) const
73   {
74     Type b = v;
75     if (sizeof (Type) < sizeof (int) && sizeof (Type2) < sizeof (int))
76       return (int) a - (int) b;
77     else
78       return a < b ? -1 : a == b ? 0 : +1;
79   }
80   bool sanitize (hb_sanitize_context_t *c) const
81   {
82     TRACE_SANITIZE (this);
83     return_trace (likely (c->check_struct (this)));
84   }
85   protected:
86   BEInt<Type, Size> v;
87   public:
88   DEFINE_SIZE_STATIC (Size);
89 };
90
91 typedef IntType<uint8_t,  1> HBUINT8;   /* 8-bit unsigned integer. */
92 typedef IntType<int8_t,   1> HBINT8;    /* 8-bit signed integer. */
93 typedef IntType<uint16_t, 2> HBUINT16;  /* 16-bit unsigned integer. */
94 typedef IntType<int16_t,  2> HBINT16;   /* 16-bit signed integer. */
95 typedef IntType<uint32_t, 4> HBUINT32;  /* 32-bit unsigned integer. */
96 typedef IntType<int32_t,  4> HBINT32;   /* 32-bit signed integer. */
97 /* Note: we cannot defined a signed HBINT24 because there's no corresponding C type.
98  * Works for unsigned, but not signed, since we rely on compiler for sign-extension. */
99 typedef IntType<uint32_t, 3> HBUINT24;  /* 24-bit unsigned integer. */
100
101 /* 16-bit signed integer (HBINT16) that describes a quantity in FUnits. */
102 typedef HBINT16 FWORD;
103
104 /* 32-bit signed integer (HBINT32) that describes a quantity in FUnits. */
105 typedef HBINT32 FWORD32;
106
107 /* 16-bit unsigned integer (HBUINT16) that describes a quantity in FUnits. */
108 typedef HBUINT16 UFWORD;
109
110 /* 16-bit signed fixed number with the low 14 bits of fraction (2.14). */
111 struct F2DOT14 : HBINT16
112 {
113   // 16384 means 1<<14
114   float to_float () const  { return ((int32_t) v) / 16384.f; }
115   void set_float (float f) { v.set (round (f * 16384.f)); }
116   public:
117   DEFINE_SIZE_STATIC (2);
118 };
119
120 /* 32-bit signed fixed-point number (16.16). */
121 struct Fixed : HBINT32
122 {
123   // 65536 means 1<<16
124   float to_float () const  { return ((int32_t) v) / 65536.f; }
125   void set_float (float f) { v.set (round (f * 65536.f)); }
126   public:
127   DEFINE_SIZE_STATIC (4);
128 };
129
130 /* Date represented in number of seconds since 12:00 midnight, January 1,
131  * 1904. The value is represented as a signed 64-bit integer. */
132 struct LONGDATETIME
133 {
134   bool sanitize (hb_sanitize_context_t *c) const
135   {
136     TRACE_SANITIZE (this);
137     return_trace (likely (c->check_struct (this)));
138   }
139   protected:
140   HBINT32 major;
141   HBUINT32 minor;
142   public:
143   DEFINE_SIZE_STATIC (8);
144 };
145
146 /* Array of four uint8s (length = 32 bits) used to identify a script, language
147  * system, feature, or baseline */
148 struct Tag : HBUINT32
149 {
150   /* What the char* converters return is NOT nul-terminated.  Print using "%.4s" */
151   operator const char* () const { return reinterpret_cast<const char *> (&this->v); }
152   operator char* ()             { return reinterpret_cast<char *> (&this->v); }
153   public:
154   DEFINE_SIZE_STATIC (4);
155 };
156
157 /* Glyph index number, same as uint16 (length = 16 bits) */
158 typedef HBUINT16 GlyphID;
159
160 /* Script/language-system/feature index */
161 struct Index : HBUINT16 {
162   static constexpr unsigned NOT_FOUND_INDEX = 0xFFFFu;
163 };
164 DECLARE_NULL_NAMESPACE_BYTES (OT, Index);
165
166 typedef Index NameID;
167
168 /* Offset, Null offset = 0 */
169 template <typename Type, bool has_null=true>
170 struct Offset : Type
171 {
172   typedef Type type;
173
174   bool is_null () const { return has_null && 0 == *this; }
175
176   void *serialize (hb_serialize_context_t *c, const void *base)
177   {
178     void *t = c->start_embed<void> ();
179     this->set ((char *) t - (char *) base); /* TODO(serialize) Overflow? */
180     return t;
181   }
182
183   public:
184   DEFINE_SIZE_STATIC (sizeof (Type));
185 };
186
187 typedef Offset<HBUINT16> Offset16;
188 typedef Offset<HBUINT32> Offset32;
189
190
191 /* CheckSum */
192 struct CheckSum : HBUINT32
193 {
194   /* This is reference implementation from the spec. */
195   static uint32_t CalcTableChecksum (const HBUINT32 *Table, uint32_t Length)
196   {
197     uint32_t Sum = 0L;
198     assert (0 == (Length & 3));
199     const HBUINT32 *EndPtr = Table + Length / HBUINT32::static_size;
200
201     while (Table < EndPtr)
202       Sum += *Table++;
203     return Sum;
204   }
205
206   /* Note: data should be 4byte aligned and have 4byte padding at the end. */
207   void set_for_data (const void *data, unsigned int length)
208   { set (CalcTableChecksum ((const HBUINT32 *) data, length)); }
209
210   public:
211   DEFINE_SIZE_STATIC (4);
212 };
213
214
215 /*
216  * Version Numbers
217  */
218
219 template <typename FixedType=HBUINT16>
220 struct FixedVersion
221 {
222   uint32_t to_int () const { return (major << (sizeof (FixedType) * 8)) + minor; }
223
224   bool sanitize (hb_sanitize_context_t *c) const
225   {
226     TRACE_SANITIZE (this);
227     return_trace (c->check_struct (this));
228   }
229
230   FixedType major;
231   FixedType minor;
232   public:
233   DEFINE_SIZE_STATIC (2 * sizeof (FixedType));
234 };
235
236
237 /*
238  * Template subclasses of Offset that do the dereferencing.
239  * Use: (base+offset)
240  */
241
242 template <typename Type, bool has_null>
243 struct _hb_has_null
244 {
245   static const Type *get_null () { return nullptr; }
246   static Type *get_crap ()       { return nullptr; }
247 };
248 template <typename Type>
249 struct _hb_has_null<Type, true>
250 {
251   static const Type *get_null () { return &Null(Type); }
252   static Type *get_crap ()       { return &Crap(Type); }
253 };
254
255 template <typename Type, typename OffsetType=HBUINT16, bool has_null=true>
256 struct OffsetTo : Offset<OffsetType, has_null>
257 {
258   const Type& operator () (const void *base) const
259   {
260     if (unlikely (this->is_null ())) return *_hb_has_null<Type, has_null>::get_null ();
261     return StructAtOffset<const Type> (base, *this);
262   }
263   Type& operator () (void *base) const
264   {
265     if (unlikely (this->is_null ())) return *_hb_has_null<Type, has_null>::get_crap ();
266     return StructAtOffset<Type> (base, *this);
267   }
268
269   Type& serialize (hb_serialize_context_t *c, const void *base)
270   {
271     return * (Type *) Offset<OffsetType>::serialize (c, base);
272   }
273
274   template <typename T>
275   void serialize_subset (hb_subset_context_t *c, const T &src, const void *base)
276   {
277     if (&src == &Null (T))
278     {
279       this->set (0);
280       return;
281     }
282     serialize (c->serializer, base);
283     if (!src.subset (c))
284       this->set (0);
285   }
286
287   bool sanitize_shallow (hb_sanitize_context_t *c, const void *base) const
288   {
289     TRACE_SANITIZE (this);
290     if (unlikely (!c->check_struct (this))) return_trace (false);
291     if (unlikely (this->is_null ())) return_trace (true);
292     if (unlikely (!c->check_range (base, *this))) return_trace (false);
293     return_trace (true);
294   }
295
296   bool sanitize (hb_sanitize_context_t *c, const void *base) const
297   {
298     TRACE_SANITIZE (this);
299     return_trace (sanitize_shallow (c, base) &&
300                   (this->is_null () ||
301                    StructAtOffset<Type> (base, *this).sanitize (c) ||
302                    neuter (c)));
303   }
304   template <typename T1>
305   bool sanitize (hb_sanitize_context_t *c, const void *base, T1 d1) const
306   {
307     TRACE_SANITIZE (this);
308     return_trace (sanitize_shallow (c, base) &&
309                   (this->is_null () ||
310                    StructAtOffset<Type> (base, *this).sanitize (c, d1) ||
311                    neuter (c)));
312   }
313   template <typename T1, typename T2>
314   bool sanitize (hb_sanitize_context_t *c, const void *base, T1 d1, T2 d2) const
315   {
316     TRACE_SANITIZE (this);
317     return_trace (sanitize_shallow (c, base) &&
318                   (this->is_null () ||
319                    StructAtOffset<Type> (base, *this).sanitize (c, d1, d2) ||
320                    neuter (c)));
321   }
322   template <typename T1, typename T2, typename T3>
323   bool sanitize (hb_sanitize_context_t *c, const void *base, T1 d1, T2 d2, T3 d3) const
324   {
325     TRACE_SANITIZE (this);
326     return_trace (sanitize_shallow (c, base) &&
327                   (this->is_null () ||
328                    StructAtOffset<Type> (base, *this).sanitize (c, d1, d2, d3) ||
329                    neuter (c)));
330   }
331
332   /* Set the offset to Null */
333   bool neuter (hb_sanitize_context_t *c) const
334   {
335     if (!has_null) return false;
336     return c->try_set (this, 0);
337   }
338   DEFINE_SIZE_STATIC (sizeof (OffsetType));
339 };
340 /* Partial specializations. */
341 template <typename Type,                               bool has_null=true> struct   LOffsetTo : OffsetTo<Type, HBUINT32,   has_null> {};
342 template <typename Type, typename OffsetType=HBUINT16                    > struct  NNOffsetTo : OffsetTo<Type, OffsetType, false> {};
343 template <typename Type                                                  > struct LNNOffsetTo : OffsetTo<Type, HBUINT32,   false> {};
344
345 template <typename Base, typename OffsetType, bool has_null, typename Type>
346 static inline const Type& operator + (const Base &base, const OffsetTo<Type, OffsetType, has_null> &offset) { return offset (base); }
347 template <typename Base, typename OffsetType, bool has_null, typename Type>
348 static inline Type& operator + (Base &base, OffsetTo<Type, OffsetType, has_null> &offset) { return offset (base); }
349
350
351 /*
352  * Array Types
353  */
354
355 template <typename Type>
356 struct UnsizedArrayOf
357 {
358   typedef Type item_t;
359   static constexpr unsigned item_size = hb_static_size (Type);
360
361   HB_NO_CREATE_COPY_ASSIGN_TEMPLATE (UnsizedArrayOf, Type);
362
363   const Type& operator [] (int i_) const
364   {
365     unsigned int i = (unsigned int) i_;
366     const Type *p = &arrayZ[i];
367     if (unlikely (p < arrayZ)) return Null (Type); /* Overflowed. */
368     return *p;
369   }
370   Type& operator [] (int i_)
371   {
372     unsigned int i = (unsigned int) i_;
373     Type *p = &arrayZ[i];
374     if (unlikely (p < arrayZ)) return Crap (Type); /* Overflowed. */
375     return *p;
376   }
377
378   unsigned int get_size (unsigned int len) const
379   { return len * Type::static_size; }
380
381   template <typename T> operator T * () { return arrayZ; }
382   template <typename T> operator const T * () const { return arrayZ; }
383   hb_array_t<Type> as_array (unsigned int len)
384   { return hb_array (arrayZ, len); }
385   hb_array_t<const Type> as_array (unsigned int len) const
386   { return hb_array (arrayZ, len); }
387   operator hb_array_t<Type> ()             { return as_array (); }
388   operator hb_array_t<const Type> () const { return as_array (); }
389
390   template <typename T>
391   Type &lsearch (unsigned int len, const T &x, Type &not_found = Crap (Type))
392   { return *as_array (len).lsearch (x, &not_found); }
393   template <typename T>
394   const Type &lsearch (unsigned int len, const T &x, const Type &not_found = Null (Type)) const
395   { return *as_array (len).lsearch (x, &not_found); }
396
397   void qsort (unsigned int len, unsigned int start = 0, unsigned int end = (unsigned int) -1)
398   { as_array (len).qsort (start, end); }
399
400   bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
401   {
402     TRACE_SANITIZE (this);
403     if (unlikely (!sanitize_shallow (c, count))) return_trace (false);
404
405     /* Note: for structs that do not reference other structs,
406      * we do not need to call their sanitize() as we already did
407      * a bound check on the aggregate array size.  We just include
408      * a small unreachable expression to make sure the structs
409      * pointed to do have a simple sanitize(), ie. they do not
410      * reference other structs via offsets.
411      */
412     (void) (false && arrayZ[0].sanitize (c));
413
414     return_trace (true);
415   }
416   bool sanitize (hb_sanitize_context_t *c, unsigned int count, const void *base) const
417   {
418     TRACE_SANITIZE (this);
419     if (unlikely (!sanitize_shallow (c, count))) return_trace (false);
420     for (unsigned int i = 0; i < count; i++)
421       if (unlikely (!arrayZ[i].sanitize (c, base)))
422         return_trace (false);
423     return_trace (true);
424   }
425   template <typename T>
426   bool sanitize (hb_sanitize_context_t *c, unsigned int count, const void *base, T user_data) const
427   {
428     TRACE_SANITIZE (this);
429     if (unlikely (!sanitize_shallow (c, count))) return_trace (false);
430     for (unsigned int i = 0; i < count; i++)
431       if (unlikely (!arrayZ[i].sanitize (c, base, user_data)))
432         return_trace (false);
433     return_trace (true);
434   }
435
436   bool sanitize_shallow (hb_sanitize_context_t *c, unsigned int count) const
437   {
438     TRACE_SANITIZE (this);
439     return_trace (c->check_array (arrayZ, count));
440   }
441
442   public:
443   Type          arrayZ[VAR];
444   public:
445   DEFINE_SIZE_UNBOUNDED (0);
446 };
447
448 /* Unsized array of offset's */
449 template <typename Type, typename OffsetType, bool has_null=true>
450 struct UnsizedOffsetArrayOf : UnsizedArrayOf<OffsetTo<Type, OffsetType, has_null> > {};
451
452 /* Unsized array of offsets relative to the beginning of the array itself. */
453 template <typename Type, typename OffsetType, bool has_null=true>
454 struct UnsizedOffsetListOf : UnsizedOffsetArrayOf<Type, OffsetType, has_null>
455 {
456   const Type& operator [] (int i_) const
457   {
458     unsigned int i = (unsigned int) i_;
459     const OffsetTo<Type, OffsetType, has_null> *p = &this->arrayZ[i];
460     if (unlikely (p < this->arrayZ)) return Null (Type); /* Overflowed. */
461     return this+*p;
462   }
463   Type& operator [] (int i_)
464   {
465     unsigned int i = (unsigned int) i_;
466     const OffsetTo<Type, OffsetType, has_null> *p = &this->arrayZ[i];
467     if (unlikely (p < this->arrayZ)) return Crap (Type); /* Overflowed. */
468     return this+*p;
469   }
470
471
472   bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
473   {
474     TRACE_SANITIZE (this);
475     return_trace ((UnsizedOffsetArrayOf<Type, OffsetType, has_null>::sanitize (c, count, this)));
476   }
477   template <typename T>
478   bool sanitize (hb_sanitize_context_t *c, unsigned int count, T user_data) const
479   {
480     TRACE_SANITIZE (this);
481     return_trace ((UnsizedOffsetArrayOf<Type, OffsetType, has_null>::sanitize (c, count, this, user_data)));
482   }
483 };
484
485 /* An array with sorted elements.  Supports binary searching. */
486 template <typename Type>
487 struct SortedUnsizedArrayOf : UnsizedArrayOf<Type>
488 {
489   hb_sorted_array_t<Type> as_array (unsigned int len)
490   { return hb_sorted_array (this->arrayZ, len); }
491   hb_sorted_array_t<const Type> as_array (unsigned int len) const
492   { return hb_sorted_array (this->arrayZ, len); }
493   operator hb_sorted_array_t<Type> ()             { return as_array (); }
494   operator hb_sorted_array_t<const Type> () const { return as_array (); }
495
496   template <typename T>
497   Type &bsearch (unsigned int len, const T &x, Type &not_found = Crap (Type))
498   { return *as_array (len).bsearch (x, &not_found); }
499   template <typename T>
500   const Type &bsearch (unsigned int len, const T &x, const Type &not_found = Null (Type)) const
501   { return *as_array (len).bsearch (x, &not_found); }
502   template <typename T>
503   bool bfind (unsigned int len, const T &x, unsigned int *i = nullptr,
504                      hb_bfind_not_found_t not_found = HB_BFIND_NOT_FOUND_DONT_STORE,
505                      unsigned int to_store = (unsigned int) -1) const
506   { return as_array (len).bfind (x, i, not_found, to_store); }
507 };
508
509
510 /* An array with a number of elements. */
511 template <typename Type, typename LenType=HBUINT16>
512 struct ArrayOf
513 {
514   typedef Type item_t;
515   static constexpr unsigned item_size = hb_static_size (Type);
516
517   HB_NO_CREATE_COPY_ASSIGN_TEMPLATE2 (ArrayOf, Type, LenType);
518
519   const Type& operator [] (int i_) const
520   {
521     unsigned int i = (unsigned int) i_;
522     if (unlikely (i >= len)) return Null (Type);
523     return arrayZ[i];
524   }
525   Type& operator [] (int i_)
526   {
527     unsigned int i = (unsigned int) i_;
528     if (unlikely (i >= len)) return Crap (Type);
529     return arrayZ[i];
530   }
531
532   unsigned int get_size () const
533   { return len.static_size + len * Type::static_size; }
534
535   hb_array_t<Type> as_array ()
536   { return hb_array (arrayZ, len); }
537   hb_array_t<const Type> as_array () const
538   { return hb_array (arrayZ, len); }
539   operator hb_array_t<Type> (void)             { return as_array (); }
540   operator hb_array_t<const Type> (void) const { return as_array (); }
541
542   hb_array_t<const Type> sub_array (unsigned int start_offset, unsigned int count) const
543   { return as_array ().sub_array (start_offset, count);}
544   hb_array_t<const Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */) const
545   { return as_array ().sub_array (start_offset, count);}
546   hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int count)
547   { return as_array ().sub_array (start_offset, count);}
548   hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */)
549   { return as_array ().sub_array (start_offset, count);}
550
551   bool serialize (hb_serialize_context_t *c, unsigned int items_len)
552   {
553     TRACE_SERIALIZE (this);
554     if (unlikely (!c->extend_min (*this))) return_trace (false);
555     len.set (items_len); /* TODO(serialize) Overflow? */
556     if (unlikely (!c->extend (*this))) return_trace (false);
557     return_trace (true);
558   }
559   template <typename T>
560   bool serialize (hb_serialize_context_t *c, hb_array_t<const T> items)
561   {
562     TRACE_SERIALIZE (this);
563     if (unlikely (!serialize (c, items.length))) return_trace (false);
564     for (unsigned int i = 0; i < items.length; i++)
565       hb_assign (arrayZ[i], items[i]);
566     return_trace (true);
567   }
568
569   bool sanitize (hb_sanitize_context_t *c) const
570   {
571     TRACE_SANITIZE (this);
572     if (unlikely (!sanitize_shallow (c))) return_trace (false);
573
574     /* Note: for structs that do not reference other structs,
575      * we do not need to call their sanitize() as we already did
576      * a bound check on the aggregate array size.  We just include
577      * a small unreachable expression to make sure the structs
578      * pointed to do have a simple sanitize(), ie. they do not
579      * reference other structs via offsets.
580      */
581     (void) (false && arrayZ[0].sanitize (c));
582
583     return_trace (true);
584   }
585   bool sanitize (hb_sanitize_context_t *c, const void *base) const
586   {
587     TRACE_SANITIZE (this);
588     if (unlikely (!sanitize_shallow (c))) return_trace (false);
589     unsigned int count = len;
590     for (unsigned int i = 0; i < count; i++)
591       if (unlikely (!arrayZ[i].sanitize (c, base)))
592         return_trace (false);
593     return_trace (true);
594   }
595   template <typename T>
596   bool sanitize (hb_sanitize_context_t *c, const void *base, T user_data) const
597   {
598     TRACE_SANITIZE (this);
599     if (unlikely (!sanitize_shallow (c))) return_trace (false);
600     unsigned int count = len;
601     for (unsigned int i = 0; i < count; i++)
602       if (unlikely (!arrayZ[i].sanitize (c, base, user_data)))
603         return_trace (false);
604     return_trace (true);
605   }
606
607   template <typename T>
608   Type &lsearch (const T &x, Type &not_found = Crap (Type))
609   { return *as_array ().lsearch (x, &not_found); }
610   template <typename T>
611   const Type &lsearch (const T &x, const Type &not_found = Null (Type)) const
612   { return *as_array ().lsearch (x, &not_found); }
613
614   void qsort (unsigned int start = 0, unsigned int end = (unsigned int) -1)
615   { as_array ().qsort (start, end); }
616
617   bool sanitize_shallow (hb_sanitize_context_t *c) const
618   {
619     TRACE_SANITIZE (this);
620     return_trace (len.sanitize (c) && c->check_array (arrayZ, len));
621   }
622
623   public:
624   LenType       len;
625   Type          arrayZ[VAR];
626   public:
627   DEFINE_SIZE_ARRAY (sizeof (LenType), arrayZ);
628 };
629 template <typename Type> struct LArrayOf : ArrayOf<Type, HBUINT32> {};
630 typedef ArrayOf<HBUINT8, HBUINT8> PString;
631
632 /* Array of Offset's */
633 template <typename Type>
634 struct OffsetArrayOf : ArrayOf<OffsetTo<Type, HBUINT16> > {};
635 template <typename Type>
636 struct LOffsetArrayOf : ArrayOf<OffsetTo<Type, HBUINT32> > {};
637 template <typename Type>
638 struct LOffsetLArrayOf : ArrayOf<OffsetTo<Type, HBUINT32>, HBUINT32> {};
639
640 /* Array of offsets relative to the beginning of the array itself. */
641 template <typename Type>
642 struct OffsetListOf : OffsetArrayOf<Type>
643 {
644   const Type& operator [] (int i_) const
645   {
646     unsigned int i = (unsigned int) i_;
647     if (unlikely (i >= this->len)) return Null (Type);
648     return this+this->arrayZ[i];
649   }
650   const Type& operator [] (int i_)
651   {
652     unsigned int i = (unsigned int) i_;
653     if (unlikely (i >= this->len)) return Crap (Type);
654     return this+this->arrayZ[i];
655   }
656
657   bool subset (hb_subset_context_t *c) const
658   {
659     TRACE_SUBSET (this);
660     struct OffsetListOf<Type> *out = c->serializer->embed (*this);
661     if (unlikely (!out)) return_trace (false);
662     unsigned int count = this->len;
663     for (unsigned int i = 0; i < count; i++)
664       out->arrayZ[i].serialize_subset (c, (*this)[i], out);
665     return_trace (true);
666   }
667
668   bool sanitize (hb_sanitize_context_t *c) const
669   {
670     TRACE_SANITIZE (this);
671     return_trace (OffsetArrayOf<Type>::sanitize (c, this));
672   }
673   template <typename T>
674   bool sanitize (hb_sanitize_context_t *c, T user_data) const
675   {
676     TRACE_SANITIZE (this);
677     return_trace (OffsetArrayOf<Type>::sanitize (c, this, user_data));
678   }
679 };
680
681 /* An array starting at second element. */
682 template <typename Type, typename LenType=HBUINT16>
683 struct HeadlessArrayOf
684 {
685   static constexpr unsigned item_size = Type::static_size;
686
687   HB_NO_CREATE_COPY_ASSIGN_TEMPLATE2 (HeadlessArrayOf, Type, LenType);
688
689   const Type& operator [] (int i_) const
690   {
691     unsigned int i = (unsigned int) i_;
692     if (unlikely (i >= lenP1 || !i)) return Null (Type);
693     return arrayZ[i-1];
694   }
695   Type& operator [] (int i_)
696   {
697     unsigned int i = (unsigned int) i_;
698     if (unlikely (i >= lenP1 || !i)) return Crap (Type);
699     return arrayZ[i-1];
700   }
701   unsigned int get_size () const
702   { return lenP1.static_size + (lenP1 ? lenP1 - 1 : 0) * Type::static_size; }
703
704   bool serialize (hb_serialize_context_t *c,
705                   hb_array_t<const Type> items)
706   {
707     TRACE_SERIALIZE (this);
708     if (unlikely (!c->extend_min (*this))) return_trace (false);
709     lenP1.set (items.length + 1); /* TODO(serialize) Overflow? */
710     if (unlikely (!c->extend (*this))) return_trace (false);
711     for (unsigned int i = 0; i < items.length; i++)
712       arrayZ[i] = items[i];
713     return_trace (true);
714   }
715
716   bool sanitize (hb_sanitize_context_t *c) const
717   {
718     TRACE_SANITIZE (this);
719     if (unlikely (!sanitize_shallow (c))) return_trace (false);
720
721     /* Note: for structs that do not reference other structs,
722      * we do not need to call their sanitize() as we already did
723      * a bound check on the aggregate array size.  We just include
724      * a small unreachable expression to make sure the structs
725      * pointed to do have a simple sanitize(), ie. they do not
726      * reference other structs via offsets.
727      */
728     (void) (false && arrayZ[0].sanitize (c));
729
730     return_trace (true);
731   }
732
733   private:
734   bool sanitize_shallow (hb_sanitize_context_t *c) const
735   {
736     TRACE_SANITIZE (this);
737     return_trace (lenP1.sanitize (c) &&
738                   (!lenP1 || c->check_array (arrayZ, lenP1 - 1)));
739   }
740
741   public:
742   LenType       lenP1;
743   Type          arrayZ[VAR];
744   public:
745   DEFINE_SIZE_ARRAY (sizeof (LenType), arrayZ);
746 };
747
748 /* An array storing length-1. */
749 template <typename Type, typename LenType=HBUINT16>
750 struct ArrayOfM1
751 {
752   HB_NO_CREATE_COPY_ASSIGN_TEMPLATE2 (ArrayOfM1, Type, LenType);
753
754   const Type& operator [] (int i_) const
755   {
756     unsigned int i = (unsigned int) i_;
757     if (unlikely (i > lenM1)) return Null (Type);
758     return arrayZ[i];
759   }
760   Type& operator [] (int i_)
761   {
762     unsigned int i = (unsigned int) i_;
763     if (unlikely (i > lenM1)) return Crap (Type);
764     return arrayZ[i];
765   }
766   unsigned int get_size () const
767   { return lenM1.static_size + (lenM1 + 1) * Type::static_size; }
768
769   template <typename T>
770   bool sanitize (hb_sanitize_context_t *c, const void *base, T user_data) const
771   {
772     TRACE_SANITIZE (this);
773     if (unlikely (!sanitize_shallow (c))) return_trace (false);
774     unsigned int count = lenM1 + 1;
775     for (unsigned int i = 0; i < count; i++)
776       if (unlikely (!arrayZ[i].sanitize (c, base, user_data)))
777         return_trace (false);
778     return_trace (true);
779   }
780
781   private:
782   bool sanitize_shallow (hb_sanitize_context_t *c) const
783   {
784     TRACE_SANITIZE (this);
785     return_trace (lenM1.sanitize (c) &&
786                   (c->check_array (arrayZ, lenM1 + 1)));
787   }
788
789   public:
790   LenType       lenM1;
791   Type          arrayZ[VAR];
792   public:
793   DEFINE_SIZE_ARRAY (sizeof (LenType), arrayZ);
794 };
795
796 /* An array with sorted elements.  Supports binary searching. */
797 template <typename Type, typename LenType=HBUINT16>
798 struct SortedArrayOf : ArrayOf<Type, LenType>
799 {
800   hb_sorted_array_t<Type> as_array ()
801   { return hb_sorted_array (this->arrayZ, this->len); }
802   hb_sorted_array_t<const Type> as_array () const
803   { return hb_sorted_array (this->arrayZ, this->len); }
804   operator hb_sorted_array_t<Type> ()             { return as_array (); }
805   operator hb_sorted_array_t<const Type> () const { return as_array (); }
806
807   hb_array_t<const Type> sub_array (unsigned int start_offset, unsigned int count) const
808   { return as_array ().sub_array (start_offset, count);}
809   hb_array_t<const Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */) const
810   { return as_array ().sub_array (start_offset, count);}
811   hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int count)
812   { return as_array ().sub_array (start_offset, count);}
813   hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */)
814   { return as_array ().sub_array (start_offset, count);}
815
816   template <typename T>
817   Type &bsearch (const T &x, Type &not_found = Crap (Type))
818   { return *as_array ().bsearch (x, &not_found); }
819   template <typename T>
820   const Type &bsearch (const T &x, const Type &not_found = Null (Type)) const
821   { return *as_array ().bsearch (x, &not_found); }
822   template <typename T>
823   bool bfind (const T &x, unsigned int *i = nullptr,
824                      hb_bfind_not_found_t not_found = HB_BFIND_NOT_FOUND_DONT_STORE,
825                      unsigned int to_store = (unsigned int) -1) const
826   { return as_array ().bfind (x, i, not_found, to_store); }
827 };
828
829 /*
830  * Binary-search arrays
831  */
832
833 template <typename LenType=HBUINT16>
834 struct BinSearchHeader
835 {
836   operator uint32_t () const { return len; }
837
838   bool sanitize (hb_sanitize_context_t *c) const
839   {
840     TRACE_SANITIZE (this);
841     return_trace (c->check_struct (this));
842   }
843
844   void set (unsigned int v)
845   {
846     len.set (v);
847     assert (len == v);
848     entrySelector.set (MAX (1u, hb_bit_storage (v)) - 1);
849     searchRange.set (16 * (1u << entrySelector));
850     rangeShift.set (v * 16 > searchRange
851                     ? 16 * v - searchRange
852                     : 0);
853   }
854
855   protected:
856   LenType       len;
857   LenType       searchRange;
858   LenType       entrySelector;
859   LenType       rangeShift;
860
861   public:
862   DEFINE_SIZE_STATIC (8);
863 };
864
865 template <typename Type, typename LenType=HBUINT16>
866 struct BinSearchArrayOf : SortedArrayOf<Type, BinSearchHeader<LenType> > {};
867
868
869 struct VarSizedBinSearchHeader
870 {
871
872   bool sanitize (hb_sanitize_context_t *c) const
873   {
874     TRACE_SANITIZE (this);
875     return_trace (c->check_struct (this));
876   }
877
878   HBUINT16      unitSize;       /* Size of a lookup unit for this search in bytes. */
879   HBUINT16      nUnits;         /* Number of units of the preceding size to be searched. */
880   HBUINT16      searchRange;    /* The value of unitSize times the largest power of 2
881                                  * that is less than or equal to the value of nUnits. */
882   HBUINT16      entrySelector;  /* The log base 2 of the largest power of 2 less than
883                                  * or equal to the value of nUnits. */
884   HBUINT16      rangeShift;     /* The value of unitSize times the difference of the
885                                  * value of nUnits minus the largest power of 2 less
886                                  * than or equal to the value of nUnits. */
887   public:
888   DEFINE_SIZE_STATIC (10);
889 };
890
891 template <typename Type>
892 struct VarSizedBinSearchArrayOf
893 {
894   static constexpr unsigned item_size = Type::static_size;
895
896   HB_NO_CREATE_COPY_ASSIGN_TEMPLATE (VarSizedBinSearchArrayOf, Type);
897
898   bool last_is_terminator () const
899   {
900     if (unlikely (!header.nUnits)) return false;
901
902     /* Gah.
903      *
904      * "The number of termination values that need to be included is table-specific.
905      * The value that indicates binary search termination is 0xFFFF." */
906     const HBUINT16 *words = &StructAtOffset<HBUINT16> (&bytesZ, (header.nUnits - 1) * header.unitSize);
907     unsigned int count = Type::TerminationWordCount;
908     for (unsigned int i = 0; i < count; i++)
909       if (words[i] != 0xFFFFu)
910         return false;
911     return true;
912   }
913
914   const Type& operator [] (int i_) const
915   {
916     unsigned int i = (unsigned int) i_;
917     if (unlikely (i >= get_length ())) return Null (Type);
918     return StructAtOffset<Type> (&bytesZ, i * header.unitSize);
919   }
920   Type& operator [] (int i_)
921   {
922     unsigned int i = (unsigned int) i_;
923     if (unlikely (i >= get_length ())) return Crap (Type);
924     return StructAtOffset<Type> (&bytesZ, i * header.unitSize);
925   }
926   unsigned int get_length () const
927   { return header.nUnits - last_is_terminator (); }
928   unsigned int get_size () const
929   { return header.static_size + header.nUnits * header.unitSize; }
930
931   bool sanitize (hb_sanitize_context_t *c) const
932   {
933     TRACE_SANITIZE (this);
934     if (unlikely (!sanitize_shallow (c))) return_trace (false);
935
936     /* Note: for structs that do not reference other structs,
937      * we do not need to call their sanitize() as we already did
938      * a bound check on the aggregate array size.  We just include
939      * a small unreachable expression to make sure the structs
940      * pointed to do have a simple sanitize(), ie. they do not
941      * reference other structs via offsets.
942      */
943     (void) (false && StructAtOffset<Type> (&bytesZ, 0).sanitize (c));
944
945     return_trace (true);
946   }
947   bool sanitize (hb_sanitize_context_t *c, const void *base) const
948   {
949     TRACE_SANITIZE (this);
950     if (unlikely (!sanitize_shallow (c))) return_trace (false);
951     unsigned int count = get_length ();
952     for (unsigned int i = 0; i < count; i++)
953       if (unlikely (!(*this)[i].sanitize (c, base)))
954         return_trace (false);
955     return_trace (true);
956   }
957   template <typename T>
958   bool sanitize (hb_sanitize_context_t *c, const void *base, T user_data) const
959   {
960     TRACE_SANITIZE (this);
961     if (unlikely (!sanitize_shallow (c))) return_trace (false);
962     unsigned int count = get_length ();
963     for (unsigned int i = 0; i < count; i++)
964       if (unlikely (!(*this)[i].sanitize (c, base, user_data)))
965         return_trace (false);
966     return_trace (true);
967   }
968
969   template <typename T>
970   const Type *bsearch (const T &key) const
971   {
972     unsigned int size = header.unitSize;
973     int min = 0, max = (int) get_length () - 1;
974     while (min <= max)
975     {
976       int mid = ((unsigned int) min + (unsigned int) max) / 2;
977       const Type *p = (const Type *) (((const char *) &bytesZ) + (mid * size));
978       int c = p->cmp (key);
979       if (c < 0) max = mid - 1;
980       else if (c > 0) min = mid + 1;
981       else return p;
982     }
983     return nullptr;
984   }
985
986   private:
987   bool sanitize_shallow (hb_sanitize_context_t *c) const
988   {
989     TRACE_SANITIZE (this);
990     return_trace (header.sanitize (c) &&
991                   Type::static_size <= header.unitSize &&
992                   c->check_range (bytesZ.arrayZ,
993                                   header.nUnits,
994                                   header.unitSize));
995   }
996
997   protected:
998   VarSizedBinSearchHeader       header;
999   UnsizedArrayOf<HBUINT8>       bytesZ;
1000   public:
1001   DEFINE_SIZE_ARRAY (10, bytesZ);
1002 };
1003
1004
1005 } /* namespace OT */
1006
1007
1008 #endif /* HB_OPEN_TYPE_HH */