2 * Copyright © 2017,2018 Google, Inc.
4 * This is part of HarfBuzz, a text shaping library.
6 * Permission is hereby granted, without written agreement and without
7 * license or royalty fees, to use, copy, modify, and distribute this
8 * software and its documentation for any purpose, provided that the
9 * above copyright notice and the following two paragraphs appear in
10 * all copies of this software.
12 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
13 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
14 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
15 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
18 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
19 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
21 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
22 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
24 * Google Author(s): Behdad Esfahbod
31 #include "hb-array.hh"
35 template <typename Type>
39 static constexpr unsigned item_size = hb_static_size (Type);
41 hb_vector_t () { init (); }
42 hb_vector_t (const hb_vector_t &o)
48 hb_vector_t (hb_vector_t &&o)
50 allocated = o.allocated;
55 ~hb_vector_t () { fini (); }
58 int allocated; /* == -1 means allocation failed. */
66 allocated = length = 0;
77 unsigned int count = length;
78 for (unsigned int i = 0; i < count; i++)
83 void reset () { resize (0); }
85 hb_vector_t& operator = (const hb_vector_t &o)
92 hb_vector_t& operator = (hb_vector_t &&o)
95 allocated = o.allocated;
102 hb_bytes_t as_bytes () const
103 { return hb_bytes_t ((const char *) arrayZ, length * item_size); }
105 bool operator == (const hb_vector_t &o) const { return as_array () == o.as_array (); }
106 bool operator != (const hb_vector_t &o) const { return !(*this == o); }
107 uint32_t hash () const { return as_array ().hash (); }
109 Type& operator [] (int i_)
111 unsigned int i = (unsigned int) i_;
112 if (unlikely (i >= length))
116 const Type& operator [] (int i_) const
118 unsigned int i = (unsigned int) i_;
119 if (unlikely (i >= length))
124 Type& tail () { return (*this)[length - 1]; }
125 const Type& tail () const { return (*this)[length - 1]; }
127 explicit operator bool () const { return length; }
128 unsigned get_size () const { return length * item_size; }
130 /* Sink interface. */
131 template <typename T>
132 hb_vector_t& operator << (T&& v) { push (hb_forward<T> (v)); return *this; }
134 hb_array_t< Type> as_array () { return hb_array (arrayZ, length); }
135 hb_array_t<const Type> as_array () const { return hb_array (arrayZ, length); }
138 typedef hb_array_t<const Type> iter_t;
139 typedef hb_array_t< Type> writer_t;
140 iter_t iter () const { return as_array (); }
141 writer_t writer () { return as_array (); }
142 operator iter_t () const { return iter (); }
143 operator writer_t () { return writer (); }
145 hb_array_t<const Type> sub_array (unsigned int start_offset, unsigned int count) const
146 { return as_array ().sub_array (start_offset, count); }
147 hb_array_t<const Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */) const
148 { return as_array ().sub_array (start_offset, count); }
149 hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int count)
150 { return as_array ().sub_array (start_offset, count); }
151 hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */)
152 { return as_array ().sub_array (start_offset, count); }
154 hb_sorted_array_t<Type> as_sorted_array ()
155 { return hb_sorted_array (arrayZ, length); }
156 hb_sorted_array_t<const Type> as_sorted_array () const
157 { return hb_sorted_array (arrayZ, length); }
159 template <typename T> explicit operator T * () { return arrayZ; }
160 template <typename T> explicit operator const T * () const { return arrayZ; }
162 Type * operator + (unsigned int i) { return arrayZ + i; }
163 const Type * operator + (unsigned int i) const { return arrayZ + i; }
167 if (unlikely (!resize (length + 1)))
169 return &arrayZ[length - 1];
171 template <typename T>
175 *p = hb_forward<T> (v);
179 bool in_error () const { return allocated < 0; }
181 /* Allocate for size but don't adjust length. */
182 bool alloc (unsigned int size)
184 if (unlikely (allocated < 0))
187 if (likely (size <= (unsigned) allocated))
192 unsigned int new_allocated = allocated;
193 while (size >= new_allocated)
194 new_allocated += (new_allocated >> 1) + 8;
196 Type *new_array = nullptr;
198 (int) new_allocated < 0 ||
199 (new_allocated < (unsigned) allocated) ||
200 hb_unsigned_mul_overflows (new_allocated, sizeof (Type));
201 if (likely (!overflows))
202 new_array = (Type *) realloc (arrayZ, new_allocated * sizeof (Type));
204 if (unlikely (!new_array))
211 allocated = new_allocated;
216 bool resize (int size_)
218 unsigned int size = size_ < 0 ? 0u : (unsigned int) size_;
223 memset (arrayZ + length, 0, (size - length) * sizeof (*arrayZ));
231 if (!length) return Null (Type);
232 return hb_move (arrayZ[--length]); /* Does this move actually work? */
235 void remove (unsigned int i)
237 if (unlikely (i >= length))
239 memmove (static_cast<void *> (&arrayZ[i]),
240 static_cast<void *> (&arrayZ[i + 1]),
241 (length - i - 1) * sizeof (Type));
245 void shrink (int size_)
247 unsigned int size = size_ < 0 ? 0u : (unsigned int) size_;
252 template <typename T>
255 for (unsigned int i = 0; i < length; i++)
260 template <typename T>
261 const Type *find (T v) const
263 for (unsigned int i = 0; i < length; i++)
269 void qsort (int (*cmp)(const void*, const void*))
270 { as_array ().qsort (cmp); }
271 void qsort (unsigned int start = 0, unsigned int end = (unsigned int) -1)
272 { as_array ().qsort (start, end); }
274 template <typename T>
275 Type *lsearch (const T &x, Type *not_found = nullptr)
276 { return as_array ().lsearch (x, not_found); }
277 template <typename T>
278 const Type *lsearch (const T &x, const Type *not_found = nullptr) const
279 { return as_array ().lsearch (x, not_found); }
282 template <typename Type>
283 struct hb_sorted_vector_t : hb_vector_t<Type>
285 hb_sorted_array_t< Type> as_array () { return hb_sorted_array (this->arrayZ, this->length); }
286 hb_sorted_array_t<const Type> as_array () const { return hb_sorted_array (this->arrayZ, this->length); }
289 typedef hb_sorted_array_t<const Type> const_iter_t;
290 typedef hb_sorted_array_t< Type> iter_t;
291 const_iter_t iter () const { return as_array (); }
292 const_iter_t citer () const { return as_array (); }
293 iter_t iter () { return as_array (); }
294 operator iter_t () { return iter (); }
295 operator const_iter_t () const { return iter (); }
297 template <typename T>
298 Type *bsearch (const T &x, Type *not_found = nullptr)
299 { return as_array ().bsearch (x, not_found); }
300 template <typename T>
301 const Type *bsearch (const T &x, const Type *not_found = nullptr) const
302 { return as_array ().bsearch (x, not_found); }
303 template <typename T>
304 bool bfind (const T &x, unsigned int *i = nullptr,
305 hb_bfind_not_found_t not_found = HB_BFIND_NOT_FOUND_DONT_STORE,
306 unsigned int to_store = (unsigned int) -1) const
307 { return as_array ().bfind (x, i, not_found, to_store); }
310 #endif /* HB_VECTOR_HH */