blob: 96d2e0a977aa4263010314646b8073492eb4e60b [file] [log] [blame]
Behdad Esfahbod5a552f72018-12-16 20:07:44 -05001/*
2 * Copyright © 2018 Google, 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 * Google Author(s): Behdad Esfahbod
25 */
26
27#ifndef HB_ARRAY_HH
28#define HB_ARRAY_HH
29
30#include "hb.hh"
Behdad Esfahbod6e3ad652019-01-09 09:05:01 -080031#include "hb-algs.hh"
Behdad Esfahbod865deeb2018-12-21 17:35:58 -050032#include "hb-iter.hh"
33#include "hb-null.hh"
Behdad Esfahbod5a552f72018-12-16 20:07:44 -050034
35
Behdad Esfahbod5a552f72018-12-16 20:07:44 -050036template <typename Type>
37struct hb_sorted_array_t;
38
39template <typename Type>
Behdad Esfahbod849a0f12019-01-29 17:10:19 -080040struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&>
Behdad Esfahbod5a552f72018-12-16 20:07:44 -050041{
Behdad Esfahboda4354d22018-12-16 23:57:27 -050042 /*
43 * Constructors.
44 */
David Corbettb854d4f2019-05-10 22:51:49 -040045 hb_array_t () : arrayZ (nullptr), length (0), backwards_length (0) {}
46 hb_array_t (Type *array_, unsigned int length_) : arrayZ (array_), length (length_), backwards_length (0) {}
Behdad Esfahbod322627a2019-05-09 16:08:10 -070047 template <unsigned int length_>
David Corbettb854d4f2019-05-10 22:51:49 -040048 hb_array_t (Type (&array_)[length_]) : arrayZ (array_), length (length_), backwards_length (0) {}
Behdad Esfahbod5a552f72018-12-16 20:07:44 -050049
Behdad Esfahbod91d958a2019-04-18 10:04:10 -040050 template <typename U,
Behdad Esfahbod726002a2019-05-09 14:53:02 -070051 hb_enable_if (hb_is_cr_convertible(U, Type))>
Behdad Esfahbod91d958a2019-04-18 10:04:10 -040052 hb_array_t (const hb_array_t<U> &o) :
Behdad Esfahboda06edf12019-08-29 15:21:18 -070053 hb_iter_with_fallback_t<hb_array_t, Type&> (),
David Corbettb854d4f2019-05-10 22:51:49 -040054 arrayZ (o.arrayZ), length (o.length), backwards_length (o.backwards_length) {}
Behdad Esfahbod91d958a2019-04-18 10:04:10 -040055 template <typename U,
Behdad Esfahbod726002a2019-05-09 14:53:02 -070056 hb_enable_if (hb_is_cr_convertible(U, Type))>
Behdad Esfahbod91d958a2019-04-18 10:04:10 -040057 hb_array_t& operator = (const hb_array_t<U> &o)
David Corbettb854d4f2019-05-10 22:51:49 -040058 { arrayZ = o.arrayZ; length = o.length; backwards_length = o.backwards_length; return *this; }
Behdad Esfahbod91d958a2019-04-18 10:04:10 -040059
Behdad Esfahbod25786f42018-12-21 19:29:00 -050060 /*
61 * Iterator implementation.
62 */
Behdad Esfahbod636786e2019-01-08 23:48:35 -080063 typedef Type& __item_t__;
Behdad Esfahbod090fe562019-01-25 15:34:03 +010064 static constexpr bool is_random_access_iterator = true;
Behdad Esfahbod25786f42018-12-21 19:29:00 -050065 Type& __item_at__ (unsigned i) const
Behdad Esfahbod5a552f72018-12-16 20:07:44 -050066 {
Behdad Esfahbod25786f42018-12-21 19:29:00 -050067 if (unlikely (i >= length)) return CrapOrNull (Type);
Behdad Esfahbod5a552f72018-12-16 20:07:44 -050068 return arrayZ[i];
69 }
Behdad Esfahbod25786f42018-12-21 19:29:00 -050070 void __forward__ (unsigned n)
71 {
72 if (unlikely (n > length))
73 n = length;
74 length -= n;
David Corbettb854d4f2019-05-10 22:51:49 -040075 backwards_length += n;
Behdad Esfahbod25786f42018-12-21 19:29:00 -050076 arrayZ += n;
77 }
78 void __rewind__ (unsigned n)
79 {
David Corbettb854d4f2019-05-10 22:51:49 -040080 if (unlikely (n > backwards_length))
81 n = backwards_length;
82 length += n;
83 backwards_length -= n;
84 arrayZ -= n;
Behdad Esfahbod25786f42018-12-21 19:29:00 -050085 }
86 unsigned __len__ () const { return length; }
Behdad Esfahbodd822e0a2019-05-15 16:30:08 -070087 /* Ouch. The operator== compares the contents of the array. For range-based for loops,
88 * it's best if we can just compare arrayZ, though comparing contents is still fast,
89 * but also would require that Type has operator==. As such, we optimize this operator
90 * for range-based for loop and just compare arrayZ. No need to compare length, as we
91 * assume we're only compared to .end(). */
Behdad Esfahbod4c2fd052019-05-06 19:57:15 -070092 bool operator != (const hb_array_t& o) const
Behdad Esfahbodd822e0a2019-05-15 16:30:08 -070093 { return arrayZ != o.arrayZ; }
Behdad Esfahbod5a552f72018-12-16 20:07:44 -050094
Behdad Esfahbod25786f42018-12-21 19:29:00 -050095 /* Extra operators.
96 */
Ebrahim Byagowie4120082018-12-17 21:31:01 +033097 Type * operator & () const { return arrayZ; }
Behdad Esfahbod474a1202018-12-21 18:46:51 -050098 operator hb_array_t<const Type> () { return hb_array_t<const Type> (arrayZ, length); }
Ebrahim Byagowie4120082018-12-17 21:31:01 +033099 template <typename T> operator T * () const { return arrayZ; }
Behdad Esfahbod94e72cf2018-12-17 00:06:40 -0500100
Behdad Esfahbodcaa20e42019-04-12 17:59:18 -0400101 HB_INTERNAL bool operator == (const hb_array_t &o) const;
102 HB_INTERNAL uint32_t hash () const;
Behdad Esfahbodb189bbc2019-03-30 19:41:48 -0700103
Behdad Esfahboda4354d22018-12-16 23:57:27 -0500104 /*
105 * Compare, Sort, and Search.
106 */
Behdad Esfahbod5a552f72018-12-16 20:07:44 -0500107
Behdad Esfahboda4354d22018-12-16 23:57:27 -0500108 /* Note: our compare is NOT lexicographic; it also does NOT call Type::cmp. */
Behdad Esfahboda06edf12019-08-29 15:21:18 -0700109 int cmp (const hb_array_t &a) const
Behdad Esfahbod5a552f72018-12-16 20:07:44 -0500110 {
Behdad Esfahbod474a1202018-12-21 18:46:51 -0500111 if (length != a.length)
112 return (int) a.length - (int) length;
Behdad Esfahboda4354d22018-12-16 23:57:27 -0500113 return hb_memcmp (a.arrayZ, arrayZ, get_size ());
Behdad Esfahbod5a552f72018-12-16 20:07:44 -0500114 }
Behdad Esfahbod95df00a2019-04-12 17:50:03 -0400115 HB_INTERNAL static int cmp (const void *pa, const void *pb)
Behdad Esfahboda4354d22018-12-16 23:57:27 -0500116 {
Behdad Esfahboda06edf12019-08-29 15:21:18 -0700117 hb_array_t *a = (hb_array_t *) pa;
118 hb_array_t *b = (hb_array_t *) pb;
Behdad Esfahboda4354d22018-12-16 23:57:27 -0500119 return b->cmp (*a);
120 }
Behdad Esfahbod5a552f72018-12-16 20:07:44 -0500121
Behdad Esfahbod5a552f72018-12-16 20:07:44 -0500122 template <typename T>
Behdad Esfahboddcfa4a82018-12-16 20:40:07 -0500123 Type *lsearch (const T &x, Type *not_found = nullptr)
Behdad Esfahbod5a552f72018-12-16 20:07:44 -0500124 {
Behdad Esfahbod474a1202018-12-21 18:46:51 -0500125 unsigned int count = length;
Behdad Esfahbod5a552f72018-12-16 20:07:44 -0500126 for (unsigned int i = 0; i < count; i++)
127 if (!this->arrayZ[i].cmp (x))
128 return &this->arrayZ[i];
129 return not_found;
130 }
131 template <typename T>
132 const Type *lsearch (const T &x, const Type *not_found = nullptr) const
133 {
Behdad Esfahbod474a1202018-12-21 18:46:51 -0500134 unsigned int count = length;
Behdad Esfahbod5a552f72018-12-16 20:07:44 -0500135 for (unsigned int i = 0; i < count; i++)
136 if (!this->arrayZ[i].cmp (x))
137 return &this->arrayZ[i];
138 return not_found;
139 }
140
Behdad Esfahboddcfa4a82018-12-16 20:40:07 -0500141 hb_sorted_array_t<Type> qsort (int (*cmp_)(const void*, const void*))
Behdad Esfahbod5a552f72018-12-16 20:07:44 -0500142 {
Behdad Esfahbod89949ed2018-12-30 01:52:19 -0500143 if (likely (length))
Ebrahim Byagowieff579f2019-06-07 12:58:09 +0430144 hb_qsort (arrayZ, length, this->item_size, cmp_);
Behdad Esfahbod5a552f72018-12-16 20:07:44 -0500145 return hb_sorted_array_t<Type> (*this);
146 }
Ebrahim Byagowie4120082018-12-17 21:31:01 +0330147 hb_sorted_array_t<Type> qsort ()
Behdad Esfahbod5a552f72018-12-16 20:07:44 -0500148 {
Behdad Esfahbod89949ed2018-12-30 01:52:19 -0500149 if (likely (length))
Ebrahim Byagowieff579f2019-06-07 12:58:09 +0430150 hb_qsort (arrayZ, length, this->item_size, Type::cmp);
Behdad Esfahbod5a552f72018-12-16 20:07:44 -0500151 return hb_sorted_array_t<Type> (*this);
152 }
153 void qsort (unsigned int start, unsigned int end)
154 {
Behdad Esfahbod41248cc2019-05-07 20:54:31 -0700155 end = hb_min (end, length);
Behdad Esfahbod5a552f72018-12-16 20:07:44 -0500156 assert (start <= end);
Behdad Esfahbod89949ed2018-12-30 01:52:19 -0500157 if (likely (start < end))
Ebrahim Byagowieff579f2019-06-07 12:58:09 +0430158 hb_qsort (arrayZ + start, end - start, this->item_size, Type::cmp);
Behdad Esfahbod5a552f72018-12-16 20:07:44 -0500159 }
160
Behdad Esfahboda4354d22018-12-16 23:57:27 -0500161 /*
162 * Other methods.
163 */
164
Behdad Esfahbod25786f42018-12-21 19:29:00 -0500165 unsigned int get_size () const { return length * this->item_size; }
Behdad Esfahboda4354d22018-12-16 23:57:27 -0500166
Behdad Esfahboda06edf12019-08-29 15:21:18 -0700167 hb_array_t sub_array (unsigned int start_offset = 0, unsigned int *seg_count = nullptr /* IN/OUT */) const
Behdad Esfahboda4354d22018-12-16 23:57:27 -0500168 {
169 if (!start_offset && !seg_count)
170 return *this;
171
Behdad Esfahbod474a1202018-12-21 18:46:51 -0500172 unsigned int count = length;
Behdad Esfahboda4354d22018-12-16 23:57:27 -0500173 if (unlikely (start_offset > count))
174 count = 0;
175 else
176 count -= start_offset;
177 if (seg_count)
Behdad Esfahbod41248cc2019-05-07 20:54:31 -0700178 count = *seg_count = hb_min (count, *seg_count);
Behdad Esfahboda06edf12019-08-29 15:21:18 -0700179 return hb_array_t (arrayZ + start_offset, count);
Behdad Esfahboda4354d22018-12-16 23:57:27 -0500180 }
Behdad Esfahboda06edf12019-08-29 15:21:18 -0700181 hb_array_t sub_array (unsigned int start_offset, unsigned int seg_count) const
Behdad Esfahboda4354d22018-12-16 23:57:27 -0500182 { return sub_array (start_offset, &seg_count); }
183
Ebrahim Byagowidce42ce2019-08-27 14:32:05 +0430184 template <typename T,
185 unsigned P = sizeof (Type),
186 hb_enable_if (P == 1)>
187 const T *as () const
188 { return length < hb_null_size (T) ? &Null (T) : reinterpret_cast<const T *> (arrayZ); }
189
Behdad Esfahboda4354d22018-12-16 23:57:27 -0500190 /* Only call if you allocated the underlying array using malloc() or similar. */
Ebrahim Byagowie4120082018-12-17 21:31:01 +0330191 void free ()
Behdad Esfahbod474a1202018-12-21 18:46:51 -0500192 { ::free ((void *) arrayZ); arrayZ = nullptr; length = 0; }
Behdad Esfahbod5a552f72018-12-16 20:07:44 -0500193
Behdad Esfahbode8b45c12019-05-08 16:37:38 -0700194 template <typename hb_serialize_context_t>
195 hb_array_t copy (hb_serialize_context_t *c) const
196 {
197 TRACE_SERIALIZE (this);
Behdad Esfahbod34764452019-05-08 21:14:01 -0700198 auto* out = c->start_embed (arrayZ);
Behdad Esfahbode8b45c12019-05-08 16:37:38 -0700199 if (unlikely (!c->extend_size (out, get_size ()))) return_trace (hb_array_t ());
200 for (unsigned i = 0; i < length; i++)
201 out[i] = arrayZ[i]; /* TODO: add version that calls c->copy() */
202 return_trace (hb_array_t (out, length));
203 }
204
Behdad Esfahbod5a552f72018-12-16 20:07:44 -0500205 template <typename hb_sanitize_context_t>
206 bool sanitize (hb_sanitize_context_t *c) const
Behdad Esfahbod474a1202018-12-21 18:46:51 -0500207 { return c->check_array (arrayZ, length); }
Behdad Esfahbod5a552f72018-12-16 20:07:44 -0500208
Behdad Esfahboda4354d22018-12-16 23:57:27 -0500209 /*
210 * Members
211 */
212
Behdad Esfahbod5a552f72018-12-16 20:07:44 -0500213 public:
214 Type *arrayZ;
Behdad Esfahbod474a1202018-12-21 18:46:51 -0500215 unsigned int length;
David Corbettb854d4f2019-05-10 22:51:49 -0400216 unsigned int backwards_length;
Behdad Esfahbod5a552f72018-12-16 20:07:44 -0500217};
Behdad Esfahbod7b4eea82018-12-21 16:02:16 -0500218template <typename T> inline hb_array_t<T>
Behdad Esfahbod474a1202018-12-21 18:46:51 -0500219hb_array (T *array, unsigned int length)
220{ return hb_array_t<T> (array, length); }
221template <typename T, unsigned int length_> inline hb_array_t<T>
222hb_array (T (&array_)[length_])
Behdad Esfahbod7b4eea82018-12-21 16:02:16 -0500223{ return hb_array_t<T> (array_); }
Behdad Esfahbod5a552f72018-12-16 20:07:44 -0500224
Behdad Esfahbod5a552f72018-12-16 20:07:44 -0500225enum hb_bfind_not_found_t
226{
227 HB_BFIND_NOT_FOUND_DONT_STORE,
228 HB_BFIND_NOT_FOUND_STORE,
229 HB_BFIND_NOT_FOUND_STORE_CLOSEST,
230};
231
232template <typename Type>
Behdad Esfahbod25786f42018-12-21 19:29:00 -0500233struct hb_sorted_array_t :
Behdad Esfahbodb5d6fe12019-01-02 16:20:40 -0500234 hb_iter_t<hb_sorted_array_t<Type>, Type&>,
Behdad Esfahbod570473a2018-12-27 13:29:51 -0500235 hb_array_t<Type>
Behdad Esfahbod5a552f72018-12-16 20:07:44 -0500236{
Behdad Esfahboda06edf12019-08-29 15:21:18 -0700237 typedef hb_iter_t<hb_sorted_array_t, Type&> iter_base_t;
Behdad Esfahbod570473a2018-12-27 13:29:51 -0500238 HB_ITER_USING (iter_base_t);
Behdad Esfahbod090fe562019-01-25 15:34:03 +0100239 static constexpr bool is_random_access_iterator = true;
Behdad Esfahbod889dc1e2019-05-14 22:28:07 -0700240 static constexpr bool is_sorted_iterator = true;
Behdad Esfahbod570473a2018-12-27 13:29:51 -0500241
Ebrahim Byagowie4120082018-12-17 21:31:01 +0330242 hb_sorted_array_t () : hb_array_t<Type> () {}
Behdad Esfahbod474a1202018-12-21 18:46:51 -0500243 hb_sorted_array_t (Type *array_, unsigned int length_) : hb_array_t<Type> (array_, length_) {}
Behdad Esfahbod322627a2019-05-09 16:08:10 -0700244 template <unsigned int length_>
245 hb_sorted_array_t (Type (&array_)[length_]) : hb_array_t<Type> (array_) {}
Behdad Esfahbod5a552f72018-12-16 20:07:44 -0500246
Behdad Esfahbodc51f15d2019-04-26 13:03:41 -0700247 template <typename U,
Behdad Esfahbod726002a2019-05-09 14:53:02 -0700248 hb_enable_if (hb_is_cr_convertible(U, Type))>
Behdad Esfahbodc51f15d2019-04-26 13:03:41 -0700249 hb_sorted_array_t (const hb_array_t<U> &o) :
Behdad Esfahboda06edf12019-08-29 15:21:18 -0700250 hb_iter_t<hb_sorted_array_t, Type&> (),
Behdad Esfahbodc51f15d2019-04-26 13:03:41 -0700251 hb_array_t<Type> (o) {}
252 template <typename U,
Behdad Esfahbod726002a2019-05-09 14:53:02 -0700253 hb_enable_if (hb_is_cr_convertible(U, Type))>
Behdad Esfahbodc51f15d2019-04-26 13:03:41 -0700254 hb_sorted_array_t& operator = (const hb_array_t<U> &o)
255 { hb_array_t<Type> (*this) = o; return *this; }
256
Behdad Esfahbod4c2fd052019-05-06 19:57:15 -0700257 /* Iterator implementation. */
258 bool operator != (const hb_sorted_array_t& o) const
259 { return this->arrayZ != o.arrayZ || this->length != o.length; }
260
Behdad Esfahboda06edf12019-08-29 15:21:18 -0700261 hb_sorted_array_t sub_array (unsigned int start_offset, unsigned int *seg_count /* IN/OUT */) const
262 { return hb_sorted_array_t (((const hb_array_t<Type> *) (this))->sub_array (start_offset, seg_count)); }
263 hb_sorted_array_t sub_array (unsigned int start_offset, unsigned int seg_count) const
Behdad Esfahbod5a552f72018-12-16 20:07:44 -0500264 { return sub_array (start_offset, &seg_count); }
265
266 template <typename T>
267 Type *bsearch (const T &x, Type *not_found = nullptr)
268 {
269 unsigned int i;
270 return bfind (x, &i) ? &this->arrayZ[i] : not_found;
271 }
272 template <typename T>
273 const Type *bsearch (const T &x, const Type *not_found = nullptr) const
274 {
275 unsigned int i;
276 return bfind (x, &i) ? &this->arrayZ[i] : not_found;
277 }
278 template <typename T>
279 bool bfind (const T &x, unsigned int *i = nullptr,
280 hb_bfind_not_found_t not_found = HB_BFIND_NOT_FOUND_DONT_STORE,
281 unsigned int to_store = (unsigned int) -1) const
282 {
Behdad Esfahbod474a1202018-12-21 18:46:51 -0500283 int min = 0, max = (int) this->length - 1;
Behdad Esfahbod5a552f72018-12-16 20:07:44 -0500284 const Type *array = this->arrayZ;
285 while (min <= max)
286 {
287 int mid = ((unsigned int) min + (unsigned int) max) / 2;
288 int c = array[mid].cmp (x);
289 if (c < 0)
Ebrahim Byagowia0b4ac42019-08-24 17:57:14 +0430290 max = mid - 1;
Behdad Esfahbod5a552f72018-12-16 20:07:44 -0500291 else if (c > 0)
Ebrahim Byagowia0b4ac42019-08-24 17:57:14 +0430292 min = mid + 1;
Behdad Esfahbod5a552f72018-12-16 20:07:44 -0500293 else
294 {
295 if (i)
296 *i = mid;
297 return true;
298 }
299 }
300 if (i)
301 {
302 switch (not_found)
303 {
304 case HB_BFIND_NOT_FOUND_DONT_STORE:
305 break;
306
307 case HB_BFIND_NOT_FOUND_STORE:
308 *i = to_store;
309 break;
310
311 case HB_BFIND_NOT_FOUND_STORE_CLOSEST:
Behdad Esfahbod474a1202018-12-21 18:46:51 -0500312 if (max < 0 || (max < (int) this->length && array[max].cmp (x) > 0))
Behdad Esfahbod5a552f72018-12-16 20:07:44 -0500313 max++;
314 *i = max;
315 break;
316 }
317 }
318 return false;
319 }
320};
Behdad Esfahbod7b4eea82018-12-21 16:02:16 -0500321template <typename T> inline hb_sorted_array_t<T>
Behdad Esfahbod474a1202018-12-21 18:46:51 -0500322hb_sorted_array (T *array, unsigned int length)
323{ return hb_sorted_array_t<T> (array, length); }
324template <typename T, unsigned int length_> inline hb_sorted_array_t<T>
325hb_sorted_array (T (&array_)[length_])
Behdad Esfahbod7b4eea82018-12-21 16:02:16 -0500326{ return hb_sorted_array_t<T> (array_); }
Behdad Esfahbod5a552f72018-12-16 20:07:44 -0500327
Behdad Esfahbodb189bbc2019-03-30 19:41:48 -0700328template <typename T>
Behdad Esfahbod5b66b032019-04-02 19:27:02 -0700329bool hb_array_t<T>::operator == (const hb_array_t<T> &o) const
330{
331 return length == o.length &&
332 + hb_zip (*this, o)
Behdad Esfahbodd0df9962019-05-15 00:32:41 -0700333 | hb_map ([] (hb_pair_t<T&, T&> &&_) { return _.first == _.second; })
Behdad Esfahbod5b66b032019-04-02 19:27:02 -0700334 | hb_all
335 ;
336}
337template <typename T>
Behdad Esfahbodb189bbc2019-03-30 19:41:48 -0700338uint32_t hb_array_t<T>::hash () const
339{
Behdad Esfahbodd0da5472019-04-02 18:22:39 -0700340 return
Behdad Esfahbod42ab32c2019-04-02 18:41:33 -0700341 + hb_iter (*this)
Behdad Esfahbodd0da5472019-04-02 18:22:39 -0700342 | hb_map (hb_hash)
Behdad Esfahbodd0df9962019-05-15 00:32:41 -0700343 | hb_reduce ([] (uint32_t a, uint32_t b) { return a * 31 + b; }, 0)
Behdad Esfahbodd0da5472019-04-02 18:22:39 -0700344 ;
Behdad Esfahbodb189bbc2019-03-30 19:41:48 -0700345}
Behdad Esfahbod5a552f72018-12-16 20:07:44 -0500346
Behdad Esfahboddcfa4a82018-12-16 20:40:07 -0500347typedef hb_array_t<const char> hb_bytes_t;
Behdad Esfahbod3d9d7dc2018-12-18 22:11:23 -0500348typedef hb_array_t<const unsigned char> hb_ubytes_t;
Behdad Esfahboddcfa4a82018-12-16 20:40:07 -0500349
Behdad Esfahbod5b66b032019-04-02 19:27:02 -0700350/* TODO Specialize opeator==/hash() for hb_bytes_t and hb_ubytes_t. */
Behdad Esfahbodb189bbc2019-03-30 19:41:48 -0700351//template <>
352//uint32_t hb_array_t<const char>::hash () const { return 0; }
Behdad Esfahbod92680362018-12-16 23:38:51 -0500353
Behdad Esfahbod5a552f72018-12-16 20:07:44 -0500354#endif /* HB_ARRAY_HH */