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