QtBase  v6.3.1
hb-array.hh
Go to the documentation of this file.
1 /*
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 #include "hb-algs.hh"
32 #include "hb-iter.hh"
33 #include "hb-null.hh"
34 
35 
36 template <typename Type>
37 struct hb_sorted_array_t;
38 
40 {
44 };
45 
46 
47 template <typename Type>
48 struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&>
49 {
50  /*
51  * Constructors.
52  */
53  hb_array_t () = default;
54  hb_array_t (const hb_array_t&) = default;
55  ~hb_array_t () = default;
56  hb_array_t& operator= (const hb_array_t&) = default;
58 
59  constexpr hb_array_t (std::nullptr_t) : hb_array_t () {}
60  constexpr hb_array_t (Type *array_, unsigned int length_) : arrayZ (array_), length (length_) {}
61  template <unsigned int length_>
62  constexpr hb_array_t (Type (&array_)[length_]) : hb_array_t (array_, length_) {}
63 
64  template <typename U,
66  constexpr hb_array_t (const hb_array_t<U> &o) :
69  template <typename U,
72  { arrayZ = o.arrayZ; length = o.length; backwards_length = o.backwards_length; return *this; }
73 
74  /*
75  * Iterator implementation.
76  */
77  typedef Type& __item_t__;
78  static constexpr bool is_random_access_iterator = true;
79  Type& __item_at__ (unsigned i) const
80  {
81  if (unlikely (i >= length)) return CrapOrNull (Type);
82  return arrayZ[i];
83  }
84  void __forward__ (unsigned n)
85  {
86  if (unlikely (n > length))
87  n = length;
88  length -= n;
90  arrayZ += n;
91  }
92  void __rewind__ (unsigned n)
93  {
94  if (unlikely (n > backwards_length))
96  length += n;
98  arrayZ -= n;
99  }
100  unsigned __len__ () const { return length; }
101  /* Ouch. The operator== compares the contents of the array. For range-based for loops,
102  * it's best if we can just compare arrayZ, though comparing contents is still fast,
103  * but also would require that Type has operator==. As such, we optimize this operator
104  * for range-based for loop and just compare arrayZ. No need to compare length, as we
105  * assume we're only compared to .end(). */
106  bool operator != (const hb_array_t& o) const
107  { return arrayZ != o.arrayZ; }
108 
109  /* Extra operators.
110  */
111  Type * operator & () const { return arrayZ; }
113  template <typename T> operator T * () const { return arrayZ; }
114 
115  HB_INTERNAL bool operator == (const hb_array_t &o) const;
116 
117  uint32_t hash () const {
118  uint32_t current = 0;
119  for (unsigned int i = 0; i < this->length; i++) {
120  current = current * 31 + hb_hash (this->arrayZ[i]);
121  }
122  return current;
123  }
124 
125  /*
126  * Compare, Sort, and Search.
127  */
128 
129  /* Note: our compare is NOT lexicographic; it also does NOT call Type::cmp. */
130  int cmp (const hb_array_t &a) const
131  {
132  if (length != a.length)
133  return (int) a.length - (int) length;
134  return hb_memcmp (a.arrayZ, arrayZ, get_size ());
135  }
136  HB_INTERNAL static int cmp (const void *pa, const void *pb)
137  {
138  hb_array_t *a = (hb_array_t *) pa;
139  hb_array_t *b = (hb_array_t *) pb;
140  return b->cmp (*a);
141  }
142 
143  template <typename T>
144  Type *lsearch (const T &x, Type *not_found = nullptr)
145  {
146  unsigned i;
147  return lfind (x, &i) ? &this->arrayZ[i] : not_found;
148  }
149  template <typename T>
150  const Type *lsearch (const T &x, const Type *not_found = nullptr) const
151  {
152  unsigned i;
153  return lfind (x, &i) ? &this->arrayZ[i] : not_found;
154  }
155  template <typename T>
156  bool lfind (const T &x, unsigned *pos = nullptr,
158  unsigned int to_store = (unsigned int) -1) const
159  {
160  for (unsigned i = 0; i < length; ++i)
161  if (hb_equal (x, this->arrayZ[i]))
162  {
163  if (pos)
164  *pos = i;
165  return true;
166  }
167 
168  if (pos)
169  {
170  switch (not_found)
171  {
173  break;
174 
175  case HB_NOT_FOUND_STORE:
176  *pos = to_store;
177  break;
178 
180  *pos = length;
181  break;
182  }
183  }
184  return false;
185  }
186 
187  hb_sorted_array_t<Type> qsort (int (*cmp_)(const void*, const void*))
188  {
189  if (likely (length))
190  hb_qsort (arrayZ, length, this->get_item_size (), cmp_);
191  return hb_sorted_array_t<Type> (*this);
192  }
194  {
195  if (likely (length))
196  hb_qsort (arrayZ, length, this->get_item_size (), Type::cmp);
197  return hb_sorted_array_t<Type> (*this);
198  }
199  void qsort (unsigned int start, unsigned int end)
200  {
201  end = hb_min (end, length);
202  assert (start <= end);
203  if (likely (start < end))
204  hb_qsort (arrayZ + start, end - start, this->get_item_size (), Type::cmp);
205  }
206 
207  /*
208  * Other methods.
209  */
210 
211  unsigned int get_size () const { return length * this->get_item_size (); }
212 
213  /*
214  * Reverse the order of items in this array in the range [start, end).
215  */
216  void reverse (unsigned start = 0, unsigned end = -1)
217  {
218  start = hb_min (start, length);
219  end = hb_min (end, length);
220 
221  if (end < start + 2)
222  return;
223 
224  for (unsigned lhs = start, rhs = end - 1; lhs < rhs; lhs++, rhs--) {
225  Type temp = arrayZ[rhs];
226  arrayZ[rhs] = arrayZ[lhs];
227  arrayZ[lhs] = temp;
228  }
229  }
230 
231  hb_array_t sub_array (unsigned int start_offset = 0, unsigned int *seg_count = nullptr /* IN/OUT */) const
232  {
233  if (!start_offset && !seg_count)
234  return *this;
235 
236  unsigned int count = length;
237  if (unlikely (start_offset > count))
238  count = 0;
239  else
240  count -= start_offset;
241  if (seg_count)
242  count = *seg_count = hb_min (count, *seg_count);
243  return hb_array_t (arrayZ + start_offset, count);
244  }
245  hb_array_t sub_array (unsigned int start_offset, unsigned int seg_count) const
246  { return sub_array (start_offset, &seg_count); }
247 
248  hb_array_t truncate (unsigned length) const { return sub_array (0, length); }
249 
250  template <typename T,
251  unsigned P = sizeof (Type),
252  hb_enable_if (P == 1)>
253  const T *as () const
255 
256  template <typename T,
257  unsigned P = sizeof (Type),
258  hb_enable_if (P == 1)>
259  bool check_range (const T *p, unsigned int size = T::static_size) const
260  {
261  return arrayZ <= ((const char *) p)
262  && ((const char *) p) <= arrayZ + length
263  && (unsigned int) (arrayZ + length - (const char *) p) >= size;
264  }
265 
266  /* Only call if you allocated the underlying array using hb_malloc() or similar. */
267  void fini ()
268  { hb_free ((void *) arrayZ); arrayZ = nullptr; length = 0; }
269 
270  template <typename hb_serialize_context_t>
272  {
273  TRACE_SERIALIZE (this);
274  auto* out = c->start_embed (arrayZ);
275  if (unlikely (!c->extend_size (out, get_size ()))) return_trace (hb_array_t ());
276  for (unsigned i = 0; i < length; i++)
277  out[i] = arrayZ[i]; /* TODO: add version that calls c->copy() */
279  }
280 
281  template <typename hb_sanitize_context_t>
283  { return c->check_array (arrayZ, length); }
284 
285  /*
286  * Members
287  */
288 
289  public:
290  Type *arrayZ = nullptr;
291  unsigned int length = 0;
292  unsigned int backwards_length = 0;
293 };
294 template <typename T> inline hb_array_t<T>
295 hb_array (T *array, unsigned int length)
296 { return hb_array_t<T> (array, length); }
297 template <typename T, unsigned int length_> inline hb_array_t<T>
298 hb_array (T (&array_)[length_])
299 { return hb_array_t<T> (array_); }
300 
301 template <typename Type>
303  hb_iter_t<hb_sorted_array_t<Type>, Type&>,
304  hb_array_t<Type>
305 {
308  static constexpr bool is_random_access_iterator = true;
309  static constexpr bool is_sorted_iterator = true;
310 
311  hb_sorted_array_t () = default;
313  ~hb_sorted_array_t () = default;
316 
317  constexpr hb_sorted_array_t (std::nullptr_t) : hb_sorted_array_t () {}
318  constexpr hb_sorted_array_t (Type *array_, unsigned int length_) : hb_array_t<Type> (array_, length_) {}
319  template <unsigned int length_>
320  constexpr hb_sorted_array_t (Type (&array_)[length_]) : hb_array_t<Type> (array_) {}
321 
322  template <typename U,
324  constexpr hb_sorted_array_t (const hb_array_t<U> &o) :
326  hb_array_t<Type> (o) {}
327  template <typename U,
330  { hb_array_t<Type> (*this) = o; return *this; }
331 
332  /* Iterator implementation. */
333  bool operator != (const hb_sorted_array_t& o) const
334  { return this->arrayZ != o.arrayZ || this->length != o.length; }
335 
336  hb_sorted_array_t sub_array (unsigned int start_offset, unsigned int *seg_count /* IN/OUT */) const
337  { return hb_sorted_array_t (((const hb_array_t<Type> *) (this))->sub_array (start_offset, seg_count)); }
338  hb_sorted_array_t sub_array (unsigned int start_offset, unsigned int seg_count) const
339  { return sub_array (start_offset, &seg_count); }
340 
341  hb_sorted_array_t truncate (unsigned length) const { return sub_array (0, length); }
342 
343  template <typename T>
344  Type *bsearch (const T &x, Type *not_found = nullptr)
345  {
346  unsigned int i;
347  return bfind (x, &i) ? &this->arrayZ[i] : not_found;
348  }
349  template <typename T>
350  const Type *bsearch (const T &x, const Type *not_found = nullptr) const
351  {
352  unsigned int i;
353  return bfind (x, &i) ? &this->arrayZ[i] : not_found;
354  }
355  template <typename T>
356  bool bfind (const T &x, unsigned int *i = nullptr,
358  unsigned int to_store = (unsigned int) -1) const
359  {
360  unsigned pos;
361 
362  if (bsearch_impl (x, &pos))
363  {
364  if (i)
365  *i = pos;
366  return true;
367  }
368 
369  if (i)
370  {
371  switch (not_found)
372  {
374  break;
375 
376  case HB_NOT_FOUND_STORE:
377  *i = to_store;
378  break;
379 
381  *i = pos;
382  break;
383  }
384  }
385  return false;
386  }
387  template <typename T>
388  bool bsearch_impl (const T &x, unsigned *pos) const
389  {
390  return hb_bsearch_impl (pos,
391  x,
392  this->arrayZ,
393  this->length,
394  sizeof (Type),
395  _hb_cmp_method<T, Type>);
396  }
397 };
398 template <typename T> inline hb_sorted_array_t<T>
399 hb_sorted_array (T *array, unsigned int length)
400 { return hb_sorted_array_t<T> (array, length); }
401 template <typename T, unsigned int length_> inline hb_sorted_array_t<T>
402 hb_sorted_array (T (&array_)[length_])
403 { return hb_sorted_array_t<T> (array_); }
404 
405 template <typename T>
407 {
408  if (o.length != this->length) return false;
409  for (unsigned int i = 0; i < this->length; i++) {
410  if (this->arrayZ[i] != o.arrayZ[i]) return false;
411  }
412  return true;
413 }
414 
415 /* TODO Specialize operator== for hb_bytes_t and hb_ubytes_t. */
416 
417 template <>
418 inline uint32_t hb_array_t<const char>::hash () const {
419  uint32_t current = 0;
420  for (unsigned int i = 0; i < this->length; i++)
421  current = current * 31 + (uint32_t) (this->arrayZ[i] * 2654435761u);
422  return current;
423 }
424 
425 template <>
426 inline uint32_t hb_array_t<const unsigned char>::hash () const {
427  uint32_t current = 0;
428  for (unsigned int i = 0; i < this->length; i++)
429  current = current * 31 + (uint32_t) (this->arrayZ[i] * 2654435761u);
430  return current;
431 }
432 
433 
436 
437 
438 
439 #endif /* HB_ARRAY_HH */
small capitals from c petite p scientific i
[1]
Definition: afcover.h:80
#define T(x)
Definition: main.cpp:42
#define this
Definition: dialogs.cpp:56
hb_not_found_t
Definition: hb-array.hh:40
@ HB_NOT_FOUND_STORE_CLOSEST
Definition: hb-array.hh:43
@ HB_NOT_FOUND_DONT_STORE
Definition: hb-array.hh:41
@ HB_NOT_FOUND_STORE
Definition: hb-array.hh:42
hb_array_t< const unsigned char > hb_ubytes_t
Definition: hb-array.hh:435
hb_array_t< T > hb_array(T *array, unsigned int length)
Definition: hb-array.hh:295
hb_sorted_array_t< T > hb_sorted_array(T *array, unsigned int length)
Definition: hb-array.hh:399
hb_array_t< const char > hb_bytes_t
Definition: hb-array.hh:434
#define TRACE_SERIALIZE(this)
Definition: hb-debug.hh:426
#define return_trace(RET)
Definition: hb-debug.hh:349
hb_bool_constant< hb_is_same(hb_decay< From >, hb_decay< To >) &&(!std::is_const< From >::value||std::is_const< To >::value) &&(!std::is_reference< To >::value||std::is_const< To >::value||std::is_reference< To >::value) > hb_is_cr_convertible
Definition: hb-meta.hh:125
#define hb_enable_if(Cond)
Definition: hb-meta.hh:65
#define CrapOrNull(Type)
Definition: hb-null.hh:169
HB_EXTERN unsigned int start_offset
#define likely(expr)
Definition: hb.hh:250
#define unlikely(expr)
Definition: hb.hh:251
#define HB_INTERNAL
Definition: hb.hh:274
#define hb_free
Definition: hb.hh:238
#define assert
Definition: qcborcommon_p.h:63
GLenum GLuint GLenum GLsizei length
Definition: qopengl.h:270
GLboolean GLboolean GLboolean b
GLint GLint GLint GLint GLint x
[0]
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint GLuint end
GLenum GLenum GLsizei count
GLuint start
GLfloat n
const GLubyte * c
Definition: qopenglext.h:12701
GLenum array
Definition: qopenglext.h:7028
GLfloat GLfloat p
[1]
Definition: qopenglext.h:12698
QTextStream out(stdout)
[7]
QDBusVariant Type
Definition: main.cpp:38
Definition: moc.h:48
bool check_range(const T *p, unsigned int size=T::static_size) const
Definition: hb-array.hh:259
hb_sorted_array_t< Type > qsort()
Definition: hb-array.hh:193
void qsort(unsigned int start, unsigned int end)
Definition: hb-array.hh:199
int cmp(const hb_array_t &a) const
Definition: hb-array.hh:130
void reverse(unsigned start=0, unsigned end=-1)
Definition: hb-array.hh:216
constexpr hb_array_t(Type(&array_)[length_])
Definition: hb-array.hh:62
static HB_INTERNAL int cmp(const void *pa, const void *pb)
Definition: hb-array.hh:136
unsigned __len__() const
Definition: hb-array.hh:100
bool operator!=(const hb_array_t &o) const
Definition: hb-array.hh:106
const Type * lsearch(const T &x, const Type *not_found=nullptr) const
Definition: hb-array.hh:150
uint32_t hash() const
Definition: hb-array.hh:117
void __rewind__(unsigned n)
Definition: hb-array.hh:92
void __forward__(unsigned n)
Definition: hb-array.hh:84
bool sanitize(hb_sanitize_context_t *c) const
Definition: hb-array.hh:282
constexpr hb_array_t(std::nullptr_t)
Definition: hb-array.hh:59
const T * as() const
Definition: hb-array.hh:253
hb_array_t & operator=(const hb_array_t &)=default
Type * operator&() const
Definition: hb-array.hh:111
constexpr hb_array_t(Type *array_, unsigned int length_)
Definition: hb-array.hh:60
hb_array_t truncate(unsigned length) const
Definition: hb-array.hh:248
Type & __item_at__(unsigned i) const
Definition: hb-array.hh:79
static constexpr bool is_random_access_iterator
Definition: hb-array.hh:78
Type * arrayZ
Definition: hb-array.hh:290
unsigned int backwards_length
Definition: hb-array.hh:292
hb_sorted_array_t< Type > qsort(int(*cmp_)(const void *, const void *))
Definition: hb-array.hh:187
hb_array_t copy(hb_serialize_context_t *c) const
Definition: hb-array.hh:271
~hb_array_t()=default
unsigned int length
Definition: hb-array.hh:291
constexpr hb_array_t(const hb_array_t< U > &o)
Definition: hb-array.hh:66
hb_array_t(const hb_array_t &)=default
HB_INTERNAL bool operator==(const hb_array_t &o) const
bool lfind(const T &x, unsigned *pos=nullptr, hb_not_found_t not_found=HB_NOT_FOUND_DONT_STORE, unsigned int to_store=(unsigned int) -1) const
Definition: hb-array.hh:156
void fini()
Definition: hb-array.hh:267
Type * lsearch(const T &x, Type *not_found=nullptr)
Definition: hb-array.hh:144
Type & __item_t__
Definition: hb-array.hh:77
hb_array_t sub_array(unsigned int start_offset=0, unsigned int *seg_count=nullptr) const
Definition: hb-array.hh:231
hb_array_t sub_array(unsigned int start_offset, unsigned int seg_count) const
Definition: hb-array.hh:245
unsigned int get_size() const
Definition: hb-array.hh:211
hb_array_t()=default
constexpr unsigned get_item_size() const
Definition: hb-iter.hh:67
Type * bsearch(const T &x, Type *not_found=nullptr)
Definition: hb-array.hh:344
hb_sorted_array_t truncate(unsigned length) const
Definition: hb-array.hh:341
constexpr hb_sorted_array_t(Type *array_, unsigned int length_)
Definition: hb-array.hh:318
hb_sorted_array_t sub_array(unsigned int start_offset, unsigned int seg_count) const
Definition: hb-array.hh:338
bool operator!=(const hb_sorted_array_t &o) const
Definition: hb-array.hh:333
static constexpr bool is_random_access_iterator
Definition: hb-array.hh:308
constexpr hb_sorted_array_t(std::nullptr_t)
Definition: hb-array.hh:317
HB_ITER_USING(iter_base_t)
bool bfind(const T &x, unsigned int *i=nullptr, hb_not_found_t not_found=HB_NOT_FOUND_DONT_STORE, unsigned int to_store=(unsigned int) -1) const
Definition: hb-array.hh:356
bool bsearch_impl(const T &x, unsigned *pos) const
Definition: hb-array.hh:388
hb_iter_t< hb_sorted_array_t, Type & > iter_base_t
Definition: hb-array.hh:306
constexpr hb_sorted_array_t(const hb_array_t< U > &o)
Definition: hb-array.hh:324
hb_sorted_array_t()=default
~hb_sorted_array_t()=default
const Type * bsearch(const T &x, const Type *not_found=nullptr) const
Definition: hb-array.hh:350
constexpr hb_sorted_array_t(Type(&array_)[length_])
Definition: hb-array.hh:320
static constexpr bool is_sorted_iterator
Definition: hb-array.hh:309
hb_sorted_array_t(const hb_sorted_array_t &)=default
hb_sorted_array_t & operator=(const hb_sorted_array_t &)=default
hb_sorted_array_t sub_array(unsigned int start_offset, unsigned int *seg_count) const
Definition: hb-array.hh:336
QCommandLinkButton * pb
#define rhs