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 #include <algorithm>
38 #include <initializer_list>
39 #include <functional>
40 #include <new>
41
42 /*
43 * Flags
44 */
45
46 /* Enable bitwise ops on enums marked as flags_t */
47 /* To my surprise, looks like the function resolver is happy to silently cast
48 * one enum to another... So this doesn't provide the type-checking that I
49 * originally had in mind... :(.
50 *
51 * For MSVC warnings, see: https://github.com/harfbuzz/harfbuzz/pull/163
52 */
53 #ifdef _MSC_VER
54 # pragma warning(disable:4200)
55 # pragma warning(disable:4800)
56 #endif
57 #define HB_MARK_AS_FLAG_T(T) \
58 extern "C++" { \
59 static inline constexpr T operator | (T l, T r) { return T ((unsigned) l | (unsigned) r); } \
60 static inline constexpr T operator & (T l, T r) { return T ((unsigned) l & (unsigned) r); } \
61 static inline constexpr T operator ^ (T l, T r) { return T ((unsigned) l ^ (unsigned) r); } \
62 static inline constexpr unsigned operator ~ (T r) { return (~(unsigned) r); } \
63 static inline T& operator |= (T &l, T r) { l = l | r; return l; } \
64 static inline T& operator &= (T& l, T r) { l = l & r; return l; } \
65 static inline T& operator ^= (T& l, T r) { l = l ^ r; return l; } \
66 } \
67 static_assert (true, "")
68
69 /* Useful for set-operations on small enums.
70 * For example, for testing "x ∈ {x1, x2, x3}" use:
71 * (FLAG_UNSAFE(x) & (FLAG(x1) | FLAG(x2) | FLAG(x3)))
72 */
73 #define FLAG(x) (static_assert_expr ((unsigned)(x) < 32) + (((uint32_t) 1U) << (unsigned)(x)))
74 #define FLAG_UNSAFE(x) ((unsigned)(x) < 32 ? (((uint32_t) 1U) << (unsigned)(x)) : 0)
75 #define FLAG_RANGE(x,y) (static_assert_expr ((x) < (y)) + FLAG(y+1) - FLAG(x))
76 #define FLAG64(x) (static_assert_expr ((unsigned)(x) < 64) + (((uint64_t) 1ULL) << (unsigned)(x)))
77 #define FLAG64_UNSAFE(x) ((unsigned)(x) < 64 ? (((uint64_t) 1ULL) << (unsigned)(x)) : 0)
78
79
80 /*
81 * Big-endian integers.
82 */
83
84 /* Endian swap, used in Windows related backends */
hb_uint16_swap(uint16_t v)85 static inline constexpr uint16_t hb_uint16_swap (uint16_t v)
86 { return (v >> 8) | (v << 8); }
hb_uint32_swap(uint32_t v)87 static inline constexpr uint32_t hb_uint32_swap (uint32_t v)
88 { return (hb_uint16_swap (v) << 16) | hb_uint16_swap (v >> 16); }
89
90 #ifndef HB_FAST_INT_ACCESS
91 #if defined(__OPTIMIZE__) && \
92 defined(__BYTE_ORDER) && \
93 (__BYTE_ORDER == __BIG_ENDIAN || \
94 (__BYTE_ORDER == __LITTLE_ENDIAN && \
95 hb_has_builtin(__builtin_bswap16) && \
96 hb_has_builtin(__builtin_bswap32)))
97 #define HB_FAST_INT_ACCESS 1
98 #else
99 #define HB_FAST_INT_ACCESS 0
100 #endif
101 #endif
102
103 template <typename Type, int Bytes = sizeof (Type)>
104 struct BEInt;
105 template <typename Type>
106 struct BEInt<Type, 1>
107 {
108 public:
109 BEInt () = default;
BEIntBEInt110 constexpr BEInt (Type V) : v {uint8_t (V)} {}
operator TypeBEInt111 constexpr operator Type () const { return v; }
112 private: uint8_t v;
113 };
114 template <typename Type>
115 struct BEInt<Type, 2>
116 {
117 struct __attribute__((packed)) packed_uint16_t { uint16_t v; };
118
119 public:
120 BEInt () = default;
121
BEIntBEInt122 BEInt (Type V)
123 #if HB_FAST_INT_ACCESS
124 #if __BYTE_ORDER == __LITTLE_ENDIAN
125 { ((packed_uint16_t *) v)->v = __builtin_bswap16 (V); }
126 #else /* __BYTE_ORDER == __BIG_ENDIAN */
127 { ((packed_uint16_t *) v)->v = V; }
128 #endif
129 #else
130 : v {uint8_t ((V >> 8) & 0xFF),
131 uint8_t ((V ) & 0xFF)} {}
132 #endif
133
operator TypeBEInt134 constexpr operator Type () const {
135 #if HB_FAST_INT_ACCESS
136 #if __BYTE_ORDER == __LITTLE_ENDIAN
137 return __builtin_bswap16 (((packed_uint16_t *) v)->v);
138 #else /* __BYTE_ORDER == __BIG_ENDIAN */
139 return ((packed_uint16_t *) v)->v;
140 #endif
141 #else
142 return (v[0] << 8)
143 + (v[1] );
144 #endif
145 }
146 private: uint8_t v[2];
147 };
148 template <typename Type>
149 struct BEInt<Type, 3>
150 {
151 static_assert (!std::is_signed<Type>::value, "");
152 public:
153 BEInt () = default;
BEIntBEInt154 constexpr BEInt (Type V) : v {uint8_t ((V >> 16) & 0xFF),
155 uint8_t ((V >> 8) & 0xFF),
156 uint8_t ((V ) & 0xFF)} {}
157
operator TypeBEInt158 constexpr operator Type () const { return (v[0] << 16)
159 + (v[1] << 8)
160 + (v[2] ); }
161 private: uint8_t v[3];
162 };
163 template <typename Type>
164 struct BEInt<Type, 4>
165 {
166 struct __attribute__((packed)) packed_uint32_t { uint32_t v; };
167
168 public:
169 BEInt () = default;
170
BEIntBEInt171 BEInt (Type V)
172 #if HB_FAST_INT_ACCESS
173 #if __BYTE_ORDER == __LITTLE_ENDIAN
174 { ((packed_uint32_t *) v)->v = __builtin_bswap32 (V); }
175 #else /* __BYTE_ORDER == __BIG_ENDIAN */
176 { ((packed_uint32_t *) v)->v = V; }
177 #endif
178 #else
179 : v {uint8_t ((V >> 24) & 0xFF),
180 uint8_t ((V >> 16) & 0xFF),
181 uint8_t ((V >> 8) & 0xFF),
182 uint8_t ((V ) & 0xFF)} {}
183 #endif
184
operator TypeBEInt185 constexpr operator Type () const {
186 #if HB_FAST_INT_ACCESS
187 #if __BYTE_ORDER == __LITTLE_ENDIAN
188 return __builtin_bswap32 (((packed_uint32_t *) v)->v);
189 #else /* __BYTE_ORDER == __BIG_ENDIAN */
190 return ((packed_uint32_t *) v)->v;
191 #endif
192 #else
193 return (v[0] << 24)
194 + (v[1] << 16)
195 + (v[2] << 8)
196 + (v[3] );
197 #endif
198 }
199 private: uint8_t v[4];
200 };
201
202 /* Floats. */
203
204 /* We want our rounding towards +infinity. */
205 static inline float
_hb_roundf(float x)206 _hb_roundf (float x) { return floorf (x + .5f); }
207 #define roundf(x) _hb_roundf(x)
208
209
210 /* Encodes three unsigned integers in one 64-bit number. If the inputs have more than 21 bits,
211 * values will be truncated / overlap, and might not decode exactly. */
212 #define HB_CODEPOINT_ENCODE3(x,y,z) (((uint64_t) (x) << 42) | ((uint64_t) (y) << 21) | (uint64_t) (z))
213 #define HB_CODEPOINT_DECODE3_1(v) ((hb_codepoint_t) ((v) >> 42))
214 #define HB_CODEPOINT_DECODE3_2(v) ((hb_codepoint_t) ((v) >> 21) & 0x1FFFFFu)
215 #define HB_CODEPOINT_DECODE3_3(v) ((hb_codepoint_t) (v) & 0x1FFFFFu)
216
217 /* Custom encoding used by hb-ucd. */
218 #define HB_CODEPOINT_ENCODE3_11_7_14(x,y,z) (((uint32_t) ((x) & 0x07FFu) << 21) | (((uint32_t) (y) & 0x007Fu) << 14) | (uint32_t) ((z) & 0x3FFFu))
219 #define HB_CODEPOINT_DECODE3_11_7_14_1(v) ((hb_codepoint_t) ((v) >> 21))
220 #define HB_CODEPOINT_DECODE3_11_7_14_2(v) ((hb_codepoint_t) (((v) >> 14) & 0x007Fu) | 0x0300)
221 #define HB_CODEPOINT_DECODE3_11_7_14_3(v) ((hb_codepoint_t) (v) & 0x3FFFu)
222
223
224 struct
225 {
226 /* Note. This is dangerous in that if it's passed an rvalue, it returns rvalue-reference. */
227 template <typename T> constexpr auto
228 operator () (T&& v) const HB_AUTO_RETURN ( std::forward<T> (v) )
229 }
230 HB_FUNCOBJ (hb_identity);
231 struct
232 {
233 /* Like identity(), but only retains lvalue-references. Rvalues are returned as rvalues. */
234 template <typename T> constexpr T&
operator ()__anon2109c4070208235 operator () (T& v) const { return v; }
236
237 template <typename T> constexpr hb_remove_reference<T>
operator ()__anon2109c4070208238 operator () (T&& v) const { return v; }
239 }
240 HB_FUNCOBJ (hb_lidentity);
241 struct
242 {
243 /* Like identity(), but always returns rvalue. */
244 template <typename T> constexpr hb_remove_reference<T>
operator ()__anon2109c4070308245 operator () (T&& v) const { return v; }
246 }
247 HB_FUNCOBJ (hb_ridentity);
248
249 struct
250 {
251 template <typename T> constexpr bool
operator ()__anon2109c4070408252 operator () (T&& v) const { return bool (std::forward<T> (v)); }
253 }
254 HB_FUNCOBJ (hb_bool);
255
256
257 /* The MIT License
258
259 Copyright (C) 2012 Zilong Tan (eric.zltan@gmail.com)
260
261 Permission is hereby granted, free of charge, to any person
262 obtaining a copy of this software and associated documentation
263 files (the "Software"), to deal in the Software without
264 restriction, including without limitation the rights to use, copy,
265 modify, merge, publish, distribute, sublicense, and/or sell copies
266 of the Software, and to permit persons to whom the Software is
267 furnished to do so, subject to the following conditions:
268
269 The above copyright notice and this permission notice shall be
270 included in all copies or substantial portions of the Software.
271
272 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
273 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
274 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
275 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
276 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
277 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
278 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
279 SOFTWARE.
280 */
281
282
283 // Compression function for Merkle-Damgard construction.
284 // This function is generated using the framework provided.
285 #define mix(h) ( \
286 (void) ((h) ^= (h) >> 23), \
287 (void) ((h) *= 0x2127599bf4325c37ULL), \
288 (h) ^= (h) >> 47)
289
fasthash64(const void * buf,size_t len,uint64_t seed)290 static inline uint64_t fasthash64(const void *buf, size_t len, uint64_t seed)
291 {
292 struct __attribute__((packed)) packed_uint64_t { uint64_t v; };
293 const uint64_t m = 0x880355f21e6d1965ULL;
294 const packed_uint64_t *pos = (const packed_uint64_t *)buf;
295 const packed_uint64_t *end = pos + (len / 8);
296 const unsigned char *pos2;
297 uint64_t h = seed ^ (len * m);
298 uint64_t v;
299
300 #ifndef HB_OPTIMIZE_SIZE
301 if (((uintptr_t) pos & 7) == 0)
302 {
303 while (pos != end)
304 {
305 #pragma GCC diagnostic push
306 #pragma GCC diagnostic ignored "-Wcast-align"
307 v = * (const uint64_t *) (pos++);
308 #pragma GCC diagnostic pop
309 h ^= mix(v);
310 h *= m;
311 }
312 }
313 else
314 #endif
315 {
316 while (pos != end)
317 {
318 v = pos++->v;
319 h ^= mix(v);
320 h *= m;
321 }
322 }
323
324 pos2 = (const unsigned char*)pos;
325 v = 0;
326
327 switch (len & 7) {
328 case 7: v ^= (uint64_t)pos2[6] << 48; HB_FALLTHROUGH;
329 case 6: v ^= (uint64_t)pos2[5] << 40; HB_FALLTHROUGH;
330 case 5: v ^= (uint64_t)pos2[4] << 32; HB_FALLTHROUGH;
331 case 4: v ^= (uint64_t)pos2[3] << 24; HB_FALLTHROUGH;
332 case 3: v ^= (uint64_t)pos2[2] << 16; HB_FALLTHROUGH;
333 case 2: v ^= (uint64_t)pos2[1] << 8; HB_FALLTHROUGH;
334 case 1: v ^= (uint64_t)pos2[0];
335 h ^= mix(v);
336 h *= m;
337 }
338
339 return mix(h);
340 }
341
fasthash32(const void * buf,size_t len,uint32_t seed)342 static inline uint32_t fasthash32(const void *buf, size_t len, uint32_t seed)
343 {
344 // the following trick converts the 64-bit hashcode to Fermat
345 // residue, which shall retain information from both the higher
346 // and lower parts of hashcode.
347 uint64_t h = fasthash64(buf, len, seed);
348 return h - (h >> 32);
349 }
350
351 struct
352 {
353 private:
354
355 template <typename T> constexpr auto
356 impl (const T& v, hb_priority<2>) const HB_RETURN (uint32_t, hb_deref (v).hash ())
357
358 // Horrible: std:hash() of integers seems to be identity in gcc / clang?!
359 // https://github.com/harfbuzz/harfbuzz/pull/4228
360 //
361 // For performance characteristics see:
362 // https://github.com/harfbuzz/harfbuzz/pull/4228#issuecomment-1565079537
363 template <typename T,
364 hb_enable_if (std::is_integral<T>::value && sizeof (T) <= sizeof (uint32_t))> constexpr auto
365 impl (const T& v, hb_priority<1>) const HB_RETURN (uint32_t, (uint32_t) v * 2654435761u /* Knuh's multiplicative hash */)
366 template <typename T,
367 hb_enable_if (std::is_integral<T>::value && sizeof (T) > sizeof (uint32_t))> constexpr auto
368 impl (const T& v, hb_priority<1>) const HB_RETURN (uint32_t, (uint32_t) (v ^ (v >> 32)) * 2654435761u /* Knuth's multiplicative hash */)
369
370 template <typename T,
371 hb_enable_if (std::is_floating_point<T>::value)> constexpr auto
372 impl (const T& v, hb_priority<1>) const HB_RETURN (uint32_t, fasthash32 (std::addressof (v), sizeof (T), 0xf437ffe6))
373
374 template <typename T> constexpr auto
375 impl (const T& v, hb_priority<0>) const HB_RETURN (uint32_t, std::hash<hb_decay<decltype (hb_deref (v))>>{} (hb_deref (v)))
376
377 public:
378
379 template <typename T> constexpr auto
380 operator () (const T& v) const HB_RETURN (uint32_t, impl (v, hb_prioritize))
381 }
382 HB_FUNCOBJ (hb_hash);
383
384
385 struct
386 {
387 private:
388
389 /* Pointer-to-member-function. */
390 template <typename Appl, typename T, typename ...Ts> auto
391 impl (Appl&& a, hb_priority<2>, T &&v, Ts&&... ds) const HB_AUTO_RETURN
392 ((hb_deref (std::forward<T> (v)).*std::forward<Appl> (a)) (std::forward<Ts> (ds)...))
393
394 /* Pointer-to-member. */
395 template <typename Appl, typename T> auto
396 impl (Appl&& a, hb_priority<1>, T &&v) const HB_AUTO_RETURN
397 ((hb_deref (std::forward<T> (v))).*std::forward<Appl> (a))
398
399 /* Operator(). */
400 template <typename Appl, typename ...Ts> auto
401 impl (Appl&& a, hb_priority<0>, Ts&&... ds) const HB_AUTO_RETURN
402 (hb_deref (std::forward<Appl> (a)) (std::forward<Ts> (ds)...))
403
404 public:
405
406 template <typename Appl, typename ...Ts> auto
407 operator () (Appl&& a, Ts&&... ds) const HB_AUTO_RETURN
408 (
409 impl (std::forward<Appl> (a),
410 hb_prioritize,
411 std::forward<Ts> (ds)...)
412 )
413 }
414 HB_FUNCOBJ (hb_invoke);
415
416 template <unsigned Pos, typename Appl, typename V>
417 struct hb_partial_t
418 {
hb_partial_thb_partial_t419 hb_partial_t (Appl a, V v) : a (a), v (v) {}
420
421 static_assert (Pos > 0, "");
422
423 template <typename ...Ts,
424 unsigned P = Pos,
425 hb_enable_if (P == 1)> auto
operator ()hb_partial_t426 operator () (Ts&& ...ds) -> decltype (hb_invoke (hb_declval (Appl),
427 hb_declval (V),
428 hb_declval (Ts)...))
429 {
430 return hb_invoke (std::forward<Appl> (a),
431 std::forward<V> (v),
432 std::forward<Ts> (ds)...);
433 }
434 template <typename T0, typename ...Ts,
435 unsigned P = Pos,
436 hb_enable_if (P == 2)> auto
operator ()hb_partial_t437 operator () (T0&& d0, Ts&& ...ds) -> decltype (hb_invoke (hb_declval (Appl),
438 hb_declval (T0),
439 hb_declval (V),
440 hb_declval (Ts)...))
441 {
442 return hb_invoke (std::forward<Appl> (a),
443 std::forward<T0> (d0),
444 std::forward<V> (v),
445 std::forward<Ts> (ds)...);
446 }
447
448 private:
449 hb_reference_wrapper<Appl> a;
450 V v;
451 };
452 template <unsigned Pos=1, typename Appl, typename V>
453 auto hb_partial (Appl&& a, V&& v) HB_AUTO_RETURN
454 (( hb_partial_t<Pos, Appl, V> (a, v) ))
455
456 /* The following, HB_PARTIALIZE, macro uses a particular corner-case
457 * of C++11 that is not particularly well-supported by all compilers.
458 * What's happening is that it's using "this" in a trailing return-type
459 * via decltype(). Broken compilers deduce the type of "this" pointer
460 * in that context differently from what it resolves to in the body
461 * of the function.
462 *
463 * One probable cause of this is that at the time of trailing return
464 * type declaration, "this" points to an incomplete type, whereas in
465 * the function body the type is complete. That doesn't justify the
466 * error in any way, but is probably what's happening.
467 *
468 * In the case of MSVC, we get around this by using C++14 "decltype(auto)"
469 * which deduces the type from the actual return statement. For gcc 4.8
470 * we use "+this" instead of "this" which produces an rvalue that seems
471 * to be deduced as the same type with this particular compiler, and seem
472 * to be fine as default code path as well.
473 */
474 #ifdef _MSC_VER
475 /* https://github.com/harfbuzz/harfbuzz/issues/1730 */ \
476 #define HB_PARTIALIZE(Pos) \
477 template <typename _T> \
478 decltype(auto) operator () (_T&& _v) const \
479 { return hb_partial<Pos> (this, std::forward<_T> (_v)); } \
480 static_assert (true, "")
481 #else
482 /* https://github.com/harfbuzz/harfbuzz/issues/1724 */
483 #define HB_PARTIALIZE(Pos) \
484 template <typename _T> \
485 auto operator () (_T&& _v) const HB_AUTO_RETURN \
486 (hb_partial<Pos> (+this, std::forward<_T> (_v))) \
487 static_assert (true, "")
488 #endif
489
490
491 struct
492 {
493 private:
494
495 template <typename Pred, typename Val> auto
496 impl (Pred&& p, Val &&v, hb_priority<1>) const HB_AUTO_RETURN
497 (
498 hb_deref (std::forward<Pred> (p)).has (std::forward<Val> (v))
499 )
500
501 template <typename Pred, typename Val> auto
502 impl (Pred&& p, Val &&v, hb_priority<0>) const HB_AUTO_RETURN
503 (
504 hb_invoke (std::forward<Pred> (p),
505 std::forward<Val> (v))
506 )
507
508 public:
509
510 template <typename Pred, typename Val> auto
511 operator () (Pred&& p, Val &&v) const HB_RETURN (bool,
512 impl (std::forward<Pred> (p),
513 std::forward<Val> (v),
514 hb_prioritize)
515 )
516 }
517 HB_FUNCOBJ (hb_has);
518
519 struct
520 {
521 private:
522
523 template <typename Pred, typename Val> auto
524 impl (Pred&& p, Val &&v, hb_priority<1>) const HB_AUTO_RETURN
525 (
526 hb_has (std::forward<Pred> (p),
527 std::forward<Val> (v))
528 )
529
530 template <typename Pred, typename Val> auto
531 impl (Pred&& p, Val &&v, hb_priority<0>) const HB_AUTO_RETURN
532 (
533 std::forward<Pred> (p) == std::forward<Val> (v)
534 )
535
536 public:
537
538 template <typename Pred, typename Val> auto
539 operator () (Pred&& p, Val &&v) const HB_RETURN (bool,
540 impl (std::forward<Pred> (p),
541 std::forward<Val> (v),
542 hb_prioritize)
543 )
544 }
545 HB_FUNCOBJ (hb_match);
546
547 struct
548 {
549 private:
550
551 template <typename Proj, typename Val> auto
552 impl (Proj&& f, Val &&v, hb_priority<2>) const HB_AUTO_RETURN
553 (
554 hb_deref (std::forward<Proj> (f)).get (std::forward<Val> (v))
555 )
556
557 template <typename Proj, typename Val> auto
558 impl (Proj&& f, Val &&v, hb_priority<1>) const HB_AUTO_RETURN
559 (
560 hb_invoke (std::forward<Proj> (f),
561 std::forward<Val> (v))
562 )
563
564 template <typename Proj, typename Val> auto
565 impl (Proj&& f, Val &&v, hb_priority<0>) const HB_AUTO_RETURN
566 (
567 std::forward<Proj> (f)[std::forward<Val> (v)]
568 )
569
570 public:
571
572 template <typename Proj, typename Val> auto
573 operator () (Proj&& f, Val &&v) const HB_AUTO_RETURN
574 (
575 impl (std::forward<Proj> (f),
576 std::forward<Val> (v),
577 hb_prioritize)
578 )
579 }
580 HB_FUNCOBJ (hb_get);
581
582 struct
583 {
584 private:
585
586 template <typename T1, typename T2> auto
587 impl (T1&& v1, T2 &&v2, hb_priority<3>) const HB_AUTO_RETURN
588 (
589 std::forward<T2> (v2).cmp (std::forward<T1> (v1)) == 0
590 )
591
592 template <typename T1, typename T2> auto
593 impl (T1&& v1, T2 &&v2, hb_priority<2>) const HB_AUTO_RETURN
594 (
595 std::forward<T1> (v1).cmp (std::forward<T2> (v2)) == 0
596 )
597
598 template <typename T1, typename T2> auto
599 impl (T1&& v1, T2 &&v2, hb_priority<1>) const HB_AUTO_RETURN
600 (
601 std::forward<T1> (v1) == std::forward<T2> (v2)
602 )
603
604 template <typename T1, typename T2> auto
605 impl (T1&& v1, T2 &&v2, hb_priority<0>) const HB_AUTO_RETURN
606 (
607 std::forward<T2> (v2) == std::forward<T1> (v1)
608 )
609
610 public:
611
612 template <typename T1, typename T2> auto
613 operator () (T1&& v1, T2 &&v2) const HB_AUTO_RETURN
614 (
615 impl (std::forward<T1> (v1),
616 std::forward<T2> (v2),
617 hb_prioritize)
618 )
619 }
620 HB_FUNCOBJ (hb_equal);
621
622 struct
623 {
624 template <typename T> void
operator ()__anon2109c4070b08625 operator () (T& a, T& b) const
626 {
627 using std::swap; // allow ADL
628 swap (a, b);
629 }
630 }
631 HB_FUNCOBJ (hb_swap);
632
633
634 template <typename T1, typename T2>
635 struct hb_pair_t
636 {
637 typedef T1 first_t;
638 typedef T2 second_t;
639 typedef hb_pair_t<T1, T2> pair_t;
640
641 template <typename U1 = T1, typename U2 = T2,
642 hb_enable_if (std::is_default_constructible<U1>::value &&
643 std::is_default_constructible<U2>::value)>
hb_pair_thb_pair_t644 hb_pair_t () : first (), second () {}
hb_pair_thb_pair_t645 hb_pair_t (T1 a, T2 b) : first (std::forward<T1> (a)), second (std::forward<T2> (b)) {}
646
647 template <typename Q1, typename Q2,
648 hb_enable_if (hb_is_convertible (T1, Q1) &&
649 hb_is_convertible (T2, Q2))>
operator hb_pair_t<Q1,Q2>hb_pair_t650 operator hb_pair_t<Q1, Q2> () { return hb_pair_t<Q1, Q2> (first, second); }
651
reversehb_pair_t652 hb_pair_t<T1, T2> reverse () const
653 { return hb_pair_t<T1, T2> (second, first); }
654
operator ==hb_pair_t655 bool operator == (const pair_t& o) const { return first == o.first && second == o.second; }
operator !=hb_pair_t656 bool operator != (const pair_t& o) const { return !(*this == o); }
operator <hb_pair_t657 bool operator < (const pair_t& o) const { return first < o.first || (first == o.first && second < o.second); }
operator >=hb_pair_t658 bool operator >= (const pair_t& o) const { return !(*this < o); }
operator >hb_pair_t659 bool operator > (const pair_t& o) const { return first > o.first || (first == o.first && second > o.second); }
operator <=hb_pair_t660 bool operator <= (const pair_t& o) const { return !(*this > o); }
661
cmphb_pair_t662 static int cmp (const void *pa, const void *pb)
663 {
664 pair_t *a = (pair_t *) pa;
665 pair_t *b = (pair_t *) pb;
666
667 if (a->first < b->first) return -1;
668 if (a->first > b->first) return +1;
669 if (a->second < b->second) return -1;
670 if (a->second > b->second) return +1;
671 return 0;
672 }
673
swap(hb_pair_t & a,hb_pair_t & b)674 friend void swap (hb_pair_t& a, hb_pair_t& b)
675 {
676 hb_swap (a.first, b.first);
677 hb_swap (a.second, b.second);
678 }
679
680
681 T1 first;
682 T2 second;
683 };
684 template <typename T1, typename T2> static inline hb_pair_t<T1, T2>
hb_pair(T1 && a,T2 && b)685 hb_pair (T1&& a, T2&& b) { return hb_pair_t<T1, T2> (a, b); }
686
687 typedef hb_pair_t<hb_codepoint_t, hb_codepoint_t> hb_codepoint_pair_t;
688
689 struct
690 {
691 template <typename Pair> constexpr typename Pair::first_t
operator ()__anon2109c4070c08692 operator () (const Pair& pair) const { return pair.first; }
693 }
694 HB_FUNCOBJ (hb_first);
695
696 struct
697 {
698 template <typename Pair> constexpr typename Pair::second_t
operator ()__anon2109c4070d08699 operator () (const Pair& pair) const { return pair.second; }
700 }
701 HB_FUNCOBJ (hb_second);
702
703 /* Note. In min/max impl, we can use hb_type_identity<T> for second argument.
704 * However, that would silently convert between different-signedness integers.
705 * Instead we accept two different types, such that compiler can err if
706 * comparing integers of different signedness. */
707 struct
708 {
709 template <typename T, typename T2> constexpr auto
710 operator () (T&& a, T2&& b) const HB_AUTO_RETURN
711 (a <= b ? a : b)
712 }
713 HB_FUNCOBJ (hb_min);
714 struct
715 {
716 template <typename T, typename T2> constexpr auto
717 operator () (T&& a, T2&& b) const HB_AUTO_RETURN
718 (a >= b ? a : b)
719 }
720 HB_FUNCOBJ (hb_max);
721 struct
722 {
723 template <typename T, typename T2, typename T3> constexpr auto
724 operator () (T&& x, T2&& min, T3&& max) const HB_AUTO_RETURN
725 (hb_min (hb_max (std::forward<T> (x), std::forward<T2> (min)), std::forward<T3> (max)))
726 }
727 HB_FUNCOBJ (hb_clamp);
728
729 /*
730 * Bithacks.
731 */
732
733 /* Return the number of 1 bits in v. */
734 template <typename T>
735 static inline unsigned int
hb_popcount(T v)736 hb_popcount (T v)
737 {
738 #if hb_has_builtin(__builtin_popcount)
739 if (sizeof (T) <= sizeof (unsigned int))
740 return __builtin_popcount (v);
741 #endif
742
743 #if hb_has_builtin(__builtin_popcountl)
744 if (sizeof (T) <= sizeof (unsigned long))
745 return __builtin_popcountl (v);
746 #endif
747
748 #if hb_has_builtin(__builtin_popcountll)
749 if (sizeof (T) <= sizeof (unsigned long long))
750 return __builtin_popcountll (v);
751 #endif
752
753 if (sizeof (T) <= 4)
754 {
755 /* "HACKMEM 169" */
756 uint32_t y;
757 y = (v >> 1) &033333333333;
758 y = v - y - ((y >>1) & 033333333333);
759 return (((y + (y >> 3)) & 030707070707) % 077);
760 }
761
762 if (sizeof (T) == 8)
763 {
764 uint64_t y = (uint64_t) v;
765 y -= ((y >> 1) & 0x5555555555555555ull);
766 y = (y & 0x3333333333333333ull) + (y >> 2 & 0x3333333333333333ull);
767 return ((y + (y >> 4)) & 0xf0f0f0f0f0f0f0full) * 0x101010101010101ull >> 56;
768 }
769
770 if (sizeof (T) == 16)
771 {
772 unsigned int shift = 64;
773 return hb_popcount<uint64_t> ((uint64_t) v) + hb_popcount ((uint64_t) (v >> shift));
774 }
775
776 assert (0);
777 return 0; /* Shut up stupid compiler. */
778 }
779
780 /* Returns the number of bits needed to store number */
781 template <typename T>
782 static inline unsigned int
hb_bit_storage(T v)783 hb_bit_storage (T v)
784 {
785 if (unlikely (!v)) return 0;
786
787 #if hb_has_builtin(__builtin_clz)
788 if (sizeof (T) <= sizeof (unsigned int))
789 return sizeof (unsigned int) * 8 - __builtin_clz (v);
790 #endif
791
792 #if hb_has_builtin(__builtin_clzl)
793 if (sizeof (T) <= sizeof (unsigned long))
794 return sizeof (unsigned long) * 8 - __builtin_clzl (v);
795 #endif
796
797 #if hb_has_builtin(__builtin_clzll)
798 if (sizeof (T) <= sizeof (unsigned long long))
799 return sizeof (unsigned long long) * 8 - __builtin_clzll (v);
800 #endif
801
802 #if (defined(_MSC_VER) && _MSC_VER >= 1500) || (defined(__MINGW32__) && (__GNUC__ < 4))
803 if (sizeof (T) <= sizeof (unsigned int))
804 {
805 unsigned long where;
806 _BitScanReverse (&where, v);
807 return 1 + where;
808 }
809 # if defined(_WIN64)
810 if (sizeof (T) <= 8)
811 {
812 unsigned long where;
813 _BitScanReverse64 (&where, v);
814 return 1 + where;
815 }
816 # endif
817 #endif
818
819 if (sizeof (T) <= 4)
820 {
821 /* "bithacks" */
822 const unsigned int b[] = {0x2, 0xC, 0xF0, 0xFF00, 0xFFFF0000};
823 const unsigned int S[] = {1, 2, 4, 8, 16};
824 unsigned int r = 0;
825 for (int i = 4; i >= 0; i--)
826 if (v & b[i])
827 {
828 v >>= S[i];
829 r |= S[i];
830 }
831 return r + 1;
832 }
833 if (sizeof (T) <= 8)
834 {
835 /* "bithacks" */
836 const uint64_t b[] = {0x2ULL, 0xCULL, 0xF0ULL, 0xFF00ULL, 0xFFFF0000ULL, 0xFFFFFFFF00000000ULL};
837 const unsigned int S[] = {1, 2, 4, 8, 16, 32};
838 unsigned int r = 0;
839 for (int i = 5; i >= 0; i--)
840 if (v & b[i])
841 {
842 v >>= S[i];
843 r |= S[i];
844 }
845 return r + 1;
846 }
847 if (sizeof (T) == 16)
848 {
849 unsigned int shift = 64;
850 return (v >> shift) ? hb_bit_storage<uint64_t> ((uint64_t) (v >> shift)) + shift :
851 hb_bit_storage<uint64_t> ((uint64_t) v);
852 }
853
854 assert (0);
855 return 0; /* Shut up stupid compiler. */
856 }
857
858 /* Returns the number of zero bits in the least significant side of v */
859 template <typename T>
860 static inline unsigned int
hb_ctz(T v)861 hb_ctz (T v)
862 {
863 if (unlikely (!v)) return 8 * sizeof (T);
864
865 #if hb_has_builtin(__builtin_ctz)
866 if (sizeof (T) <= sizeof (unsigned int))
867 return __builtin_ctz (v);
868 #endif
869
870 #if hb_has_builtin(__builtin_ctzl)
871 if (sizeof (T) <= sizeof (unsigned long))
872 return __builtin_ctzl (v);
873 #endif
874
875 #if hb_has_builtin(__builtin_ctzll)
876 if (sizeof (T) <= sizeof (unsigned long long))
877 return __builtin_ctzll (v);
878 #endif
879
880 #if (defined(_MSC_VER) && _MSC_VER >= 1500) || (defined(__MINGW32__) && (__GNUC__ < 4))
881 if (sizeof (T) <= sizeof (unsigned int))
882 {
883 unsigned long where;
884 _BitScanForward (&where, v);
885 return where;
886 }
887 # if defined(_WIN64)
888 if (sizeof (T) <= 8)
889 {
890 unsigned long where;
891 _BitScanForward64 (&where, v);
892 return where;
893 }
894 # endif
895 #endif
896
897 if (sizeof (T) <= 4)
898 {
899 /* "bithacks" */
900 unsigned int c = 32;
901 v &= - (int32_t) v;
902 if (v) c--;
903 if (v & 0x0000FFFF) c -= 16;
904 if (v & 0x00FF00FF) c -= 8;
905 if (v & 0x0F0F0F0F) c -= 4;
906 if (v & 0x33333333) c -= 2;
907 if (v & 0x55555555) c -= 1;
908 return c;
909 }
910 if (sizeof (T) <= 8)
911 {
912 /* "bithacks" */
913 unsigned int c = 64;
914 v &= - (int64_t) (v);
915 if (v) c--;
916 if (v & 0x00000000FFFFFFFFULL) c -= 32;
917 if (v & 0x0000FFFF0000FFFFULL) c -= 16;
918 if (v & 0x00FF00FF00FF00FFULL) c -= 8;
919 if (v & 0x0F0F0F0F0F0F0F0FULL) c -= 4;
920 if (v & 0x3333333333333333ULL) c -= 2;
921 if (v & 0x5555555555555555ULL) c -= 1;
922 return c;
923 }
924 if (sizeof (T) == 16)
925 {
926 unsigned int shift = 64;
927 return (uint64_t) v ? hb_bit_storage<uint64_t> ((uint64_t) v) :
928 hb_bit_storage<uint64_t> ((uint64_t) (v >> shift)) + shift;
929 }
930
931 assert (0);
932 return 0; /* Shut up stupid compiler. */
933 }
934
935
936 /*
937 * Tiny stuff.
938 */
939
940 /* ASCII tag/character handling */
ISALPHA(unsigned char c)941 static inline bool ISALPHA (unsigned char c)
942 { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); }
ISALNUM(unsigned char c)943 static inline bool ISALNUM (unsigned char c)
944 { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'); }
ISSPACE(unsigned char c)945 static inline bool ISSPACE (unsigned char c)
946 { return c == ' ' || c =='\f'|| c =='\n'|| c =='\r'|| c =='\t'|| c =='\v'; }
TOUPPER(unsigned char c)947 static inline unsigned char TOUPPER (unsigned char c)
948 { return (c >= 'a' && c <= 'z') ? c - 'a' + 'A' : c; }
TOLOWER(unsigned char c)949 static inline unsigned char TOLOWER (unsigned char c)
950 { return (c >= 'A' && c <= 'Z') ? c - 'A' + 'a' : c; }
ISHEX(unsigned char c)951 static inline bool ISHEX (unsigned char c)
952 { return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'); }
TOHEX(uint8_t c)953 static inline unsigned char TOHEX (uint8_t c)
954 { return (c & 0xF) <= 9 ? (c & 0xF) + '0' : (c & 0xF) + 'a' - 10; }
FROMHEX(unsigned char c)955 static inline uint8_t FROMHEX (unsigned char c)
956 { return (c >= '0' && c <= '9') ? c - '0' : TOLOWER (c) - 'a' + 10; }
957
DIV_CEIL(const unsigned int a,unsigned int b)958 static inline unsigned int DIV_CEIL (const unsigned int a, unsigned int b)
959 { return (a + (b - 1)) / b; }
960
961
962 #undef ARRAY_LENGTH
963 template <typename Type, unsigned int n>
ARRAY_LENGTH(const Type (&)[n])964 static inline unsigned int ARRAY_LENGTH (const Type (&)[n]) { return n; }
965 /* A const version, but does not detect erratically being called on pointers. */
966 #define ARRAY_LENGTH_CONST(__array) ((signed int) (sizeof (__array) / sizeof (__array[0])))
967
968
969 static inline void *
hb_memcpy(void * __restrict dst,const void * __restrict src,size_t len)970 hb_memcpy (void *__restrict dst, const void *__restrict src, size_t len)
971 {
972 /* It's illegal to pass 0 as size to memcpy. */
973 if (unlikely (!len)) return dst;
974 return memcpy (dst, src, len);
975 }
976
977 static inline int
hb_memcmp(const void * a,const void * b,unsigned int len)978 hb_memcmp (const void *a, const void *b, unsigned int len)
979 {
980 /* It's illegal to pass NULL to memcmp(), even if len is zero.
981 * So, wrap it.
982 * https://sourceware.org/bugzilla/show_bug.cgi?id=23878 */
983 if (unlikely (!len)) return 0;
984 return memcmp (a, b, len);
985 }
986
987 static inline void *
hb_memset(void * s,int c,unsigned int n)988 hb_memset (void *s, int c, unsigned int n)
989 {
990 /* It's illegal to pass NULL to memset(), even if n is zero. */
991 if (unlikely (!n)) return s;
992 return memset (s, c, n);
993 }
994
995 static inline unsigned int
hb_ceil_to_4(unsigned int v)996 hb_ceil_to_4 (unsigned int v)
997 {
998 return ((v - 1) | 3) + 1;
999 }
1000
1001 template <typename T> static inline bool
hb_in_range(T u,T lo,T hi)1002 hb_in_range (T u, T lo, T hi)
1003 {
1004 static_assert (!std::is_signed<T>::value, "");
1005
1006 /* The casts below are important as if T is smaller than int,
1007 * the subtract results will become a signed int! */
1008 return (T)(u - lo) <= (T)(hi - lo);
1009 }
1010 template <typename T> static inline bool
hb_in_ranges(T u,T lo1,T hi1)1011 hb_in_ranges (T u, T lo1, T hi1)
1012 {
1013 return hb_in_range (u, lo1, hi1);
1014 }
1015 template <typename T, typename ...Ts> static inline bool
hb_in_ranges(T u,T lo1,T hi1,Ts...ds)1016 hb_in_ranges (T u, T lo1, T hi1, Ts... ds)
1017 {
1018 return hb_in_range<T> (u, lo1, hi1) || hb_in_ranges<T> (u, ds...);
1019 }
1020
1021
1022 /*
1023 * Overflow checking.
1024 */
1025
1026 static inline bool
hb_unsigned_mul_overflows(unsigned int count,unsigned int size,unsigned * result=nullptr)1027 hb_unsigned_mul_overflows (unsigned int count, unsigned int size, unsigned *result = nullptr)
1028 {
1029 #if hb_has_builtin(__builtin_mul_overflow)
1030 unsigned stack_result;
1031 if (!result)
1032 result = &stack_result;
1033 return __builtin_mul_overflow (count, size, result);
1034 #endif
1035
1036 if (result)
1037 *result = count * size;
1038 return (size > 0) && (count >= ((unsigned int) -1) / size);
1039 }
1040
1041
1042 /*
1043 * Sort and search.
1044 */
1045
1046 template <typename K, typename V, typename ...Ts>
1047 static int
_hb_cmp_method(const void * pkey,const void * pval,Ts...ds)1048 _hb_cmp_method (const void *pkey, const void *pval, Ts... ds)
1049 {
1050 const K& key = * (const K*) pkey;
1051 const V& val = * (const V*) pval;
1052
1053 return val.cmp (key, ds...);
1054 }
1055
1056 template <typename V, typename K, typename ...Ts>
1057 static inline bool
hb_bsearch_impl(unsigned * pos,const K & key,V * base,size_t nmemb,size_t stride,int (* compar)(const void * _key,const void * _item,Ts..._ds),Ts...ds)1058 hb_bsearch_impl (unsigned *pos, /* Out */
1059 const K& key,
1060 V* base, size_t nmemb, size_t stride,
1061 int (*compar)(const void *_key, const void *_item, Ts... _ds),
1062 Ts... ds)
1063 {
1064 /* This is our *only* bsearch implementation. */
1065
1066 int min = 0, max = (int) nmemb - 1;
1067 while (min <= max)
1068 {
1069 int mid = ((unsigned int) min + (unsigned int) max) / 2;
1070 #pragma GCC diagnostic push
1071 #pragma GCC diagnostic ignored "-Wcast-align"
1072 V* p = (V*) (((const char *) base) + (mid * stride));
1073 #pragma GCC diagnostic pop
1074 int c = compar ((const void *) std::addressof (key), (const void *) p, ds...);
1075 if (c < 0)
1076 max = mid - 1;
1077 else if (c > 0)
1078 min = mid + 1;
1079 else
1080 {
1081 *pos = mid;
1082 return true;
1083 }
1084 }
1085 *pos = min;
1086 return false;
1087 }
1088
1089 template <typename V, typename K>
1090 static inline V*
1091 hb_bsearch (const K& key, V* base,
1092 size_t nmemb, size_t stride = sizeof (V),
1093 int (*compar)(const void *_key, const void *_item) = _hb_cmp_method<K, V>)
1094 {
1095 unsigned pos;
1096 #pragma GCC diagnostic push
1097 #pragma GCC diagnostic ignored "-Wcast-align"
1098 return hb_bsearch_impl (&pos, key, base, nmemb, stride, compar) ?
1099 (V*) (((const char *) base) + (pos * stride)) : nullptr;
1100 #pragma GCC diagnostic pop
1101 }
1102 template <typename V, typename K, typename ...Ts>
1103 static inline V*
hb_bsearch(const K & key,V * base,size_t nmemb,size_t stride,int (* compar)(const void * _key,const void * _item,Ts..._ds),Ts...ds)1104 hb_bsearch (const K& key, V* base,
1105 size_t nmemb, size_t stride,
1106 int (*compar)(const void *_key, const void *_item, Ts... _ds),
1107 Ts... ds)
1108 {
1109 unsigned pos;
1110 #pragma GCC diagnostic push
1111 #pragma GCC diagnostic ignored "-Wcast-align"
1112 return hb_bsearch_impl (&pos, key, base, nmemb, stride, compar, ds...) ?
1113 (V*) (((const char *) base) + (pos * stride)) : nullptr;
1114 #pragma GCC diagnostic pop
1115 }
1116
1117
1118 /* From https://github.com/noporpoise/sort_r
1119 Feb 5, 2019 (c8c65c1e)
1120 Modified to support optional argument using templates */
1121
1122 /* Isaac Turner 29 April 2014 Public Domain */
1123
1124 /*
1125 hb_qsort function to be exported.
1126 Parameters:
1127 base is the array to be sorted
1128 nel is the number of elements in the array
1129 width is the size in bytes of each element of the array
1130 compar is the comparison function
1131 arg (optional) is a pointer to be passed to the comparison function
1132
1133 void hb_qsort(void *base, size_t nel, size_t width,
1134 int (*compar)(const void *_a, const void *_b, [void *_arg]),
1135 [void *arg]);
1136 */
1137
1138 #define SORT_R_SWAP(a,b,tmp) ((void) ((tmp) = (a)), (void) ((a) = (b)), (b) = (tmp))
1139
1140 /* swap a and b */
1141 /* a and b must not be equal! */
sort_r_swap(char * __restrict a,char * __restrict b,size_t w)1142 static inline void sort_r_swap(char *__restrict a, char *__restrict b,
1143 size_t w)
1144 {
1145 char tmp, *end = a+w;
1146 for(; a < end; a++, b++) { SORT_R_SWAP(*a, *b, tmp); }
1147 }
1148
1149 /* swap a, b iff a>b */
1150 /* a and b must not be equal! */
1151 /* __restrict is same as restrict but better support on old machines */
1152 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)1153 static inline int sort_r_cmpswap(char *__restrict a,
1154 char *__restrict b, size_t w,
1155 int (*compar)(const void *_a,
1156 const void *_b,
1157 Ts... _ds),
1158 Ts... ds)
1159 {
1160 if(compar(a, b, ds...) > 0) {
1161 sort_r_swap(a, b, w);
1162 return 1;
1163 }
1164 return 0;
1165 }
1166
1167 /*
1168 Swap consecutive blocks of bytes of size na and nb starting at memory addr ptr,
1169 with the smallest swap so that the blocks are in the opposite order. Blocks may
1170 be internally re-ordered e.g.
1171 12345ab -> ab34512
1172 123abc -> abc123
1173 12abcde -> deabc12
1174 */
sort_r_swap_blocks(char * ptr,size_t na,size_t nb)1175 static inline void sort_r_swap_blocks(char *ptr, size_t na, size_t nb)
1176 {
1177 if(na > 0 && nb > 0) {
1178 if(na > nb) { sort_r_swap(ptr, ptr+na, nb); }
1179 else { sort_r_swap(ptr, ptr+nb, na); }
1180 }
1181 }
1182
1183 /* Implement recursive quicksort ourselves */
1184 /* Note: quicksort is not stable, equivalent values may be swapped */
1185 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)1186 static inline void sort_r_simple(void *base, size_t nel, size_t w,
1187 int (*compar)(const void *_a,
1188 const void *_b,
1189 Ts... _ds),
1190 Ts... ds)
1191 {
1192 char *b = (char *)base, *end = b + nel*w;
1193
1194 /* for(size_t i=0; i<nel; i++) {printf("%4i", *(int*)(b + i*sizeof(int)));}
1195 printf("\n"); */
1196
1197 if(nel < 10) {
1198 /* Insertion sort for arbitrarily small inputs */
1199 char *pi, *pj;
1200 for(pi = b+w; pi < end; pi += w) {
1201 for(pj = pi; pj > b && sort_r_cmpswap(pj-w,pj,w,compar,ds...); pj -= w) {}
1202 }
1203 }
1204 else
1205 {
1206 /* nel > 9; Quicksort */
1207
1208 int cmp;
1209 char *pl, *ple, *pr, *pre, *pivot;
1210 char *last = b+w*(nel-1), *tmp;
1211
1212 /*
1213 Use median of second, middle and second-last items as pivot.
1214 First and last may have been swapped with pivot and therefore be extreme
1215 */
1216 char *l[3];
1217 l[0] = b + w;
1218 l[1] = b+w*(nel/2);
1219 l[2] = last - w;
1220
1221 /* printf("pivots: %i, %i, %i\n", *(int*)l[0], *(int*)l[1], *(int*)l[2]); */
1222
1223 if(compar(l[0],l[1],ds...) > 0) { SORT_R_SWAP(l[0], l[1], tmp); }
1224 if(compar(l[1],l[2],ds...) > 0) {
1225 SORT_R_SWAP(l[1], l[2], tmp);
1226 if(compar(l[0],l[1],ds...) > 0) { SORT_R_SWAP(l[0], l[1], tmp); }
1227 }
1228
1229 /* swap mid value (l[1]), and last element to put pivot as last element */
1230 if(l[1] != last) { sort_r_swap(l[1], last, w); }
1231
1232 /*
1233 pl is the next item on the left to be compared to the pivot
1234 pr is the last item on the right that was compared to the pivot
1235 ple is the left position to put the next item that equals the pivot
1236 ple is the last right position where we put an item that equals the pivot
1237 v- end (beyond the array)
1238 EEEEEELLLLLLLLuuuuuuuuGGGGGGGEEEEEEEE.
1239 ^- b ^- ple ^- pl ^- pr ^- pre ^- last (where the pivot is)
1240 Pivot comparison key:
1241 E = equal, L = less than, u = unknown, G = greater than, E = equal
1242 */
1243 pivot = last;
1244 ple = pl = b;
1245 pre = pr = last;
1246
1247 /*
1248 Strategy:
1249 Loop into the list from the left and right at the same time to find:
1250 - an item on the left that is greater than the pivot
1251 - an item on the right that is less than the pivot
1252 Once found, they are swapped and the loop continues.
1253 Meanwhile items that are equal to the pivot are moved to the edges of the
1254 array.
1255 */
1256 while(pl < pr) {
1257 /* Move left hand items which are equal to the pivot to the far left.
1258 break when we find an item that is greater than the pivot */
1259 for(; pl < pr; pl += w) {
1260 cmp = compar(pl, pivot, ds...);
1261 if(cmp > 0) { break; }
1262 else if(cmp == 0) {
1263 if(ple < pl) { sort_r_swap(ple, pl, w); }
1264 ple += w;
1265 }
1266 }
1267 /* break if last batch of left hand items were equal to pivot */
1268 if(pl >= pr) { break; }
1269 /* Move right hand items which are equal to the pivot to the far right.
1270 break when we find an item that is less than the pivot */
1271 for(; pl < pr; ) {
1272 pr -= w; /* Move right pointer onto an unprocessed item */
1273 cmp = compar(pr, pivot, ds...);
1274 if(cmp == 0) {
1275 pre -= w;
1276 if(pr < pre) { sort_r_swap(pr, pre, w); }
1277 }
1278 else if(cmp < 0) {
1279 if(pl < pr) { sort_r_swap(pl, pr, w); }
1280 pl += w;
1281 break;
1282 }
1283 }
1284 }
1285
1286 pl = pr; /* pr may have gone below pl */
1287
1288 /*
1289 Now we need to go from: EEELLLGGGGEEEE
1290 to: LLLEEEEEEEGGGG
1291 Pivot comparison key:
1292 E = equal, L = less than, u = unknown, G = greater than, E = equal
1293 */
1294 sort_r_swap_blocks(b, ple-b, pl-ple);
1295 sort_r_swap_blocks(pr, pre-pr, end-pre);
1296
1297 /*for(size_t i=0; i<nel; i++) {printf("%4i", *(int*)(b + i*sizeof(int)));}
1298 printf("\n");*/
1299
1300 sort_r_simple(b, (pl-ple)/w, w, compar, ds...);
1301 sort_r_simple(end-(pre-pr), (pre-pr)/w, w, compar, ds...);
1302 }
1303 }
1304
1305 static inline void
hb_qsort(void * base,size_t nel,size_t width,int (* compar)(const void * _a,const void * _b))1306 hb_qsort (void *base, size_t nel, size_t width,
1307 int (*compar)(const void *_a, const void *_b))
1308 {
1309 #if defined(__OPTIMIZE_SIZE__) && !defined(HB_USE_INTERNAL_QSORT)
1310 qsort (base, nel, width, compar);
1311 #else
1312 sort_r_simple (base, nel, width, compar);
1313 #endif
1314 }
1315
1316 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)1317 hb_qsort (void *base, size_t nel, size_t width,
1318 int (*compar)(const void *_a, const void *_b, void *_arg),
1319 void *arg)
1320 {
1321 #ifdef HAVE_GNU_QSORT_R
1322 qsort_r (base, nel, width, compar, arg);
1323 #else
1324 sort_r_simple (base, nel, width, compar, arg);
1325 #endif
1326 }
1327
1328
1329 template <typename T, typename T2, typename T3 = int> static inline void
hb_stable_sort(T * array,unsigned int len,int (* compar)(const T2 *,const T2 *),T3 * array2=nullptr)1330 hb_stable_sort (T *array, unsigned int len, int(*compar)(const T2 *, const T2 *), T3 *array2 = nullptr)
1331 {
1332 static_assert (hb_is_trivially_copy_assignable (T), "");
1333 static_assert (hb_is_trivially_copy_assignable (T3), "");
1334
1335 for (unsigned int i = 1; i < len; i++)
1336 {
1337 unsigned int j = i;
1338 while (j && compar (&array[j - 1], &array[i]) > 0)
1339 j--;
1340 if (i == j)
1341 continue;
1342 /* Move item i to occupy place for item j, shift what's in between. */
1343 {
1344 T t = array[i];
1345 memmove (&array[j + 1], &array[j], (i - j) * sizeof (T));
1346 array[j] = t;
1347 }
1348 if (array2)
1349 {
1350 T3 t = array2[i];
1351 memmove (&array2[j + 1], &array2[j], (i - j) * sizeof (T3));
1352 array2[j] = t;
1353 }
1354 }
1355 }
1356
1357 static inline hb_bool_t
hb_codepoint_parse(const char * s,unsigned int len,int base,hb_codepoint_t * out)1358 hb_codepoint_parse (const char *s, unsigned int len, int base, hb_codepoint_t *out)
1359 {
1360 unsigned int v;
1361 const char *p = s;
1362 const char *end = p + len;
1363 if (unlikely (!hb_parse_uint (&p, end, &v, true/* whole buffer */, base)))
1364 return false;
1365
1366 *out = v;
1367 return true;
1368 }
1369
1370
1371 /* Operators. */
1372
1373 struct
1374 { HB_PARTIALIZE(2);
1375 template <typename T> constexpr auto
1376 operator () (const T &a, const T &b) const HB_AUTO_RETURN (a & b)
1377 }
1378 HB_FUNCOBJ (hb_bitwise_and);
1379 struct
1380 { HB_PARTIALIZE(2);
1381 template <typename T> constexpr auto
1382 operator () (const T &a, const T &b) const HB_AUTO_RETURN (a | b)
1383 }
1384 HB_FUNCOBJ (hb_bitwise_or);
1385 struct
1386 { HB_PARTIALIZE(2);
1387 template <typename T> constexpr auto
1388 operator () (const T &a, const T &b) const HB_AUTO_RETURN (a ^ b)
1389 }
1390 HB_FUNCOBJ (hb_bitwise_xor);
1391 struct
1392 { HB_PARTIALIZE(2);
1393 template <typename T> constexpr auto
1394 operator () (const T &a, const T &b) const HB_AUTO_RETURN (~a & b)
1395 }
1396 HB_FUNCOBJ (hb_bitwise_lt);
1397 struct
1398 { HB_PARTIALIZE(2);
1399 template <typename T> constexpr auto
1400 operator () (const T &a, const T &b) const HB_AUTO_RETURN (a & ~b)
1401 }
1402 HB_FUNCOBJ (hb_bitwise_gt); // aka sub
1403 struct
1404 { HB_PARTIALIZE(2);
1405 template <typename T> constexpr auto
1406 operator () (const T &a, const T &b) const HB_AUTO_RETURN (~a | b)
1407 }
1408 HB_FUNCOBJ (hb_bitwise_le);
1409 struct
1410 { HB_PARTIALIZE(2);
1411 template <typename T> constexpr auto
1412 operator () (const T &a, const T &b) const HB_AUTO_RETURN (a | ~b)
1413 }
1414 HB_FUNCOBJ (hb_bitwise_ge);
1415 struct
1416 {
1417 template <typename T> constexpr auto
1418 operator () (const T &a) const HB_AUTO_RETURN (~a)
1419 }
1420 HB_FUNCOBJ (hb_bitwise_neg);
1421
1422 struct
1423 { HB_PARTIALIZE(2);
1424 template <typename T, typename T2> constexpr auto
1425 operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (a + b)
1426 }
1427 HB_FUNCOBJ (hb_add);
1428 struct
1429 { HB_PARTIALIZE(2);
1430 template <typename T, typename T2> constexpr auto
1431 operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (a - b)
1432 }
1433 HB_FUNCOBJ (hb_sub);
1434 struct
1435 { HB_PARTIALIZE(2);
1436 template <typename T, typename T2> constexpr auto
1437 operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (b - a)
1438 }
1439 HB_FUNCOBJ (hb_rsub);
1440 struct
1441 { HB_PARTIALIZE(2);
1442 template <typename T, typename T2> constexpr auto
1443 operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (a * b)
1444 }
1445 HB_FUNCOBJ (hb_mul);
1446 struct
1447 { HB_PARTIALIZE(2);
1448 template <typename T, typename T2> constexpr auto
1449 operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (a / b)
1450 }
1451 HB_FUNCOBJ (hb_div);
1452 struct
1453 { HB_PARTIALIZE(2);
1454 template <typename T, typename T2> constexpr auto
1455 operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (a % b)
1456 }
1457 HB_FUNCOBJ (hb_mod);
1458 struct
1459 {
1460 template <typename T> constexpr auto
1461 operator () (const T &a) const HB_AUTO_RETURN (+a)
1462 }
1463 HB_FUNCOBJ (hb_pos);
1464 struct
1465 {
1466 template <typename T> constexpr auto
1467 operator () (const T &a) const HB_AUTO_RETURN (-a)
1468 }
1469 HB_FUNCOBJ (hb_neg);
1470 struct
1471 {
1472 template <typename T> constexpr auto
1473 operator () (T &a) const HB_AUTO_RETURN (++a)
1474 }
1475 HB_FUNCOBJ (hb_inc);
1476 struct
1477 {
1478 template <typename T> constexpr auto
1479 operator () (T &a) const HB_AUTO_RETURN (--a)
1480 }
1481 HB_FUNCOBJ (hb_dec);
1482
1483
1484 /* Adapted from kurbo implementation with extra parameters added,
1485 * and finding for a particular range instead of 0.
1486 *
1487 * For documentation and implementation see:
1488 *
1489 * [ITP method]: https://en.wikipedia.org/wiki/ITP_Method
1490 * [An Enhancement of the Bisection Method Average Performance Preserving Minmax Optimality]: https://dl.acm.org/doi/10.1145/3423597
1491 * https://docs.rs/kurbo/0.8.1/kurbo/common/fn.solve_itp.html
1492 * https://github.com/linebender/kurbo/blob/fd839c25ea0c98576c7ce5789305822675a89938/src/common.rs#L162-L248
1493 */
1494 template <typename func_t>
solve_itp(func_t f,double a,double b,double epsilon,double min_y,double max_y,double & ya,double & yb,double & y)1495 double solve_itp (func_t f,
1496 double a, double b,
1497 double epsilon,
1498 double min_y, double max_y,
1499 double &ya, double &yb, double &y)
1500 {
1501 unsigned n1_2 = (unsigned) (hb_max (ceil (log2 ((b - a) / epsilon)) - 1.0, 0.0));
1502 const unsigned n0 = 1; // Hardwired
1503 const double k1 = 0.2 / (b - a); // Hardwired.
1504 unsigned nmax = n0 + n1_2;
1505 double scaled_epsilon = epsilon * double (1llu << nmax);
1506 double _2_epsilon = 2.0 * epsilon;
1507 while (b - a > _2_epsilon)
1508 {
1509 double x1_2 = 0.5 * (a + b);
1510 double r = scaled_epsilon - 0.5 * (b - a);
1511 double xf = (yb * a - ya * b) / (yb - ya);
1512 double sigma = x1_2 - xf;
1513 double b_a = b - a;
1514 // This has k2 = 2 hardwired for efficiency.
1515 double b_a_k2 = b_a * b_a;
1516 double delta = k1 * b_a_k2;
1517 int sigma_sign = sigma >= 0 ? +1 : -1;
1518 double xt = delta <= fabs (x1_2 - xf) ? xf + delta * sigma_sign : x1_2;
1519 double xitp = fabs (xt - x1_2) <= r ? xt : x1_2 - r * sigma_sign;
1520 double yitp = f (xitp);
1521 if (yitp > max_y)
1522 {
1523 b = xitp;
1524 yb = yitp;
1525 }
1526 else if (yitp < min_y)
1527 {
1528 a = xitp;
1529 ya = yitp;
1530 }
1531 else
1532 {
1533 y = yitp;
1534 return xitp;
1535 }
1536 scaled_epsilon *= 0.5;
1537 }
1538 return 0.5 * (a + b);
1539 }
1540
1541
1542 #endif /* HB_ALGS_HH */
1543