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