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 template <typename Type, int Bytes = sizeof (Type)>
91 struct BEInt;
92 template <typename Type>
93 struct BEInt<Type, 1>
94 {
95 public:
96 BEInt () = default;
BEIntBEInt97 constexpr BEInt (Type V) : v {uint8_t (V)} {}
operator TypeBEInt98 constexpr operator Type () const { return v; }
99 private: uint8_t v;
100 };
101 template <typename Type>
102 struct BEInt<Type, 2>
103 {
104 public:
105 BEInt () = default;
BEIntBEInt106 constexpr BEInt (Type V) : v {uint8_t ((V >> 8) & 0xFF),
107 uint8_t ((V ) & 0xFF)} {}
108
109 struct __attribute__((packed)) packed_uint16_t { uint16_t v; };
operator TypeBEInt110 constexpr operator Type () const
111 {
112 #if defined(__OPTIMIZE__) && !defined(HB_NO_PACKED) && \
113 ((defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__)) && \
114 defined(__BYTE_ORDER) && \
115 (__BYTE_ORDER == __LITTLE_ENDIAN || __BYTE_ORDER == __BIG_ENDIAN)
116 /* Spoon-feed the compiler a big-endian integer with alignment 1.
117 * https://github.com/harfbuzz/harfbuzz/pull/1398 */
118 #if __BYTE_ORDER == __LITTLE_ENDIAN
119 return __builtin_bswap16 (((packed_uint16_t *) v)->v);
120 #else /* __BYTE_ORDER == __BIG_ENDIAN */
121 return ((packed_uint16_t *) v)->v;
122 #endif
123 #else
124 return (v[0] << 8)
125 + (v[1] );
126 #endif
127 }
128 private: uint8_t v[2];
129 };
130 template <typename Type>
131 struct BEInt<Type, 3>
132 {
133 static_assert (!std::is_signed<Type>::value, "");
134 public:
135 BEInt () = default;
BEIntBEInt136 constexpr BEInt (Type V) : v {uint8_t ((V >> 16) & 0xFF),
137 uint8_t ((V >> 8) & 0xFF),
138 uint8_t ((V ) & 0xFF)} {}
139
operator TypeBEInt140 constexpr operator Type () const { return (v[0] << 16)
141 + (v[1] << 8)
142 + (v[2] ); }
143 private: uint8_t v[3];
144 };
145 template <typename Type>
146 struct BEInt<Type, 4>
147 {
148 public:
149 BEInt () = default;
BEIntBEInt150 constexpr BEInt (Type V) : v {uint8_t ((V >> 24) & 0xFF),
151 uint8_t ((V >> 16) & 0xFF),
152 uint8_t ((V >> 8) & 0xFF),
153 uint8_t ((V ) & 0xFF)} {}
154
155 struct __attribute__((packed)) packed_uint32_t { uint32_t v; };
operator TypeBEInt156 constexpr operator Type () const {
157 #if defined(__OPTIMIZE__) && !defined(HB_NO_PACKED) && \
158 ((defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__)) && \
159 defined(__BYTE_ORDER) && \
160 (__BYTE_ORDER == __LITTLE_ENDIAN || __BYTE_ORDER == __BIG_ENDIAN)
161 /* Spoon-feed the compiler a big-endian integer with alignment 1.
162 * https://github.com/harfbuzz/harfbuzz/pull/1398 */
163 #if __BYTE_ORDER == __LITTLE_ENDIAN
164 return __builtin_bswap32 (((packed_uint32_t *) v)->v);
165 #else /* __BYTE_ORDER == __BIG_ENDIAN */
166 return ((packed_uint32_t *) v)->v;
167 #endif
168 #else
169 return (v[0] << 24)
170 + (v[1] << 16)
171 + (v[2] << 8)
172 + (v[3] );
173 #endif
174 }
175 private: uint8_t v[4];
176 };
177
178 /* Floats. */
179
180 /* We want our rounding towards +infinity. */
181 static inline float
_hb_roundf(float x)182 _hb_roundf (float x) { return floorf (x + .5f); }
183 #define roundf(x) _hb_roundf(x)
184
185
186 /* Encodes three unsigned integers in one 64-bit number. If the inputs have more than 21 bits,
187 * values will be truncated / overlap, and might not decode exactly. */
188 #define HB_CODEPOINT_ENCODE3(x,y,z) (((uint64_t) (x) << 42) | ((uint64_t) (y) << 21) | (uint64_t) (z))
189 #define HB_CODEPOINT_DECODE3_1(v) ((hb_codepoint_t) ((v) >> 42))
190 #define HB_CODEPOINT_DECODE3_2(v) ((hb_codepoint_t) ((v) >> 21) & 0x1FFFFFu)
191 #define HB_CODEPOINT_DECODE3_3(v) ((hb_codepoint_t) (v) & 0x1FFFFFu)
192
193 /* Custom encoding used by hb-ucd. */
194 #define HB_CODEPOINT_ENCODE3_11_7_14(x,y,z) (((uint32_t) ((x) & 0x07FFu) << 21) | (((uint32_t) (y) & 0x007Fu) << 14) | (uint32_t) ((z) & 0x3FFFu))
195 #define HB_CODEPOINT_DECODE3_11_7_14_1(v) ((hb_codepoint_t) ((v) >> 21))
196 #define HB_CODEPOINT_DECODE3_11_7_14_2(v) ((hb_codepoint_t) (((v) >> 14) & 0x007Fu) | 0x0300)
197 #define HB_CODEPOINT_DECODE3_11_7_14_3(v) ((hb_codepoint_t) (v) & 0x3FFFu)
198
199
200 struct
201 {
202 /* Note. This is dangerous in that if it's passed an rvalue, it returns rvalue-reference. */
203 template <typename T> constexpr auto
204 operator () (T&& v) const HB_AUTO_RETURN ( std::forward<T> (v) )
205 }
206 HB_FUNCOBJ (hb_identity);
207 struct
208 {
209 /* Like identity(), but only retains lvalue-references. Rvalues are returned as rvalues. */
210 template <typename T> constexpr T&
operator ()__anondc819c580208211 operator () (T& v) const { return v; }
212
213 template <typename T> constexpr hb_remove_reference<T>
operator ()__anondc819c580208214 operator () (T&& v) const { return v; }
215 }
216 HB_FUNCOBJ (hb_lidentity);
217 struct
218 {
219 /* Like identity(), but always returns rvalue. */
220 template <typename T> constexpr hb_remove_reference<T>
operator ()__anondc819c580308221 operator () (T&& v) const { return v; }
222 }
223 HB_FUNCOBJ (hb_ridentity);
224
225 struct
226 {
227 template <typename T> constexpr bool
operator ()__anondc819c580408228 operator () (T&& v) const { return bool (std::forward<T> (v)); }
229 }
230 HB_FUNCOBJ (hb_bool);
231
232 struct
233 {
234 private:
235
236 template <typename T> constexpr auto
237 impl (const T& v, hb_priority<1>) const HB_RETURN (uint32_t, hb_deref (v).hash ())
238
239 template <typename T> constexpr auto
240 impl (const T& v, hb_priority<0>) const HB_RETURN (uint32_t, std::hash<hb_decay<decltype (hb_deref (v))>>{} (hb_deref (v)))
241
242 public:
243
244 template <typename T> constexpr auto
245 operator () (const T& v) const HB_RETURN (uint32_t, impl (v, hb_prioritize))
246 }
247 HB_FUNCOBJ (hb_hash);
248
249
250 struct
251 {
252 private:
253
254 /* Pointer-to-member-function. */
255 template <typename Appl, typename T, typename ...Ts> auto
256 impl (Appl&& a, hb_priority<2>, T &&v, Ts&&... ds) const HB_AUTO_RETURN
257 ((hb_deref (std::forward<T> (v)).*std::forward<Appl> (a)) (std::forward<Ts> (ds)...))
258
259 /* Pointer-to-member. */
260 template <typename Appl, typename T> auto
261 impl (Appl&& a, hb_priority<1>, T &&v) const HB_AUTO_RETURN
262 ((hb_deref (std::forward<T> (v))).*std::forward<Appl> (a))
263
264 /* Operator(). */
265 template <typename Appl, typename ...Ts> auto
266 impl (Appl&& a, hb_priority<0>, Ts&&... ds) const HB_AUTO_RETURN
267 (hb_deref (std::forward<Appl> (a)) (std::forward<Ts> (ds)...))
268
269 public:
270
271 template <typename Appl, typename ...Ts> auto
272 operator () (Appl&& a, Ts&&... ds) const HB_AUTO_RETURN
273 (
274 impl (std::forward<Appl> (a),
275 hb_prioritize,
276 std::forward<Ts> (ds)...)
277 )
278 }
279 HB_FUNCOBJ (hb_invoke);
280
281 template <unsigned Pos, typename Appl, typename V>
282 struct hb_partial_t
283 {
hb_partial_thb_partial_t284 hb_partial_t (Appl a, V v) : a (a), v (v) {}
285
286 static_assert (Pos > 0, "");
287
288 template <typename ...Ts,
289 unsigned P = Pos,
290 hb_enable_if (P == 1)> auto
operator ()hb_partial_t291 operator () (Ts&& ...ds) -> decltype (hb_invoke (hb_declval (Appl),
292 hb_declval (V),
293 hb_declval (Ts)...))
294 {
295 return hb_invoke (std::forward<Appl> (a),
296 std::forward<V> (v),
297 std::forward<Ts> (ds)...);
298 }
299 template <typename T0, typename ...Ts,
300 unsigned P = Pos,
301 hb_enable_if (P == 2)> auto
operator ()hb_partial_t302 operator () (T0&& d0, Ts&& ...ds) -> decltype (hb_invoke (hb_declval (Appl),
303 hb_declval (T0),
304 hb_declval (V),
305 hb_declval (Ts)...))
306 {
307 return hb_invoke (std::forward<Appl> (a),
308 std::forward<T0> (d0),
309 std::forward<V> (v),
310 std::forward<Ts> (ds)...);
311 }
312
313 private:
314 hb_reference_wrapper<Appl> a;
315 V v;
316 };
317 template <unsigned Pos=1, typename Appl, typename V>
318 auto hb_partial (Appl&& a, V&& v) HB_AUTO_RETURN
319 (( hb_partial_t<Pos, Appl, V> (a, v) ))
320
321 /* The following, HB_PARTIALIZE, macro uses a particular corner-case
322 * of C++11 that is not particularly well-supported by all compilers.
323 * What's happening is that it's using "this" in a trailing return-type
324 * via decltype(). Broken compilers deduce the type of "this" pointer
325 * in that context differently from what it resolves to in the body
326 * of the function.
327 *
328 * One probable cause of this is that at the time of trailing return
329 * type declaration, "this" points to an incomplete type, whereas in
330 * the function body the type is complete. That doesn't justify the
331 * error in any way, but is probably what's happening.
332 *
333 * In the case of MSVC, we get around this by using C++14 "decltype(auto)"
334 * which deduces the type from the actual return statement. For gcc 4.8
335 * we use "+this" instead of "this" which produces an rvalue that seems
336 * to be deduced as the same type with this particular compiler, and seem
337 * to be fine as default code path as well.
338 */
339 #ifdef _MSC_VER
340 /* https://github.com/harfbuzz/harfbuzz/issues/1730 */ \
341 #define HB_PARTIALIZE(Pos) \
342 template <typename _T> \
343 decltype(auto) operator () (_T&& _v) const \
344 { return hb_partial<Pos> (this, std::forward<_T> (_v)); } \
345 static_assert (true, "")
346 #else
347 /* https://github.com/harfbuzz/harfbuzz/issues/1724 */
348 #define HB_PARTIALIZE(Pos) \
349 template <typename _T> \
350 auto operator () (_T&& _v) const HB_AUTO_RETURN \
351 (hb_partial<Pos> (+this, std::forward<_T> (_v))) \
352 static_assert (true, "")
353 #endif
354
355
356 struct
357 {
358 private:
359
360 template <typename Pred, typename Val> auto
361 impl (Pred&& p, Val &&v, hb_priority<1>) const HB_AUTO_RETURN
362 (
363 hb_deref (std::forward<Pred> (p)).has (std::forward<Val> (v))
364 )
365
366 template <typename Pred, typename Val> auto
367 impl (Pred&& p, Val &&v, hb_priority<0>) const HB_AUTO_RETURN
368 (
369 hb_invoke (std::forward<Pred> (p),
370 std::forward<Val> (v))
371 )
372
373 public:
374
375 template <typename Pred, typename Val> auto
376 operator () (Pred&& p, Val &&v) const HB_RETURN (bool,
377 impl (std::forward<Pred> (p),
378 std::forward<Val> (v),
379 hb_prioritize)
380 )
381 }
382 HB_FUNCOBJ (hb_has);
383
384 struct
385 {
386 private:
387
388 template <typename Pred, typename Val> auto
389 impl (Pred&& p, Val &&v, hb_priority<1>) const HB_AUTO_RETURN
390 (
391 hb_has (std::forward<Pred> (p),
392 std::forward<Val> (v))
393 )
394
395 template <typename Pred, typename Val> auto
396 impl (Pred&& p, Val &&v, hb_priority<0>) const HB_AUTO_RETURN
397 (
398 std::forward<Pred> (p) == std::forward<Val> (v)
399 )
400
401 public:
402
403 template <typename Pred, typename Val> auto
404 operator () (Pred&& p, Val &&v) const HB_RETURN (bool,
405 impl (std::forward<Pred> (p),
406 std::forward<Val> (v),
407 hb_prioritize)
408 )
409 }
410 HB_FUNCOBJ (hb_match);
411
412 struct
413 {
414 private:
415
416 template <typename Proj, typename Val> auto
417 impl (Proj&& f, Val &&v, hb_priority<2>) const HB_AUTO_RETURN
418 (
419 hb_deref (std::forward<Proj> (f)).get (std::forward<Val> (v))
420 )
421
422 template <typename Proj, typename Val> auto
423 impl (Proj&& f, Val &&v, hb_priority<1>) const HB_AUTO_RETURN
424 (
425 hb_invoke (std::forward<Proj> (f),
426 std::forward<Val> (v))
427 )
428
429 template <typename Proj, typename Val> auto
430 impl (Proj&& f, Val &&v, hb_priority<0>) const HB_AUTO_RETURN
431 (
432 std::forward<Proj> (f)[std::forward<Val> (v)]
433 )
434
435 public:
436
437 template <typename Proj, typename Val> auto
438 operator () (Proj&& f, Val &&v) const HB_AUTO_RETURN
439 (
440 impl (std::forward<Proj> (f),
441 std::forward<Val> (v),
442 hb_prioritize)
443 )
444 }
445 HB_FUNCOBJ (hb_get);
446
447 struct
448 {
449 private:
450
451 template <typename T1, typename T2> auto
452 impl (T1&& v1, T2 &&v2, hb_priority<3>) const HB_AUTO_RETURN
453 (
454 std::forward<T2> (v2).cmp (std::forward<T1> (v1)) == 0
455 )
456
457 template <typename T1, typename T2> auto
458 impl (T1&& v1, T2 &&v2, hb_priority<2>) const HB_AUTO_RETURN
459 (
460 std::forward<T1> (v1).cmp (std::forward<T2> (v2)) == 0
461 )
462
463 template <typename T1, typename T2> auto
464 impl (T1&& v1, T2 &&v2, hb_priority<1>) const HB_AUTO_RETURN
465 (
466 std::forward<T1> (v1) == std::forward<T2> (v2)
467 )
468
469 template <typename T1, typename T2> auto
470 impl (T1&& v1, T2 &&v2, hb_priority<0>) const HB_AUTO_RETURN
471 (
472 std::forward<T2> (v2) == std::forward<T1> (v1)
473 )
474
475 public:
476
477 template <typename T1, typename T2> auto
478 operator () (T1&& v1, T2 &&v2) const HB_AUTO_RETURN
479 (
480 impl (std::forward<T1> (v1),
481 std::forward<T2> (v2),
482 hb_prioritize)
483 )
484 }
485 HB_FUNCOBJ (hb_equal);
486
487 struct
488 {
489 template <typename T> void
operator ()__anondc819c580b08490 operator () (T& a, T& b) const
491 {
492 using std::swap; // allow ADL
493 swap (a, b);
494 }
495 }
496 HB_FUNCOBJ (hb_swap);
497
498
499 template <typename T1, typename T2>
500 struct hb_pair_t
501 {
502 typedef T1 first_t;
503 typedef T2 second_t;
504 typedef hb_pair_t<T1, T2> pair_t;
505
506 template <typename U1 = T1, typename U2 = T2,
507 hb_enable_if (std::is_default_constructible<U1>::value &&
508 std::is_default_constructible<U2>::value)>
hb_pair_thb_pair_t509 hb_pair_t () : first (), second () {}
hb_pair_thb_pair_t510 hb_pair_t (T1 a, T2 b) : first (std::forward<T1> (a)), second (std::forward<T2> (b)) {}
511
512 template <typename Q1, typename Q2,
513 hb_enable_if (hb_is_convertible (T1, Q1) &&
514 hb_is_convertible (T2, Q2))>
operator hb_pair_t<Q1,Q2>hb_pair_t515 operator hb_pair_t<Q1, Q2> () { return hb_pair_t<Q1, Q2> (first, second); }
516
reversehb_pair_t517 hb_pair_t<T1, T2> reverse () const
518 { return hb_pair_t<T1, T2> (second, first); }
519
operator ==hb_pair_t520 bool operator == (const pair_t& o) const { return first == o.first && second == o.second; }
operator !=hb_pair_t521 bool operator != (const pair_t& o) const { return !(*this == o); }
operator <hb_pair_t522 bool operator < (const pair_t& o) const { return first < o.first || (first == o.first && second < o.second); }
operator >=hb_pair_t523 bool operator >= (const pair_t& o) const { return !(*this < o); }
operator >hb_pair_t524 bool operator > (const pair_t& o) const { return first > o.first || (first == o.first && second > o.second); }
operator <=hb_pair_t525 bool operator <= (const pair_t& o) const { return !(*this > o); }
526
cmphb_pair_t527 static int cmp (const void *pa, const void *pb)
528 {
529 pair_t *a = (pair_t *) pa;
530 pair_t *b = (pair_t *) pb;
531
532 if (a->first < b->first) return -1;
533 if (a->first > b->first) return +1;
534 if (a->second < b->second) return -1;
535 if (a->second > b->second) return +1;
536 return 0;
537 }
538
swap(hb_pair_t & a,hb_pair_t & b)539 friend void swap (hb_pair_t& a, hb_pair_t& b)
540 {
541 hb_swap (a.first, b.first);
542 hb_swap (a.second, b.second);
543 }
544
545
546 T1 first;
547 T2 second;
548 };
549 template <typename T1, typename T2> static inline hb_pair_t<T1, T2>
hb_pair(T1 && a,T2 && b)550 hb_pair (T1&& a, T2&& b) { return hb_pair_t<T1, T2> (a, b); }
551
552 struct
553 {
554 template <typename Pair> constexpr typename Pair::first_t
operator ()__anondc819c580c08555 operator () (const Pair& pair) const { return pair.first; }
556 }
557 HB_FUNCOBJ (hb_first);
558
559 struct
560 {
561 template <typename Pair> constexpr typename Pair::second_t
operator ()__anondc819c580d08562 operator () (const Pair& pair) const { return pair.second; }
563 }
564 HB_FUNCOBJ (hb_second);
565
566 /* Note. In min/max impl, we can use hb_type_identity<T> for second argument.
567 * However, that would silently convert between different-signedness integers.
568 * Instead we accept two different types, such that compiler can err if
569 * comparing integers of different signedness. */
570 struct
571 {
572 template <typename T, typename T2> constexpr auto
573 operator () (T&& a, T2&& b) const HB_AUTO_RETURN
574 (a <= b ? a : b)
575 }
576 HB_FUNCOBJ (hb_min);
577 struct
578 {
579 template <typename T, typename T2> constexpr auto
580 operator () (T&& a, T2&& b) const HB_AUTO_RETURN
581 (a >= b ? a : b)
582 }
583 HB_FUNCOBJ (hb_max);
584 struct
585 {
586 template <typename T, typename T2, typename T3> constexpr auto
587 operator () (T&& x, T2&& min, T3&& max) const HB_AUTO_RETURN
588 (hb_min (hb_max (std::forward<T> (x), std::forward<T2> (min)), std::forward<T3> (max)))
589 }
590 HB_FUNCOBJ (hb_clamp);
591
592 /*
593 * Bithacks.
594 */
595
596 /* Return the number of 1 bits in v. */
597 template <typename T>
598 static inline unsigned int
hb_popcount(T v)599 hb_popcount (T v)
600 {
601 #if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__)
602 if (sizeof (T) <= sizeof (unsigned int))
603 return __builtin_popcount (v);
604
605 if (sizeof (T) <= sizeof (unsigned long))
606 return __builtin_popcountl (v);
607
608 if (sizeof (T) <= sizeof (unsigned long long))
609 return __builtin_popcountll (v);
610 #endif
611
612 if (sizeof (T) <= 4)
613 {
614 /* "HACKMEM 169" */
615 uint32_t y;
616 y = (v >> 1) &033333333333;
617 y = v - y - ((y >>1) & 033333333333);
618 return (((y + (y >> 3)) & 030707070707) % 077);
619 }
620
621 if (sizeof (T) == 8)
622 {
623 unsigned int shift = 32;
624 return hb_popcount<uint32_t> ((uint32_t) v) + hb_popcount ((uint32_t) (v >> shift));
625 }
626
627 if (sizeof (T) == 16)
628 {
629 unsigned int shift = 64;
630 return hb_popcount<uint64_t> ((uint64_t) v) + hb_popcount ((uint64_t) (v >> shift));
631 }
632
633 assert (0);
634 return 0; /* Shut up stupid compiler. */
635 }
636
637 /* Returns the number of bits needed to store number */
638 template <typename T>
639 static inline unsigned int
hb_bit_storage(T v)640 hb_bit_storage (T v)
641 {
642 if (unlikely (!v)) return 0;
643
644 #if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__)
645 if (sizeof (T) <= sizeof (unsigned int))
646 return sizeof (unsigned int) * 8 - __builtin_clz (v);
647
648 if (sizeof (T) <= sizeof (unsigned long))
649 return sizeof (unsigned long) * 8 - __builtin_clzl (v);
650
651 if (sizeof (T) <= sizeof (unsigned long long))
652 return sizeof (unsigned long long) * 8 - __builtin_clzll (v);
653 #endif
654
655 #if (defined(_MSC_VER) && _MSC_VER >= 1500) || (defined(__MINGW32__) && (__GNUC__ < 4))
656 if (sizeof (T) <= sizeof (unsigned int))
657 {
658 unsigned long where;
659 _BitScanReverse (&where, v);
660 return 1 + where;
661 }
662 # if defined(_WIN64)
663 if (sizeof (T) <= 8)
664 {
665 unsigned long where;
666 _BitScanReverse64 (&where, v);
667 return 1 + where;
668 }
669 # endif
670 #endif
671
672 if (sizeof (T) <= 4)
673 {
674 /* "bithacks" */
675 const unsigned int b[] = {0x2, 0xC, 0xF0, 0xFF00, 0xFFFF0000};
676 const unsigned int S[] = {1, 2, 4, 8, 16};
677 unsigned int r = 0;
678 for (int i = 4; i >= 0; i--)
679 if (v & b[i])
680 {
681 v >>= S[i];
682 r |= S[i];
683 }
684 return r + 1;
685 }
686 if (sizeof (T) <= 8)
687 {
688 /* "bithacks" */
689 const uint64_t b[] = {0x2ULL, 0xCULL, 0xF0ULL, 0xFF00ULL, 0xFFFF0000ULL, 0xFFFFFFFF00000000ULL};
690 const unsigned int S[] = {1, 2, 4, 8, 16, 32};
691 unsigned int r = 0;
692 for (int i = 5; i >= 0; i--)
693 if (v & b[i])
694 {
695 v >>= S[i];
696 r |= S[i];
697 }
698 return r + 1;
699 }
700 if (sizeof (T) == 16)
701 {
702 unsigned int shift = 64;
703 return (v >> shift) ? hb_bit_storage<uint64_t> ((uint64_t) (v >> shift)) + shift :
704 hb_bit_storage<uint64_t> ((uint64_t) v);
705 }
706
707 assert (0);
708 return 0; /* Shut up stupid compiler. */
709 }
710
711 /* Returns the number of zero bits in the least significant side of v */
712 template <typename T>
713 static inline unsigned int
hb_ctz(T v)714 hb_ctz (T v)
715 {
716 if (unlikely (!v)) return 8 * sizeof (T);
717
718 #if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__)
719 if (sizeof (T) <= sizeof (unsigned int))
720 return __builtin_ctz (v);
721
722 if (sizeof (T) <= sizeof (unsigned long))
723 return __builtin_ctzl (v);
724
725 if (sizeof (T) <= sizeof (unsigned long long))
726 return __builtin_ctzll (v);
727 #endif
728
729 #if (defined(_MSC_VER) && _MSC_VER >= 1500) || (defined(__MINGW32__) && (__GNUC__ < 4))
730 if (sizeof (T) <= sizeof (unsigned int))
731 {
732 unsigned long where;
733 _BitScanForward (&where, v);
734 return where;
735 }
736 # if defined(_WIN64)
737 if (sizeof (T) <= 8)
738 {
739 unsigned long where;
740 _BitScanForward64 (&where, v);
741 return where;
742 }
743 # endif
744 #endif
745
746 if (sizeof (T) <= 4)
747 {
748 /* "bithacks" */
749 unsigned int c = 32;
750 v &= - (int32_t) v;
751 if (v) c--;
752 if (v & 0x0000FFFF) c -= 16;
753 if (v & 0x00FF00FF) c -= 8;
754 if (v & 0x0F0F0F0F) c -= 4;
755 if (v & 0x33333333) c -= 2;
756 if (v & 0x55555555) c -= 1;
757 return c;
758 }
759 if (sizeof (T) <= 8)
760 {
761 /* "bithacks" */
762 unsigned int c = 64;
763 v &= - (int64_t) (v);
764 if (v) c--;
765 if (v & 0x00000000FFFFFFFFULL) c -= 32;
766 if (v & 0x0000FFFF0000FFFFULL) c -= 16;
767 if (v & 0x00FF00FF00FF00FFULL) c -= 8;
768 if (v & 0x0F0F0F0F0F0F0F0FULL) c -= 4;
769 if (v & 0x3333333333333333ULL) c -= 2;
770 if (v & 0x5555555555555555ULL) c -= 1;
771 return c;
772 }
773 if (sizeof (T) == 16)
774 {
775 unsigned int shift = 64;
776 return (uint64_t) v ? hb_bit_storage<uint64_t> ((uint64_t) v) :
777 hb_bit_storage<uint64_t> ((uint64_t) (v >> shift)) + shift;
778 }
779
780 assert (0);
781 return 0; /* Shut up stupid compiler. */
782 }
783
784
785 /*
786 * Tiny stuff.
787 */
788
789 /* ASCII tag/character handling */
ISALPHA(unsigned char c)790 static inline bool ISALPHA (unsigned char c)
791 { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); }
ISALNUM(unsigned char c)792 static inline bool ISALNUM (unsigned char c)
793 { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'); }
ISSPACE(unsigned char c)794 static inline bool ISSPACE (unsigned char c)
795 { return c == ' ' || c =='\f'|| c =='\n'|| c =='\r'|| c =='\t'|| c =='\v'; }
TOUPPER(unsigned char c)796 static inline unsigned char TOUPPER (unsigned char c)
797 { return (c >= 'a' && c <= 'z') ? c - 'a' + 'A' : c; }
TOLOWER(unsigned char c)798 static inline unsigned char TOLOWER (unsigned char c)
799 { return (c >= 'A' && c <= 'Z') ? c - 'A' + 'a' : c; }
ISHEX(unsigned char c)800 static inline bool ISHEX (unsigned char c)
801 { return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'); }
TOHEX(uint8_t c)802 static inline unsigned char TOHEX (uint8_t c)
803 { return (c & 0xF) <= 9 ? (c & 0xF) + '0' : (c & 0xF) + 'a' - 10; }
FROMHEX(unsigned char c)804 static inline uint8_t FROMHEX (unsigned char c)
805 { return (c >= '0' && c <= '9') ? c - '0' : TOLOWER (c) - 'a' + 10; }
806
DIV_CEIL(const unsigned int a,unsigned int b)807 static inline unsigned int DIV_CEIL (const unsigned int a, unsigned int b)
808 { return (a + (b - 1)) / b; }
809
810
811 #undef ARRAY_LENGTH
812 template <typename Type, unsigned int n>
ARRAY_LENGTH(const Type (&)[n])813 static inline unsigned int ARRAY_LENGTH (const Type (&)[n]) { return n; }
814 /* A const version, but does not detect erratically being called on pointers. */
815 #define ARRAY_LENGTH_CONST(__array) ((signed int) (sizeof (__array) / sizeof (__array[0])))
816
817
818 static inline void *
hb_memcpy(void * __restrict dst,const void * __restrict src,size_t len)819 hb_memcpy (void *__restrict dst, const void *__restrict src, size_t len)
820 {
821 /* It's illegal to pass 0 as size to memcpy. */
822 if (unlikely (!len)) return dst;
823 return memcpy (dst, src, len);
824 }
825
826 static inline int
hb_memcmp(const void * a,const void * b,unsigned int len)827 hb_memcmp (const void *a, const void *b, unsigned int len)
828 {
829 /* It's illegal to pass NULL to memcmp(), even if len is zero.
830 * So, wrap it.
831 * https://sourceware.org/bugzilla/show_bug.cgi?id=23878 */
832 if (unlikely (!len)) return 0;
833 return memcmp (a, b, len);
834 }
835
836 static inline void *
hb_memset(void * s,int c,unsigned int n)837 hb_memset (void *s, int c, unsigned int n)
838 {
839 /* It's illegal to pass NULL to memset(), even if n is zero. */
840 if (unlikely (!n)) return 0;
841 return memset (s, c, n);
842 }
843
844 static inline unsigned int
hb_ceil_to_4(unsigned int v)845 hb_ceil_to_4 (unsigned int v)
846 {
847 return ((v - 1) | 3) + 1;
848 }
849
850 template <typename T> static inline bool
hb_in_range(T u,T lo,T hi)851 hb_in_range (T u, T lo, T hi)
852 {
853 static_assert (!std::is_signed<T>::value, "");
854
855 /* The casts below are important as if T is smaller than int,
856 * the subtract results will become a signed int! */
857 return (T)(u - lo) <= (T)(hi - lo);
858 }
859 template <typename T> static inline bool
hb_in_ranges(T u,T lo1,T hi1)860 hb_in_ranges (T u, T lo1, T hi1)
861 {
862 return hb_in_range (u, lo1, hi1);
863 }
864 template <typename T, typename ...Ts> static inline bool
hb_in_ranges(T u,T lo1,T hi1,Ts...ds)865 hb_in_ranges (T u, T lo1, T hi1, Ts... ds)
866 {
867 return hb_in_range<T> (u, lo1, hi1) || hb_in_ranges<T> (u, ds...);
868 }
869
870
871 /*
872 * Overflow checking.
873 */
874
875 static inline bool
hb_unsigned_mul_overflows(unsigned int count,unsigned int size,unsigned * result=nullptr)876 hb_unsigned_mul_overflows (unsigned int count, unsigned int size, unsigned *result = nullptr)
877 {
878 #if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__)
879 unsigned stack_result;
880 if (!result)
881 result = &stack_result;
882 return __builtin_mul_overflow (count, size, result);
883 #endif
884
885 if (result)
886 *result = count * size;
887 return (size > 0) && (count >= ((unsigned int) -1) / size);
888 }
889
890
891 /*
892 * Sort and search.
893 */
894
895 template <typename K, typename V, typename ...Ts>
896 static int
_hb_cmp_method(const void * pkey,const void * pval,Ts...ds)897 _hb_cmp_method (const void *pkey, const void *pval, Ts... ds)
898 {
899 const K& key = * (const K*) pkey;
900 const V& val = * (const V*) pval;
901
902 return val.cmp (key, ds...);
903 }
904
905 template <typename V, typename K, typename ...Ts>
906 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)907 hb_bsearch_impl (unsigned *pos, /* Out */
908 const K& key,
909 V* base, size_t nmemb, size_t stride,
910 int (*compar)(const void *_key, const void *_item, Ts... _ds),
911 Ts... ds)
912 {
913 /* This is our *only* bsearch implementation. */
914
915 int min = 0, max = (int) nmemb - 1;
916 while (min <= max)
917 {
918 int mid = ((unsigned int) min + (unsigned int) max) / 2;
919 #pragma GCC diagnostic push
920 #pragma GCC diagnostic ignored "-Wcast-align"
921 V* p = (V*) (((const char *) base) + (mid * stride));
922 #pragma GCC diagnostic pop
923 int c = compar ((const void *) std::addressof (key), (const void *) p, ds...);
924 if (c < 0)
925 max = mid - 1;
926 else if (c > 0)
927 min = mid + 1;
928 else
929 {
930 *pos = mid;
931 return true;
932 }
933 }
934 *pos = min;
935 return false;
936 }
937
938 template <typename V, typename K>
939 static inline V*
940 hb_bsearch (const K& key, V* base,
941 size_t nmemb, size_t stride = sizeof (V),
942 int (*compar)(const void *_key, const void *_item) = _hb_cmp_method<K, V>)
943 {
944 unsigned pos;
945 #pragma GCC diagnostic push
946 #pragma GCC diagnostic ignored "-Wcast-align"
947 return hb_bsearch_impl (&pos, key, base, nmemb, stride, compar) ?
948 (V*) (((const char *) base) + (pos * stride)) : nullptr;
949 #pragma GCC diagnostic pop
950 }
951 template <typename V, typename K, typename ...Ts>
952 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)953 hb_bsearch (const K& key, V* base,
954 size_t nmemb, size_t stride,
955 int (*compar)(const void *_key, const void *_item, Ts... _ds),
956 Ts... ds)
957 {
958 unsigned pos;
959 #pragma GCC diagnostic push
960 #pragma GCC diagnostic ignored "-Wcast-align"
961 return hb_bsearch_impl (&pos, key, base, nmemb, stride, compar, ds...) ?
962 (V*) (((const char *) base) + (pos * stride)) : nullptr;
963 #pragma GCC diagnostic pop
964 }
965
966
967 /* From https://github.com/noporpoise/sort_r
968 Feb 5, 2019 (c8c65c1e)
969 Modified to support optional argument using templates */
970
971 /* Isaac Turner 29 April 2014 Public Domain */
972
973 /*
974 hb_qsort function to be exported.
975 Parameters:
976 base is the array to be sorted
977 nel is the number of elements in the array
978 width is the size in bytes of each element of the array
979 compar is the comparison function
980 arg (optional) is a pointer to be passed to the comparison function
981
982 void hb_qsort(void *base, size_t nel, size_t width,
983 int (*compar)(const void *_a, const void *_b, [void *_arg]),
984 [void *arg]);
985 */
986
987 #define SORT_R_SWAP(a,b,tmp) ((void) ((tmp) = (a)), (void) ((a) = (b)), (b) = (tmp))
988
989 /* swap a and b */
990 /* a and b must not be equal! */
sort_r_swap(char * __restrict a,char * __restrict b,size_t w)991 static inline void sort_r_swap(char *__restrict a, char *__restrict b,
992 size_t w)
993 {
994 char tmp, *end = a+w;
995 for(; a < end; a++, b++) { SORT_R_SWAP(*a, *b, tmp); }
996 }
997
998 /* swap a, b iff a>b */
999 /* a and b must not be equal! */
1000 /* __restrict is same as restrict but better support on old machines */
1001 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)1002 static inline int sort_r_cmpswap(char *__restrict a,
1003 char *__restrict b, size_t w,
1004 int (*compar)(const void *_a,
1005 const void *_b,
1006 Ts... _ds),
1007 Ts... ds)
1008 {
1009 if(compar(a, b, ds...) > 0) {
1010 sort_r_swap(a, b, w);
1011 return 1;
1012 }
1013 return 0;
1014 }
1015
1016 /*
1017 Swap consecutive blocks of bytes of size na and nb starting at memory addr ptr,
1018 with the smallest swap so that the blocks are in the opposite order. Blocks may
1019 be internally re-ordered e.g.
1020 12345ab -> ab34512
1021 123abc -> abc123
1022 12abcde -> deabc12
1023 */
sort_r_swap_blocks(char * ptr,size_t na,size_t nb)1024 static inline void sort_r_swap_blocks(char *ptr, size_t na, size_t nb)
1025 {
1026 if(na > 0 && nb > 0) {
1027 if(na > nb) { sort_r_swap(ptr, ptr+na, nb); }
1028 else { sort_r_swap(ptr, ptr+nb, na); }
1029 }
1030 }
1031
1032 /* Implement recursive quicksort ourselves */
1033 /* Note: quicksort is not stable, equivalent values may be swapped */
1034 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)1035 static inline void sort_r_simple(void *base, size_t nel, size_t w,
1036 int (*compar)(const void *_a,
1037 const void *_b,
1038 Ts... _ds),
1039 Ts... ds)
1040 {
1041 char *b = (char *)base, *end = b + nel*w;
1042
1043 /* for(size_t i=0; i<nel; i++) {printf("%4i", *(int*)(b + i*sizeof(int)));}
1044 printf("\n"); */
1045
1046 if(nel < 10) {
1047 /* Insertion sort for arbitrarily small inputs */
1048 char *pi, *pj;
1049 for(pi = b+w; pi < end; pi += w) {
1050 for(pj = pi; pj > b && sort_r_cmpswap(pj-w,pj,w,compar,ds...); pj -= w) {}
1051 }
1052 }
1053 else
1054 {
1055 /* nel > 9; Quicksort */
1056
1057 int cmp;
1058 char *pl, *ple, *pr, *pre, *pivot;
1059 char *last = b+w*(nel-1), *tmp;
1060
1061 /*
1062 Use median of second, middle and second-last items as pivot.
1063 First and last may have been swapped with pivot and therefore be extreme
1064 */
1065 char *l[3];
1066 l[0] = b + w;
1067 l[1] = b+w*(nel/2);
1068 l[2] = last - w;
1069
1070 /* printf("pivots: %i, %i, %i\n", *(int*)l[0], *(int*)l[1], *(int*)l[2]); */
1071
1072 if(compar(l[0],l[1],ds...) > 0) { SORT_R_SWAP(l[0], l[1], tmp); }
1073 if(compar(l[1],l[2],ds...) > 0) {
1074 SORT_R_SWAP(l[1], l[2], tmp);
1075 if(compar(l[0],l[1],ds...) > 0) { SORT_R_SWAP(l[0], l[1], tmp); }
1076 }
1077
1078 /* swap mid value (l[1]), and last element to put pivot as last element */
1079 if(l[1] != last) { sort_r_swap(l[1], last, w); }
1080
1081 /*
1082 pl is the next item on the left to be compared to the pivot
1083 pr is the last item on the right that was compared to the pivot
1084 ple is the left position to put the next item that equals the pivot
1085 ple is the last right position where we put an item that equals the pivot
1086 v- end (beyond the array)
1087 EEEEEELLLLLLLLuuuuuuuuGGGGGGGEEEEEEEE.
1088 ^- b ^- ple ^- pl ^- pr ^- pre ^- last (where the pivot is)
1089 Pivot comparison key:
1090 E = equal, L = less than, u = unknown, G = greater than, E = equal
1091 */
1092 pivot = last;
1093 ple = pl = b;
1094 pre = pr = last;
1095
1096 /*
1097 Strategy:
1098 Loop into the list from the left and right at the same time to find:
1099 - an item on the left that is greater than the pivot
1100 - an item on the right that is less than the pivot
1101 Once found, they are swapped and the loop continues.
1102 Meanwhile items that are equal to the pivot are moved to the edges of the
1103 array.
1104 */
1105 while(pl < pr) {
1106 /* Move left hand items which are equal to the pivot to the far left.
1107 break when we find an item that is greater than the pivot */
1108 for(; pl < pr; pl += w) {
1109 cmp = compar(pl, pivot, ds...);
1110 if(cmp > 0) { break; }
1111 else if(cmp == 0) {
1112 if(ple < pl) { sort_r_swap(ple, pl, w); }
1113 ple += w;
1114 }
1115 }
1116 /* break if last batch of left hand items were equal to pivot */
1117 if(pl >= pr) { break; }
1118 /* Move right hand items which are equal to the pivot to the far right.
1119 break when we find an item that is less than the pivot */
1120 for(; pl < pr; ) {
1121 pr -= w; /* Move right pointer onto an unprocessed item */
1122 cmp = compar(pr, pivot, ds...);
1123 if(cmp == 0) {
1124 pre -= w;
1125 if(pr < pre) { sort_r_swap(pr, pre, w); }
1126 }
1127 else if(cmp < 0) {
1128 if(pl < pr) { sort_r_swap(pl, pr, w); }
1129 pl += w;
1130 break;
1131 }
1132 }
1133 }
1134
1135 pl = pr; /* pr may have gone below pl */
1136
1137 /*
1138 Now we need to go from: EEELLLGGGGEEEE
1139 to: LLLEEEEEEEGGGG
1140 Pivot comparison key:
1141 E = equal, L = less than, u = unknown, G = greater than, E = equal
1142 */
1143 sort_r_swap_blocks(b, ple-b, pl-ple);
1144 sort_r_swap_blocks(pr, pre-pr, end-pre);
1145
1146 /*for(size_t i=0; i<nel; i++) {printf("%4i", *(int*)(b + i*sizeof(int)));}
1147 printf("\n");*/
1148
1149 sort_r_simple(b, (pl-ple)/w, w, compar, ds...);
1150 sort_r_simple(end-(pre-pr), (pre-pr)/w, w, compar, ds...);
1151 }
1152 }
1153
1154 static inline void
hb_qsort(void * base,size_t nel,size_t width,int (* compar)(const void * _a,const void * _b))1155 hb_qsort (void *base, size_t nel, size_t width,
1156 int (*compar)(const void *_a, const void *_b))
1157 {
1158 #if defined(__OPTIMIZE_SIZE__) && !defined(HB_USE_INTERNAL_QSORT)
1159 qsort (base, nel, width, compar);
1160 #else
1161 sort_r_simple (base, nel, width, compar);
1162 #endif
1163 }
1164
1165 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)1166 hb_qsort (void *base, size_t nel, size_t width,
1167 int (*compar)(const void *_a, const void *_b, void *_arg),
1168 void *arg)
1169 {
1170 #ifdef HAVE_GNU_QSORT_R
1171 qsort_r (base, nel, width, compar, arg);
1172 #else
1173 sort_r_simple (base, nel, width, compar, arg);
1174 #endif
1175 }
1176
1177
1178 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)1179 hb_stable_sort (T *array, unsigned int len, int(*compar)(const T2 *, const T2 *), T3 *array2 = nullptr)
1180 {
1181 static_assert (hb_is_trivially_copy_assignable (T), "");
1182 static_assert (hb_is_trivially_copy_assignable (T3), "");
1183
1184 for (unsigned int i = 1; i < len; i++)
1185 {
1186 unsigned int j = i;
1187 while (j && compar (&array[j - 1], &array[i]) > 0)
1188 j--;
1189 if (i == j)
1190 continue;
1191 /* Move item i to occupy place for item j, shift what's in between. */
1192 {
1193 T t = array[i];
1194 memmove (&array[j + 1], &array[j], (i - j) * sizeof (T));
1195 array[j] = t;
1196 }
1197 if (array2)
1198 {
1199 T3 t = array2[i];
1200 memmove (&array2[j + 1], &array2[j], (i - j) * sizeof (T3));
1201 array2[j] = t;
1202 }
1203 }
1204 }
1205
1206 static inline hb_bool_t
hb_codepoint_parse(const char * s,unsigned int len,int base,hb_codepoint_t * out)1207 hb_codepoint_parse (const char *s, unsigned int len, int base, hb_codepoint_t *out)
1208 {
1209 unsigned int v;
1210 const char *p = s;
1211 const char *end = p + len;
1212 if (unlikely (!hb_parse_uint (&p, end, &v, true/* whole buffer */, base)))
1213 return false;
1214
1215 *out = v;
1216 return true;
1217 }
1218
1219
1220 /* Operators. */
1221
1222 struct
1223 { HB_PARTIALIZE(2);
1224 template <typename T> constexpr auto
1225 operator () (const T &a, const T &b) const HB_AUTO_RETURN (a & b)
1226 }
1227 HB_FUNCOBJ (hb_bitwise_and);
1228 struct
1229 { HB_PARTIALIZE(2);
1230 template <typename T> constexpr auto
1231 operator () (const T &a, const T &b) const HB_AUTO_RETURN (a | b)
1232 }
1233 HB_FUNCOBJ (hb_bitwise_or);
1234 struct
1235 { HB_PARTIALIZE(2);
1236 template <typename T> constexpr auto
1237 operator () (const T &a, const T &b) const HB_AUTO_RETURN (a ^ b)
1238 }
1239 HB_FUNCOBJ (hb_bitwise_xor);
1240 struct
1241 { HB_PARTIALIZE(2);
1242 template <typename T> constexpr auto
1243 operator () (const T &a, const T &b) const HB_AUTO_RETURN (~a & b)
1244 }
1245 HB_FUNCOBJ (hb_bitwise_lt);
1246 struct
1247 { HB_PARTIALIZE(2);
1248 template <typename T> constexpr auto
1249 operator () (const T &a, const T &b) const HB_AUTO_RETURN (a & ~b)
1250 }
1251 HB_FUNCOBJ (hb_bitwise_gt); // aka sub
1252 struct
1253 { HB_PARTIALIZE(2);
1254 template <typename T> constexpr auto
1255 operator () (const T &a, const T &b) const HB_AUTO_RETURN (~a | b)
1256 }
1257 HB_FUNCOBJ (hb_bitwise_le);
1258 struct
1259 { HB_PARTIALIZE(2);
1260 template <typename T> constexpr auto
1261 operator () (const T &a, const T &b) const HB_AUTO_RETURN (a | ~b)
1262 }
1263 HB_FUNCOBJ (hb_bitwise_ge);
1264 struct
1265 {
1266 template <typename T> constexpr auto
1267 operator () (const T &a) const HB_AUTO_RETURN (~a)
1268 }
1269 HB_FUNCOBJ (hb_bitwise_neg);
1270
1271 struct
1272 { HB_PARTIALIZE(2);
1273 template <typename T, typename T2> constexpr auto
1274 operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (a + b)
1275 }
1276 HB_FUNCOBJ (hb_add);
1277 struct
1278 { HB_PARTIALIZE(2);
1279 template <typename T, typename T2> constexpr auto
1280 operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (a - b)
1281 }
1282 HB_FUNCOBJ (hb_sub);
1283 struct
1284 { HB_PARTIALIZE(2);
1285 template <typename T, typename T2> constexpr auto
1286 operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (b - a)
1287 }
1288 HB_FUNCOBJ (hb_rsub);
1289 struct
1290 { HB_PARTIALIZE(2);
1291 template <typename T, typename T2> constexpr auto
1292 operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (a * b)
1293 }
1294 HB_FUNCOBJ (hb_mul);
1295 struct
1296 { HB_PARTIALIZE(2);
1297 template <typename T, typename T2> constexpr auto
1298 operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (a / b)
1299 }
1300 HB_FUNCOBJ (hb_div);
1301 struct
1302 { HB_PARTIALIZE(2);
1303 template <typename T, typename T2> constexpr auto
1304 operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (a % b)
1305 }
1306 HB_FUNCOBJ (hb_mod);
1307 struct
1308 {
1309 template <typename T> constexpr auto
1310 operator () (const T &a) const HB_AUTO_RETURN (+a)
1311 }
1312 HB_FUNCOBJ (hb_pos);
1313 struct
1314 {
1315 template <typename T> constexpr auto
1316 operator () (const T &a) const HB_AUTO_RETURN (-a)
1317 }
1318 HB_FUNCOBJ (hb_neg);
1319 struct
1320 {
1321 template <typename T> constexpr auto
1322 operator () (T &a) const HB_AUTO_RETURN (++a)
1323 }
1324 HB_FUNCOBJ (hb_inc);
1325 struct
1326 {
1327 template <typename T> constexpr auto
1328 operator () (T &a) const HB_AUTO_RETURN (--a)
1329 }
1330 HB_FUNCOBJ (hb_dec);
1331
1332
1333 #endif /* HB_ALGS_HH */
1334