blob: d4df16546cd74ba576ae09cae89233b500643c3a [file] [log] [blame]
Behdad Esfahbod5a552f72018-12-16 20:07:44 -05001/*
2 * Copyright © 2018 Google, Inc.
3 *
4 * This is part of HarfBuzz, a text shaping library.
5 *
6 * Permission is hereby granted, without written agreement and without
7 * license or royalty fees, to use, copy, modify, and distribute this
8 * software and its documentation for any purpose, provided that the
9 * above copyright notice and the following two paragraphs appear in
10 * all copies of this software.
11 *
12 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
13 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
14 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
15 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
16 * DAMAGE.
17 *
18 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
19 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
21 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
22 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
23 *
24 * Google Author(s): Behdad Esfahbod
25 */
26
27#ifndef HB_ARRAY_HH
28#define HB_ARRAY_HH
29
30#include "hb.hh"
31
32
Behdad Esfahbod5a552f72018-12-16 20:07:44 -050033template <typename Type>
34struct hb_sorted_array_t;
35
36template <typename Type>
37struct hb_array_t
38{
Behdad Esfahbod3656f562018-12-16 20:35:11 -050039 typedef Type ItemType;
40 enum { item_size = hb_static_size (Type) };
Behdad Esfahbod5a552f72018-12-16 20:07:44 -050041
Behdad Esfahboda4354d22018-12-16 23:57:27 -050042 /*
43 * Constructors.
44 */
Ebrahim Byagowie4120082018-12-17 21:31:01 +033045 hb_array_t () : arrayZ (nullptr), len (0) {}
Behdad Esfahbod5a552f72018-12-16 20:07:44 -050046 hb_array_t (const hb_array_t &o) : arrayZ (o.arrayZ), len (o.len) {}
47 hb_array_t (Type *array_, unsigned int len_) : arrayZ (array_), len (len_) {}
Behdad Esfahbod68d4a5e2018-12-17 00:02:42 -050048 template <unsigned int len_> hb_array_t (Type (&array_)[len_]) : arrayZ (array_), len (len_) {}
Behdad Esfahbod5a552f72018-12-16 20:07:44 -050049
Behdad Esfahboda4354d22018-12-16 23:57:27 -050050 /*
51 * Operators.
52 */
53
Behdad Esfahbod5a552f72018-12-16 20:07:44 -050054 Type& operator [] (int i_) const
55 {
56 unsigned int i = (unsigned int) i_;
Behdad Esfahbod6cd60c22018-12-17 00:09:06 -050057 if (unlikely (i >= len)) return CrapOrNull(Type);
Behdad Esfahbod5a552f72018-12-16 20:07:44 -050058 return arrayZ[i];
59 }
60
Ebrahim Byagowie4120082018-12-17 21:31:01 +033061 explicit_operator bool () const { return len; }
62 Type * operator & () const { return arrayZ; }
63 Type & operator * () { return (this->operator [])[0]; }
64 operator hb_array_t<const Type> () { return hb_array_t<const Type> (arrayZ, len); }
65 template <typename T> operator T * () const { return arrayZ; }
Behdad Esfahbod94e72cf2018-12-17 00:06:40 -050066
Behdad Esfahbodf85f6e82018-12-16 23:45:07 -050067 hb_array_t<Type> & operator += (unsigned int count)
68 {
69 if (unlikely (count > len))
70 count = len;
71 len -= count;
72 arrayZ += count;
73 return *this;
74 }
Behdad Esfahbod470369a2018-12-17 00:20:19 -050075 hb_array_t<Type> & operator -= (unsigned int count)
76 {
77 if (unlikely (count > len))
78 count = len;
79 len -= count;
80 return *this;
81 }
Ebrahim Byagowie4120082018-12-17 21:31:01 +033082 hb_array_t<Type> & operator ++ () { *this += 1; }
83 hb_array_t<Type> & operator -- () { *this -= 1; }
Behdad Esfahbod470369a2018-12-17 00:20:19 -050084 hb_array_t<Type> operator + (unsigned int count)
85 { hb_array_t<Type> copy (*this); *this += count; return copy; }
86 hb_array_t<Type> operator - (unsigned int count)
87 { hb_array_t<Type> copy (*this); *this -= count; return copy; }
88 hb_array_t<Type> operator ++ (int)
89 { hb_array_t<Type> copy (*this); ++*this; return copy; }
90 hb_array_t<Type> operator -- (int)
91 { hb_array_t<Type> copy (*this); --*this; return copy; }
Behdad Esfahbodf85f6e82018-12-16 23:45:07 -050092
Behdad Esfahboda4354d22018-12-16 23:57:27 -050093 /*
94 * Compare, Sort, and Search.
95 */
Behdad Esfahbod5a552f72018-12-16 20:07:44 -050096
Behdad Esfahboda4354d22018-12-16 23:57:27 -050097 /* Note: our compare is NOT lexicographic; it also does NOT call Type::cmp. */
98 int cmp (const hb_array_t<Type> &a) const
Behdad Esfahbod5a552f72018-12-16 20:07:44 -050099 {
Behdad Esfahboda4354d22018-12-16 23:57:27 -0500100 if (len != a.len)
101 return (int) a.len - (int) len;
102 return hb_memcmp (a.arrayZ, arrayZ, get_size ());
Behdad Esfahbod5a552f72018-12-16 20:07:44 -0500103 }
Behdad Esfahboda4354d22018-12-16 23:57:27 -0500104 static int cmp (const void *pa, const void *pb)
105 {
106 hb_array_t<Type> *a = (hb_array_t<Type> *) pa;
107 hb_array_t<Type> *b = (hb_array_t<Type> *) pb;
108 return b->cmp (*a);
109 }
Behdad Esfahbod5a552f72018-12-16 20:07:44 -0500110
Behdad Esfahbod5a552f72018-12-16 20:07:44 -0500111 template <typename T>
Behdad Esfahboddcfa4a82018-12-16 20:40:07 -0500112 Type *lsearch (const T &x, Type *not_found = nullptr)
Behdad Esfahbod5a552f72018-12-16 20:07:44 -0500113 {
114 unsigned int count = len;
115 for (unsigned int i = 0; i < count; i++)
116 if (!this->arrayZ[i].cmp (x))
117 return &this->arrayZ[i];
118 return not_found;
119 }
120 template <typename T>
121 const Type *lsearch (const T &x, const Type *not_found = nullptr) const
122 {
123 unsigned int count = len;
124 for (unsigned int i = 0; i < count; i++)
125 if (!this->arrayZ[i].cmp (x))
126 return &this->arrayZ[i];
127 return not_found;
128 }
129
Behdad Esfahboddcfa4a82018-12-16 20:40:07 -0500130 hb_sorted_array_t<Type> qsort (int (*cmp_)(const void*, const void*))
Behdad Esfahbod5a552f72018-12-16 20:07:44 -0500131 {
Behdad Esfahboddcfa4a82018-12-16 20:40:07 -0500132 ::qsort (arrayZ, len, item_size, cmp_);
Behdad Esfahbod5a552f72018-12-16 20:07:44 -0500133 return hb_sorted_array_t<Type> (*this);
134 }
Ebrahim Byagowie4120082018-12-17 21:31:01 +0330135 hb_sorted_array_t<Type> qsort ()
Behdad Esfahbod5a552f72018-12-16 20:07:44 -0500136 {
Behdad Esfahboddcfa4a82018-12-16 20:40:07 -0500137 ::qsort (arrayZ, len, item_size, Type::cmp);
Behdad Esfahbod5a552f72018-12-16 20:07:44 -0500138 return hb_sorted_array_t<Type> (*this);
139 }
140 void qsort (unsigned int start, unsigned int end)
141 {
142 end = MIN (end, len);
143 assert (start <= end);
Behdad Esfahboddcfa4a82018-12-16 20:40:07 -0500144 ::qsort (arrayZ + start, end - start, item_size, Type::cmp);
Behdad Esfahbod5a552f72018-12-16 20:07:44 -0500145 }
146
Behdad Esfahboda4354d22018-12-16 23:57:27 -0500147 /*
148 * Other methods.
149 */
150
Ebrahim Byagowie4120082018-12-17 21:31:01 +0330151 unsigned int get_size () const { return len * item_size; }
Behdad Esfahboda4354d22018-12-16 23:57:27 -0500152
153 hb_array_t<Type> sub_array (unsigned int start_offset = 0, unsigned int *seg_count = nullptr /* IN/OUT */) const
154 {
155 if (!start_offset && !seg_count)
156 return *this;
157
158 unsigned int count = len;
159 if (unlikely (start_offset > count))
160 count = 0;
161 else
162 count -= start_offset;
163 if (seg_count)
164 count = *seg_count = MIN (count, *seg_count);
165 return hb_array_t<Type> (arrayZ + start_offset, count);
166 }
167 hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int seg_count) const
168 { return sub_array (start_offset, &seg_count); }
169
170 /* Only call if you allocated the underlying array using malloc() or similar. */
Ebrahim Byagowie4120082018-12-17 21:31:01 +0330171 void free ()
Behdad Esfahbod5a552f72018-12-16 20:07:44 -0500172 { ::free ((void *) arrayZ); arrayZ = nullptr; len = 0; }
173
174 template <typename hb_sanitize_context_t>
175 bool sanitize (hb_sanitize_context_t *c) const
176 { return c->check_array (arrayZ, len); }
177
Behdad Esfahboda4354d22018-12-16 23:57:27 -0500178 /*
179 * Members
180 */
181
Behdad Esfahbod5a552f72018-12-16 20:07:44 -0500182 public:
183 Type *arrayZ;
184 unsigned int len;
185};
186template <typename T>
187inline hb_array_t<T> hb_array (T *array, unsigned int len)
188{ return hb_array_t<T> (array, len); }
189
190
191enum hb_bfind_not_found_t
192{
193 HB_BFIND_NOT_FOUND_DONT_STORE,
194 HB_BFIND_NOT_FOUND_STORE,
195 HB_BFIND_NOT_FOUND_STORE_CLOSEST,
196};
197
198template <typename Type>
199struct hb_sorted_array_t : hb_array_t<Type>
200{
Ebrahim Byagowie4120082018-12-17 21:31:01 +0330201 hb_sorted_array_t () : hb_array_t<Type> () {}
Behdad Esfahbod5a552f72018-12-16 20:07:44 -0500202 hb_sorted_array_t (const hb_array_t<Type> &o) : hb_array_t<Type> (o) {}
203 hb_sorted_array_t (Type *array_, unsigned int len_) : hb_array_t<Type> (array_, len_) {}
204
205 hb_sorted_array_t<Type> sub_array (unsigned int start_offset, unsigned int *seg_count /* IN/OUT */) const
206 { return hb_sorted_array_t<Type> (((const hb_array_t<Type> *) (this))->sub_array (start_offset, seg_count)); }
207 hb_sorted_array_t<Type> sub_array (unsigned int start_offset, unsigned int seg_count) const
208 { return sub_array (start_offset, &seg_count); }
209
210 template <typename T>
211 Type *bsearch (const T &x, Type *not_found = nullptr)
212 {
213 unsigned int i;
214 return bfind (x, &i) ? &this->arrayZ[i] : not_found;
215 }
216 template <typename T>
217 const Type *bsearch (const T &x, const Type *not_found = nullptr) const
218 {
219 unsigned int i;
220 return bfind (x, &i) ? &this->arrayZ[i] : not_found;
221 }
222 template <typename T>
223 bool bfind (const T &x, unsigned int *i = nullptr,
224 hb_bfind_not_found_t not_found = HB_BFIND_NOT_FOUND_DONT_STORE,
225 unsigned int to_store = (unsigned int) -1) const
226 {
227 int min = 0, max = (int) this->len - 1;
228 const Type *array = this->arrayZ;
229 while (min <= max)
230 {
231 int mid = ((unsigned int) min + (unsigned int) max) / 2;
232 int c = array[mid].cmp (x);
233 if (c < 0)
234 max = mid - 1;
235 else if (c > 0)
236 min = mid + 1;
237 else
238 {
239 if (i)
240 *i = mid;
241 return true;
242 }
243 }
244 if (i)
245 {
246 switch (not_found)
247 {
248 case HB_BFIND_NOT_FOUND_DONT_STORE:
249 break;
250
251 case HB_BFIND_NOT_FOUND_STORE:
252 *i = to_store;
253 break;
254
255 case HB_BFIND_NOT_FOUND_STORE_CLOSEST:
256 if (max < 0 || (max < (int) this->len && array[max].cmp (x) > 0))
257 max++;
258 *i = max;
259 break;
260 }
261 }
262 return false;
263 }
264};
265template <typename T>
266inline hb_sorted_array_t<T> hb_sorted_array (T *array, unsigned int len)
267{ return hb_sorted_array_t<T> (array, len); }
268
269
Behdad Esfahboddcfa4a82018-12-16 20:40:07 -0500270typedef hb_array_t<const char> hb_bytes_t;
Behdad Esfahbod3d9d7dc2018-12-18 22:11:23 -0500271typedef hb_array_t<const unsigned char> hb_ubytes_t;
Behdad Esfahboddcfa4a82018-12-16 20:40:07 -0500272
Behdad Esfahbod92680362018-12-16 23:38:51 -0500273
Behdad Esfahbod5a552f72018-12-16 20:07:44 -0500274#endif /* HB_ARRAY_HH */