2 * Copyright © 2017 Google, Inc.
4 * This is part of HarfBuzz, a text shaping library.
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.
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
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.
24 * Google Author(s): Behdad Esfahbod
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)
43 /* Return the number of 1 bits in v. */
45 static inline HB_CONST_FUNC unsigned int
48 #if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__)
49 if (sizeof (T) <= sizeof (unsigned int))
50 return __builtin_popcount (v);
52 if (sizeof (T) <= sizeof (unsigned long))
53 return __builtin_popcountl (v);
55 if (sizeof (T) <= sizeof (unsigned long long))
56 return __builtin_popcountll (v);
63 y = (v >> 1) &033333333333;
64 y = v - y - ((y >>1) & 033333333333);
65 return (((y + (y >> 3)) & 030707070707) % 077);
70 unsigned int shift = 32;
71 return hb_popcount<uint32_t> ((uint32_t) v) + hb_popcount ((uint32_t) (v >> shift));
76 unsigned int shift = 64;
77 return hb_popcount<uint64_t> ((uint64_t) v) + hb_popcount ((uint64_t) (v >> shift));
81 return 0; /* Shut up stupid compiler. */
84 /* Returns the number of bits needed to store number */
86 static inline HB_CONST_FUNC unsigned int
89 if (unlikely (!v)) return 0;
91 #if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__)
92 if (sizeof (T) <= sizeof (unsigned int))
93 return sizeof (unsigned int) * 8 - __builtin_clz (v);
95 if (sizeof (T) <= sizeof (unsigned long))
96 return sizeof (unsigned long) * 8 - __builtin_clzl (v);
98 if (sizeof (T) <= sizeof (unsigned long long))
99 return sizeof (unsigned long long) * 8 - __builtin_clzll (v);
102 #if (defined(_MSC_VER) && _MSC_VER >= 1500) || defined(__MINGW32__)
103 if (sizeof (T) <= sizeof (unsigned int))
106 _BitScanReverse (&where, v);
113 _BitScanReverse64 (&where, v);
122 const unsigned int b[] = {0x2, 0xC, 0xF0, 0xFF00, 0xFFFF0000};
123 const unsigned int S[] = {1, 2, 4, 8, 16};
125 for (int i = 4; i >= 0; i--)
136 const uint64_t b[] = {0x2ULL, 0xCULL, 0xF0ULL, 0xFF00ULL, 0xFFFF0000ULL, 0xFFFFFFFF00000000ULL};
137 const unsigned int S[] = {1, 2, 4, 8, 16, 32};
139 for (int i = 5; i >= 0; i--)
147 if (sizeof (T) == 16)
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);
155 return 0; /* Shut up stupid compiler. */
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
163 if (unlikely (!v)) return 0;
165 #if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__)
166 if (sizeof (T) <= sizeof (unsigned int))
167 return __builtin_ctz (v);
169 if (sizeof (T) <= sizeof (unsigned long))
170 return __builtin_ctzl (v);
172 if (sizeof (T) <= sizeof (unsigned long long))
173 return __builtin_ctzll (v);
176 #if (defined(_MSC_VER) && _MSC_VER >= 1500) || defined(__MINGW32__)
177 if (sizeof (T) <= sizeof (unsigned int))
180 _BitScanForward (&where, v);
187 _BitScanForward64 (&where, v);
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;
210 v &= - (int64_t) (v);
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;
220 if (sizeof (T) == 16)
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;
228 return 0; /* Shut up stupid compiler. */
236 template <typename T>
237 static inline T* hb_addressof (T& arg)
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*>(
244 reinterpret_cast<const volatile char&>(arg)));
245 #pragma GCC diagnostic pop
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; }
261 template <typename Type>
262 static inline Type MIN (const Type &a, const Type &b) { return a < b ? a : b; }
265 template <typename Type>
266 static inline Type MAX (const Type &a, const Type &b) { return a > b ? a : b; }
268 static inline unsigned int DIV_CEIL (const unsigned int a, unsigned int b)
269 { return (a + (b - 1)) / b; }
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])))
280 hb_memcmp (const void *a, const void *b, unsigned int len)
282 /* It's illegal to pass NULL to memcmp(), even if len is zero.
284 * https://sourceware.org/bugzilla/show_bug.cgi?id=23878 */
286 return memcmp (a, b, len);
290 hb_unsigned_mul_overflows (unsigned int count, unsigned int size)
292 return (size > 0) && (count >= ((unsigned int) -1) / size);
295 static inline unsigned int
296 hb_ceil_to_4 (unsigned int v)
298 return ((v - 1) | 3) + 1;
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
315 * https://github.com/harfbuzz/harfbuzz/pull/1499
317 #if defined(_MSC_VER) && (_MSC_VER < 1600)
318 template <> struct hb_is_signed<__int8> { enum { value = true }; };
321 template <typename T> static inline bool
322 hb_in_range (T u, T lo, T hi)
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, "");
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);
335 template <typename T> static inline bool
336 hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2)
338 return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2);
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)
343 return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2) || hb_in_range (u, lo3, hi3);
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))
356 int min = 0, max = (int) nmemb - 1;
359 int mid = (min + max) / 2;
360 const void *p = (const void *) (((const char *) base) + (mid * size));
361 int c = compar (key, p);
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),
378 int min = 0, max = (int) nmemb - 1;
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);
395 /* From https://github.com/noporpoise/sort_r
396 * With following modifications:
399 * https://github.com/noporpoise/sort_r/issues/7
402 /* Isaac Turner 29 April 2014 Public Domain */
406 hb_sort_r function to be exported.
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
415 void hb_sort_r(void *base, size_t nel, size_t width,
416 int (*compar)(const void *_a, const void *_b, void *_arg),
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,
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; }
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,
442 char *b = (char *)base, *end = b + nel*w;
444 /* Insertion sort for arbitrarily small inputs */
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) {}
452 /* nel > 6; Quicksort */
454 /* Use median of first, middle and last items as pivot */
455 char *x, *y, *xend, ch;
457 char *last = b+w*(nel-1), *tmp;
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; }
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;
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 */
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 */
494 sort_r_simple(b, (pl-b)/w, w, compar, arg);
495 sort_r_simple(pl+w, (end-(pl+w))/w, w, compar, arg);
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),
503 sort_r_simple(base, nel, width, compar, arg);
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)
510 for (unsigned int i = 1; i < len; i++)
513 while (j && compar (&array[j - 1], &array[i]) > 0)
517 /* Move item i to occupy place for item j, shift what's in between. */
520 memmove (&array[j + 1], &array[j], (i - j) * sizeof (T));
526 memmove (&array2[j + 1], &array2[j], (i - j) * sizeof (T2));
532 template <typename T> static inline void
533 hb_stable_sort (T *array, unsigned int len, int(*compar)(const T *, const T *))
535 hb_stable_sort (array, len, compar, (int *) nullptr);
538 static inline hb_bool_t
539 hb_codepoint_parse (const char *s, unsigned int len, int base, hb_codepoint_t *out)
541 /* Pain because we don't know whether s is nul-terminated. */
543 len = MIN (ARRAY_LENGTH (buf) - 1, len);
544 strncpy (buf, s, len);
549 unsigned long v = strtoul (buf, &end, base);
550 if (errno) return false;
551 if (*end) return false;
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; }
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; }
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; }
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; }
583 /* Compiler-assisted vectorization. */
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
591 elt_t& operator [] (unsigned int i) { return u.v[i]; }
592 const elt_t& operator [] (unsigned int i) const { return u.v[i]; }
594 void clear (unsigned char v = 0) { memset (this, v, sizeof (*this)); }
597 hb_vector_size_t process (const hb_vector_size_t &o) const
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]);
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]);
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
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];
625 for (unsigned int i = 0; i < ARRAY_LENGTH (u.v); i++)
631 static_assert (byte_size / sizeof (elt_t) * sizeof (elt_t) == byte_size, "");
633 elt_t v[byte_size / sizeof (elt_t)];
635 hb_vector_size_impl_t vec[byte_size / sizeof (hb_vector_size_impl_t)];
641 #endif /* HB_DSALGS_HH */