cb3057c54cdb986fbfbc75b686b035d2d7df77da
[platform/upstream/harfbuzz.git] / src / hb-dsalgs.hh
1 /*
2  * Copyright © 2017  Google, Inc.
3  *
4  *  This is part of HarfBuzz, a text shaping library.
5  *
6  * Permission is hereby granted, without written agreement and without
7  * license or royalty fees, to use, copy, modify, and distribute this
8  * software and its documentation for any purpose, provided that the
9  * above copyright notice and the following two paragraphs appear in
10  * all copies of this software.
11  *
12  * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
13  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
14  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
15  * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
16  * DAMAGE.
17  *
18  * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
19  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
21  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
22  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
23  *
24  * Google Author(s): Behdad Esfahbod
25  */
26
27 #ifndef HB_DSALGS_HH
28 #define HB_DSALGS_HH
29
30 #include "hb.hh"
31 #include "hb-null.hh"
32
33
34 /* Void! For when we need a expression-type of void. */
35 typedef const struct _hb_void_t *hb_void_t;
36 #define HB_VOID ((const _hb_void_t *) nullptr)
37
38
39 /*
40  * Bithacks.
41  */
42
43 /* Return the number of 1 bits in v. */
44 template <typename T>
45 static inline HB_CONST_FUNC unsigned int
46 hb_popcount (T v)
47 {
48 #if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__)
49   if (sizeof (T) <= sizeof (unsigned int))
50     return __builtin_popcount (v);
51
52   if (sizeof (T) <= sizeof (unsigned long))
53     return __builtin_popcountl (v);
54
55   if (sizeof (T) <= sizeof (unsigned long long))
56     return __builtin_popcountll (v);
57 #endif
58
59   if (sizeof (T) <= 4)
60   {
61     /* "HACKMEM 169" */
62     uint32_t y;
63     y = (v >> 1) &033333333333;
64     y = v - y - ((y >>1) & 033333333333);
65     return (((y + (y >> 3)) & 030707070707) % 077);
66   }
67
68   if (sizeof (T) == 8)
69   {
70     unsigned int shift = 32;
71     return hb_popcount<uint32_t> ((uint32_t) v) + hb_popcount ((uint32_t) (v >> shift));
72   }
73
74   if (sizeof (T) == 16)
75   {
76     unsigned int shift = 64;
77     return hb_popcount<uint64_t> ((uint64_t) v) + hb_popcount ((uint64_t) (v >> shift));
78   }
79
80   assert (0);
81   return 0; /* Shut up stupid compiler. */
82 }
83
84 /* Returns the number of bits needed to store number */
85 template <typename T>
86 static inline HB_CONST_FUNC unsigned int
87 hb_bit_storage (T v)
88 {
89   if (unlikely (!v)) return 0;
90
91 #if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__)
92   if (sizeof (T) <= sizeof (unsigned int))
93     return sizeof (unsigned int) * 8 - __builtin_clz (v);
94
95   if (sizeof (T) <= sizeof (unsigned long))
96     return sizeof (unsigned long) * 8 - __builtin_clzl (v);
97
98   if (sizeof (T) <= sizeof (unsigned long long))
99     return sizeof (unsigned long long) * 8 - __builtin_clzll (v);
100 #endif
101
102 #if (defined(_MSC_VER) && _MSC_VER >= 1500) || defined(__MINGW32__)
103   if (sizeof (T) <= sizeof (unsigned int))
104   {
105     unsigned long where;
106     _BitScanReverse (&where, v);
107     return 1 + where;
108   }
109 # if defined(_WIN64)
110   if (sizeof (T) <= 8)
111   {
112     unsigned long where;
113     _BitScanReverse64 (&where, v);
114     return 1 + where;
115   }
116 # endif
117 #endif
118
119   if (sizeof (T) <= 4)
120   {
121     /* "bithacks" */
122     const unsigned int b[] = {0x2, 0xC, 0xF0, 0xFF00, 0xFFFF0000};
123     const unsigned int S[] = {1, 2, 4, 8, 16};
124     unsigned int r = 0;
125     for (int i = 4; i >= 0; i--)
126       if (v & b[i])
127       {
128         v >>= S[i];
129         r |= S[i];
130       }
131     return r + 1;
132   }
133   if (sizeof (T) <= 8)
134   {
135     /* "bithacks" */
136     const uint64_t b[] = {0x2ULL, 0xCULL, 0xF0ULL, 0xFF00ULL, 0xFFFF0000ULL, 0xFFFFFFFF00000000ULL};
137     const unsigned int S[] = {1, 2, 4, 8, 16, 32};
138     unsigned int r = 0;
139     for (int i = 5; i >= 0; i--)
140       if (v & b[i])
141       {
142         v >>= S[i];
143         r |= S[i];
144       }
145     return r + 1;
146   }
147   if (sizeof (T) == 16)
148   {
149     unsigned int shift = 64;
150     return (v >> shift) ? hb_bit_storage<uint64_t> ((uint64_t) (v >> shift)) + shift :
151                           hb_bit_storage<uint64_t> ((uint64_t) v);
152   }
153
154   assert (0);
155   return 0; /* Shut up stupid compiler. */
156 }
157
158 /* Returns the number of zero bits in the least significant side of v */
159 template <typename T>
160 static inline HB_CONST_FUNC unsigned int
161 hb_ctz (T v)
162 {
163   if (unlikely (!v)) return 0;
164
165 #if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__)
166   if (sizeof (T) <= sizeof (unsigned int))
167     return __builtin_ctz (v);
168
169   if (sizeof (T) <= sizeof (unsigned long))
170     return __builtin_ctzl (v);
171
172   if (sizeof (T) <= sizeof (unsigned long long))
173     return __builtin_ctzll (v);
174 #endif
175
176 #if (defined(_MSC_VER) && _MSC_VER >= 1500) || defined(__MINGW32__)
177   if (sizeof (T) <= sizeof (unsigned int))
178   {
179     unsigned long where;
180     _BitScanForward (&where, v);
181     return where;
182   }
183 # if defined(_WIN64)
184   if (sizeof (T) <= 8)
185   {
186     unsigned long where;
187     _BitScanForward64 (&where, v);
188     return where;
189   }
190 # endif
191 #endif
192
193   if (sizeof (T) <= 4)
194   {
195     /* "bithacks" */
196     unsigned int c = 32;
197     v &= - (int32_t) v;
198     if (v) c--;
199     if (v & 0x0000FFFF) c -= 16;
200     if (v & 0x00FF00FF) c -= 8;
201     if (v & 0x0F0F0F0F) c -= 4;
202     if (v & 0x33333333) c -= 2;
203     if (v & 0x55555555) c -= 1;
204     return c;
205   }
206   if (sizeof (T) <= 8)
207   {
208     /* "bithacks" */
209     unsigned int c = 64;
210     v &= - (int64_t) (v);
211     if (v) c--;
212     if (v & 0x00000000FFFFFFFFULL) c -= 32;
213     if (v & 0x0000FFFF0000FFFFULL) c -= 16;
214     if (v & 0x00FF00FF00FF00FFULL) c -= 8;
215     if (v & 0x0F0F0F0F0F0F0F0FULL) c -= 4;
216     if (v & 0x3333333333333333ULL) c -= 2;
217     if (v & 0x5555555555555555ULL) c -= 1;
218     return c;
219   }
220   if (sizeof (T) == 16)
221   {
222     unsigned int shift = 64;
223     return (uint64_t) v ? hb_bit_storage<uint64_t> ((uint64_t) v) :
224                           hb_bit_storage<uint64_t> ((uint64_t) (v >> shift)) + shift;
225   }
226
227   assert (0);
228   return 0; /* Shut up stupid compiler. */
229 }
230
231
232 /*
233  * Tiny stuff.
234  */
235
236 template <typename T>
237 static inline T* hb_addressof (T& arg)
238 {
239 #pragma GCC diagnostic push
240 #pragma GCC diagnostic ignored "-Wcast-align"
241   /* https://en.cppreference.com/w/cpp/memory/addressof */
242   return reinterpret_cast<T*>(
243            &const_cast<char&>(
244               reinterpret_cast<const volatile char&>(arg)));
245 #pragma GCC diagnostic pop
246 }
247
248 /* ASCII tag/character handling */
249 static inline bool ISALPHA (unsigned char c)
250 { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); }
251 static inline bool ISALNUM (unsigned char c)
252 { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'); }
253 static inline bool ISSPACE (unsigned char c)
254 { return c == ' ' || c =='\f'|| c =='\n'|| c =='\r'|| c =='\t'|| c =='\v'; }
255 static inline unsigned char TOUPPER (unsigned char c)
256 { return (c >= 'a' && c <= 'z') ? c - 'a' + 'A' : c; }
257 static inline unsigned char TOLOWER (unsigned char c)
258 { return (c >= 'A' && c <= 'Z') ? c - 'A' + 'a' : c; }
259
260 #undef MIN
261 template <typename Type>
262 static inline Type MIN (const Type &a, const Type &b) { return a < b ? a : b; }
263
264 #undef MAX
265 template <typename Type>
266 static inline Type MAX (const Type &a, const Type &b) { return a > b ? a : b; }
267
268 static inline unsigned int DIV_CEIL (const unsigned int a, unsigned int b)
269 { return (a + (b - 1)) / b; }
270
271
272 #undef  ARRAY_LENGTH
273 template <typename Type, unsigned int n>
274 static inline unsigned int ARRAY_LENGTH (const Type (&)[n]) { return n; }
275 /* A const version, but does not detect erratically being called on pointers. */
276 #define ARRAY_LENGTH_CONST(__array) ((signed int) (sizeof (__array) / sizeof (__array[0])))
277
278
279 static inline int
280 hb_memcmp (const void *a, const void *b, unsigned int len)
281 {
282   /* It's illegal to pass NULL to memcmp(), even if len is zero.
283    * So, wrap it.
284    * https://sourceware.org/bugzilla/show_bug.cgi?id=23878 */
285   if (!len) return 0;
286   return memcmp (a, b, len);
287 }
288
289 static inline bool
290 hb_unsigned_mul_overflows (unsigned int count, unsigned int size)
291 {
292   return (size > 0) && (count >= ((unsigned int) -1) / size);
293 }
294
295 static inline unsigned int
296 hb_ceil_to_4 (unsigned int v)
297 {
298   return ((v - 1) | 3) + 1;
299 }
300
301 template <typename T> struct hb_is_signed;
302 template <> struct hb_is_signed<signed char> { enum { value = true }; };
303 template <> struct hb_is_signed<signed short> { enum { value = true }; };
304 template <> struct hb_is_signed<signed int> { enum { value = true }; };
305 template <> struct hb_is_signed<signed long> { enum { value = true }; };
306 template <> struct hb_is_signed<unsigned char> { enum { value = false }; };
307 template <> struct hb_is_signed<unsigned short> { enum { value = false }; };
308 template <> struct hb_is_signed<unsigned int> { enum { value = false }; };
309 template <> struct hb_is_signed<unsigned long> { enum { value = false }; };
310 /* We need to define hb_is_signed for the typedefs we use on pre-Visual
311  * Studio 2010 for the int8_t type, since __int8/__int64 is not considered
312  * the same as char/long.  The previous lines will suffice for the other
313  * types, though.  Note that somehow, unsigned __int8 is considered same
314  * as unsigned char.
315  * https://github.com/harfbuzz/harfbuzz/pull/1499
316  */
317 #if defined(_MSC_VER) && (_MSC_VER < 1600)
318 template <> struct hb_is_signed<__int8> { enum { value = true }; };
319 #endif
320
321 template <typename T> static inline bool
322 hb_in_range (T u, T lo, T hi)
323 {
324   /* The sizeof() is here to force template instantiation.
325    * I'm sure there are better ways to do this but can't think of
326    * one right now.  Declaring a variable won't work as HB_UNUSED
327    * is unusable on some platforms and unused types are less likely
328    * to generate a warning than unused variables. */
329   static_assert (!hb_is_signed<T>::value, "");
330
331   /* The casts below are important as if T is smaller than int,
332    * the subtract results will become a signed int! */
333   return (T)(u - lo) <= (T)(hi - lo);
334 }
335 template <typename T> static inline bool
336 hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2)
337 {
338   return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2);
339 }
340 template <typename T> static inline bool
341 hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3)
342 {
343   return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2) || hb_in_range (u, lo3, hi3);
344 }
345
346
347 /*
348  * Sort and search.
349  */
350
351 static inline void *
352 hb_bsearch (const void *key, const void *base,
353             size_t nmemb, size_t size,
354             int (*compar)(const void *_key, const void *_item))
355 {
356   int min = 0, max = (int) nmemb - 1;
357   while (min <= max)
358   {
359     int mid = (min + max) / 2;
360     const void *p = (const void *) (((const char *) base) + (mid * size));
361     int c = compar (key, p);
362     if (c < 0)
363       max = mid - 1;
364     else if (c > 0)
365       min = mid + 1;
366     else
367       return (void *) p;
368   }
369   return nullptr;
370 }
371
372 static inline void *
373 hb_bsearch_r (const void *key, const void *base,
374               size_t nmemb, size_t size,
375               int (*compar)(const void *_key, const void *_item, void *_arg),
376               void *arg)
377 {
378   int min = 0, max = (int) nmemb - 1;
379   while (min <= max)
380   {
381     int mid = ((unsigned int) min + (unsigned int) max) / 2;
382     const void *p = (const void *) (((const char *) base) + (mid * size));
383     int c = compar (key, p, arg);
384     if (c < 0)
385       max = mid - 1;
386     else if (c > 0)
387       min = mid + 1;
388     else
389       return (void *) p;
390   }
391   return nullptr;
392 }
393
394
395 /* From https://github.com/noporpoise/sort_r
396  * With following modifications:
397  *
398  * 10 November 2018:
399  * https://github.com/noporpoise/sort_r/issues/7
400  */
401
402 /* Isaac Turner 29 April 2014 Public Domain */
403
404 /*
405
406 hb_sort_r function to be exported.
407
408 Parameters:
409   base is the array to be sorted
410   nel is the number of elements in the array
411   width is the size in bytes of each element of the array
412   compar is the comparison function
413   arg is a pointer to be passed to the comparison function
414
415 void hb_sort_r(void *base, size_t nel, size_t width,
416                int (*compar)(const void *_a, const void *_b, void *_arg),
417                void *arg);
418 */
419
420
421 /* swap a, b iff a>b */
422 /* __restrict is same as restrict but better support on old machines */
423 static int sort_r_cmpswap(char *__restrict a, char *__restrict b, size_t w,
424                           int (*compar)(const void *_a, const void *_b,
425                                         void *_arg),
426                           void *arg)
427 {
428   char tmp, *end = a+w;
429   if(compar(a, b, arg) > 0) {
430     for(; a < end; a++, b++) { tmp = *a; *a = *b; *b = tmp; }
431     return 1;
432   }
433   return 0;
434 }
435
436 /* Note: quicksort is not stable, equivalent values may be swapped */
437 static inline void sort_r_simple(void *base, size_t nel, size_t w,
438                                  int (*compar)(const void *_a, const void *_b,
439                                                void *_arg),
440                                  void *arg)
441 {
442   char *b = (char *)base, *end = b + nel*w;
443   if(nel < 7) {
444     /* Insertion sort for arbitrarily small inputs */
445     char *pi, *pj;
446     for(pi = b+w; pi < end; pi += w) {
447       for(pj = pi; pj > b && sort_r_cmpswap(pj-w,pj,w,compar,arg); pj -= w) {}
448     }
449   }
450   else
451   {
452     /* nel > 6; Quicksort */
453
454     /* Use median of first, middle and last items as pivot */
455     char *x, *y, *xend, ch;
456     char *pl, *pm, *pr;
457     char *last = b+w*(nel-1), *tmp;
458     char *l[3];
459     l[0] = b;
460     l[1] = b+w*(nel/2);
461     l[2] = last;
462
463     if(compar(l[0],l[1],arg) > 0) { tmp=l[0]; l[0]=l[1]; l[1]=tmp; }
464     if(compar(l[1],l[2],arg) > 0) {
465       tmp=l[1]; l[1]=l[2]; l[2]=tmp; /* swap(l[1],l[2]) */
466       if(compar(l[0],l[1],arg) > 0) { tmp=l[0]; l[0]=l[1]; l[1]=tmp; }
467     }
468
469     /* swap l[id], l[2] to put pivot as last element */
470     for(x = l[1], y = last, xend = x+w; x<xend; x++, y++) {
471       ch = *x; *x = *y; *y = ch;
472     }
473
474     pl = b;
475     pr = last;
476
477     while(pl < pr) {
478       pm = pl+((pr-pl+1)>>1);
479       for(; pl < pm; pl += w) {
480         if(sort_r_cmpswap(pl, pr, w, compar, arg)) {
481           pr -= w; /* pivot now at pl */
482           break;
483         }
484       }
485       pm = pl+((pr-pl)>>1);
486       for(; pm < pr; pr -= w) {
487         if(sort_r_cmpswap(pl, pr, w, compar, arg)) {
488           pl += w; /* pivot now at pr */
489           break;
490         }
491       }
492     }
493
494     sort_r_simple(b, (pl-b)/w, w, compar, arg);
495     sort_r_simple(pl+w, (end-(pl+w))/w, w, compar, arg);
496   }
497 }
498
499 static inline void hb_sort_r(void *base, size_t nel, size_t width,
500                              int (*compar)(const void *_a, const void *_b, void *_arg),
501                              void *arg)
502 {
503     sort_r_simple(base, nel, width, compar, arg);
504 }
505
506
507 template <typename T, typename T2> static inline void
508 hb_stable_sort (T *array, unsigned int len, int(*compar)(const T *, const T *), T2 *array2)
509 {
510   for (unsigned int i = 1; i < len; i++)
511   {
512     unsigned int j = i;
513     while (j && compar (&array[j - 1], &array[i]) > 0)
514       j--;
515     if (i == j)
516       continue;
517     /* Move item i to occupy place for item j, shift what's in between. */
518     {
519       T t = array[i];
520       memmove (&array[j + 1], &array[j], (i - j) * sizeof (T));
521       array[j] = t;
522     }
523     if (array2)
524     {
525       T2 t = array2[i];
526       memmove (&array2[j + 1], &array2[j], (i - j) * sizeof (T2));
527       array2[j] = t;
528     }
529   }
530 }
531
532 template <typename T> static inline void
533 hb_stable_sort (T *array, unsigned int len, int(*compar)(const T *, const T *))
534 {
535   hb_stable_sort (array, len, compar, (int *) nullptr);
536 }
537
538 static inline hb_bool_t
539 hb_codepoint_parse (const char *s, unsigned int len, int base, hb_codepoint_t *out)
540 {
541   /* Pain because we don't know whether s is nul-terminated. */
542   char buf[64];
543   len = MIN (ARRAY_LENGTH (buf) - 1, len);
544   strncpy (buf, s, len);
545   buf[len] = '\0';
546
547   char *end;
548   errno = 0;
549   unsigned long v = strtoul (buf, &end, base);
550   if (errno) return false;
551   if (*end) return false;
552   *out = v;
553   return true;
554 }
555
556
557 struct HbOpOr
558 {
559   static constexpr bool passthru_left = true;
560   static constexpr bool passthru_right = true;
561   template <typename T> static void process (T &o, const T &a, const T &b) { o = a | b; }
562 };
563 struct HbOpAnd
564 {
565   static constexpr bool passthru_left = false;
566   static constexpr bool passthru_right = false;
567   template <typename T> static void process (T &o, const T &a, const T &b) { o = a & b; }
568 };
569 struct HbOpMinus
570 {
571   static constexpr bool passthru_left = true;
572   static constexpr bool passthru_right = false;
573   template <typename T> static void process (T &o, const T &a, const T &b) { o = a & ~b; }
574 };
575 struct HbOpXor
576 {
577   static constexpr bool passthru_left = true;
578   static constexpr bool passthru_right = true;
579   template <typename T> static void process (T &o, const T &a, const T &b) { o = a ^ b; }
580 };
581
582
583 /* Compiler-assisted vectorization. */
584
585 /* Type behaving similar to vectorized vars defined using __attribute__((vector_size(...))),
586  * using vectorized operations if HB_VECTOR_SIZE is set to **bit** numbers (eg 128).
587  * Define that to 0 to disable. */
588 template <typename elt_t, unsigned int byte_size>
589 struct hb_vector_size_t
590 {
591   elt_t& operator [] (unsigned int i) { return u.v[i]; }
592   const elt_t& operator [] (unsigned int i) const { return u.v[i]; }
593
594   void clear (unsigned char v = 0) { memset (this, v, sizeof (*this)); }
595
596   template <class Op>
597   hb_vector_size_t process (const hb_vector_size_t &o) const
598   {
599     hb_vector_size_t r;
600 #if HB_VECTOR_SIZE
601     if (HB_VECTOR_SIZE && 0 == (byte_size * 8) % HB_VECTOR_SIZE)
602       for (unsigned int i = 0; i < ARRAY_LENGTH (u.vec); i++)
603         Op::process (r.u.vec[i], u.vec[i], o.u.vec[i]);
604     else
605 #endif
606       for (unsigned int i = 0; i < ARRAY_LENGTH (u.v); i++)
607         Op::process (r.u.v[i], u.v[i], o.u.v[i]);
608     return r;
609   }
610   hb_vector_size_t operator | (const hb_vector_size_t &o) const
611   { return process<HbOpOr> (o); }
612   hb_vector_size_t operator & (const hb_vector_size_t &o) const
613   { return process<HbOpAnd> (o); }
614   hb_vector_size_t operator ^ (const hb_vector_size_t &o) const
615   { return process<HbOpXor> (o); }
616   hb_vector_size_t operator ~ () const
617   {
618     hb_vector_size_t r;
619 #if HB_VECTOR_SIZE && 0
620     if (HB_VECTOR_SIZE && 0 == (byte_size * 8) % HB_VECTOR_SIZE)
621       for (unsigned int i = 0; i < ARRAY_LENGTH (u.vec); i++)
622         r.u.vec[i] = ~u.vec[i];
623     else
624 #endif
625     for (unsigned int i = 0; i < ARRAY_LENGTH (u.v); i++)
626       r.u.v[i] = ~u.v[i];
627     return r;
628   }
629
630   private:
631   static_assert (byte_size / sizeof (elt_t) * sizeof (elt_t) == byte_size, "");
632   union {
633     elt_t v[byte_size / sizeof (elt_t)];
634 #if HB_VECTOR_SIZE
635     hb_vector_size_impl_t vec[byte_size / sizeof (hb_vector_size_impl_t)];
636 #endif
637   } u;
638 };
639
640
641 #endif /* HB_DSALGS_HH */