xref: /aosp_15_r20/external/harfbuzz_ng/src/hb-vector.hh (revision 2d1272b857b1f7575e6e246373e1cb218663db8a)
1*2d1272b8SAndroid Build Coastguard Worker /*
2*2d1272b8SAndroid Build Coastguard Worker  * Copyright © 2017,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_VECTOR_HH
28*2d1272b8SAndroid Build Coastguard Worker #define HB_VECTOR_HH
29*2d1272b8SAndroid Build Coastguard Worker 
30*2d1272b8SAndroid Build Coastguard Worker #include "hb.hh"
31*2d1272b8SAndroid Build Coastguard Worker #include "hb-array.hh"
32*2d1272b8SAndroid Build Coastguard Worker #include "hb-meta.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 	  bool sorted=false>
38*2d1272b8SAndroid Build Coastguard Worker struct hb_vector_t
39*2d1272b8SAndroid Build Coastguard Worker {
40*2d1272b8SAndroid Build Coastguard Worker   static constexpr bool realloc_move = true;
41*2d1272b8SAndroid Build Coastguard Worker 
42*2d1272b8SAndroid Build Coastguard Worker   typedef Type item_t;
43*2d1272b8SAndroid Build Coastguard Worker   static constexpr unsigned item_size = hb_static_size (Type);
44*2d1272b8SAndroid Build Coastguard Worker   using array_t = typename std::conditional<sorted, hb_sorted_array_t<Type>, hb_array_t<Type>>::type;
45*2d1272b8SAndroid Build Coastguard Worker   using c_array_t = typename std::conditional<sorted, hb_sorted_array_t<const Type>, hb_array_t<const Type>>::type;
46*2d1272b8SAndroid Build Coastguard Worker 
47*2d1272b8SAndroid Build Coastguard Worker   hb_vector_t () = default;
hb_vector_thb_vector_t48*2d1272b8SAndroid Build Coastguard Worker   hb_vector_t (std::initializer_list<Type> lst) : hb_vector_t ()
49*2d1272b8SAndroid Build Coastguard Worker   {
50*2d1272b8SAndroid Build Coastguard Worker     alloc (lst.size (), true);
51*2d1272b8SAndroid Build Coastguard Worker     for (auto&& item : lst)
52*2d1272b8SAndroid Build Coastguard Worker       push (item);
53*2d1272b8SAndroid Build Coastguard Worker   }
54*2d1272b8SAndroid Build Coastguard Worker   template <typename Iterable,
55*2d1272b8SAndroid Build Coastguard Worker 	    hb_requires (hb_is_iterable (Iterable))>
hb_vector_thb_vector_t56*2d1272b8SAndroid Build Coastguard Worker   hb_vector_t (const Iterable &o) : hb_vector_t ()
57*2d1272b8SAndroid Build Coastguard Worker   {
58*2d1272b8SAndroid Build Coastguard Worker     auto iter = hb_iter (o);
59*2d1272b8SAndroid Build Coastguard Worker     if (iter.is_random_access_iterator || iter.has_fast_len)
60*2d1272b8SAndroid Build Coastguard Worker       alloc (hb_len (iter), true);
61*2d1272b8SAndroid Build Coastguard Worker     hb_copy (iter, *this);
62*2d1272b8SAndroid Build Coastguard Worker   }
hb_vector_thb_vector_t63*2d1272b8SAndroid Build Coastguard Worker   hb_vector_t (const hb_vector_t &o) : hb_vector_t ()
64*2d1272b8SAndroid Build Coastguard Worker   {
65*2d1272b8SAndroid Build Coastguard Worker     alloc (o.length, true);
66*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (in_error ())) return;
67*2d1272b8SAndroid Build Coastguard Worker     copy_array (o.as_array ());
68*2d1272b8SAndroid Build Coastguard Worker   }
hb_vector_thb_vector_t69*2d1272b8SAndroid Build Coastguard Worker   hb_vector_t (array_t o) : hb_vector_t ()
70*2d1272b8SAndroid Build Coastguard Worker   {
71*2d1272b8SAndroid Build Coastguard Worker     alloc (o.length, true);
72*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (in_error ())) return;
73*2d1272b8SAndroid Build Coastguard Worker     copy_array (o);
74*2d1272b8SAndroid Build Coastguard Worker   }
hb_vector_thb_vector_t75*2d1272b8SAndroid Build Coastguard Worker   hb_vector_t (c_array_t o) : hb_vector_t ()
76*2d1272b8SAndroid Build Coastguard Worker   {
77*2d1272b8SAndroid Build Coastguard Worker     alloc (o.length, true);
78*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (in_error ())) return;
79*2d1272b8SAndroid Build Coastguard Worker     copy_array (o);
80*2d1272b8SAndroid Build Coastguard Worker   }
hb_vector_thb_vector_t81*2d1272b8SAndroid Build Coastguard Worker   hb_vector_t (hb_vector_t &&o) noexcept
82*2d1272b8SAndroid Build Coastguard Worker   {
83*2d1272b8SAndroid Build Coastguard Worker     allocated = o.allocated;
84*2d1272b8SAndroid Build Coastguard Worker     length = o.length;
85*2d1272b8SAndroid Build Coastguard Worker     arrayZ = o.arrayZ;
86*2d1272b8SAndroid Build Coastguard Worker     o.init ();
87*2d1272b8SAndroid Build Coastguard Worker   }
~hb_vector_thb_vector_t88*2d1272b8SAndroid Build Coastguard Worker   ~hb_vector_t () { fini (); }
89*2d1272b8SAndroid Build Coastguard Worker 
90*2d1272b8SAndroid Build Coastguard Worker   public:
91*2d1272b8SAndroid Build Coastguard Worker   int allocated = 0; /* < 0 means allocation failed. */
92*2d1272b8SAndroid Build Coastguard Worker   unsigned int length = 0;
93*2d1272b8SAndroid Build Coastguard Worker   public:
94*2d1272b8SAndroid Build Coastguard Worker   Type *arrayZ = nullptr;
95*2d1272b8SAndroid Build Coastguard Worker 
inithb_vector_t96*2d1272b8SAndroid Build Coastguard Worker   void init ()
97*2d1272b8SAndroid Build Coastguard Worker   {
98*2d1272b8SAndroid Build Coastguard Worker     allocated = length = 0;
99*2d1272b8SAndroid Build Coastguard Worker     arrayZ = nullptr;
100*2d1272b8SAndroid Build Coastguard Worker   }
init0hb_vector_t101*2d1272b8SAndroid Build Coastguard Worker   void init0 ()
102*2d1272b8SAndroid Build Coastguard Worker   {
103*2d1272b8SAndroid Build Coastguard Worker   }
104*2d1272b8SAndroid Build Coastguard Worker 
finihb_vector_t105*2d1272b8SAndroid Build Coastguard Worker   void fini ()
106*2d1272b8SAndroid Build Coastguard Worker   {
107*2d1272b8SAndroid Build Coastguard Worker     /* We allow a hack to make the vector point to a foreign array
108*2d1272b8SAndroid Build Coastguard Worker      * by the user. In that case length/arrayZ are non-zero but
109*2d1272b8SAndroid Build Coastguard Worker      * allocated is zero. Don't free anything. */
110*2d1272b8SAndroid Build Coastguard Worker     if (allocated)
111*2d1272b8SAndroid Build Coastguard Worker     {
112*2d1272b8SAndroid Build Coastguard Worker       shrink_vector (0);
113*2d1272b8SAndroid Build Coastguard Worker       hb_free (arrayZ);
114*2d1272b8SAndroid Build Coastguard Worker     }
115*2d1272b8SAndroid Build Coastguard Worker     init ();
116*2d1272b8SAndroid Build Coastguard Worker   }
117*2d1272b8SAndroid Build Coastguard Worker 
resethb_vector_t118*2d1272b8SAndroid Build Coastguard Worker   void reset ()
119*2d1272b8SAndroid Build Coastguard Worker   {
120*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (in_error ()))
121*2d1272b8SAndroid Build Coastguard Worker       reset_error ();
122*2d1272b8SAndroid Build Coastguard Worker     resize (0);
123*2d1272b8SAndroid Build Coastguard Worker   }
124*2d1272b8SAndroid Build Coastguard Worker 
swap(hb_vector_t & a,hb_vector_t & b)125*2d1272b8SAndroid Build Coastguard Worker   friend void swap (hb_vector_t& a, hb_vector_t& b) noexcept
126*2d1272b8SAndroid Build Coastguard Worker   {
127*2d1272b8SAndroid Build Coastguard Worker     hb_swap (a.allocated, b.allocated);
128*2d1272b8SAndroid Build Coastguard Worker     hb_swap (a.length, b.length);
129*2d1272b8SAndroid Build Coastguard Worker     hb_swap (a.arrayZ, b.arrayZ);
130*2d1272b8SAndroid Build Coastguard Worker   }
131*2d1272b8SAndroid Build Coastguard Worker 
operator =hb_vector_t132*2d1272b8SAndroid Build Coastguard Worker   hb_vector_t& operator = (const hb_vector_t &o)
133*2d1272b8SAndroid Build Coastguard Worker   {
134*2d1272b8SAndroid Build Coastguard Worker     reset ();
135*2d1272b8SAndroid Build Coastguard Worker     alloc (o.length, true);
136*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (in_error ())) return *this;
137*2d1272b8SAndroid Build Coastguard Worker 
138*2d1272b8SAndroid Build Coastguard Worker     copy_array (o.as_array ());
139*2d1272b8SAndroid Build Coastguard Worker 
140*2d1272b8SAndroid Build Coastguard Worker     return *this;
141*2d1272b8SAndroid Build Coastguard Worker   }
operator =hb_vector_t142*2d1272b8SAndroid Build Coastguard Worker   hb_vector_t& operator = (hb_vector_t &&o) noexcept
143*2d1272b8SAndroid Build Coastguard Worker   {
144*2d1272b8SAndroid Build Coastguard Worker     hb_swap (*this, o);
145*2d1272b8SAndroid Build Coastguard Worker     return *this;
146*2d1272b8SAndroid Build Coastguard Worker   }
147*2d1272b8SAndroid Build Coastguard Worker 
as_byteshb_vector_t148*2d1272b8SAndroid Build Coastguard Worker   hb_bytes_t as_bytes () const
149*2d1272b8SAndroid Build Coastguard Worker   { return hb_bytes_t ((const char *) arrayZ, get_size ()); }
150*2d1272b8SAndroid Build Coastguard Worker 
operator ==hb_vector_t151*2d1272b8SAndroid Build Coastguard Worker   bool operator == (const hb_vector_t &o) const { return as_array () == o.as_array (); }
operator !=hb_vector_t152*2d1272b8SAndroid Build Coastguard Worker   bool operator != (const hb_vector_t &o) const { return !(*this == o); }
hashhb_vector_t153*2d1272b8SAndroid Build Coastguard Worker   uint32_t hash () const { return as_array ().hash (); }
154*2d1272b8SAndroid Build Coastguard Worker 
operator []hb_vector_t155*2d1272b8SAndroid Build Coastguard Worker   Type& operator [] (int i_)
156*2d1272b8SAndroid Build Coastguard Worker   {
157*2d1272b8SAndroid Build Coastguard Worker     unsigned int i = (unsigned int) i_;
158*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (i >= length))
159*2d1272b8SAndroid Build Coastguard Worker       return Crap (Type);
160*2d1272b8SAndroid Build Coastguard Worker     return arrayZ[i];
161*2d1272b8SAndroid Build Coastguard Worker   }
operator []hb_vector_t162*2d1272b8SAndroid Build Coastguard Worker   const Type& operator [] (int i_) const
163*2d1272b8SAndroid Build Coastguard Worker   {
164*2d1272b8SAndroid Build Coastguard Worker     unsigned int i = (unsigned int) i_;
165*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (i >= length))
166*2d1272b8SAndroid Build Coastguard Worker       return Null (Type);
167*2d1272b8SAndroid Build Coastguard Worker     return arrayZ[i];
168*2d1272b8SAndroid Build Coastguard Worker   }
169*2d1272b8SAndroid Build Coastguard Worker 
tailhb_vector_t170*2d1272b8SAndroid Build Coastguard Worker   Type& tail () { return (*this)[length - 1]; }
tailhb_vector_t171*2d1272b8SAndroid Build Coastguard Worker   const Type& tail () const { return (*this)[length - 1]; }
172*2d1272b8SAndroid Build Coastguard Worker 
operator boolhb_vector_t173*2d1272b8SAndroid Build Coastguard Worker   explicit operator bool () const { return length; }
get_sizehb_vector_t174*2d1272b8SAndroid Build Coastguard Worker   unsigned get_size () const { return length * item_size; }
175*2d1272b8SAndroid Build Coastguard Worker 
176*2d1272b8SAndroid Build Coastguard Worker   /* Sink interface. */
177*2d1272b8SAndroid Build Coastguard Worker   template <typename T>
operator <<hb_vector_t178*2d1272b8SAndroid Build Coastguard Worker   hb_vector_t& operator << (T&& v) { push (std::forward<T> (v)); return *this; }
179*2d1272b8SAndroid Build Coastguard Worker 
as_arrayhb_vector_t180*2d1272b8SAndroid Build Coastguard Worker   array_t   as_array ()       { return hb_array (arrayZ, length); }
as_arrayhb_vector_t181*2d1272b8SAndroid Build Coastguard Worker   c_array_t as_array () const { return hb_array (arrayZ, length); }
182*2d1272b8SAndroid Build Coastguard Worker 
183*2d1272b8SAndroid Build Coastguard Worker   /* Iterator. */
184*2d1272b8SAndroid Build Coastguard Worker   typedef c_array_t   iter_t;
185*2d1272b8SAndroid Build Coastguard Worker   typedef array_t   writer_t;
iterhb_vector_t186*2d1272b8SAndroid Build Coastguard Worker     iter_t   iter () const { return as_array (); }
writerhb_vector_t187*2d1272b8SAndroid Build Coastguard Worker   writer_t writer ()       { return as_array (); }
operator iter_thb_vector_t188*2d1272b8SAndroid Build Coastguard Worker   operator   iter_t () const { return   iter (); }
operator writer_thb_vector_t189*2d1272b8SAndroid Build Coastguard Worker   operator writer_t ()       { return writer (); }
190*2d1272b8SAndroid Build Coastguard Worker 
191*2d1272b8SAndroid Build Coastguard Worker   /* Faster range-based for loop. */
beginhb_vector_t192*2d1272b8SAndroid Build Coastguard Worker   Type *begin () const { return arrayZ; }
endhb_vector_t193*2d1272b8SAndroid Build Coastguard Worker   Type *end () const { return arrayZ + length; }
194*2d1272b8SAndroid Build Coastguard Worker 
195*2d1272b8SAndroid Build Coastguard Worker 
as_sorted_arrayhb_vector_t196*2d1272b8SAndroid Build Coastguard Worker   hb_sorted_array_t<Type> as_sorted_array ()
197*2d1272b8SAndroid Build Coastguard Worker   { return hb_sorted_array (arrayZ, length); }
as_sorted_arrayhb_vector_t198*2d1272b8SAndroid Build Coastguard Worker   hb_sorted_array_t<const Type> as_sorted_array () const
199*2d1272b8SAndroid Build Coastguard Worker   { return hb_sorted_array (arrayZ, length); }
200*2d1272b8SAndroid Build Coastguard Worker 
operator T*hb_vector_t201*2d1272b8SAndroid Build Coastguard Worker   template <typename T> explicit operator T * () { return arrayZ; }
operator const T*hb_vector_t202*2d1272b8SAndroid Build Coastguard Worker   template <typename T> explicit operator const T * () const { return arrayZ; }
203*2d1272b8SAndroid Build Coastguard Worker 
operator +hb_vector_t204*2d1272b8SAndroid Build Coastguard Worker   Type * operator  + (unsigned int i) { return arrayZ + i; }
operator +hb_vector_t205*2d1272b8SAndroid Build Coastguard Worker   const Type * operator  + (unsigned int i) const { return arrayZ + i; }
206*2d1272b8SAndroid Build Coastguard Worker 
pushhb_vector_t207*2d1272b8SAndroid Build Coastguard Worker   Type *push ()
208*2d1272b8SAndroid Build Coastguard Worker   {
209*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (!resize (length + 1)))
210*2d1272b8SAndroid Build Coastguard Worker       return std::addressof (Crap (Type));
211*2d1272b8SAndroid Build Coastguard Worker     return std::addressof (arrayZ[length - 1]);
212*2d1272b8SAndroid Build Coastguard Worker   }
pushhb_vector_t213*2d1272b8SAndroid Build Coastguard Worker   template <typename... Args> Type *push (Args&&... args)
214*2d1272b8SAndroid Build Coastguard Worker   {
215*2d1272b8SAndroid Build Coastguard Worker     if (unlikely ((int) length >= allocated && !alloc (length + 1)))
216*2d1272b8SAndroid Build Coastguard Worker       // If push failed to allocate then don't copy v, since this may cause
217*2d1272b8SAndroid Build Coastguard Worker       // the created copy to leak memory since we won't have stored a
218*2d1272b8SAndroid Build Coastguard Worker       // reference to it.
219*2d1272b8SAndroid Build Coastguard Worker       return std::addressof (Crap (Type));
220*2d1272b8SAndroid Build Coastguard Worker 
221*2d1272b8SAndroid Build Coastguard Worker     /* Emplace. */
222*2d1272b8SAndroid Build Coastguard Worker     Type *p = std::addressof (arrayZ[length++]);
223*2d1272b8SAndroid Build Coastguard Worker     return new (p) Type (std::forward<Args> (args)...);
224*2d1272b8SAndroid Build Coastguard Worker   }
225*2d1272b8SAndroid Build Coastguard Worker 
in_errorhb_vector_t226*2d1272b8SAndroid Build Coastguard Worker   bool in_error () const { return allocated < 0; }
set_errorhb_vector_t227*2d1272b8SAndroid Build Coastguard Worker   void set_error ()
228*2d1272b8SAndroid Build Coastguard Worker   {
229*2d1272b8SAndroid Build Coastguard Worker     assert (allocated >= 0);
230*2d1272b8SAndroid Build Coastguard Worker     allocated = -allocated - 1;
231*2d1272b8SAndroid Build Coastguard Worker   }
reset_errorhb_vector_t232*2d1272b8SAndroid Build Coastguard Worker   void reset_error ()
233*2d1272b8SAndroid Build Coastguard Worker   {
234*2d1272b8SAndroid Build Coastguard Worker     assert (allocated < 0);
235*2d1272b8SAndroid Build Coastguard Worker     allocated = -(allocated + 1);
236*2d1272b8SAndroid Build Coastguard Worker   }
237*2d1272b8SAndroid Build Coastguard Worker 
238*2d1272b8SAndroid Build Coastguard Worker   template <typename T = Type,
239*2d1272b8SAndroid Build Coastguard Worker 	    hb_enable_if (hb_is_trivially_copy_assignable(T))>
240*2d1272b8SAndroid Build Coastguard Worker   Type *
realloc_vectorhb_vector_t241*2d1272b8SAndroid Build Coastguard Worker   realloc_vector (unsigned new_allocated, hb_priority<0>)
242*2d1272b8SAndroid Build Coastguard Worker   {
243*2d1272b8SAndroid Build Coastguard Worker     if (!new_allocated)
244*2d1272b8SAndroid Build Coastguard Worker     {
245*2d1272b8SAndroid Build Coastguard Worker       hb_free (arrayZ);
246*2d1272b8SAndroid Build Coastguard Worker       return nullptr;
247*2d1272b8SAndroid Build Coastguard Worker     }
248*2d1272b8SAndroid Build Coastguard Worker     return (Type *) hb_realloc (arrayZ, new_allocated * sizeof (Type));
249*2d1272b8SAndroid Build Coastguard Worker   }
250*2d1272b8SAndroid Build Coastguard Worker   template <typename T = Type,
251*2d1272b8SAndroid Build Coastguard Worker 	    hb_enable_if (!hb_is_trivially_copy_assignable(T))>
252*2d1272b8SAndroid Build Coastguard Worker   Type *
realloc_vectorhb_vector_t253*2d1272b8SAndroid Build Coastguard Worker   realloc_vector (unsigned new_allocated, hb_priority<0>)
254*2d1272b8SAndroid Build Coastguard Worker   {
255*2d1272b8SAndroid Build Coastguard Worker     if (!new_allocated)
256*2d1272b8SAndroid Build Coastguard Worker     {
257*2d1272b8SAndroid Build Coastguard Worker       hb_free (arrayZ);
258*2d1272b8SAndroid Build Coastguard Worker       return nullptr;
259*2d1272b8SAndroid Build Coastguard Worker     }
260*2d1272b8SAndroid Build Coastguard Worker     Type *new_array = (Type *) hb_malloc (new_allocated * sizeof (Type));
261*2d1272b8SAndroid Build Coastguard Worker     if (likely (new_array))
262*2d1272b8SAndroid Build Coastguard Worker     {
263*2d1272b8SAndroid Build Coastguard Worker       for (unsigned i = 0; i < length; i++)
264*2d1272b8SAndroid Build Coastguard Worker       {
265*2d1272b8SAndroid Build Coastguard Worker 	new (std::addressof (new_array[i])) Type ();
266*2d1272b8SAndroid Build Coastguard Worker 	new_array[i] = std::move (arrayZ[i]);
267*2d1272b8SAndroid Build Coastguard Worker 	arrayZ[i].~Type ();
268*2d1272b8SAndroid Build Coastguard Worker       }
269*2d1272b8SAndroid Build Coastguard Worker       hb_free (arrayZ);
270*2d1272b8SAndroid Build Coastguard Worker     }
271*2d1272b8SAndroid Build Coastguard Worker     return new_array;
272*2d1272b8SAndroid Build Coastguard Worker   }
273*2d1272b8SAndroid Build Coastguard Worker   /* Specialization for types that can be moved using realloc(). */
274*2d1272b8SAndroid Build Coastguard Worker   template <typename T = Type,
275*2d1272b8SAndroid Build Coastguard Worker 	    hb_enable_if (T::realloc_move)>
276*2d1272b8SAndroid Build Coastguard Worker   Type *
realloc_vectorhb_vector_t277*2d1272b8SAndroid Build Coastguard Worker   realloc_vector (unsigned new_allocated, hb_priority<1>)
278*2d1272b8SAndroid Build Coastguard Worker   {
279*2d1272b8SAndroid Build Coastguard Worker     if (!new_allocated)
280*2d1272b8SAndroid Build Coastguard Worker     {
281*2d1272b8SAndroid Build Coastguard Worker       hb_free (arrayZ);
282*2d1272b8SAndroid Build Coastguard Worker       return nullptr;
283*2d1272b8SAndroid Build Coastguard Worker     }
284*2d1272b8SAndroid Build Coastguard Worker     return (Type *) hb_realloc (arrayZ, new_allocated * sizeof (Type));
285*2d1272b8SAndroid Build Coastguard Worker   }
286*2d1272b8SAndroid Build Coastguard Worker 
287*2d1272b8SAndroid Build Coastguard Worker   template <typename T = Type,
288*2d1272b8SAndroid Build Coastguard Worker 	    hb_enable_if (hb_is_trivially_constructible(T))>
289*2d1272b8SAndroid Build Coastguard Worker   void
grow_vectorhb_vector_t290*2d1272b8SAndroid Build Coastguard Worker   grow_vector (unsigned size, hb_priority<0>)
291*2d1272b8SAndroid Build Coastguard Worker   {
292*2d1272b8SAndroid Build Coastguard Worker     hb_memset (arrayZ + length, 0, (size - length) * sizeof (*arrayZ));
293*2d1272b8SAndroid Build Coastguard Worker     length = size;
294*2d1272b8SAndroid Build Coastguard Worker   }
295*2d1272b8SAndroid Build Coastguard Worker   template <typename T = Type,
296*2d1272b8SAndroid Build Coastguard Worker 	    hb_enable_if (!hb_is_trivially_constructible(T))>
297*2d1272b8SAndroid Build Coastguard Worker   void
grow_vectorhb_vector_t298*2d1272b8SAndroid Build Coastguard Worker   grow_vector (unsigned size, hb_priority<0>)
299*2d1272b8SAndroid Build Coastguard Worker   {
300*2d1272b8SAndroid Build Coastguard Worker     for (; length < size; length++)
301*2d1272b8SAndroid Build Coastguard Worker       new (std::addressof (arrayZ[length])) Type ();
302*2d1272b8SAndroid Build Coastguard Worker   }
303*2d1272b8SAndroid Build Coastguard Worker   /* Specialization for hb_vector_t<hb_{vector,array}_t<U>> to speed up. */
304*2d1272b8SAndroid Build Coastguard Worker   template <typename T = Type,
305*2d1272b8SAndroid Build Coastguard Worker 	    hb_enable_if (hb_is_same (T, hb_vector_t<typename T::item_t>) ||
306*2d1272b8SAndroid Build Coastguard Worker 			  hb_is_same (T, hb_array_t <typename T::item_t>))>
307*2d1272b8SAndroid Build Coastguard Worker   void
grow_vectorhb_vector_t308*2d1272b8SAndroid Build Coastguard Worker   grow_vector (unsigned size, hb_priority<1>)
309*2d1272b8SAndroid Build Coastguard Worker   {
310*2d1272b8SAndroid Build Coastguard Worker     hb_memset (arrayZ + length, 0, (size - length) * sizeof (*arrayZ));
311*2d1272b8SAndroid Build Coastguard Worker     length = size;
312*2d1272b8SAndroid Build Coastguard Worker   }
313*2d1272b8SAndroid Build Coastguard Worker 
314*2d1272b8SAndroid Build Coastguard Worker   template <typename T = Type,
315*2d1272b8SAndroid Build Coastguard Worker 	    hb_enable_if (hb_is_trivially_copyable (T))>
316*2d1272b8SAndroid Build Coastguard Worker   void
copy_arrayhb_vector_t317*2d1272b8SAndroid Build Coastguard Worker   copy_array (hb_array_t<const Type> other)
318*2d1272b8SAndroid Build Coastguard Worker   {
319*2d1272b8SAndroid Build Coastguard Worker     length = other.length;
320*2d1272b8SAndroid Build Coastguard Worker     if (!HB_OPTIMIZE_SIZE_VAL && sizeof (T) >= sizeof (long long))
321*2d1272b8SAndroid Build Coastguard Worker       /* This runs faster because of alignment. */
322*2d1272b8SAndroid Build Coastguard Worker       for (unsigned i = 0; i < length; i++)
323*2d1272b8SAndroid Build Coastguard Worker 	arrayZ[i] = other.arrayZ[i];
324*2d1272b8SAndroid Build Coastguard Worker     else
325*2d1272b8SAndroid Build Coastguard Worker        hb_memcpy ((void *) arrayZ, (const void *) other.arrayZ, length * item_size);
326*2d1272b8SAndroid Build Coastguard Worker   }
327*2d1272b8SAndroid Build Coastguard Worker   template <typename T = Type,
328*2d1272b8SAndroid Build Coastguard Worker 	    hb_enable_if (!hb_is_trivially_copyable (T) &&
329*2d1272b8SAndroid Build Coastguard Worker 			   std::is_copy_constructible<T>::value)>
330*2d1272b8SAndroid Build Coastguard Worker   void
copy_arrayhb_vector_t331*2d1272b8SAndroid Build Coastguard Worker   copy_array (hb_array_t<const Type> other)
332*2d1272b8SAndroid Build Coastguard Worker   {
333*2d1272b8SAndroid Build Coastguard Worker     length = 0;
334*2d1272b8SAndroid Build Coastguard Worker     while (length < other.length)
335*2d1272b8SAndroid Build Coastguard Worker     {
336*2d1272b8SAndroid Build Coastguard Worker       length++;
337*2d1272b8SAndroid Build Coastguard Worker       new (std::addressof (arrayZ[length - 1])) Type (other.arrayZ[length - 1]);
338*2d1272b8SAndroid Build Coastguard Worker     }
339*2d1272b8SAndroid Build Coastguard Worker   }
340*2d1272b8SAndroid Build Coastguard Worker   template <typename T = Type,
341*2d1272b8SAndroid Build Coastguard Worker 	    hb_enable_if (!hb_is_trivially_copyable (T) &&
342*2d1272b8SAndroid Build Coastguard Worker 			  !std::is_copy_constructible<T>::value &&
343*2d1272b8SAndroid Build Coastguard Worker 			  std::is_default_constructible<T>::value &&
344*2d1272b8SAndroid Build Coastguard Worker 			  std::is_copy_assignable<T>::value)>
345*2d1272b8SAndroid Build Coastguard Worker   void
copy_arrayhb_vector_t346*2d1272b8SAndroid Build Coastguard Worker   copy_array (hb_array_t<const Type> other)
347*2d1272b8SAndroid Build Coastguard Worker   {
348*2d1272b8SAndroid Build Coastguard Worker     length = 0;
349*2d1272b8SAndroid Build Coastguard Worker     while (length < other.length)
350*2d1272b8SAndroid Build Coastguard Worker     {
351*2d1272b8SAndroid Build Coastguard Worker       length++;
352*2d1272b8SAndroid Build Coastguard Worker       new (std::addressof (arrayZ[length - 1])) Type ();
353*2d1272b8SAndroid Build Coastguard Worker       arrayZ[length - 1] = other.arrayZ[length - 1];
354*2d1272b8SAndroid Build Coastguard Worker     }
355*2d1272b8SAndroid Build Coastguard Worker   }
356*2d1272b8SAndroid Build Coastguard Worker 
357*2d1272b8SAndroid Build Coastguard Worker   void
shrink_vectorhb_vector_t358*2d1272b8SAndroid Build Coastguard Worker   shrink_vector (unsigned size)
359*2d1272b8SAndroid Build Coastguard Worker   {
360*2d1272b8SAndroid Build Coastguard Worker     assert (size <= length);
361*2d1272b8SAndroid Build Coastguard Worker     if (!std::is_trivially_destructible<Type>::value)
362*2d1272b8SAndroid Build Coastguard Worker     {
363*2d1272b8SAndroid Build Coastguard Worker       unsigned count = length - size;
364*2d1272b8SAndroid Build Coastguard Worker       Type *p = arrayZ + length - 1;
365*2d1272b8SAndroid Build Coastguard Worker       while (count--)
366*2d1272b8SAndroid Build Coastguard Worker         p--->~Type ();
367*2d1272b8SAndroid Build Coastguard Worker     }
368*2d1272b8SAndroid Build Coastguard Worker     length = size;
369*2d1272b8SAndroid Build Coastguard Worker   }
370*2d1272b8SAndroid Build Coastguard Worker 
371*2d1272b8SAndroid Build Coastguard Worker   void
shift_down_vectorhb_vector_t372*2d1272b8SAndroid Build Coastguard Worker   shift_down_vector (unsigned i)
373*2d1272b8SAndroid Build Coastguard Worker   {
374*2d1272b8SAndroid Build Coastguard Worker     for (; i < length; i++)
375*2d1272b8SAndroid Build Coastguard Worker       arrayZ[i - 1] = std::move (arrayZ[i]);
376*2d1272b8SAndroid Build Coastguard Worker   }
377*2d1272b8SAndroid Build Coastguard Worker 
378*2d1272b8SAndroid Build Coastguard Worker   /* Allocate for size but don't adjust length. */
allochb_vector_t379*2d1272b8SAndroid Build Coastguard Worker   bool alloc (unsigned int size, bool exact=false)
380*2d1272b8SAndroid Build Coastguard Worker   {
381*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (in_error ()))
382*2d1272b8SAndroid Build Coastguard Worker       return false;
383*2d1272b8SAndroid Build Coastguard Worker 
384*2d1272b8SAndroid Build Coastguard Worker     unsigned int new_allocated;
385*2d1272b8SAndroid Build Coastguard Worker     if (exact)
386*2d1272b8SAndroid Build Coastguard Worker     {
387*2d1272b8SAndroid Build Coastguard Worker       /* If exact was specified, we allow shrinking the storage. */
388*2d1272b8SAndroid Build Coastguard Worker       size = hb_max (size, length);
389*2d1272b8SAndroid Build Coastguard Worker       if (size <= (unsigned) allocated &&
390*2d1272b8SAndroid Build Coastguard Worker 	  size >= (unsigned) allocated >> 2)
391*2d1272b8SAndroid Build Coastguard Worker 	return true;
392*2d1272b8SAndroid Build Coastguard Worker 
393*2d1272b8SAndroid Build Coastguard Worker       new_allocated = size;
394*2d1272b8SAndroid Build Coastguard Worker     }
395*2d1272b8SAndroid Build Coastguard Worker     else
396*2d1272b8SAndroid Build Coastguard Worker     {
397*2d1272b8SAndroid Build Coastguard Worker       if (likely (size <= (unsigned) allocated))
398*2d1272b8SAndroid Build Coastguard Worker 	return true;
399*2d1272b8SAndroid Build Coastguard Worker 
400*2d1272b8SAndroid Build Coastguard Worker       new_allocated = allocated;
401*2d1272b8SAndroid Build Coastguard Worker       while (size > new_allocated)
402*2d1272b8SAndroid Build Coastguard Worker 	new_allocated += (new_allocated >> 1) + 8;
403*2d1272b8SAndroid Build Coastguard Worker     }
404*2d1272b8SAndroid Build Coastguard Worker 
405*2d1272b8SAndroid Build Coastguard Worker 
406*2d1272b8SAndroid Build Coastguard Worker     /* Reallocate */
407*2d1272b8SAndroid Build Coastguard Worker 
408*2d1272b8SAndroid Build Coastguard Worker     bool overflows =
409*2d1272b8SAndroid Build Coastguard Worker       (int) in_error () ||
410*2d1272b8SAndroid Build Coastguard Worker       (new_allocated < size) ||
411*2d1272b8SAndroid Build Coastguard Worker       hb_unsigned_mul_overflows (new_allocated, sizeof (Type));
412*2d1272b8SAndroid Build Coastguard Worker 
413*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (overflows))
414*2d1272b8SAndroid Build Coastguard Worker     {
415*2d1272b8SAndroid Build Coastguard Worker       set_error ();
416*2d1272b8SAndroid Build Coastguard Worker       return false;
417*2d1272b8SAndroid Build Coastguard Worker     }
418*2d1272b8SAndroid Build Coastguard Worker 
419*2d1272b8SAndroid Build Coastguard Worker     Type *new_array = realloc_vector (new_allocated, hb_prioritize);
420*2d1272b8SAndroid Build Coastguard Worker 
421*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (new_allocated && !new_array))
422*2d1272b8SAndroid Build Coastguard Worker     {
423*2d1272b8SAndroid Build Coastguard Worker       if (new_allocated <= (unsigned) allocated)
424*2d1272b8SAndroid Build Coastguard Worker         return true; // shrinking failed; it's okay; happens in our fuzzer
425*2d1272b8SAndroid Build Coastguard Worker 
426*2d1272b8SAndroid Build Coastguard Worker       set_error ();
427*2d1272b8SAndroid Build Coastguard Worker       return false;
428*2d1272b8SAndroid Build Coastguard Worker     }
429*2d1272b8SAndroid Build Coastguard Worker 
430*2d1272b8SAndroid Build Coastguard Worker     arrayZ = new_array;
431*2d1272b8SAndroid Build Coastguard Worker     allocated = new_allocated;
432*2d1272b8SAndroid Build Coastguard Worker 
433*2d1272b8SAndroid Build Coastguard Worker     return true;
434*2d1272b8SAndroid Build Coastguard Worker   }
435*2d1272b8SAndroid Build Coastguard Worker 
resizehb_vector_t436*2d1272b8SAndroid Build Coastguard Worker   bool resize (int size_, bool initialize = true, bool exact = false)
437*2d1272b8SAndroid Build Coastguard Worker   {
438*2d1272b8SAndroid Build Coastguard Worker     unsigned int size = size_ < 0 ? 0u : (unsigned int) size_;
439*2d1272b8SAndroid Build Coastguard Worker     if (!alloc (size, exact))
440*2d1272b8SAndroid Build Coastguard Worker       return false;
441*2d1272b8SAndroid Build Coastguard Worker 
442*2d1272b8SAndroid Build Coastguard Worker     if (size > length)
443*2d1272b8SAndroid Build Coastguard Worker     {
444*2d1272b8SAndroid Build Coastguard Worker       if (initialize)
445*2d1272b8SAndroid Build Coastguard Worker 	grow_vector (size, hb_prioritize);
446*2d1272b8SAndroid Build Coastguard Worker     }
447*2d1272b8SAndroid Build Coastguard Worker     else if (size < length)
448*2d1272b8SAndroid Build Coastguard Worker     {
449*2d1272b8SAndroid Build Coastguard Worker       if (initialize)
450*2d1272b8SAndroid Build Coastguard Worker 	shrink_vector (size);
451*2d1272b8SAndroid Build Coastguard Worker     }
452*2d1272b8SAndroid Build Coastguard Worker 
453*2d1272b8SAndroid Build Coastguard Worker     length = size;
454*2d1272b8SAndroid Build Coastguard Worker     return true;
455*2d1272b8SAndroid Build Coastguard Worker   }
resize_exacthb_vector_t456*2d1272b8SAndroid Build Coastguard Worker   bool resize_exact (int size_, bool initialize = true)
457*2d1272b8SAndroid Build Coastguard Worker   {
458*2d1272b8SAndroid Build Coastguard Worker     return resize (size_, initialize, true);
459*2d1272b8SAndroid Build Coastguard Worker   }
460*2d1272b8SAndroid Build Coastguard Worker 
pophb_vector_t461*2d1272b8SAndroid Build Coastguard Worker   Type pop ()
462*2d1272b8SAndroid Build Coastguard Worker   {
463*2d1272b8SAndroid Build Coastguard Worker     if (!length) return Null (Type);
464*2d1272b8SAndroid Build Coastguard Worker     Type v (std::move (arrayZ[length - 1]));
465*2d1272b8SAndroid Build Coastguard Worker     arrayZ[length - 1].~Type ();
466*2d1272b8SAndroid Build Coastguard Worker     length--;
467*2d1272b8SAndroid Build Coastguard Worker     return v;
468*2d1272b8SAndroid Build Coastguard Worker   }
469*2d1272b8SAndroid Build Coastguard Worker 
remove_orderedhb_vector_t470*2d1272b8SAndroid Build Coastguard Worker   void remove_ordered (unsigned int i)
471*2d1272b8SAndroid Build Coastguard Worker   {
472*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (i >= length))
473*2d1272b8SAndroid Build Coastguard Worker       return;
474*2d1272b8SAndroid Build Coastguard Worker     shift_down_vector (i + 1);
475*2d1272b8SAndroid Build Coastguard Worker     arrayZ[length - 1].~Type ();
476*2d1272b8SAndroid Build Coastguard Worker     length--;
477*2d1272b8SAndroid Build Coastguard Worker   }
478*2d1272b8SAndroid Build Coastguard Worker 
479*2d1272b8SAndroid Build Coastguard Worker   template <bool Sorted = sorted,
480*2d1272b8SAndroid Build Coastguard Worker 	    hb_enable_if (!Sorted)>
remove_unorderedhb_vector_t481*2d1272b8SAndroid Build Coastguard Worker   void remove_unordered (unsigned int i)
482*2d1272b8SAndroid Build Coastguard Worker   {
483*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (i >= length))
484*2d1272b8SAndroid Build Coastguard Worker       return;
485*2d1272b8SAndroid Build Coastguard Worker     if (i != length - 1)
486*2d1272b8SAndroid Build Coastguard Worker       arrayZ[i] = std::move (arrayZ[length - 1]);
487*2d1272b8SAndroid Build Coastguard Worker     arrayZ[length - 1].~Type ();
488*2d1272b8SAndroid Build Coastguard Worker     length--;
489*2d1272b8SAndroid Build Coastguard Worker   }
490*2d1272b8SAndroid Build Coastguard Worker 
shrinkhb_vector_t491*2d1272b8SAndroid Build Coastguard Worker   void shrink (int size_, bool shrink_memory = true)
492*2d1272b8SAndroid Build Coastguard Worker   {
493*2d1272b8SAndroid Build Coastguard Worker     unsigned int size = size_ < 0 ? 0u : (unsigned int) size_;
494*2d1272b8SAndroid Build Coastguard Worker     if (size >= length)
495*2d1272b8SAndroid Build Coastguard Worker       return;
496*2d1272b8SAndroid Build Coastguard Worker 
497*2d1272b8SAndroid Build Coastguard Worker     shrink_vector (size);
498*2d1272b8SAndroid Build Coastguard Worker 
499*2d1272b8SAndroid Build Coastguard Worker     if (shrink_memory)
500*2d1272b8SAndroid Build Coastguard Worker       alloc (size, true); /* To force shrinking memory if needed. */
501*2d1272b8SAndroid Build Coastguard Worker   }
502*2d1272b8SAndroid Build Coastguard Worker 
503*2d1272b8SAndroid Build Coastguard Worker 
504*2d1272b8SAndroid Build Coastguard Worker   /* Sorting API. */
qsorthb_vector_t505*2d1272b8SAndroid Build Coastguard Worker   void qsort (int (*cmp)(const void*, const void*) = Type::cmp)
506*2d1272b8SAndroid Build Coastguard Worker   { as_array ().qsort (cmp); }
507*2d1272b8SAndroid Build Coastguard Worker 
508*2d1272b8SAndroid Build Coastguard Worker   /* Unsorted search API. */
509*2d1272b8SAndroid Build Coastguard Worker   template <typename T>
lsearchhb_vector_t510*2d1272b8SAndroid Build Coastguard Worker   Type *lsearch (const T &x, Type *not_found = nullptr)
511*2d1272b8SAndroid Build Coastguard Worker   { return as_array ().lsearch (x, not_found); }
512*2d1272b8SAndroid Build Coastguard Worker   template <typename T>
lsearchhb_vector_t513*2d1272b8SAndroid Build Coastguard Worker   const Type *lsearch (const T &x, const Type *not_found = nullptr) const
514*2d1272b8SAndroid Build Coastguard Worker   { return as_array ().lsearch (x, not_found); }
515*2d1272b8SAndroid Build Coastguard Worker   template <typename T>
lfindhb_vector_t516*2d1272b8SAndroid Build Coastguard Worker   bool lfind (const T &x, unsigned *pos = nullptr) const
517*2d1272b8SAndroid Build Coastguard Worker   { return as_array ().lfind (x, pos); }
518*2d1272b8SAndroid Build Coastguard Worker 
519*2d1272b8SAndroid Build Coastguard Worker   /* Sorted search API. */
520*2d1272b8SAndroid Build Coastguard Worker   template <typename T,
521*2d1272b8SAndroid Build Coastguard Worker 	    bool Sorted=sorted, hb_enable_if (Sorted)>
bsearchhb_vector_t522*2d1272b8SAndroid Build Coastguard Worker   Type *bsearch (const T &x, Type *not_found = nullptr)
523*2d1272b8SAndroid Build Coastguard Worker   { return as_array ().bsearch (x, not_found); }
524*2d1272b8SAndroid Build Coastguard Worker   template <typename T,
525*2d1272b8SAndroid Build Coastguard Worker 	    bool Sorted=sorted, hb_enable_if (Sorted)>
bsearchhb_vector_t526*2d1272b8SAndroid Build Coastguard Worker   const Type *bsearch (const T &x, const Type *not_found = nullptr) const
527*2d1272b8SAndroid Build Coastguard Worker   { return as_array ().bsearch (x, not_found); }
528*2d1272b8SAndroid Build Coastguard Worker   template <typename T,
529*2d1272b8SAndroid Build Coastguard Worker 	    bool Sorted=sorted, hb_enable_if (Sorted)>
bfindhb_vector_t530*2d1272b8SAndroid Build Coastguard Worker   bool bfind (const T &x, unsigned int *i = nullptr,
531*2d1272b8SAndroid Build Coastguard Worker 	      hb_not_found_t not_found = HB_NOT_FOUND_DONT_STORE,
532*2d1272b8SAndroid Build Coastguard Worker 	      unsigned int to_store = (unsigned int) -1) const
533*2d1272b8SAndroid Build Coastguard Worker   { return as_array ().bfind (x, i, not_found, to_store); }
534*2d1272b8SAndroid Build Coastguard Worker };
535*2d1272b8SAndroid Build Coastguard Worker 
536*2d1272b8SAndroid Build Coastguard Worker template <typename Type>
537*2d1272b8SAndroid Build Coastguard Worker using hb_sorted_vector_t = hb_vector_t<Type, true>;
538*2d1272b8SAndroid Build Coastguard Worker 
539*2d1272b8SAndroid Build Coastguard Worker #endif /* HB_VECTOR_HH */
540