1*2d1272b8SAndroid Build Coastguard Worker /*
2*2d1272b8SAndroid Build Coastguard Worker * Copyright © 2018 Google, Inc.
3*2d1272b8SAndroid Build Coastguard Worker *
4*2d1272b8SAndroid Build Coastguard Worker * This is part of HarfBuzz, a text shaping library.
5*2d1272b8SAndroid Build Coastguard Worker *
6*2d1272b8SAndroid Build Coastguard Worker * Permission is hereby granted, without written agreement and without
7*2d1272b8SAndroid Build Coastguard Worker * license or royalty fees, to use, copy, modify, and distribute this
8*2d1272b8SAndroid Build Coastguard Worker * software and its documentation for any purpose, provided that the
9*2d1272b8SAndroid Build Coastguard Worker * above copyright notice and the following two paragraphs appear in
10*2d1272b8SAndroid Build Coastguard Worker * all copies of this software.
11*2d1272b8SAndroid Build Coastguard Worker *
12*2d1272b8SAndroid Build Coastguard Worker * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
13*2d1272b8SAndroid Build Coastguard Worker * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
14*2d1272b8SAndroid Build Coastguard Worker * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
15*2d1272b8SAndroid Build Coastguard Worker * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
16*2d1272b8SAndroid Build Coastguard Worker * DAMAGE.
17*2d1272b8SAndroid Build Coastguard Worker *
18*2d1272b8SAndroid Build Coastguard Worker * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
19*2d1272b8SAndroid Build Coastguard Worker * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20*2d1272b8SAndroid Build Coastguard Worker * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
21*2d1272b8SAndroid Build Coastguard Worker * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
22*2d1272b8SAndroid Build Coastguard Worker * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
23*2d1272b8SAndroid Build Coastguard Worker *
24*2d1272b8SAndroid Build Coastguard Worker * Google Author(s): Behdad Esfahbod
25*2d1272b8SAndroid Build Coastguard Worker */
26*2d1272b8SAndroid Build Coastguard Worker
27*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_ARRAY_HH
28*2d1272b8SAndroid Build Coastguard Worker #define HB_ARRAY_HH
29*2d1272b8SAndroid Build Coastguard Worker
30*2d1272b8SAndroid Build Coastguard Worker #include "hb.hh"
31*2d1272b8SAndroid Build Coastguard Worker #include "hb-algs.hh"
32*2d1272b8SAndroid Build Coastguard Worker #include "hb-iter.hh"
33*2d1272b8SAndroid Build Coastguard Worker #include "hb-null.hh"
34*2d1272b8SAndroid Build Coastguard Worker
35*2d1272b8SAndroid Build Coastguard Worker
36*2d1272b8SAndroid Build Coastguard Worker template <typename Type>
37*2d1272b8SAndroid Build Coastguard Worker struct hb_sorted_array_t;
38*2d1272b8SAndroid Build Coastguard Worker
39*2d1272b8SAndroid Build Coastguard Worker enum hb_not_found_t
40*2d1272b8SAndroid Build Coastguard Worker {
41*2d1272b8SAndroid Build Coastguard Worker HB_NOT_FOUND_DONT_STORE,
42*2d1272b8SAndroid Build Coastguard Worker HB_NOT_FOUND_STORE,
43*2d1272b8SAndroid Build Coastguard Worker HB_NOT_FOUND_STORE_CLOSEST,
44*2d1272b8SAndroid Build Coastguard Worker };
45*2d1272b8SAndroid Build Coastguard Worker
46*2d1272b8SAndroid Build Coastguard Worker
47*2d1272b8SAndroid Build Coastguard Worker template <typename Type>
48*2d1272b8SAndroid Build Coastguard Worker struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&>
49*2d1272b8SAndroid Build Coastguard Worker {
50*2d1272b8SAndroid Build Coastguard Worker static constexpr bool realloc_move = true;
51*2d1272b8SAndroid Build Coastguard Worker
52*2d1272b8SAndroid Build Coastguard Worker /*
53*2d1272b8SAndroid Build Coastguard Worker * Constructors.
54*2d1272b8SAndroid Build Coastguard Worker */
55*2d1272b8SAndroid Build Coastguard Worker hb_array_t () = default;
56*2d1272b8SAndroid Build Coastguard Worker hb_array_t (const hb_array_t&) = default;
57*2d1272b8SAndroid Build Coastguard Worker ~hb_array_t () = default;
58*2d1272b8SAndroid Build Coastguard Worker hb_array_t& operator= (const hb_array_t&) = default;
59*2d1272b8SAndroid Build Coastguard Worker hb_array_t& operator= (hb_array_t&&) = default;
60*2d1272b8SAndroid Build Coastguard Worker
hb_array_thb_array_t61*2d1272b8SAndroid Build Coastguard Worker constexpr hb_array_t (Type *array_, unsigned int length_) : arrayZ (array_), length (length_) {}
62*2d1272b8SAndroid Build Coastguard Worker template <unsigned int length_>
hb_array_thb_array_t63*2d1272b8SAndroid Build Coastguard Worker constexpr hb_array_t (Type (&array_)[length_]) : hb_array_t (array_, length_) {}
64*2d1272b8SAndroid Build Coastguard Worker
65*2d1272b8SAndroid Build Coastguard Worker template <typename U,
66*2d1272b8SAndroid Build Coastguard Worker hb_enable_if (hb_is_cr_convertible(U, Type))>
hb_array_thb_array_t67*2d1272b8SAndroid Build Coastguard Worker constexpr hb_array_t (const hb_array_t<U> &o) :
68*2d1272b8SAndroid Build Coastguard Worker hb_iter_with_fallback_t<hb_array_t, Type&> (),
69*2d1272b8SAndroid Build Coastguard Worker arrayZ (o.arrayZ), length (o.length), backwards_length (o.backwards_length) {}
70*2d1272b8SAndroid Build Coastguard Worker template <typename U,
71*2d1272b8SAndroid Build Coastguard Worker hb_enable_if (hb_is_cr_convertible(U, Type))>
operator =hb_array_t72*2d1272b8SAndroid Build Coastguard Worker hb_array_t& operator = (const hb_array_t<U> &o)
73*2d1272b8SAndroid Build Coastguard Worker { arrayZ = o.arrayZ; length = o.length; backwards_length = o.backwards_length; return *this; }
74*2d1272b8SAndroid Build Coastguard Worker
75*2d1272b8SAndroid Build Coastguard Worker /*
76*2d1272b8SAndroid Build Coastguard Worker * Iterator implementation.
77*2d1272b8SAndroid Build Coastguard Worker */
78*2d1272b8SAndroid Build Coastguard Worker typedef Type& __item_t__;
79*2d1272b8SAndroid Build Coastguard Worker static constexpr bool is_random_access_iterator = true;
80*2d1272b8SAndroid Build Coastguard Worker static constexpr bool has_fast_len = true;
__item__hb_array_t81*2d1272b8SAndroid Build Coastguard Worker Type& __item__ () const
82*2d1272b8SAndroid Build Coastguard Worker {
83*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!length)) return CrapOrNull (Type);
84*2d1272b8SAndroid Build Coastguard Worker return *arrayZ;
85*2d1272b8SAndroid Build Coastguard Worker }
__item_at__hb_array_t86*2d1272b8SAndroid Build Coastguard Worker Type& __item_at__ (unsigned i) const
87*2d1272b8SAndroid Build Coastguard Worker {
88*2d1272b8SAndroid Build Coastguard Worker if (unlikely (i >= length)) return CrapOrNull (Type);
89*2d1272b8SAndroid Build Coastguard Worker return arrayZ[i];
90*2d1272b8SAndroid Build Coastguard Worker }
__next__hb_array_t91*2d1272b8SAndroid Build Coastguard Worker void __next__ ()
92*2d1272b8SAndroid Build Coastguard Worker {
93*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!length))
94*2d1272b8SAndroid Build Coastguard Worker return;
95*2d1272b8SAndroid Build Coastguard Worker length--;
96*2d1272b8SAndroid Build Coastguard Worker backwards_length++;
97*2d1272b8SAndroid Build Coastguard Worker arrayZ++;
98*2d1272b8SAndroid Build Coastguard Worker }
__forward__hb_array_t99*2d1272b8SAndroid Build Coastguard Worker void __forward__ (unsigned n)
100*2d1272b8SAndroid Build Coastguard Worker {
101*2d1272b8SAndroid Build Coastguard Worker if (unlikely (n > length))
102*2d1272b8SAndroid Build Coastguard Worker n = length;
103*2d1272b8SAndroid Build Coastguard Worker length -= n;
104*2d1272b8SAndroid Build Coastguard Worker backwards_length += n;
105*2d1272b8SAndroid Build Coastguard Worker arrayZ += n;
106*2d1272b8SAndroid Build Coastguard Worker }
__prev__hb_array_t107*2d1272b8SAndroid Build Coastguard Worker void __prev__ ()
108*2d1272b8SAndroid Build Coastguard Worker {
109*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!backwards_length))
110*2d1272b8SAndroid Build Coastguard Worker return;
111*2d1272b8SAndroid Build Coastguard Worker length++;
112*2d1272b8SAndroid Build Coastguard Worker backwards_length--;
113*2d1272b8SAndroid Build Coastguard Worker arrayZ--;
114*2d1272b8SAndroid Build Coastguard Worker }
__rewind__hb_array_t115*2d1272b8SAndroid Build Coastguard Worker void __rewind__ (unsigned n)
116*2d1272b8SAndroid Build Coastguard Worker {
117*2d1272b8SAndroid Build Coastguard Worker if (unlikely (n > backwards_length))
118*2d1272b8SAndroid Build Coastguard Worker n = backwards_length;
119*2d1272b8SAndroid Build Coastguard Worker length += n;
120*2d1272b8SAndroid Build Coastguard Worker backwards_length -= n;
121*2d1272b8SAndroid Build Coastguard Worker arrayZ -= n;
122*2d1272b8SAndroid Build Coastguard Worker }
__len__hb_array_t123*2d1272b8SAndroid Build Coastguard Worker unsigned __len__ () const { return length; }
124*2d1272b8SAndroid Build Coastguard Worker /* Ouch. The operator== compares the contents of the array. For range-based for loops,
125*2d1272b8SAndroid Build Coastguard Worker * it's best if we can just compare arrayZ, though comparing contents is still fast,
126*2d1272b8SAndroid Build Coastguard Worker * but also would require that Type has operator==. As such, we optimize this operator
127*2d1272b8SAndroid Build Coastguard Worker * for range-based for loop and just compare arrayZ and length.
128*2d1272b8SAndroid Build Coastguard Worker *
129*2d1272b8SAndroid Build Coastguard Worker * The above comment is outdated now because we implemented separate begin/end to
130*2d1272b8SAndroid Build Coastguard Worker * objects that were using hb_array_t for range-based loop before. */
operator !=hb_array_t131*2d1272b8SAndroid Build Coastguard Worker bool operator != (const hb_array_t& o) const
132*2d1272b8SAndroid Build Coastguard Worker { return this->arrayZ != o.arrayZ || this->length != o.length; }
133*2d1272b8SAndroid Build Coastguard Worker
134*2d1272b8SAndroid Build Coastguard Worker /* Faster range-based for loop without bounds-check. */
beginhb_array_t135*2d1272b8SAndroid Build Coastguard Worker Type *begin () const { return arrayZ; }
endhb_array_t136*2d1272b8SAndroid Build Coastguard Worker Type *end () const { return arrayZ + length; }
137*2d1272b8SAndroid Build Coastguard Worker
138*2d1272b8SAndroid Build Coastguard Worker
139*2d1272b8SAndroid Build Coastguard Worker /* Extra operators.
140*2d1272b8SAndroid Build Coastguard Worker */
operator &hb_array_t141*2d1272b8SAndroid Build Coastguard Worker Type * operator & () const { return arrayZ; }
operator hb_array_t<const Type>hb_array_t142*2d1272b8SAndroid Build Coastguard Worker operator hb_array_t<const Type> () { return hb_array_t<const Type> (arrayZ, length); }
operator T*hb_array_t143*2d1272b8SAndroid Build Coastguard Worker template <typename T> operator T * () const { return arrayZ; }
144*2d1272b8SAndroid Build Coastguard Worker
145*2d1272b8SAndroid Build Coastguard Worker HB_INTERNAL bool operator == (const hb_array_t &o) const;
146*2d1272b8SAndroid Build Coastguard Worker
hashhb_array_t147*2d1272b8SAndroid Build Coastguard Worker uint32_t hash () const
148*2d1272b8SAndroid Build Coastguard Worker {
149*2d1272b8SAndroid Build Coastguard Worker // FNV-1a hash function
150*2d1272b8SAndroid Build Coastguard Worker // https://github.com/harfbuzz/harfbuzz/pull/4228
151*2d1272b8SAndroid Build Coastguard Worker uint32_t current = /*cbf29ce4*/0x84222325;
152*2d1272b8SAndroid Build Coastguard Worker for (auto &v : *this)
153*2d1272b8SAndroid Build Coastguard Worker {
154*2d1272b8SAndroid Build Coastguard Worker current = current ^ hb_hash (v);
155*2d1272b8SAndroid Build Coastguard Worker current = current * 16777619;
156*2d1272b8SAndroid Build Coastguard Worker }
157*2d1272b8SAndroid Build Coastguard Worker return current;
158*2d1272b8SAndroid Build Coastguard Worker }
159*2d1272b8SAndroid Build Coastguard Worker
160*2d1272b8SAndroid Build Coastguard Worker /*
161*2d1272b8SAndroid Build Coastguard Worker * Compare, Sort, and Search.
162*2d1272b8SAndroid Build Coastguard Worker */
163*2d1272b8SAndroid Build Coastguard Worker
164*2d1272b8SAndroid Build Coastguard Worker /* Note: our compare is NOT lexicographic; it also does NOT call Type::cmp. */
cmphb_array_t165*2d1272b8SAndroid Build Coastguard Worker int cmp (const hb_array_t &a) const
166*2d1272b8SAndroid Build Coastguard Worker {
167*2d1272b8SAndroid Build Coastguard Worker if (length != a.length)
168*2d1272b8SAndroid Build Coastguard Worker return (int) a.length - (int) length;
169*2d1272b8SAndroid Build Coastguard Worker return hb_memcmp (a.arrayZ, arrayZ, get_size ());
170*2d1272b8SAndroid Build Coastguard Worker }
cmphb_array_t171*2d1272b8SAndroid Build Coastguard Worker HB_INTERNAL static int cmp (const void *pa, const void *pb)
172*2d1272b8SAndroid Build Coastguard Worker {
173*2d1272b8SAndroid Build Coastguard Worker hb_array_t *a = (hb_array_t *) pa;
174*2d1272b8SAndroid Build Coastguard Worker hb_array_t *b = (hb_array_t *) pb;
175*2d1272b8SAndroid Build Coastguard Worker return b->cmp (*a);
176*2d1272b8SAndroid Build Coastguard Worker }
177*2d1272b8SAndroid Build Coastguard Worker
178*2d1272b8SAndroid Build Coastguard Worker template <typename T>
lsearchhb_array_t179*2d1272b8SAndroid Build Coastguard Worker Type *lsearch (const T &x, Type *not_found = nullptr)
180*2d1272b8SAndroid Build Coastguard Worker {
181*2d1272b8SAndroid Build Coastguard Worker unsigned i;
182*2d1272b8SAndroid Build Coastguard Worker return lfind (x, &i) ? &this->arrayZ[i] : not_found;
183*2d1272b8SAndroid Build Coastguard Worker }
184*2d1272b8SAndroid Build Coastguard Worker template <typename T>
lsearchhb_array_t185*2d1272b8SAndroid Build Coastguard Worker const Type *lsearch (const T &x, const Type *not_found = nullptr) const
186*2d1272b8SAndroid Build Coastguard Worker {
187*2d1272b8SAndroid Build Coastguard Worker unsigned i;
188*2d1272b8SAndroid Build Coastguard Worker return lfind (x, &i) ? &this->arrayZ[i] : not_found;
189*2d1272b8SAndroid Build Coastguard Worker }
190*2d1272b8SAndroid Build Coastguard Worker template <typename T>
lfindhb_array_t191*2d1272b8SAndroid Build Coastguard Worker bool lfind (const T &x, unsigned *pos = nullptr,
192*2d1272b8SAndroid Build Coastguard Worker hb_not_found_t not_found = HB_NOT_FOUND_DONT_STORE,
193*2d1272b8SAndroid Build Coastguard Worker unsigned int to_store = (unsigned int) -1) const
194*2d1272b8SAndroid Build Coastguard Worker {
195*2d1272b8SAndroid Build Coastguard Worker for (unsigned i = 0; i < length; ++i)
196*2d1272b8SAndroid Build Coastguard Worker if (hb_equal (x, this->arrayZ[i]))
197*2d1272b8SAndroid Build Coastguard Worker {
198*2d1272b8SAndroid Build Coastguard Worker if (pos)
199*2d1272b8SAndroid Build Coastguard Worker *pos = i;
200*2d1272b8SAndroid Build Coastguard Worker return true;
201*2d1272b8SAndroid Build Coastguard Worker }
202*2d1272b8SAndroid Build Coastguard Worker
203*2d1272b8SAndroid Build Coastguard Worker if (pos)
204*2d1272b8SAndroid Build Coastguard Worker {
205*2d1272b8SAndroid Build Coastguard Worker switch (not_found)
206*2d1272b8SAndroid Build Coastguard Worker {
207*2d1272b8SAndroid Build Coastguard Worker case HB_NOT_FOUND_DONT_STORE:
208*2d1272b8SAndroid Build Coastguard Worker break;
209*2d1272b8SAndroid Build Coastguard Worker
210*2d1272b8SAndroid Build Coastguard Worker case HB_NOT_FOUND_STORE:
211*2d1272b8SAndroid Build Coastguard Worker *pos = to_store;
212*2d1272b8SAndroid Build Coastguard Worker break;
213*2d1272b8SAndroid Build Coastguard Worker
214*2d1272b8SAndroid Build Coastguard Worker case HB_NOT_FOUND_STORE_CLOSEST:
215*2d1272b8SAndroid Build Coastguard Worker *pos = length;
216*2d1272b8SAndroid Build Coastguard Worker break;
217*2d1272b8SAndroid Build Coastguard Worker }
218*2d1272b8SAndroid Build Coastguard Worker }
219*2d1272b8SAndroid Build Coastguard Worker return false;
220*2d1272b8SAndroid Build Coastguard Worker }
221*2d1272b8SAndroid Build Coastguard Worker
qsorthb_array_t222*2d1272b8SAndroid Build Coastguard Worker hb_sorted_array_t<Type> qsort (int (*cmp_)(const void*, const void*))
223*2d1272b8SAndroid Build Coastguard Worker {
224*2d1272b8SAndroid Build Coastguard Worker //static_assert (hb_enable_if (hb_is_trivially_copy_assignable(Type)), "");
225*2d1272b8SAndroid Build Coastguard Worker if (likely (length))
226*2d1272b8SAndroid Build Coastguard Worker hb_qsort (arrayZ, length, this->get_item_size (), cmp_);
227*2d1272b8SAndroid Build Coastguard Worker return hb_sorted_array_t<Type> (*this);
228*2d1272b8SAndroid Build Coastguard Worker }
qsorthb_array_t229*2d1272b8SAndroid Build Coastguard Worker hb_sorted_array_t<Type> qsort ()
230*2d1272b8SAndroid Build Coastguard Worker {
231*2d1272b8SAndroid Build Coastguard Worker //static_assert (hb_enable_if (hb_is_trivially_copy_assignable(Type)), "");
232*2d1272b8SAndroid Build Coastguard Worker if (likely (length))
233*2d1272b8SAndroid Build Coastguard Worker hb_qsort (arrayZ, length, this->get_item_size (), Type::cmp);
234*2d1272b8SAndroid Build Coastguard Worker return hb_sorted_array_t<Type> (*this);
235*2d1272b8SAndroid Build Coastguard Worker }
236*2d1272b8SAndroid Build Coastguard Worker
237*2d1272b8SAndroid Build Coastguard Worker /*
238*2d1272b8SAndroid Build Coastguard Worker * Other methods.
239*2d1272b8SAndroid Build Coastguard Worker */
240*2d1272b8SAndroid Build Coastguard Worker
get_sizehb_array_t241*2d1272b8SAndroid Build Coastguard Worker unsigned int get_size () const { return length * this->get_item_size (); }
242*2d1272b8SAndroid Build Coastguard Worker
243*2d1272b8SAndroid Build Coastguard Worker /*
244*2d1272b8SAndroid Build Coastguard Worker * Reverse the order of items in this array in the range [start, end).
245*2d1272b8SAndroid Build Coastguard Worker */
reversehb_array_t246*2d1272b8SAndroid Build Coastguard Worker void reverse (unsigned start = 0, unsigned end = -1)
247*2d1272b8SAndroid Build Coastguard Worker {
248*2d1272b8SAndroid Build Coastguard Worker start = hb_min (start, length);
249*2d1272b8SAndroid Build Coastguard Worker end = hb_min (end, length);
250*2d1272b8SAndroid Build Coastguard Worker
251*2d1272b8SAndroid Build Coastguard Worker if (end < start + 2)
252*2d1272b8SAndroid Build Coastguard Worker return;
253*2d1272b8SAndroid Build Coastguard Worker
254*2d1272b8SAndroid Build Coastguard Worker for (unsigned lhs = start, rhs = end - 1; lhs < rhs; lhs++, rhs--)
255*2d1272b8SAndroid Build Coastguard Worker hb_swap (arrayZ[rhs], arrayZ[lhs]);
256*2d1272b8SAndroid Build Coastguard Worker }
257*2d1272b8SAndroid Build Coastguard Worker
sub_arrayhb_array_t258*2d1272b8SAndroid Build Coastguard Worker hb_array_t sub_array (unsigned int start_offset = 0, unsigned int *seg_count = nullptr /* IN/OUT */) const
259*2d1272b8SAndroid Build Coastguard Worker {
260*2d1272b8SAndroid Build Coastguard Worker if (!start_offset && !seg_count)
261*2d1272b8SAndroid Build Coastguard Worker return *this;
262*2d1272b8SAndroid Build Coastguard Worker
263*2d1272b8SAndroid Build Coastguard Worker unsigned int count = length;
264*2d1272b8SAndroid Build Coastguard Worker if (unlikely (start_offset > count))
265*2d1272b8SAndroid Build Coastguard Worker count = 0;
266*2d1272b8SAndroid Build Coastguard Worker else
267*2d1272b8SAndroid Build Coastguard Worker count -= start_offset;
268*2d1272b8SAndroid Build Coastguard Worker if (seg_count)
269*2d1272b8SAndroid Build Coastguard Worker count = *seg_count = hb_min (count, *seg_count);
270*2d1272b8SAndroid Build Coastguard Worker return hb_array_t (arrayZ + start_offset, count);
271*2d1272b8SAndroid Build Coastguard Worker }
sub_arrayhb_array_t272*2d1272b8SAndroid Build Coastguard Worker hb_array_t sub_array (unsigned int start_offset, unsigned int seg_count) const
273*2d1272b8SAndroid Build Coastguard Worker { return sub_array (start_offset, &seg_count); }
274*2d1272b8SAndroid Build Coastguard Worker
truncatehb_array_t275*2d1272b8SAndroid Build Coastguard Worker hb_array_t truncate (unsigned length) const { return sub_array (0, length); }
276*2d1272b8SAndroid Build Coastguard Worker
277*2d1272b8SAndroid Build Coastguard Worker template <typename T,
278*2d1272b8SAndroid Build Coastguard Worker unsigned P = sizeof (Type),
279*2d1272b8SAndroid Build Coastguard Worker hb_enable_if (P == 1)>
ashb_array_t280*2d1272b8SAndroid Build Coastguard Worker const T *as () const
281*2d1272b8SAndroid Build Coastguard Worker { return length < hb_min_size (T) ? &Null (T) : reinterpret_cast<const T *> (arrayZ); }
282*2d1272b8SAndroid Build Coastguard Worker
283*2d1272b8SAndroid Build Coastguard Worker template <typename T,
284*2d1272b8SAndroid Build Coastguard Worker unsigned P = sizeof (Type),
285*2d1272b8SAndroid Build Coastguard Worker hb_enable_if (P == 1)>
check_rangehb_array_t286*2d1272b8SAndroid Build Coastguard Worker bool check_range (const T *p, unsigned int size = T::static_size) const
287*2d1272b8SAndroid Build Coastguard Worker {
288*2d1272b8SAndroid Build Coastguard Worker return arrayZ <= ((const char *) p)
289*2d1272b8SAndroid Build Coastguard Worker && ((const char *) p) <= arrayZ + length
290*2d1272b8SAndroid Build Coastguard Worker && (unsigned int) (arrayZ + length - (const char *) p) >= size;
291*2d1272b8SAndroid Build Coastguard Worker }
292*2d1272b8SAndroid Build Coastguard Worker
293*2d1272b8SAndroid Build Coastguard Worker /* Only call if you allocated the underlying array using hb_malloc() or similar. */
finihb_array_t294*2d1272b8SAndroid Build Coastguard Worker void fini ()
295*2d1272b8SAndroid Build Coastguard Worker { hb_free ((void *) arrayZ); arrayZ = nullptr; length = 0; }
296*2d1272b8SAndroid Build Coastguard Worker
297*2d1272b8SAndroid Build Coastguard Worker template <typename hb_serialize_context_t,
298*2d1272b8SAndroid Build Coastguard Worker typename U = Type,
299*2d1272b8SAndroid Build Coastguard Worker hb_enable_if (!(sizeof (U) < sizeof (long long) && hb_is_trivially_copy_assignable(hb_decay<Type>)))>
copyhb_array_t300*2d1272b8SAndroid Build Coastguard Worker hb_array_t copy (hb_serialize_context_t *c) const
301*2d1272b8SAndroid Build Coastguard Worker {
302*2d1272b8SAndroid Build Coastguard Worker TRACE_SERIALIZE (this);
303*2d1272b8SAndroid Build Coastguard Worker auto* out = c->start_embed (arrayZ);
304*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!c->extend_size (out, get_size (), false))) return_trace (hb_array_t ());
305*2d1272b8SAndroid Build Coastguard Worker for (unsigned i = 0; i < length; i++)
306*2d1272b8SAndroid Build Coastguard Worker out[i] = arrayZ[i]; /* TODO: add version that calls c->copy() */
307*2d1272b8SAndroid Build Coastguard Worker return_trace (hb_array_t (out, length));
308*2d1272b8SAndroid Build Coastguard Worker }
309*2d1272b8SAndroid Build Coastguard Worker
310*2d1272b8SAndroid Build Coastguard Worker template <typename hb_serialize_context_t,
311*2d1272b8SAndroid Build Coastguard Worker typename U = Type,
312*2d1272b8SAndroid Build Coastguard Worker hb_enable_if (sizeof (U) < sizeof (long long) && hb_is_trivially_copy_assignable(hb_decay<Type>))>
copyhb_array_t313*2d1272b8SAndroid Build Coastguard Worker hb_array_t copy (hb_serialize_context_t *c) const
314*2d1272b8SAndroid Build Coastguard Worker {
315*2d1272b8SAndroid Build Coastguard Worker TRACE_SERIALIZE (this);
316*2d1272b8SAndroid Build Coastguard Worker auto* out = c->start_embed (arrayZ);
317*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!c->extend_size (out, get_size (), false))) return_trace (hb_array_t ());
318*2d1272b8SAndroid Build Coastguard Worker hb_memcpy (out, arrayZ, get_size ());
319*2d1272b8SAndroid Build Coastguard Worker return_trace (hb_array_t (out, length));
320*2d1272b8SAndroid Build Coastguard Worker }
321*2d1272b8SAndroid Build Coastguard Worker
322*2d1272b8SAndroid Build Coastguard Worker template <typename hb_sanitize_context_t>
sanitizehb_array_t323*2d1272b8SAndroid Build Coastguard Worker bool sanitize (hb_sanitize_context_t *c) const
324*2d1272b8SAndroid Build Coastguard Worker { return c->check_array (arrayZ, length); }
325*2d1272b8SAndroid Build Coastguard Worker
326*2d1272b8SAndroid Build Coastguard Worker /*
327*2d1272b8SAndroid Build Coastguard Worker * Members
328*2d1272b8SAndroid Build Coastguard Worker */
329*2d1272b8SAndroid Build Coastguard Worker
330*2d1272b8SAndroid Build Coastguard Worker public:
331*2d1272b8SAndroid Build Coastguard Worker Type *arrayZ = nullptr;
332*2d1272b8SAndroid Build Coastguard Worker unsigned int length = 0;
333*2d1272b8SAndroid Build Coastguard Worker unsigned int backwards_length = 0;
334*2d1272b8SAndroid Build Coastguard Worker };
335*2d1272b8SAndroid Build Coastguard Worker template <typename T> inline hb_array_t<T>
hb_array()336*2d1272b8SAndroid Build Coastguard Worker hb_array ()
337*2d1272b8SAndroid Build Coastguard Worker { return hb_array_t<T> (); }
338*2d1272b8SAndroid Build Coastguard Worker template <typename T> inline hb_array_t<T>
hb_array(T * array,unsigned int length)339*2d1272b8SAndroid Build Coastguard Worker hb_array (T *array, unsigned int length)
340*2d1272b8SAndroid Build Coastguard Worker { return hb_array_t<T> (array, length); }
341*2d1272b8SAndroid Build Coastguard Worker template <typename T, unsigned int length_> inline hb_array_t<T>
hb_array(T (& array_)[length_])342*2d1272b8SAndroid Build Coastguard Worker hb_array (T (&array_)[length_])
343*2d1272b8SAndroid Build Coastguard Worker { return hb_array_t<T> (array_); }
344*2d1272b8SAndroid Build Coastguard Worker
345*2d1272b8SAndroid Build Coastguard Worker template <typename Type>
346*2d1272b8SAndroid Build Coastguard Worker struct hb_sorted_array_t :
347*2d1272b8SAndroid Build Coastguard Worker hb_array_t<Type>,
348*2d1272b8SAndroid Build Coastguard Worker hb_iter_t<hb_sorted_array_t<Type>, Type&>
349*2d1272b8SAndroid Build Coastguard Worker {
350*2d1272b8SAndroid Build Coastguard Worker typedef hb_iter_t<hb_sorted_array_t, Type&> iter_base_t;
351*2d1272b8SAndroid Build Coastguard Worker HB_ITER_USING (iter_base_t);
352*2d1272b8SAndroid Build Coastguard Worker static constexpr bool is_random_access_iterator = true;
353*2d1272b8SAndroid Build Coastguard Worker static constexpr bool is_sorted_iterator = true;
354*2d1272b8SAndroid Build Coastguard Worker static constexpr bool has_fast_len = true;
355*2d1272b8SAndroid Build Coastguard Worker
356*2d1272b8SAndroid Build Coastguard Worker hb_sorted_array_t () = default;
357*2d1272b8SAndroid Build Coastguard Worker hb_sorted_array_t (const hb_sorted_array_t&) = default;
358*2d1272b8SAndroid Build Coastguard Worker ~hb_sorted_array_t () = default;
359*2d1272b8SAndroid Build Coastguard Worker hb_sorted_array_t& operator= (const hb_sorted_array_t&) = default;
360*2d1272b8SAndroid Build Coastguard Worker hb_sorted_array_t& operator= (hb_sorted_array_t&&) = default;
361*2d1272b8SAndroid Build Coastguard Worker
hb_sorted_array_thb_sorted_array_t362*2d1272b8SAndroid Build Coastguard Worker constexpr hb_sorted_array_t (Type *array_, unsigned int length_) : hb_array_t<Type> (array_, length_) {}
363*2d1272b8SAndroid Build Coastguard Worker template <unsigned int length_>
hb_sorted_array_thb_sorted_array_t364*2d1272b8SAndroid Build Coastguard Worker constexpr hb_sorted_array_t (Type (&array_)[length_]) : hb_array_t<Type> (array_) {}
365*2d1272b8SAndroid Build Coastguard Worker
366*2d1272b8SAndroid Build Coastguard Worker template <typename U,
367*2d1272b8SAndroid Build Coastguard Worker hb_enable_if (hb_is_cr_convertible(U, Type))>
hb_sorted_array_thb_sorted_array_t368*2d1272b8SAndroid Build Coastguard Worker constexpr hb_sorted_array_t (const hb_array_t<U> &o) :
369*2d1272b8SAndroid Build Coastguard Worker hb_array_t<Type> (o),
370*2d1272b8SAndroid Build Coastguard Worker hb_iter_t<hb_sorted_array_t, Type&> () {}
371*2d1272b8SAndroid Build Coastguard Worker template <typename U,
372*2d1272b8SAndroid Build Coastguard Worker hb_enable_if (hb_is_cr_convertible(U, Type))>
operator =hb_sorted_array_t373*2d1272b8SAndroid Build Coastguard Worker hb_sorted_array_t& operator = (const hb_array_t<U> &o)
374*2d1272b8SAndroid Build Coastguard Worker { hb_array_t<Type> (*this) = o; return *this; }
375*2d1272b8SAndroid Build Coastguard Worker
376*2d1272b8SAndroid Build Coastguard Worker /* Iterator implementation. */
377*2d1272b8SAndroid Build Coastguard Worker
378*2d1272b8SAndroid Build Coastguard Worker /* See comment in hb_array_of::operator != */
operator !=hb_sorted_array_t379*2d1272b8SAndroid Build Coastguard Worker bool operator != (const hb_sorted_array_t& o) const
380*2d1272b8SAndroid Build Coastguard Worker { return this->arrayZ != o.arrayZ || this->length != o.length; }
381*2d1272b8SAndroid Build Coastguard Worker
382*2d1272b8SAndroid Build Coastguard Worker /* Faster range-based for loop without bounds-check. */
beginhb_sorted_array_t383*2d1272b8SAndroid Build Coastguard Worker Type *begin () const { return this->arrayZ; }
endhb_sorted_array_t384*2d1272b8SAndroid Build Coastguard Worker Type *end () const { return this->arrayZ + this->length; }
385*2d1272b8SAndroid Build Coastguard Worker
386*2d1272b8SAndroid Build Coastguard Worker
sub_arrayhb_sorted_array_t387*2d1272b8SAndroid Build Coastguard Worker hb_sorted_array_t sub_array (unsigned int start_offset, unsigned int *seg_count /* IN/OUT */) const
388*2d1272b8SAndroid Build Coastguard Worker { return hb_sorted_array_t (((const hb_array_t<Type> *) (this))->sub_array (start_offset, seg_count)); }
sub_arrayhb_sorted_array_t389*2d1272b8SAndroid Build Coastguard Worker hb_sorted_array_t sub_array (unsigned int start_offset, unsigned int seg_count) const
390*2d1272b8SAndroid Build Coastguard Worker { return sub_array (start_offset, &seg_count); }
391*2d1272b8SAndroid Build Coastguard Worker
truncatehb_sorted_array_t392*2d1272b8SAndroid Build Coastguard Worker hb_sorted_array_t truncate (unsigned length) const { return sub_array (0, length); }
393*2d1272b8SAndroid Build Coastguard Worker
394*2d1272b8SAndroid Build Coastguard Worker template <typename T>
bsearchhb_sorted_array_t395*2d1272b8SAndroid Build Coastguard Worker Type *bsearch (const T &x, Type *not_found = nullptr)
396*2d1272b8SAndroid Build Coastguard Worker {
397*2d1272b8SAndroid Build Coastguard Worker unsigned int i;
398*2d1272b8SAndroid Build Coastguard Worker return bfind (x, &i) ? &this->arrayZ[i] : not_found;
399*2d1272b8SAndroid Build Coastguard Worker }
400*2d1272b8SAndroid Build Coastguard Worker template <typename T>
bsearchhb_sorted_array_t401*2d1272b8SAndroid Build Coastguard Worker const Type *bsearch (const T &x, const Type *not_found = nullptr) const
402*2d1272b8SAndroid Build Coastguard Worker {
403*2d1272b8SAndroid Build Coastguard Worker unsigned int i;
404*2d1272b8SAndroid Build Coastguard Worker return bfind (x, &i) ? &this->arrayZ[i] : not_found;
405*2d1272b8SAndroid Build Coastguard Worker }
406*2d1272b8SAndroid Build Coastguard Worker template <typename T>
bfindhb_sorted_array_t407*2d1272b8SAndroid Build Coastguard Worker bool bfind (const T &x, unsigned int *i = nullptr,
408*2d1272b8SAndroid Build Coastguard Worker hb_not_found_t not_found = HB_NOT_FOUND_DONT_STORE,
409*2d1272b8SAndroid Build Coastguard Worker unsigned int to_store = (unsigned int) -1) const
410*2d1272b8SAndroid Build Coastguard Worker {
411*2d1272b8SAndroid Build Coastguard Worker unsigned pos;
412*2d1272b8SAndroid Build Coastguard Worker
413*2d1272b8SAndroid Build Coastguard Worker if (bsearch_impl (x, &pos))
414*2d1272b8SAndroid Build Coastguard Worker {
415*2d1272b8SAndroid Build Coastguard Worker if (i)
416*2d1272b8SAndroid Build Coastguard Worker *i = pos;
417*2d1272b8SAndroid Build Coastguard Worker return true;
418*2d1272b8SAndroid Build Coastguard Worker }
419*2d1272b8SAndroid Build Coastguard Worker
420*2d1272b8SAndroid Build Coastguard Worker if (i)
421*2d1272b8SAndroid Build Coastguard Worker {
422*2d1272b8SAndroid Build Coastguard Worker switch (not_found)
423*2d1272b8SAndroid Build Coastguard Worker {
424*2d1272b8SAndroid Build Coastguard Worker case HB_NOT_FOUND_DONT_STORE:
425*2d1272b8SAndroid Build Coastguard Worker break;
426*2d1272b8SAndroid Build Coastguard Worker
427*2d1272b8SAndroid Build Coastguard Worker case HB_NOT_FOUND_STORE:
428*2d1272b8SAndroid Build Coastguard Worker *i = to_store;
429*2d1272b8SAndroid Build Coastguard Worker break;
430*2d1272b8SAndroid Build Coastguard Worker
431*2d1272b8SAndroid Build Coastguard Worker case HB_NOT_FOUND_STORE_CLOSEST:
432*2d1272b8SAndroid Build Coastguard Worker *i = pos;
433*2d1272b8SAndroid Build Coastguard Worker break;
434*2d1272b8SAndroid Build Coastguard Worker }
435*2d1272b8SAndroid Build Coastguard Worker }
436*2d1272b8SAndroid Build Coastguard Worker return false;
437*2d1272b8SAndroid Build Coastguard Worker }
438*2d1272b8SAndroid Build Coastguard Worker template <typename T, typename ...Ts>
bsearch_implhb_sorted_array_t439*2d1272b8SAndroid Build Coastguard Worker bool bsearch_impl (const T &x, unsigned *pos, Ts... ds) const
440*2d1272b8SAndroid Build Coastguard Worker {
441*2d1272b8SAndroid Build Coastguard Worker return hb_bsearch_impl (pos,
442*2d1272b8SAndroid Build Coastguard Worker x,
443*2d1272b8SAndroid Build Coastguard Worker this->arrayZ,
444*2d1272b8SAndroid Build Coastguard Worker this->length,
445*2d1272b8SAndroid Build Coastguard Worker sizeof (Type),
446*2d1272b8SAndroid Build Coastguard Worker _hb_cmp_method<T, Type, Ts...>,
447*2d1272b8SAndroid Build Coastguard Worker std::forward<Ts> (ds)...);
448*2d1272b8SAndroid Build Coastguard Worker }
449*2d1272b8SAndroid Build Coastguard Worker };
450*2d1272b8SAndroid Build Coastguard Worker template <typename T> inline hb_sorted_array_t<T>
hb_sorted_array(T * array,unsigned int length)451*2d1272b8SAndroid Build Coastguard Worker hb_sorted_array (T *array, unsigned int length)
452*2d1272b8SAndroid Build Coastguard Worker { return hb_sorted_array_t<T> (array, length); }
453*2d1272b8SAndroid Build Coastguard Worker template <typename T, unsigned int length_> inline hb_sorted_array_t<T>
hb_sorted_array(T (& array_)[length_])454*2d1272b8SAndroid Build Coastguard Worker hb_sorted_array (T (&array_)[length_])
455*2d1272b8SAndroid Build Coastguard Worker { return hb_sorted_array_t<T> (array_); }
456*2d1272b8SAndroid Build Coastguard Worker
457*2d1272b8SAndroid Build Coastguard Worker template <typename T>
operator ==(const hb_array_t<T> & o) const458*2d1272b8SAndroid Build Coastguard Worker inline bool hb_array_t<T>::operator == (const hb_array_t<T> &o) const
459*2d1272b8SAndroid Build Coastguard Worker {
460*2d1272b8SAndroid Build Coastguard Worker if (o.length != this->length) return false;
461*2d1272b8SAndroid Build Coastguard Worker for (unsigned int i = 0; i < this->length; i++) {
462*2d1272b8SAndroid Build Coastguard Worker if (this->arrayZ[i] != o.arrayZ[i]) return false;
463*2d1272b8SAndroid Build Coastguard Worker }
464*2d1272b8SAndroid Build Coastguard Worker return true;
465*2d1272b8SAndroid Build Coastguard Worker }
466*2d1272b8SAndroid Build Coastguard Worker template <>
operator ==(const hb_array_t<const char> & o) const467*2d1272b8SAndroid Build Coastguard Worker inline bool hb_array_t<const char>::operator == (const hb_array_t<const char> &o) const
468*2d1272b8SAndroid Build Coastguard Worker {
469*2d1272b8SAndroid Build Coastguard Worker if (o.length != this->length) return false;
470*2d1272b8SAndroid Build Coastguard Worker return 0 == hb_memcmp (arrayZ, o.arrayZ, length);
471*2d1272b8SAndroid Build Coastguard Worker }
472*2d1272b8SAndroid Build Coastguard Worker template <>
operator ==(const hb_array_t<const unsigned char> & o) const473*2d1272b8SAndroid Build Coastguard Worker inline bool hb_array_t<const unsigned char>::operator == (const hb_array_t<const unsigned char> &o) const
474*2d1272b8SAndroid Build Coastguard Worker {
475*2d1272b8SAndroid Build Coastguard Worker if (o.length != this->length) return false;
476*2d1272b8SAndroid Build Coastguard Worker return 0 == hb_memcmp (arrayZ, o.arrayZ, length);
477*2d1272b8SAndroid Build Coastguard Worker }
478*2d1272b8SAndroid Build Coastguard Worker
479*2d1272b8SAndroid Build Coastguard Worker
480*2d1272b8SAndroid Build Coastguard Worker /* Specialize hash() for byte arrays. */
481*2d1272b8SAndroid Build Coastguard Worker
482*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_OPTIMIZE_SIZE_MORE
483*2d1272b8SAndroid Build Coastguard Worker template <>
hash() const484*2d1272b8SAndroid Build Coastguard Worker inline uint32_t hb_array_t<const char>::hash () const
485*2d1272b8SAndroid Build Coastguard Worker {
486*2d1272b8SAndroid Build Coastguard Worker // https://github.com/harfbuzz/harfbuzz/pull/4228
487*2d1272b8SAndroid Build Coastguard Worker return fasthash32(arrayZ, length, 0xf437ffe6 /* magic? */);
488*2d1272b8SAndroid Build Coastguard Worker }
489*2d1272b8SAndroid Build Coastguard Worker
490*2d1272b8SAndroid Build Coastguard Worker template <>
hash() const491*2d1272b8SAndroid Build Coastguard Worker inline uint32_t hb_array_t<const unsigned char>::hash () const
492*2d1272b8SAndroid Build Coastguard Worker {
493*2d1272b8SAndroid Build Coastguard Worker // https://github.com/harfbuzz/harfbuzz/pull/4228
494*2d1272b8SAndroid Build Coastguard Worker return fasthash32(arrayZ, length, 0xf437ffe6 /* magic? */);
495*2d1272b8SAndroid Build Coastguard Worker }
496*2d1272b8SAndroid Build Coastguard Worker #endif
497*2d1272b8SAndroid Build Coastguard Worker
498*2d1272b8SAndroid Build Coastguard Worker
499*2d1272b8SAndroid Build Coastguard Worker typedef hb_array_t<const char> hb_bytes_t;
500*2d1272b8SAndroid Build Coastguard Worker typedef hb_array_t<const unsigned char> hb_ubytes_t;
501*2d1272b8SAndroid Build Coastguard Worker
502*2d1272b8SAndroid Build Coastguard Worker
503*2d1272b8SAndroid Build Coastguard Worker
504*2d1272b8SAndroid Build Coastguard Worker #endif /* HB_ARRAY_HH */
505