• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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