1 /*
2 * Copyright © 2017 Google, Inc.
3 * Copyright © 2019 Facebook, Inc.
4 *
5 * This is part of HarfBuzz, a text shaping library.
6 *
7 * Permission is hereby granted, without written agreement and without
8 * license or royalty fees, to use, copy, modify, and distribute this
9 * software and its documentation for any purpose, provided that the
10 * above copyright notice and the following two paragraphs appear in
11 * all copies of this software.
12 *
13 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
14 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
15 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
16 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
17 * DAMAGE.
18 *
19 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
20 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
21 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
22 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
23 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
24 *
25 * Google Author(s): Behdad Esfahbod
26 * Facebook Author(s): Behdad Esfahbod
27 */
28
29 #ifndef HB_ALGS_HH
30 #define HB_ALGS_HH
31
32 #include "hb.hh"
33 #include "hb-meta.hh"
34 #include "hb-null.hh"
35 #include "hb-number.hh"
36
37
38 /* Encodes three unsigned integers in one 64-bit number. If the inputs have more than 21 bits,
39 * values will be truncated / overlap, and might not decode exactly. */
40 #define HB_CODEPOINT_ENCODE3(x,y,z) (((uint64_t) (x) << 42) | ((uint64_t) (y) << 21) | (uint64_t) (z))
41 #define HB_CODEPOINT_DECODE3_1(v) ((hb_codepoint_t) ((v) >> 42))
42 #define HB_CODEPOINT_DECODE3_2(v) ((hb_codepoint_t) ((v) >> 21) & 0x1FFFFFu)
43 #define HB_CODEPOINT_DECODE3_3(v) ((hb_codepoint_t) (v) & 0x1FFFFFu)
44
45 /* Custom encoding used by hb-ucd. */
46 #define HB_CODEPOINT_ENCODE3_11_7_14(x,y,z) (((uint32_t) ((x) & 0x07FFu) << 21) | (((uint32_t) (y) & 0x007Fu) << 14) | (uint32_t) ((z) & 0x3FFFu))
47 #define HB_CODEPOINT_DECODE3_11_7_14_1(v) ((hb_codepoint_t) ((v) >> 21))
48 #define HB_CODEPOINT_DECODE3_11_7_14_2(v) ((hb_codepoint_t) (((v) >> 14) & 0x007Fu) | 0x0300)
49 #define HB_CODEPOINT_DECODE3_11_7_14_3(v) ((hb_codepoint_t) (v) & 0x3FFFu)
50
51 struct
52 {
53 /* Note. This is dangerous in that if it's passed an rvalue, it returns rvalue-reference. */
54 template <typename T> constexpr auto
55 operator () (T&& v) const HB_AUTO_RETURN ( hb_forward<T> (v) )
56 }
57 HB_FUNCOBJ (hb_identity);
58 struct
59 {
60 /* Like identity(), but only retains lvalue-references. Rvalues are returned as rvalues. */
61 template <typename T> constexpr T&
operator ()__anone04d149e020862 operator () (T& v) const { return v; }
63
64 template <typename T> constexpr hb_remove_reference<T>
operator ()__anone04d149e020865 operator () (T&& v) const { return v; }
66 }
67 HB_FUNCOBJ (hb_lidentity);
68 struct
69 {
70 /* Like identity(), but always returns rvalue. */
71 template <typename T> constexpr hb_remove_reference<T>
operator ()__anone04d149e030872 operator () (T&& v) const { return v; }
73 }
74 HB_FUNCOBJ (hb_ridentity);
75
76 struct
77 {
78 template <typename T> constexpr bool
operator ()__anone04d149e040879 operator () (T&& v) const { return bool (hb_forward<T> (v)); }
80 }
81 HB_FUNCOBJ (hb_bool);
82
83 struct
84 {
85 private:
86
87 template <typename T> constexpr auto
88 impl (const T& v, hb_priority<1>) const HB_RETURN (uint32_t, hb_deref (v).hash ())
89
90 template <typename T,
91 hb_enable_if (hb_is_integral (T))> constexpr auto
92 impl (const T& v, hb_priority<0>) const HB_AUTO_RETURN
93 (
94 /* Knuth's multiplicative method: */
95 (uint32_t) v * 2654435761u
96 )
97
98 public:
99
100 template <typename T> constexpr auto
101 operator () (const T& v) const HB_RETURN (uint32_t, impl (v, hb_prioritize))
102 }
103 HB_FUNCOBJ (hb_hash);
104
105
106 struct
107 {
108 private:
109
110 /* Pointer-to-member-function. */
111 template <typename Appl, typename T, typename ...Ts> auto
112 impl (Appl&& a, hb_priority<2>, T &&v, Ts&&... ds) const HB_AUTO_RETURN
113 ((hb_deref (hb_forward<T> (v)).*hb_forward<Appl> (a)) (hb_forward<Ts> (ds)...))
114
115 /* Pointer-to-member. */
116 template <typename Appl, typename T> auto
117 impl (Appl&& a, hb_priority<1>, T &&v) const HB_AUTO_RETURN
118 ((hb_deref (hb_forward<T> (v))).*hb_forward<Appl> (a))
119
120 /* Operator(). */
121 template <typename Appl, typename ...Ts> auto
122 impl (Appl&& a, hb_priority<0>, Ts&&... ds) const HB_AUTO_RETURN
123 (hb_deref (hb_forward<Appl> (a)) (hb_forward<Ts> (ds)...))
124
125 public:
126
127 template <typename Appl, typename ...Ts> auto
128 operator () (Appl&& a, Ts&&... ds) const HB_AUTO_RETURN
129 (
130 impl (hb_forward<Appl> (a),
131 hb_prioritize,
132 hb_forward<Ts> (ds)...)
133 )
134 }
135 HB_FUNCOBJ (hb_invoke);
136
137 template <unsigned Pos, typename Appl, typename V>
138 struct hb_partial_t
139 {
hb_partial_thb_partial_t140 hb_partial_t (Appl a, V v) : a (a), v (v) {}
141
142 static_assert (Pos > 0, "");
143
144 template <typename ...Ts,
145 unsigned P = Pos,
146 hb_enable_if (P == 1)> auto
operator ()hb_partial_t147 operator () (Ts&& ...ds) -> decltype (hb_invoke (hb_declval (Appl),
148 hb_declval (V),
149 hb_declval (Ts)...))
150 {
151 return hb_invoke (hb_forward<Appl> (a),
152 hb_forward<V> (v),
153 hb_forward<Ts> (ds)...);
154 }
155 template <typename T0, typename ...Ts,
156 unsigned P = Pos,
157 hb_enable_if (P == 2)> auto
operator ()hb_partial_t158 operator () (T0&& d0, Ts&& ...ds) -> decltype (hb_invoke (hb_declval (Appl),
159 hb_declval (T0),
160 hb_declval (V),
161 hb_declval (Ts)...))
162 {
163 return hb_invoke (hb_forward<Appl> (a),
164 hb_forward<T0> (d0),
165 hb_forward<V> (v),
166 hb_forward<Ts> (ds)...);
167 }
168
169 private:
170 hb_reference_wrapper<Appl> a;
171 V v;
172 };
173 template <unsigned Pos=1, typename Appl, typename V>
174 auto hb_partial (Appl&& a, V&& v) HB_AUTO_RETURN
175 (( hb_partial_t<Pos, Appl, V> (a, v) ))
176
177 /* The following, HB_PARTIALIZE, macro uses a particular corner-case
178 * of C++11 that is not particularly well-supported by all compilers.
179 * What's happening is that it's using "this" in a trailing return-type
180 * via decltype(). Broken compilers deduce the type of "this" pointer
181 * in that context differently from what it resolves to in the body
182 * of the function.
183 *
184 * One probable cause of this is that at the time of trailing return
185 * type declaration, "this" points to an incomplete type, whereas in
186 * the function body the type is complete. That doesn't justify the
187 * error in any way, but is probably what's happening.
188 *
189 * In the case of MSVC, we get around this by using C++14 "decltype(auto)"
190 * which deduces the type from the actual return statement. For gcc 4.8
191 * we use "+this" instead of "this" which produces an rvalue that seems
192 * to be deduced as the same type with this particular compiler, and seem
193 * to be fine as default code path as well.
194 */
195 #ifdef _MSC_VER
196 /* https://github.com/harfbuzz/harfbuzz/issues/1730 */ \
197 #define HB_PARTIALIZE(Pos) \
198 template <typename _T> \
199 decltype(auto) operator () (_T&& _v) const \
200 { return hb_partial<Pos> (this, hb_forward<_T> (_v)); } \
201 static_assert (true, "")
202 #else
203 /* https://github.com/harfbuzz/harfbuzz/issues/1724 */
204 #define HB_PARTIALIZE(Pos) \
205 template <typename _T> \
206 auto operator () (_T&& _v) const HB_AUTO_RETURN \
207 (hb_partial<Pos> (+this, hb_forward<_T> (_v))) \
208 static_assert (true, "")
209 #endif
210
211
212 struct
213 {
214 private:
215
216 template <typename Pred, typename Val> auto
217 impl (Pred&& p, Val &&v, hb_priority<1>) const HB_AUTO_RETURN
218 (hb_deref (hb_forward<Pred> (p)).has (hb_forward<Val> (v)))
219
220 template <typename Pred, typename Val> auto
221 impl (Pred&& p, Val &&v, hb_priority<0>) const HB_AUTO_RETURN
222 (
223 hb_invoke (hb_forward<Pred> (p),
224 hb_forward<Val> (v))
225 )
226
227 public:
228
229 template <typename Pred, typename Val> auto
230 operator () (Pred&& p, Val &&v) const HB_RETURN (bool,
231 impl (hb_forward<Pred> (p),
232 hb_forward<Val> (v),
233 hb_prioritize)
234 )
235 }
236 HB_FUNCOBJ (hb_has);
237
238 struct
239 {
240 private:
241
242 template <typename Pred, typename Val> auto
243 impl (Pred&& p, Val &&v, hb_priority<1>) const HB_AUTO_RETURN
244 (
245 hb_has (hb_forward<Pred> (p),
246 hb_forward<Val> (v))
247 )
248
249 template <typename Pred, typename Val> auto
250 impl (Pred&& p, Val &&v, hb_priority<0>) const HB_AUTO_RETURN
251 (
252 hb_forward<Pred> (p) == hb_forward<Val> (v)
253 )
254
255 public:
256
257 template <typename Pred, typename Val> auto
258 operator () (Pred&& p, Val &&v) const HB_RETURN (bool,
259 impl (hb_forward<Pred> (p),
260 hb_forward<Val> (v),
261 hb_prioritize)
262 )
263 }
264 HB_FUNCOBJ (hb_match);
265
266 struct
267 {
268 private:
269
270 template <typename Proj, typename Val> auto
271 impl (Proj&& f, Val &&v, hb_priority<2>) const HB_AUTO_RETURN
272 (hb_deref (hb_forward<Proj> (f)).get (hb_forward<Val> (v)))
273
274 template <typename Proj, typename Val> auto
275 impl (Proj&& f, Val &&v, hb_priority<1>) const HB_AUTO_RETURN
276 (
277 hb_invoke (hb_forward<Proj> (f),
278 hb_forward<Val> (v))
279 )
280
281 template <typename Proj, typename Val> auto
282 impl (Proj&& f, Val &&v, hb_priority<0>) const HB_AUTO_RETURN
283 (
284 hb_forward<Proj> (f)[hb_forward<Val> (v)]
285 )
286
287 public:
288
289 template <typename Proj, typename Val> auto
290 operator () (Proj&& f, Val &&v) const HB_AUTO_RETURN
291 (
292 impl (hb_forward<Proj> (f),
293 hb_forward<Val> (v),
294 hb_prioritize)
295 )
296 }
297 HB_FUNCOBJ (hb_get);
298
299
300 template <typename T1, typename T2>
301 struct hb_pair_t
302 {
303 typedef T1 first_t;
304 typedef T2 second_t;
305 typedef hb_pair_t<T1, T2> pair_t;
306
hb_pair_thb_pair_t307 hb_pair_t (T1 a, T2 b) : first (a), second (b) {}
308
309 template <typename Q1, typename Q2,
310 hb_enable_if (hb_is_convertible (T1, Q1) &&
311 hb_is_convertible (T2, T2))>
operator hb_pair_t<Q1,Q2>hb_pair_t312 operator hb_pair_t<Q1, Q2> () { return hb_pair_t<Q1, Q2> (first, second); }
313
reversehb_pair_t314 hb_pair_t<T1, T2> reverse () const
315 { return hb_pair_t<T1, T2> (second, first); }
316
operator ==hb_pair_t317 bool operator == (const pair_t& o) const { return first == o.first && second == o.second; }
operator !=hb_pair_t318 bool operator != (const pair_t& o) const { return !(*this == o); }
operator <hb_pair_t319 bool operator < (const pair_t& o) const { return first < o.first || (first == o.first && second < o.second); }
operator >=hb_pair_t320 bool operator >= (const pair_t& o) const { return !(*this < o); }
operator >hb_pair_t321 bool operator > (const pair_t& o) const { return first > o.first || (first == o.first && second > o.second); }
operator <=hb_pair_t322 bool operator <= (const pair_t& o) const { return !(*this > o); }
323
324 T1 first;
325 T2 second;
326 };
327 #define hb_pair_t(T1,T2) hb_pair_t<T1, T2>
328 template <typename T1, typename T2> static inline hb_pair_t<T1, T2>
hb_pair(T1 && a,T2 && b)329 hb_pair (T1&& a, T2&& b) { return hb_pair_t<T1, T2> (a, b); }
330
331 struct
332 {
333 template <typename Pair> constexpr typename Pair::first_t
operator ()__anone04d149e0a08334 operator () (const Pair& pair) const { return pair.first; }
335 }
336 HB_FUNCOBJ (hb_first);
337
338 struct
339 {
340 template <typename Pair> constexpr typename Pair::second_t
operator ()__anone04d149e0b08341 operator () (const Pair& pair) const { return pair.second; }
342 }
343 HB_FUNCOBJ (hb_second);
344
345 /* Note. In min/max impl, we can use hb_type_identity<T> for second argument.
346 * However, that would silently convert between different-signedness integers.
347 * Instead we accept two different types, such that compiler can err if
348 * comparing integers of different signedness. */
349 struct
350 {
351 template <typename T, typename T2> constexpr auto
352 operator () (T&& a, T2&& b) const HB_AUTO_RETURN
353 (hb_forward<T> (a) <= hb_forward<T2> (b) ? hb_forward<T> (a) : hb_forward<T2> (b))
354 }
355 HB_FUNCOBJ (hb_min);
356 struct
357 {
358 template <typename T, typename T2> constexpr auto
359 operator () (T&& a, T2&& b) const HB_AUTO_RETURN
360 (hb_forward<T> (a) >= hb_forward<T2> (b) ? hb_forward<T> (a) : hb_forward<T2> (b))
361 }
362 HB_FUNCOBJ (hb_max);
363
364
365 /*
366 * Bithacks.
367 */
368
369 /* Return the number of 1 bits in v. */
370 template <typename T>
371 static inline HB_CONST_FUNC unsigned int
hb_popcount(T v)372 hb_popcount (T v)
373 {
374 #if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__)
375 if (sizeof (T) <= sizeof (unsigned int))
376 return __builtin_popcount (v);
377
378 if (sizeof (T) <= sizeof (unsigned long))
379 return __builtin_popcountl (v);
380
381 if (sizeof (T) <= sizeof (unsigned long long))
382 return __builtin_popcountll (v);
383 #endif
384
385 if (sizeof (T) <= 4)
386 {
387 /* "HACKMEM 169" */
388 uint32_t y;
389 y = (v >> 1) &033333333333;
390 y = v - y - ((y >>1) & 033333333333);
391 return (((y + (y >> 3)) & 030707070707) % 077);
392 }
393
394 if (sizeof (T) == 8)
395 {
396 unsigned int shift = 32;
397 return hb_popcount<uint32_t> ((uint32_t) v) + hb_popcount ((uint32_t) (v >> shift));
398 }
399
400 if (sizeof (T) == 16)
401 {
402 unsigned int shift = 64;
403 return hb_popcount<uint64_t> ((uint64_t) v) + hb_popcount ((uint64_t) (v >> shift));
404 }
405
406 assert (0);
407 return 0; /* Shut up stupid compiler. */
408 }
409
410 /* Returns the number of bits needed to store number */
411 template <typename T>
412 static inline HB_CONST_FUNC unsigned int
hb_bit_storage(T v)413 hb_bit_storage (T v)
414 {
415 if (unlikely (!v)) return 0;
416
417 #if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__)
418 if (sizeof (T) <= sizeof (unsigned int))
419 return sizeof (unsigned int) * 8 - __builtin_clz (v);
420
421 if (sizeof (T) <= sizeof (unsigned long))
422 return sizeof (unsigned long) * 8 - __builtin_clzl (v);
423
424 if (sizeof (T) <= sizeof (unsigned long long))
425 return sizeof (unsigned long long) * 8 - __builtin_clzll (v);
426 #endif
427
428 #if (defined(_MSC_VER) && _MSC_VER >= 1500) || (defined(__MINGW32__) && (__GNUC__ < 4))
429 if (sizeof (T) <= sizeof (unsigned int))
430 {
431 unsigned long where;
432 _BitScanReverse (&where, v);
433 return 1 + where;
434 }
435 # if defined(_WIN64)
436 if (sizeof (T) <= 8)
437 {
438 unsigned long where;
439 _BitScanReverse64 (&where, v);
440 return 1 + where;
441 }
442 # endif
443 #endif
444
445 if (sizeof (T) <= 4)
446 {
447 /* "bithacks" */
448 const unsigned int b[] = {0x2, 0xC, 0xF0, 0xFF00, 0xFFFF0000};
449 const unsigned int S[] = {1, 2, 4, 8, 16};
450 unsigned int r = 0;
451 for (int i = 4; i >= 0; i--)
452 if (v & b[i])
453 {
454 v >>= S[i];
455 r |= S[i];
456 }
457 return r + 1;
458 }
459 if (sizeof (T) <= 8)
460 {
461 /* "bithacks" */
462 const uint64_t b[] = {0x2ULL, 0xCULL, 0xF0ULL, 0xFF00ULL, 0xFFFF0000ULL, 0xFFFFFFFF00000000ULL};
463 const unsigned int S[] = {1, 2, 4, 8, 16, 32};
464 unsigned int r = 0;
465 for (int i = 5; i >= 0; i--)
466 if (v & b[i])
467 {
468 v >>= S[i];
469 r |= S[i];
470 }
471 return r + 1;
472 }
473 if (sizeof (T) == 16)
474 {
475 unsigned int shift = 64;
476 return (v >> shift) ? hb_bit_storage<uint64_t> ((uint64_t) (v >> shift)) + shift :
477 hb_bit_storage<uint64_t> ((uint64_t) v);
478 }
479
480 assert (0);
481 return 0; /* Shut up stupid compiler. */
482 }
483
484 /* Returns the number of zero bits in the least significant side of v */
485 template <typename T>
486 static inline HB_CONST_FUNC unsigned int
hb_ctz(T v)487 hb_ctz (T v)
488 {
489 if (unlikely (!v)) return 0;
490
491 #if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__)
492 if (sizeof (T) <= sizeof (unsigned int))
493 return __builtin_ctz (v);
494
495 if (sizeof (T) <= sizeof (unsigned long))
496 return __builtin_ctzl (v);
497
498 if (sizeof (T) <= sizeof (unsigned long long))
499 return __builtin_ctzll (v);
500 #endif
501
502 #if (defined(_MSC_VER) && _MSC_VER >= 1500) || (defined(__MINGW32__) && (__GNUC__ < 4))
503 if (sizeof (T) <= sizeof (unsigned int))
504 {
505 unsigned long where;
506 _BitScanForward (&where, v);
507 return where;
508 }
509 # if defined(_WIN64)
510 if (sizeof (T) <= 8)
511 {
512 unsigned long where;
513 _BitScanForward64 (&where, v);
514 return where;
515 }
516 # endif
517 #endif
518
519 if (sizeof (T) <= 4)
520 {
521 /* "bithacks" */
522 unsigned int c = 32;
523 v &= - (int32_t) v;
524 if (v) c--;
525 if (v & 0x0000FFFF) c -= 16;
526 if (v & 0x00FF00FF) c -= 8;
527 if (v & 0x0F0F0F0F) c -= 4;
528 if (v & 0x33333333) c -= 2;
529 if (v & 0x55555555) c -= 1;
530 return c;
531 }
532 if (sizeof (T) <= 8)
533 {
534 /* "bithacks" */
535 unsigned int c = 64;
536 v &= - (int64_t) (v);
537 if (v) c--;
538 if (v & 0x00000000FFFFFFFFULL) c -= 32;
539 if (v & 0x0000FFFF0000FFFFULL) c -= 16;
540 if (v & 0x00FF00FF00FF00FFULL) c -= 8;
541 if (v & 0x0F0F0F0F0F0F0F0FULL) c -= 4;
542 if (v & 0x3333333333333333ULL) c -= 2;
543 if (v & 0x5555555555555555ULL) c -= 1;
544 return c;
545 }
546 if (sizeof (T) == 16)
547 {
548 unsigned int shift = 64;
549 return (uint64_t) v ? hb_bit_storage<uint64_t> ((uint64_t) v) :
550 hb_bit_storage<uint64_t> ((uint64_t) (v >> shift)) + shift;
551 }
552
553 assert (0);
554 return 0; /* Shut up stupid compiler. */
555 }
556
557
558 /*
559 * Tiny stuff.
560 */
561
562 /* ASCII tag/character handling */
ISALPHA(unsigned char c)563 static inline bool ISALPHA (unsigned char c)
564 { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); }
ISALNUM(unsigned char c)565 static inline bool ISALNUM (unsigned char c)
566 { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'); }
ISSPACE(unsigned char c)567 static inline bool ISSPACE (unsigned char c)
568 { return c == ' ' || c =='\f'|| c =='\n'|| c =='\r'|| c =='\t'|| c =='\v'; }
TOUPPER(unsigned char c)569 static inline unsigned char TOUPPER (unsigned char c)
570 { return (c >= 'a' && c <= 'z') ? c - 'a' + 'A' : c; }
TOLOWER(unsigned char c)571 static inline unsigned char TOLOWER (unsigned char c)
572 { return (c >= 'A' && c <= 'Z') ? c - 'A' + 'a' : c; }
573
DIV_CEIL(const unsigned int a,unsigned int b)574 static inline unsigned int DIV_CEIL (const unsigned int a, unsigned int b)
575 { return (a + (b - 1)) / b; }
576
577
578 #undef ARRAY_LENGTH
579 template <typename Type, unsigned int n>
ARRAY_LENGTH(const Type (&)[n])580 static inline unsigned int ARRAY_LENGTH (const Type (&)[n]) { return n; }
581 /* A const version, but does not detect erratically being called on pointers. */
582 #define ARRAY_LENGTH_CONST(__array) ((signed int) (sizeof (__array) / sizeof (__array[0])))
583
584
585 static inline int
hb_memcmp(const void * a,const void * b,unsigned int len)586 hb_memcmp (const void *a, const void *b, unsigned int len)
587 {
588 /* It's illegal to pass NULL to memcmp(), even if len is zero.
589 * So, wrap it.
590 * https://sourceware.org/bugzilla/show_bug.cgi?id=23878 */
591 if (unlikely (!len)) return 0;
592 return memcmp (a, b, len);
593 }
594
595 static inline void *
hb_memset(void * s,int c,unsigned int n)596 hb_memset (void *s, int c, unsigned int n)
597 {
598 /* It's illegal to pass NULL to memset(), even if n is zero. */
599 if (unlikely (!n)) return 0;
600 return memset (s, c, n);
601 }
602
603 static inline bool
hb_unsigned_mul_overflows(unsigned int count,unsigned int size)604 hb_unsigned_mul_overflows (unsigned int count, unsigned int size)
605 {
606 return (size > 0) && (count >= ((unsigned int) -1) / size);
607 }
608
609 static inline unsigned int
hb_ceil_to_4(unsigned int v)610 hb_ceil_to_4 (unsigned int v)
611 {
612 return ((v - 1) | 3) + 1;
613 }
614
615 template <typename T> static inline bool
hb_in_range(T u,T lo,T hi)616 hb_in_range (T u, T lo, T hi)
617 {
618 static_assert (!hb_is_signed<T>::value, "");
619
620 /* The casts below are important as if T is smaller than int,
621 * the subtract results will become a signed int! */
622 return (T)(u - lo) <= (T)(hi - lo);
623 }
624 template <typename T> static inline bool
hb_in_ranges(T u,T lo1,T hi1,T lo2,T hi2)625 hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2)
626 {
627 return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2);
628 }
629 template <typename T> static inline bool
hb_in_ranges(T u,T lo1,T hi1,T lo2,T hi2,T lo3,T hi3)630 hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3)
631 {
632 return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2) || hb_in_range (u, lo3, hi3);
633 }
634
635
636 /*
637 * Sort and search.
638 */
639 template <typename ...Ts>
640 static inline void *
hb_bsearch(const void * key,const void * base,size_t nmemb,size_t size,int (* compar)(const void * _key,const void * _item,Ts..._ds),Ts...ds)641 hb_bsearch (const void *key, const void *base,
642 size_t nmemb, size_t size,
643 int (*compar)(const void *_key, const void *_item, Ts... _ds),
644 Ts... ds)
645 {
646 int min = 0, max = (int) nmemb - 1;
647 while (min <= max)
648 {
649 int mid = ((unsigned int) min + (unsigned int) max) / 2;
650 const void *p = (const void *) (((const char *) base) + (mid * size));
651 int c = compar (key, p, ds...);
652 if (c < 0)
653 max = mid - 1;
654 else if (c > 0)
655 min = mid + 1;
656 else
657 return (void *) p;
658 }
659 return nullptr;
660 }
661
662
663 /* From https://github.com/noporpoise/sort_r
664 Feb 5, 2019 (c8c65c1e)
665 Modified to support optional argument using templates */
666
667 /* Isaac Turner 29 April 2014 Public Domain */
668
669 /*
670 hb_qsort function to be exported.
671 Parameters:
672 base is the array to be sorted
673 nel is the number of elements in the array
674 width is the size in bytes of each element of the array
675 compar is the comparison function
676 arg (optional) is a pointer to be passed to the comparison function
677
678 void hb_qsort(void *base, size_t nel, size_t width,
679 int (*compar)(const void *_a, const void *_b, [void *_arg]),
680 [void *arg]);
681 */
682
683 #define SORT_R_SWAP(a,b,tmp) ((tmp) = (a), (a) = (b), (b) = (tmp))
684
685 /* swap a and b */
686 /* a and b must not be equal! */
sort_r_swap(char * __restrict a,char * __restrict b,size_t w)687 static inline void sort_r_swap(char *__restrict a, char *__restrict b,
688 size_t w)
689 {
690 char tmp, *end = a+w;
691 for(; a < end; a++, b++) { SORT_R_SWAP(*a, *b, tmp); }
692 }
693
694 /* swap a, b iff a>b */
695 /* a and b must not be equal! */
696 /* __restrict is same as restrict but better support on old machines */
697 template <typename ...Ts>
sort_r_cmpswap(char * __restrict a,char * __restrict b,size_t w,int (* compar)(const void * _a,const void * _b,Ts..._ds),Ts...ds)698 static inline int sort_r_cmpswap(char *__restrict a,
699 char *__restrict b, size_t w,
700 int (*compar)(const void *_a,
701 const void *_b,
702 Ts... _ds),
703 Ts... ds)
704 {
705 if(compar(a, b, ds...) > 0) {
706 sort_r_swap(a, b, w);
707 return 1;
708 }
709 return 0;
710 }
711
712 /*
713 Swap consecutive blocks of bytes of size na and nb starting at memory addr ptr,
714 with the smallest swap so that the blocks are in the opposite order. Blocks may
715 be internally re-ordered e.g.
716 12345ab -> ab34512
717 123abc -> abc123
718 12abcde -> deabc12
719 */
sort_r_swap_blocks(char * ptr,size_t na,size_t nb)720 static inline void sort_r_swap_blocks(char *ptr, size_t na, size_t nb)
721 {
722 if(na > 0 && nb > 0) {
723 if(na > nb) { sort_r_swap(ptr, ptr+na, nb); }
724 else { sort_r_swap(ptr, ptr+nb, na); }
725 }
726 }
727
728 /* Implement recursive quicksort ourselves */
729 /* Note: quicksort is not stable, equivalent values may be swapped */
730 template <typename ...Ts>
sort_r_simple(void * base,size_t nel,size_t w,int (* compar)(const void * _a,const void * _b,Ts..._ds),Ts...ds)731 static inline void sort_r_simple(void *base, size_t nel, size_t w,
732 int (*compar)(const void *_a,
733 const void *_b,
734 Ts... _ds),
735 Ts... ds)
736 {
737 char *b = (char *)base, *end = b + nel*w;
738
739 /* for(size_t i=0; i<nel; i++) {printf("%4i", *(int*)(b + i*sizeof(int)));}
740 printf("\n"); */
741
742 if(nel < 10) {
743 /* Insertion sort for arbitrarily small inputs */
744 char *pi, *pj;
745 for(pi = b+w; pi < end; pi += w) {
746 for(pj = pi; pj > b && sort_r_cmpswap(pj-w,pj,w,compar,ds...); pj -= w) {}
747 }
748 }
749 else
750 {
751 /* nel > 9; Quicksort */
752
753 int cmp;
754 char *pl, *ple, *pr, *pre, *pivot;
755 char *last = b+w*(nel-1), *tmp;
756
757 /*
758 Use median of second, middle and second-last items as pivot.
759 First and last may have been swapped with pivot and therefore be extreme
760 */
761 char *l[3];
762 l[0] = b + w;
763 l[1] = b+w*(nel/2);
764 l[2] = last - w;
765
766 /* printf("pivots: %i, %i, %i\n", *(int*)l[0], *(int*)l[1], *(int*)l[2]); */
767
768 if(compar(l[0],l[1],ds...) > 0) { SORT_R_SWAP(l[0], l[1], tmp); }
769 if(compar(l[1],l[2],ds...) > 0) {
770 SORT_R_SWAP(l[1], l[2], tmp);
771 if(compar(l[0],l[1],ds...) > 0) { SORT_R_SWAP(l[0], l[1], tmp); }
772 }
773
774 /* swap mid value (l[1]), and last element to put pivot as last element */
775 if(l[1] != last) { sort_r_swap(l[1], last, w); }
776
777 /*
778 pl is the next item on the left to be compared to the pivot
779 pr is the last item on the right that was compared to the pivot
780 ple is the left position to put the next item that equals the pivot
781 ple is the last right position where we put an item that equals the pivot
782 v- end (beyond the array)
783 EEEEEELLLLLLLLuuuuuuuuGGGGGGGEEEEEEEE.
784 ^- b ^- ple ^- pl ^- pr ^- pre ^- last (where the pivot is)
785 Pivot comparison key:
786 E = equal, L = less than, u = unknown, G = greater than, E = equal
787 */
788 pivot = last;
789 ple = pl = b;
790 pre = pr = last;
791
792 /*
793 Strategy:
794 Loop into the list from the left and right at the same time to find:
795 - an item on the left that is greater than the pivot
796 - an item on the right that is less than the pivot
797 Once found, they are swapped and the loop continues.
798 Meanwhile items that are equal to the pivot are moved to the edges of the
799 array.
800 */
801 while(pl < pr) {
802 /* Move left hand items which are equal to the pivot to the far left.
803 break when we find an item that is greater than the pivot */
804 for(; pl < pr; pl += w) {
805 cmp = compar(pl, pivot, ds...);
806 if(cmp > 0) { break; }
807 else if(cmp == 0) {
808 if(ple < pl) { sort_r_swap(ple, pl, w); }
809 ple += w;
810 }
811 }
812 /* break if last batch of left hand items were equal to pivot */
813 if(pl >= pr) { break; }
814 /* Move right hand items which are equal to the pivot to the far right.
815 break when we find an item that is less than the pivot */
816 for(; pl < pr; ) {
817 pr -= w; /* Move right pointer onto an unprocessed item */
818 cmp = compar(pr, pivot, ds...);
819 if(cmp == 0) {
820 pre -= w;
821 if(pr < pre) { sort_r_swap(pr, pre, w); }
822 }
823 else if(cmp < 0) {
824 if(pl < pr) { sort_r_swap(pl, pr, w); }
825 pl += w;
826 break;
827 }
828 }
829 }
830
831 pl = pr; /* pr may have gone below pl */
832
833 /*
834 Now we need to go from: EEELLLGGGGEEEE
835 to: LLLEEEEEEEGGGG
836 Pivot comparison key:
837 E = equal, L = less than, u = unknown, G = greater than, E = equal
838 */
839 sort_r_swap_blocks(b, ple-b, pl-ple);
840 sort_r_swap_blocks(pr, pre-pr, end-pre);
841
842 /*for(size_t i=0; i<nel; i++) {printf("%4i", *(int*)(b + i*sizeof(int)));}
843 printf("\n");*/
844
845 sort_r_simple(b, (pl-ple)/w, w, compar, ds...);
846 sort_r_simple(end-(pre-pr), (pre-pr)/w, w, compar, ds...);
847 }
848 }
849
850 static inline void
hb_qsort(void * base,size_t nel,size_t width,int (* compar)(const void * _a,const void * _b))851 hb_qsort (void *base, size_t nel, size_t width,
852 int (*compar)(const void *_a, const void *_b))
853 {
854 #if defined(__OPTIMIZE_SIZE__) && !defined(HB_USE_INTERNAL_QSORT)
855 qsort (base, nel, width, compar);
856 #else
857 sort_r_simple (base, nel, width, compar);
858 #endif
859 }
860
861 static inline void
hb_qsort(void * base,size_t nel,size_t width,int (* compar)(const void * _a,const void * _b,void * _arg),void * arg)862 hb_qsort (void *base, size_t nel, size_t width,
863 int (*compar)(const void *_a, const void *_b, void *_arg),
864 void *arg)
865 {
866 #ifdef HAVE_GNU_QSORT_R
867 qsort_r (base, nel, width, compar, arg);
868 #else
869 sort_r_simple (base, nel, width, compar, arg);
870 #endif
871 }
872
873
874 template <typename T, typename T2, typename T3> static inline void
hb_stable_sort(T * array,unsigned int len,int (* compar)(const T2 *,const T2 *),T3 * array2)875 hb_stable_sort (T *array, unsigned int len, int(*compar)(const T2 *, const T2 *), T3 *array2)
876 {
877 for (unsigned int i = 1; i < len; i++)
878 {
879 unsigned int j = i;
880 while (j && compar (&array[j - 1], &array[i]) > 0)
881 j--;
882 if (i == j)
883 continue;
884 /* Move item i to occupy place for item j, shift what's in between. */
885 {
886 T t = array[i];
887 memmove (&array[j + 1], &array[j], (i - j) * sizeof (T));
888 array[j] = t;
889 }
890 if (array2)
891 {
892 T3 t = array2[i];
893 memmove (&array2[j + 1], &array2[j], (i - j) * sizeof (T3));
894 array2[j] = t;
895 }
896 }
897 }
898
899 template <typename T> static inline void
hb_stable_sort(T * array,unsigned int len,int (* compar)(const T *,const T *))900 hb_stable_sort (T *array, unsigned int len, int(*compar)(const T *, const T *))
901 {
902 hb_stable_sort (array, len, compar, (int *) nullptr);
903 }
904
905 static inline hb_bool_t
hb_codepoint_parse(const char * s,unsigned int len,int base,hb_codepoint_t * out)906 hb_codepoint_parse (const char *s, unsigned int len, int base, hb_codepoint_t *out)
907 {
908 unsigned int v;
909 const char *p = s;
910 const char *end = p + len;
911 if (unlikely (!hb_parse_uint (&p, end, &v, true/* whole buffer */, base)))
912 return false;
913
914 *out = v;
915 return true;
916 }
917
918
919 /* Operators. */
920
921 struct hb_bitwise_and
922 { HB_PARTIALIZE(2);
923 static constexpr bool passthru_left = false;
924 static constexpr bool passthru_right = false;
925 template <typename T> constexpr auto
926 operator () (const T &a, const T &b) const HB_AUTO_RETURN (a & b)
927 }
928 HB_FUNCOBJ (hb_bitwise_and);
929 struct hb_bitwise_or
930 { HB_PARTIALIZE(2);
931 static constexpr bool passthru_left = true;
932 static constexpr bool passthru_right = true;
933 template <typename T> constexpr auto
934 operator () (const T &a, const T &b) const HB_AUTO_RETURN (a | b)
935 }
936 HB_FUNCOBJ (hb_bitwise_or);
937 struct hb_bitwise_xor
938 { HB_PARTIALIZE(2);
939 static constexpr bool passthru_left = true;
940 static constexpr bool passthru_right = true;
941 template <typename T> constexpr auto
942 operator () (const T &a, const T &b) const HB_AUTO_RETURN (a ^ b)
943 }
944 HB_FUNCOBJ (hb_bitwise_xor);
945 struct hb_bitwise_sub
946 { HB_PARTIALIZE(2);
947 static constexpr bool passthru_left = true;
948 static constexpr bool passthru_right = false;
949 template <typename T> constexpr auto
950 operator () (const T &a, const T &b) const HB_AUTO_RETURN (a & ~b)
951 }
952 HB_FUNCOBJ (hb_bitwise_sub);
953 struct
954 {
955 template <typename T> constexpr auto
956 operator () (const T &a) const HB_AUTO_RETURN (~a)
957 }
958 HB_FUNCOBJ (hb_bitwise_neg);
959
960 struct
961 { HB_PARTIALIZE(2);
962 template <typename T, typename T2> constexpr auto
963 operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (a + b)
964 }
965 HB_FUNCOBJ (hb_add);
966 struct
967 { HB_PARTIALIZE(2);
968 template <typename T, typename T2> constexpr auto
969 operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (a - b)
970 }
971 HB_FUNCOBJ (hb_sub);
972 struct
973 { HB_PARTIALIZE(2);
974 template <typename T, typename T2> constexpr auto
975 operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (a * b)
976 }
977 HB_FUNCOBJ (hb_mul);
978 struct
979 { HB_PARTIALIZE(2);
980 template <typename T, typename T2> constexpr auto
981 operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (a / b)
982 }
983 HB_FUNCOBJ (hb_div);
984 struct
985 { HB_PARTIALIZE(2);
986 template <typename T, typename T2> constexpr auto
987 operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (a % b)
988 }
989 HB_FUNCOBJ (hb_mod);
990 struct
991 {
992 template <typename T> constexpr auto
993 operator () (const T &a) const HB_AUTO_RETURN (+a)
994 }
995 HB_FUNCOBJ (hb_pos);
996 struct
997 {
998 template <typename T> constexpr auto
999 operator () (const T &a) const HB_AUTO_RETURN (-a)
1000 }
1001 HB_FUNCOBJ (hb_neg);
1002 struct
1003 {
1004 template <typename T> constexpr auto
1005 operator () (T &a) const HB_AUTO_RETURN (++a)
1006 }
1007 HB_FUNCOBJ (hb_inc);
1008 struct
1009 {
1010 template <typename T> constexpr auto
1011 operator () (T &a) const HB_AUTO_RETURN (--a)
1012 }
1013 HB_FUNCOBJ (hb_dec);
1014
1015
1016 /* Compiler-assisted vectorization. */
1017
1018 /* Type behaving similar to vectorized vars defined using __attribute__((vector_size(...))),
1019 * basically a fixed-size bitset. */
1020 template <typename elt_t, unsigned int byte_size>
1021 struct hb_vector_size_t
1022 {
operator []hb_vector_size_t1023 elt_t& operator [] (unsigned int i) { return v[i]; }
operator []hb_vector_size_t1024 const elt_t& operator [] (unsigned int i) const { return v[i]; }
1025
clearhb_vector_size_t1026 void clear (unsigned char v = 0) { memset (this, v, sizeof (*this)); }
1027
1028 template <typename Op>
processhb_vector_size_t1029 hb_vector_size_t process (const Op& op) const
1030 {
1031 hb_vector_size_t r;
1032 for (unsigned int i = 0; i < ARRAY_LENGTH (v); i++)
1033 r.v[i] = op (v[i]);
1034 return r;
1035 }
1036 template <typename Op>
processhb_vector_size_t1037 hb_vector_size_t process (const Op& op, const hb_vector_size_t &o) const
1038 {
1039 hb_vector_size_t r;
1040 for (unsigned int i = 0; i < ARRAY_LENGTH (v); i++)
1041 r.v[i] = op (v[i], o.v[i]);
1042 return r;
1043 }
operator |hb_vector_size_t1044 hb_vector_size_t operator | (const hb_vector_size_t &o) const
1045 { return process (hb_bitwise_or, o); }
operator &hb_vector_size_t1046 hb_vector_size_t operator & (const hb_vector_size_t &o) const
1047 { return process (hb_bitwise_and, o); }
operator ^hb_vector_size_t1048 hb_vector_size_t operator ^ (const hb_vector_size_t &o) const
1049 { return process (hb_bitwise_xor, o); }
operator ~hb_vector_size_t1050 hb_vector_size_t operator ~ () const
1051 { return process (hb_bitwise_neg); }
1052
1053 private:
1054 static_assert (0 == byte_size % sizeof (elt_t), "");
1055 elt_t v[byte_size / sizeof (elt_t)];
1056 };
1057
1058
1059 #endif /* HB_ALGS_HH */
1060