164aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod/*
22409d5f8d7dd8b535ce5ea29e933f7db27d33793Behdad Esfahbod * Copyright © 2007,2008,2009  Red Hat, Inc.
30ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod * Copyright © 2011,2012  Google, Inc.
464aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod *
5c755cb3e3ac55156d0d2ec05adea7a650b97cc41Behdad Esfahbod *  This is part of HarfBuzz, a text shaping library.
664aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod *
764aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * Permission is hereby granted, without written agreement and without
864aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * license or royalty fees, to use, copy, modify, and distribute this
964aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * software and its documentation for any purpose, provided that the
1064aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * above copyright notice and the following two paragraphs appear in
1164aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * all copies of this software.
1264aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod *
1364aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
1464aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
1564aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
1664aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
1764aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * DAMAGE.
1864aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod *
1964aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
2064aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
2164aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
2264aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
2364aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
2464aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod *
2564aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod * Red Hat Author(s): Behdad Esfahbod
262409d5f8d7dd8b535ce5ea29e933f7db27d33793Behdad Esfahbod * Google Author(s): Behdad Esfahbod
2764aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod */
2864aef3a54999496fd1de4f5aa5b019e4c03b3836Behdad Esfahbod
29c57d454accff66e5f2c58006e8fb40bc020b6182Behdad Esfahbod#ifndef HB_PRIVATE_HH
30c57d454accff66e5f2c58006e8fb40bc020b6182Behdad Esfahbod#define HB_PRIVATE_HH
315b3f7702a64fe0513d08a67bdb72704e46fd7cd4Behdad Esfahbod
325ddd9cc499f2470eca239ae357a5c8a3626c0809Behdad Esfahbod#ifdef HAVE_CONFIG_H
33df66028781a7609a515980e64396e6f1044d764aBehdad Esfahbod#include "config.h"
34df66028781a7609a515980e64396e6f1044d764aBehdad Esfahbod#endif
35c7d457aa3ae7138630f52ca7263f663a3ea284c0Behdad Esfahbod
36d1c9eb458c843215da8df84b596bfae51fee135bBehdad Esfahbod#include "hb.h"
37d1c9eb458c843215da8df84b596bfae51fee135bBehdad Esfahbod#define HB_H_IN
383e32cd9570fd8b09901fb790b80365ae425f681aBehdad Esfahbod#ifdef HAVE_OT
393e32cd9570fd8b09901fb790b80365ae425f681aBehdad Esfahbod#include "hb-ot.h"
40d1c9eb458c843215da8df84b596bfae51fee135bBehdad Esfahbod#define HB_OT_H_IN
413e32cd9570fd8b09901fb790b80365ae425f681aBehdad Esfahbod#endif
42b28815c1f6e46d38471cacbc31248ca6fda8c4d1Behdad Esfahbod
43c7d457aa3ae7138630f52ca7263f663a3ea284c0Behdad Esfahbod#include <stdlib.h>
44b65c06025d2b54a44f716e030d4b10072c65bea8Behdad Esfahbod#include <stddef.h>
45f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod#include <string.h>
46f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod#include <assert.h>
477acb389569cf99c6bae9db31a8ed7c7007fbb566Behdad Esfahbod#include <errno.h>
4840ec3bbb55b8af1668bb3d5f6232a85b15cff136Behdad Esfahbod#include <stdio.h>
49cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod#include <stdarg.h>
50c7d457aa3ae7138630f52ca7263f663a3ea284c0Behdad Esfahbod
51acdba3f90b232fc12fcb200dca2584481b339118Behdad Esfahbod
522a749680441bbe6b4aa8134bb6ce9f21a8b1bc3cBehdad Esfahbod#define HB_PASTE1(a,b) a##b
532a749680441bbe6b4aa8134bb6ce9f21a8b1bc3cBehdad Esfahbod#define HB_PASTE(a,b) HB_PASTE1(a,b)
542a749680441bbe6b4aa8134bb6ce9f21a8b1bc3cBehdad Esfahbod
5552b418555b62a3b25399f202c1fa72ab7288c224Behdad Esfahbod/* Compile-time custom allocator support. */
5652b418555b62a3b25399f202c1fa72ab7288c224Behdad Esfahbod
5752b418555b62a3b25399f202c1fa72ab7288c224Behdad Esfahbod#if defined(hb_malloc_impl) \
5852b418555b62a3b25399f202c1fa72ab7288c224Behdad Esfahbod && defined(hb_calloc_impl) \
5952b418555b62a3b25399f202c1fa72ab7288c224Behdad Esfahbod && defined(hb_realloc_impl) \
6052b418555b62a3b25399f202c1fa72ab7288c224Behdad Esfahbod && defined(hb_free_impl)
61cc6ea308d4c99b9dd6d625fa3a9b0ef62fa2614fBehdad Esfahbodextern "C" void* hb_malloc_impl(size_t size);
62cc6ea308d4c99b9dd6d625fa3a9b0ef62fa2614fBehdad Esfahbodextern "C" void* hb_calloc_impl(size_t nmemb, size_t size);
63cc6ea308d4c99b9dd6d625fa3a9b0ef62fa2614fBehdad Esfahbodextern "C" void* hb_realloc_impl(void *ptr, size_t size);
64cc6ea308d4c99b9dd6d625fa3a9b0ef62fa2614fBehdad Esfahbodextern "C" void  hb_free_impl(void *ptr);
6552b418555b62a3b25399f202c1fa72ab7288c224Behdad Esfahbod#define malloc hb_malloc_impl
6652b418555b62a3b25399f202c1fa72ab7288c224Behdad Esfahbod#define calloc hb_calloc_impl
6752b418555b62a3b25399f202c1fa72ab7288c224Behdad Esfahbod#define realloc hb_realloc_impl
6852b418555b62a3b25399f202c1fa72ab7288c224Behdad Esfahbod#define free hb_free_impl
6952b418555b62a3b25399f202c1fa72ab7288c224Behdad Esfahbod#endif
7052b418555b62a3b25399f202c1fa72ab7288c224Behdad Esfahbod
7152b418555b62a3b25399f202c1fa72ab7288c224Behdad Esfahbod
72ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod/* Compiler attributes */
73bc200457430c083914a64bf4b056153506749610Behdad Esfahbod
74bc200457430c083914a64bf4b056153506749610Behdad Esfahbod
7576dcbf8b23475b25f8f1918f982bfd8f0dd3456eBehdad Esfahbod#if __cplusplus < 201103L
7676dcbf8b23475b25f8f1918f982bfd8f0dd3456eBehdad Esfahbod
7762e312ead808cec055049592b0d40aa3a8882bc9Behdad Esfahbod#ifndef nullptr
7862e312ead808cec055049592b0d40aa3a8882bc9Behdad Esfahbod#define nullptr NULL
7962e312ead808cec055049592b0d40aa3a8882bc9Behdad Esfahbod#endif
8076dcbf8b23475b25f8f1918f982bfd8f0dd3456eBehdad Esfahbod
8176dcbf8b23475b25f8f1918f982bfd8f0dd3456eBehdad Esfahbod// Static assertions
8276dcbf8b23475b25f8f1918f982bfd8f0dd3456eBehdad Esfahbod#ifndef static_assert
8376dcbf8b23475b25f8f1918f982bfd8f0dd3456eBehdad Esfahbod#define static_assert(e, msg) \
846f08b12bc38166dee2f9740d396d617b32e887a3Behdad Esfahbod	HB_UNUSED typedef int HB_PASTE(static_assertion_failed_at_line_, __LINE__) [(e) ? 1 : -1]
8576dcbf8b23475b25f8f1918f982bfd8f0dd3456eBehdad Esfahbod#endif // static_assert
8676dcbf8b23475b25f8f1918f982bfd8f0dd3456eBehdad Esfahbod
8776dcbf8b23475b25f8f1918f982bfd8f0dd3456eBehdad Esfahbod#endif // __cplusplus < 201103L
8876dcbf8b23475b25f8f1918f982bfd8f0dd3456eBehdad Esfahbod
89c290ba5b7d4e9e4a5f02340a22e6c9c46564906bBehdad Esfahbod#define _GNU_SOURCE 1
9076dcbf8b23475b25f8f1918f982bfd8f0dd3456eBehdad Esfahbod
9176c4873e8cad2871d2d547318d371b9a89d8c806Ebrahim Byagowi#if (defined(__GNUC__) || defined(__clang__)) && defined(__OPTIMIZE__)
9276c4873e8cad2871d2d547318d371b9a89d8c806Ebrahim Byagowi#define likely(expr) (__builtin_expect (!!(expr), 1))
9376c4873e8cad2871d2d547318d371b9a89d8c806Ebrahim Byagowi#define unlikely(expr) (__builtin_expect (!!(expr), 0))
94ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#else
95ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#define likely(expr) (expr)
96ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#define unlikely(expr) (expr)
97bc200457430c083914a64bf4b056153506749610Behdad Esfahbod#endif
98bc200457430c083914a64bf4b056153506749610Behdad Esfahbod
990b8f3ab0220ca4731516313828515f26bb480645Steve Lhomme#if !defined(__GNUC__) && !defined(__clang__)
100ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#undef __attribute__
101ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#define __attribute__(x)
102ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#endif
103ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod
104ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#if __GNUC__ >= 3
105ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#define HB_PURE_FUNC	__attribute__((pure))
106ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#define HB_CONST_FUNC	__attribute__((const))
107ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#define HB_PRINTF_FUNC(format_idx, arg_idx) __attribute__((__format__ (__printf__, format_idx, arg_idx)))
108ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#else
109ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#define HB_PURE_FUNC
110ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#define HB_CONST_FUNC
111ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#define HB_PRINTF_FUNC(format_idx, arg_idx)
112ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#endif
113ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#if __GNUC__ >= 4
114ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#define HB_UNUSED	__attribute__((unused))
115be59f3cbf4e3269ea05d5a707cdae04a32e097ceBehdad Esfahbod#elif defined(_MSC_VER) /* https://github.com/harfbuzz/harfbuzz/issues/635 */
116be59f3cbf4e3269ea05d5a707cdae04a32e097ceBehdad Esfahbod#define HB_UNUSED __pragma(warning(suppress: 4100 4101))
117ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#else
118ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#define HB_UNUSED
119ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#endif
120ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod
121ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#ifndef HB_INTERNAL
122f1a8d50a87edfb8147aa1bec732ed7ccbfef2877Behdad Esfahbod# if !defined(__MINGW32__) && !defined(__CYGWIN__)
123ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#  define HB_INTERNAL __attribute__((__visibility__("hidden")))
124ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod# else
125ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#  define HB_INTERNAL
126ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod# endif
127ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#endif
128ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod
129ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#if __GNUC__ >= 3
130ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#define HB_FUNC __PRETTY_FUNCTION__
131ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#elif defined(_MSC_VER)
132ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#define HB_FUNC __FUNCSIG__
133ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#else
134ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#define HB_FUNC __func__
135ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod#endif
136a794ebf4be9896393f4badf02905a4007981a588Behdad Esfahbod
137305d2fbf5a2db51447c8ed894a48a88896930673Behdad Esfahbod/*
138305d2fbf5a2db51447c8ed894a48a88896930673Behdad Esfahbod * Borrowed from https://bugzilla.mozilla.org/show_bug.cgi?id=1215411
139305d2fbf5a2db51447c8ed894a48a88896930673Behdad Esfahbod * HB_FALLTHROUGH is an annotation to suppress compiler warnings about switch
140305d2fbf5a2db51447c8ed894a48a88896930673Behdad Esfahbod * cases that fall through without a break or return statement. HB_FALLTHROUGH
141305d2fbf5a2db51447c8ed894a48a88896930673Behdad Esfahbod * is only needed on cases that have code:
142305d2fbf5a2db51447c8ed894a48a88896930673Behdad Esfahbod *
143305d2fbf5a2db51447c8ed894a48a88896930673Behdad Esfahbod * switch (foo) {
144305d2fbf5a2db51447c8ed894a48a88896930673Behdad Esfahbod *   case 1: // These cases have no code. No fallthrough annotations are needed.
145305d2fbf5a2db51447c8ed894a48a88896930673Behdad Esfahbod *   case 2:
146305d2fbf5a2db51447c8ed894a48a88896930673Behdad Esfahbod *   case 3:
147305d2fbf5a2db51447c8ed894a48a88896930673Behdad Esfahbod *     foo = 4; // This case has code, so a fallthrough annotation is needed:
148305d2fbf5a2db51447c8ed894a48a88896930673Behdad Esfahbod *     HB_FALLTHROUGH;
149305d2fbf5a2db51447c8ed894a48a88896930673Behdad Esfahbod *   default:
150305d2fbf5a2db51447c8ed894a48a88896930673Behdad Esfahbod *     return foo;
151305d2fbf5a2db51447c8ed894a48a88896930673Behdad Esfahbod * }
152305d2fbf5a2db51447c8ed894a48a88896930673Behdad Esfahbod */
153305d2fbf5a2db51447c8ed894a48a88896930673Behdad Esfahbod#if defined(__clang__) && __cplusplus >= 201103L
154305d2fbf5a2db51447c8ed894a48a88896930673Behdad Esfahbod   /* clang's fallthrough annotations are only available starting in C++11. */
155305d2fbf5a2db51447c8ed894a48a88896930673Behdad Esfahbod#  define HB_FALLTHROUGH [[clang::fallthrough]]
156305d2fbf5a2db51447c8ed894a48a88896930673Behdad Esfahbod#elif defined(_MSC_VER)
157305d2fbf5a2db51447c8ed894a48a88896930673Behdad Esfahbod   /*
158305d2fbf5a2db51447c8ed894a48a88896930673Behdad Esfahbod    * MSVC's __fallthrough annotations are checked by /analyze (Code Analysis):
159305d2fbf5a2db51447c8ed894a48a88896930673Behdad Esfahbod    * https://msdn.microsoft.com/en-us/library/ms235402%28VS.80%29.aspx
160305d2fbf5a2db51447c8ed894a48a88896930673Behdad Esfahbod    */
161305d2fbf5a2db51447c8ed894a48a88896930673Behdad Esfahbod#  include <sal.h>
162305d2fbf5a2db51447c8ed894a48a88896930673Behdad Esfahbod#  define HB_FALLTHROUGH __fallthrough
163305d2fbf5a2db51447c8ed894a48a88896930673Behdad Esfahbod#else
164305d2fbf5a2db51447c8ed894a48a88896930673Behdad Esfahbod#  define HB_FALLTHROUGH /* FALLTHROUGH */
165305d2fbf5a2db51447c8ed894a48a88896930673Behdad Esfahbod#endif
166305d2fbf5a2db51447c8ed894a48a88896930673Behdad Esfahbod
1670fc0a1022854324261fea8893678a3e9fd9443ebBehdad Esfahbod#if defined(_WIN32) || defined(__CYGWIN__)
168db308280488c2ee11ba865a9922eb6a0c1abeef3Behdad Esfahbod   /* We need Windows Vista for both Uniscribe backend and for
169db308280488c2ee11ba865a9922eb6a0c1abeef3Behdad Esfahbod    * MemoryBarrier.  We don't support compiling on Windows XP,
170db308280488c2ee11ba865a9922eb6a0c1abeef3Behdad Esfahbod    * though we run on it fine. */
171db308280488c2ee11ba865a9922eb6a0c1abeef3Behdad Esfahbod#  if defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0600
172db308280488c2ee11ba865a9922eb6a0c1abeef3Behdad Esfahbod#    undef _WIN32_WINNT
173db308280488c2ee11ba865a9922eb6a0c1abeef3Behdad Esfahbod#  endif
174db308280488c2ee11ba865a9922eb6a0c1abeef3Behdad Esfahbod#  ifndef _WIN32_WINNT
175db308280488c2ee11ba865a9922eb6a0c1abeef3Behdad Esfahbod#    define _WIN32_WINNT 0x0600
176db308280488c2ee11ba865a9922eb6a0c1abeef3Behdad Esfahbod#  endif
177270971a0fccdf4964fd3e8ab8e5cf53037a3518dBehdad Esfahbod#  ifndef WIN32_LEAN_AND_MEAN
178270971a0fccdf4964fd3e8ab8e5cf53037a3518dBehdad Esfahbod#    define WIN32_LEAN_AND_MEAN 1
179270971a0fccdf4964fd3e8ab8e5cf53037a3518dBehdad Esfahbod#  endif
180270971a0fccdf4964fd3e8ab8e5cf53037a3518dBehdad Esfahbod#  ifndef STRICT
181270971a0fccdf4964fd3e8ab8e5cf53037a3518dBehdad Esfahbod#    define STRICT 1
182270971a0fccdf4964fd3e8ab8e5cf53037a3518dBehdad Esfahbod#  endif
183dabe698fcbeb02911128b17aa8e3b2d864795960Behdad Esfahbod
184f3537b620b0a7392ea27f01f465c5ba79459c858Konstantin Ritt#  if defined(_WIN32_WCE)
185f3537b620b0a7392ea27f01f465c5ba79459c858Konstantin Ritt     /* Some things not defined on Windows CE. */
1865069062d0a9342bb716eebf3ddc1efad91924caaKonstantin Ritt#    define vsnprintf _vsnprintf
187dbdbfe3d7b36613d893832dcb1884c756c20bfdaBehdad Esfahbod#    define getenv(Name) nullptr
188855a5d7cb8f585bf66dd18cb480b8c3feef62480Konstantin Ritt#    if _WIN32_WCE < 0x800
189855a5d7cb8f585bf66dd18cb480b8c3feef62480Konstantin Ritt#      define setlocale(Category, Locale) "C"
19026a963b9cb4af3119177f277a2d48a5d537458fbBehdad Esfahbodstatic int errno = 0; /* Use something better? */
191855a5d7cb8f585bf66dd18cb480b8c3feef62480Konstantin Ritt#    endif
192f3537b620b0a7392ea27f01f465c5ba79459c858Konstantin Ritt#  elif defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP)
193dbdbfe3d7b36613d893832dcb1884c756c20bfdaBehdad Esfahbod#    define getenv(Name) nullptr
194f3537b620b0a7392ea27f01f465c5ba79459c858Konstantin Ritt#  endif
195ce01ad7c2f5a259030f4dbec746f85522aa9c3f9Behdad Esfahbod#  if defined(_MSC_VER) && _MSC_VER < 1900
196f3537b620b0a7392ea27f01f465c5ba79459c858Konstantin Ritt#    define snprintf _snprintf
197f3537b620b0a7392ea27f01f465c5ba79459c858Konstantin Ritt#  endif
19826a963b9cb4af3119177f277a2d48a5d537458fbBehdad Esfahbod#endif
19926a963b9cb4af3119177f277a2d48a5d537458fbBehdad Esfahbod
20038fb30d7420a4b01f99cee31baa8c3990a1d1c5fBehdad Esfahbod#if HAVE_ATEXIT
20138fb30d7420a4b01f99cee31baa8c3990a1d1c5fBehdad Esfahbod/* atexit() is only safe to be called from shared libraries on certain
20238fb30d7420a4b01f99cee31baa8c3990a1d1c5fBehdad Esfahbod * platforms.  Whitelist.
20338fb30d7420a4b01f99cee31baa8c3990a1d1c5fBehdad Esfahbod * https://bugs.freedesktop.org/show_bug.cgi?id=82246 */
20438fb30d7420a4b01f99cee31baa8c3990a1d1c5fBehdad Esfahbod#  if defined(__linux) && defined(__GLIBC_PREREQ)
20538fb30d7420a4b01f99cee31baa8c3990a1d1c5fBehdad Esfahbod#    if __GLIBC_PREREQ(2,3)
20638fb30d7420a4b01f99cee31baa8c3990a1d1c5fBehdad Esfahbod/* From atexit() manpage, it's safe with glibc 2.2.3 on Linux. */
20738fb30d7420a4b01f99cee31baa8c3990a1d1c5fBehdad Esfahbod#      define HB_USE_ATEXIT 1
20838fb30d7420a4b01f99cee31baa8c3990a1d1c5fBehdad Esfahbod#    endif
20938fb30d7420a4b01f99cee31baa8c3990a1d1c5fBehdad Esfahbod#  elif defined(_MSC_VER) || defined(__MINGW32__)
21038fb30d7420a4b01f99cee31baa8c3990a1d1c5fBehdad Esfahbod/* For MSVC:
21138fb30d7420a4b01f99cee31baa8c3990a1d1c5fBehdad Esfahbod * http://msdn.microsoft.com/en-ca/library/tze57ck3.aspx
21238fb30d7420a4b01f99cee31baa8c3990a1d1c5fBehdad Esfahbod * http://msdn.microsoft.com/en-ca/library/zk17ww08.aspx
21338fb30d7420a4b01f99cee31baa8c3990a1d1c5fBehdad Esfahbod * mingw32 headers say atexit is safe to use in shared libraries.
21438fb30d7420a4b01f99cee31baa8c3990a1d1c5fBehdad Esfahbod */
21538fb30d7420a4b01f99cee31baa8c3990a1d1c5fBehdad Esfahbod#    define HB_USE_ATEXIT 1
21638fb30d7420a4b01f99cee31baa8c3990a1d1c5fBehdad Esfahbod#  elif defined(__ANDROID__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
21738fb30d7420a4b01f99cee31baa8c3990a1d1c5fBehdad Esfahbod/* This was fixed in Android NKD r8 or r8b:
21838fb30d7420a4b01f99cee31baa8c3990a1d1c5fBehdad Esfahbod * https://code.google.com/p/android/issues/detail?id=6455
21938fb30d7420a4b01f99cee31baa8c3990a1d1c5fBehdad Esfahbod * which introduced GCC 4.6:
22038fb30d7420a4b01f99cee31baa8c3990a1d1c5fBehdad Esfahbod * https://developer.android.com/tools/sdk/ndk/index.html
22138fb30d7420a4b01f99cee31baa8c3990a1d1c5fBehdad Esfahbod */
22238fb30d7420a4b01f99cee31baa8c3990a1d1c5fBehdad Esfahbod#    define HB_USE_ATEXIT 1
22338fb30d7420a4b01f99cee31baa8c3990a1d1c5fBehdad Esfahbod#  endif
22438fb30d7420a4b01f99cee31baa8c3990a1d1c5fBehdad Esfahbod#endif
225dabe698fcbeb02911128b17aa8e3b2d864795960Behdad Esfahbod
226c7d457aa3ae7138630f52ca7263f663a3ea284c0Behdad Esfahbod/* Basics */
227c7d457aa3ae7138630f52ca7263f663a3ea284c0Behdad Esfahbod
228c7d457aa3ae7138630f52ca7263f663a3ea284c0Behdad Esfahbod#undef MIN
22925326c2359b0a3e25222b94acd142bc36eff78a4Behdad Esfahbodtemplate <typename Type>
23025326c2359b0a3e25222b94acd142bc36eff78a4Behdad Esfahbodstatic inline Type MIN (const Type &a, const Type &b) { return a < b ? a : b; }
2317586089c6fa8185cad8387869d3703c637e5cbb1Behdad Esfahbod
2328a3511ac6c795226699c2b36e03401ecdf88f5f8Behdad Esfahbod#undef MAX
23325326c2359b0a3e25222b94acd142bc36eff78a4Behdad Esfahbodtemplate <typename Type>
23425326c2359b0a3e25222b94acd142bc36eff78a4Behdad Esfahbodstatic inline Type MAX (const Type &a, const Type &b) { return a > b ? a : b; }
235153142dac8dd9abaf164bb88af07c600c17fc3a1Behdad Esfahbod
23616f175cb2e081e605fe7f9cd01bbe8c24380278aBehdad Esfahbodstatic inline unsigned int DIV_CEIL (const unsigned int a, unsigned int b)
23716f175cb2e081e605fe7f9cd01bbe8c24380278aBehdad Esfahbod{ return (a + (b - 1)) / b; }
23816f175cb2e081e605fe7f9cd01bbe8c24380278aBehdad Esfahbod
2398a3511ac6c795226699c2b36e03401ecdf88f5f8Behdad Esfahbod
2404591753ad4b5ec0224e3f1befdfe4fc5f6075562Behdad Esfahbod#undef  ARRAY_LENGTH
24125326c2359b0a3e25222b94acd142bc36eff78a4Behdad Esfahbodtemplate <typename Type, unsigned int n>
2420beb66e3a61ae8bb1fa66e54b1ff1abb2f8711e9Behdad Esfahbodstatic inline unsigned int ARRAY_LENGTH (const Type (&)[n]) { return n; }
243fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod/* A const version, but does not detect erratically being called on pointers. */
244fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod#define ARRAY_LENGTH_CONST(__array) ((signed int) (sizeof (__array) / sizeof (__array[0])))
24512360f7c159826ae72271b34486dee59d96aa8caBehdad Esfahbod
24635a7383c6138fd705560f0d4bb30659cbd1ab64cBehdad Esfahbod#define HB_STMT_START do
24735a7383c6138fd705560f0d4bb30659cbd1ab64cBehdad Esfahbod#define HB_STMT_END   while (0)
2485b3f7702a64fe0513d08a67bdb72704e46fd7cd4Behdad Esfahbod
24976dcbf8b23475b25f8f1918f982bfd8f0dd3456eBehdad Esfahbodtemplate <unsigned int cond> class hb_assert_constant_t;
25076dcbf8b23475b25f8f1918f982bfd8f0dd3456eBehdad Esfahbodtemplate <> class hb_assert_constant_t<1> {};
251672ca3b4e65a75fb3a418ec5d117ad242a98acbbBehdad Esfahbod
252672ca3b4e65a75fb3a418ec5d117ad242a98acbbBehdad Esfahbod#define ASSERT_STATIC_EXPR_ZERO(_cond) (0 * (unsigned int) sizeof (hb_assert_constant_t<_cond>))
253dcb7026f33cbcdf60e9b7fcdd44c64cc08702c74Behdad Esfahbod
2546fd5364bdc3a2b459175377e9e16c86cff054232Behdad Esfahbod/* Lets assert int types.  Saves trouble down the road. */
2556fd5364bdc3a2b459175377e9e16c86cff054232Behdad Esfahbod
256c3448e8d21963eb7fc357a37a7a426a4bf130ef3Behdad Esfahbodstatic_assert ((sizeof (int8_t) == 1), "");
257c3448e8d21963eb7fc357a37a7a426a4bf130ef3Behdad Esfahbodstatic_assert ((sizeof (uint8_t) == 1), "");
258c3448e8d21963eb7fc357a37a7a426a4bf130ef3Behdad Esfahbodstatic_assert ((sizeof (int16_t) == 2), "");
259c3448e8d21963eb7fc357a37a7a426a4bf130ef3Behdad Esfahbodstatic_assert ((sizeof (uint16_t) == 2), "");
260c3448e8d21963eb7fc357a37a7a426a4bf130ef3Behdad Esfahbodstatic_assert ((sizeof (int32_t) == 4), "");
261c3448e8d21963eb7fc357a37a7a426a4bf130ef3Behdad Esfahbodstatic_assert ((sizeof (uint32_t) == 4), "");
262c3448e8d21963eb7fc357a37a7a426a4bf130ef3Behdad Esfahbodstatic_assert ((sizeof (int64_t) == 8), "");
263c3448e8d21963eb7fc357a37a7a426a4bf130ef3Behdad Esfahbodstatic_assert ((sizeof (uint64_t) == 8), "");
2646fd5364bdc3a2b459175377e9e16c86cff054232Behdad Esfahbod
265c3448e8d21963eb7fc357a37a7a426a4bf130ef3Behdad Esfahbodstatic_assert ((sizeof (hb_codepoint_t) == 4), "");
266c3448e8d21963eb7fc357a37a7a426a4bf130ef3Behdad Esfahbodstatic_assert ((sizeof (hb_position_t) == 4), "");
267c3448e8d21963eb7fc357a37a7a426a4bf130ef3Behdad Esfahbodstatic_assert ((sizeof (hb_mask_t) == 4), "");
268c3448e8d21963eb7fc357a37a7a426a4bf130ef3Behdad Esfahbodstatic_assert ((sizeof (hb_var_int_t) == 4), "");
2696fd5364bdc3a2b459175377e9e16c86cff054232Behdad Esfahbod
270a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod
271a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod/* We like our types POD */
272a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod
27373cb02de2dd28b09d4aa76230132248215cfe83dBehdad Esfahbod#define _ASSERT_TYPE_POD1(_line, _type)	union _type_##_type##_on_line_##_line##_is_not_POD { _type instance; }
27473cb02de2dd28b09d4aa76230132248215cfe83dBehdad Esfahbod#define _ASSERT_TYPE_POD0(_line, _type)	_ASSERT_TYPE_POD1 (_line, _type)
27573cb02de2dd28b09d4aa76230132248215cfe83dBehdad Esfahbod#define ASSERT_TYPE_POD(_type)		_ASSERT_TYPE_POD0 (__LINE__, _type)
276a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod
277a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod#ifdef __GNUC__
27879e2b4791fe95ede9a1e6b1c71ccc6e36c4fc0e5Behdad Esfahbod# define _ASSERT_INSTANCE_POD1(_line, _instance) \
27979e2b4791fe95ede9a1e6b1c71ccc6e36c4fc0e5Behdad Esfahbod	HB_STMT_START { \
28079e2b4791fe95ede9a1e6b1c71ccc6e36c4fc0e5Behdad Esfahbod		typedef __typeof__(_instance) _type_##_line; \
28179e2b4791fe95ede9a1e6b1c71ccc6e36c4fc0e5Behdad Esfahbod		_ASSERT_TYPE_POD1 (_line, _type_##_line); \
28279e2b4791fe95ede9a1e6b1c71ccc6e36c4fc0e5Behdad Esfahbod	} HB_STMT_END
283a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod#else
28473cb02de2dd28b09d4aa76230132248215cfe83dBehdad Esfahbod# define _ASSERT_INSTANCE_POD1(_line, _instance)	typedef int _assertion_on_line_##_line##_not_tested
285a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod#endif
28673cb02de2dd28b09d4aa76230132248215cfe83dBehdad Esfahbod# define _ASSERT_INSTANCE_POD0(_line, _instance)	_ASSERT_INSTANCE_POD1 (_line, _instance)
28773cb02de2dd28b09d4aa76230132248215cfe83dBehdad Esfahbod# define ASSERT_INSTANCE_POD(_instance)			_ASSERT_INSTANCE_POD0 (__LINE__, _instance)
288a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod
289a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod/* Check _assertion in a method environment */
290a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod#define _ASSERT_POD1(_line) \
291dac86026a6bae5a8a03cfe885bf93f32e5f48614Behdad Esfahbod	HB_UNUSED inline void _static_assertion_on_line_##_line (void) const \
29273cb02de2dd28b09d4aa76230132248215cfe83dBehdad Esfahbod	{ _ASSERT_INSTANCE_POD1 (_line, *this); /* Make sure it's POD. */ }
29373cb02de2dd28b09d4aa76230132248215cfe83dBehdad Esfahbod# define _ASSERT_POD0(_line)	_ASSERT_POD1 (_line)
29473cb02de2dd28b09d4aa76230132248215cfe83dBehdad Esfahbod# define ASSERT_POD()		_ASSERT_POD0 (__LINE__)
295a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod
296a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod
297a00a63b5ef503fafa87e26b517732b2214e01719Behdad Esfahbod
298bc200457430c083914a64bf4b056153506749610Behdad Esfahbod/* Misc */
299bc200457430c083914a64bf4b056153506749610Behdad Esfahbod
300ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbod/* Void! */
301ae2b854eab7f1c48e56751c987a714c2c18d6eb6Behdad Esfahbodstruct _hb_void_t {};
302a5e4f6d6088f6ed37fb1d68d3682b8eb4c9b46feBehdad Esfahbodtypedef const _hb_void_t *hb_void_t;
303dbdbfe3d7b36613d893832dcb1884c756c20bfdaBehdad Esfahbod#define HB_VOID ((const _hb_void_t *) nullptr)
3047d3a126334f8e6f6441561c1bb592bd3fa7a2c5cBehdad Esfahbod
3059b6023338530a2dbb8214eb4391ef3e8372f3892Behdad Esfahbod/* Return the number of 1 bits in mask. */
30697e7f8f305c47caf2968a9da3b8407825547286dBehdad Esfahbodstatic inline HB_CONST_FUNC unsigned int
307c7d457aa3ae7138630f52ca7263f663a3ea284c0Behdad Esfahbod_hb_popcount32 (uint32_t mask)
308c7d457aa3ae7138630f52ca7263f663a3ea284c0Behdad Esfahbod{
309c7d457aa3ae7138630f52ca7263f663a3ea284c0Behdad Esfahbod#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
3109b6023338530a2dbb8214eb4391ef3e8372f3892Behdad Esfahbod  return __builtin_popcount (mask);
311c7d457aa3ae7138630f52ca7263f663a3ea284c0Behdad Esfahbod#else
3129b6023338530a2dbb8214eb4391ef3e8372f3892Behdad Esfahbod  /* "HACKMEM 169" */
313a949cd329e49d2c0ad6f1e023f324790d886dafeBehdad Esfahbod  uint32_t y;
3149b6023338530a2dbb8214eb4391ef3e8372f3892Behdad Esfahbod  y = (mask >> 1) &033333333333;
3159b6023338530a2dbb8214eb4391ef3e8372f3892Behdad Esfahbod  y = mask - y - ((y >>1) & 033333333333);
3169b6023338530a2dbb8214eb4391ef3e8372f3892Behdad Esfahbod  return (((y + (y >> 3)) & 030707070707) % 077);
317c7d457aa3ae7138630f52ca7263f663a3ea284c0Behdad Esfahbod#endif
318c7d457aa3ae7138630f52ca7263f663a3ea284c0Behdad Esfahbod}
3196fb4ac73f94636d19fcac143472b84f9d91985c9Behdad Esfahbodstatic inline HB_CONST_FUNC unsigned int
3206fb4ac73f94636d19fcac143472b84f9d91985c9Behdad Esfahbod_hb_popcount64 (uint64_t mask)
3216fb4ac73f94636d19fcac143472b84f9d91985c9Behdad Esfahbod{
3226fb4ac73f94636d19fcac143472b84f9d91985c9Behdad Esfahbod#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
323ced86da7ddbbd0d64f8ba1290b8e67600b1db2d4Behdad Esfahbod  if (sizeof (long) >= sizeof (mask))
324ced86da7ddbbd0d64f8ba1290b8e67600b1db2d4Behdad Esfahbod    return __builtin_popcountl (mask);
3256fb4ac73f94636d19fcac143472b84f9d91985c9Behdad Esfahbod#endif
3262ee710e02fad1a8a4b94589bb6f0b90e2aeb7121Behdad Esfahbod  return _hb_popcount32 (mask & 0xFFFFFFFF) + _hb_popcount32 (mask >> 32);
3276fb4ac73f94636d19fcac143472b84f9d91985c9Behdad Esfahbod}
3286fb4ac73f94636d19fcac143472b84f9d91985c9Behdad Esfahbodtemplate <typename T> static inline unsigned int _hb_popcount (T mask);
3296fb4ac73f94636d19fcac143472b84f9d91985c9Behdad Esfahbodtemplate <> inline unsigned int _hb_popcount<uint32_t> (uint32_t mask) { return _hb_popcount32 (mask); }
3306fb4ac73f94636d19fcac143472b84f9d91985c9Behdad Esfahbodtemplate <> inline unsigned int _hb_popcount<uint64_t> (uint64_t mask) { return _hb_popcount64 (mask); }
331c7d457aa3ae7138630f52ca7263f663a3ea284c0Behdad Esfahbod
3329b6023338530a2dbb8214eb4391ef3e8372f3892Behdad Esfahbod/* Returns the number of bits needed to store number */
3339b6023338530a2dbb8214eb4391ef3e8372f3892Behdad Esfahbodstatic inline HB_CONST_FUNC unsigned int
3349b6023338530a2dbb8214eb4391ef3e8372f3892Behdad Esfahbod_hb_bit_storage (unsigned int number)
3359b6023338530a2dbb8214eb4391ef3e8372f3892Behdad Esfahbod{
3369b6023338530a2dbb8214eb4391ef3e8372f3892Behdad Esfahbod#if defined(__GNUC__) && (__GNUC__ >= 4) && defined(__OPTIMIZE__)
337f7acd8df5146155b51d6f50aeb04f54f3030c1c3Behdad Esfahbod  return likely (number) ? (sizeof (unsigned int) * 8 - __builtin_clz (number)) : 0;
3389b6023338530a2dbb8214eb4391ef3e8372f3892Behdad Esfahbod#else
339a949cd329e49d2c0ad6f1e023f324790d886dafeBehdad Esfahbod  unsigned int n_bits = 0;
3409b6023338530a2dbb8214eb4391ef3e8372f3892Behdad Esfahbod  while (number) {
3419b6023338530a2dbb8214eb4391ef3e8372f3892Behdad Esfahbod    n_bits++;
3429b6023338530a2dbb8214eb4391ef3e8372f3892Behdad Esfahbod    number >>= 1;
3439b6023338530a2dbb8214eb4391ef3e8372f3892Behdad Esfahbod  }
3449b6023338530a2dbb8214eb4391ef3e8372f3892Behdad Esfahbod  return n_bits;
3459b6023338530a2dbb8214eb4391ef3e8372f3892Behdad Esfahbod#endif
3469b6023338530a2dbb8214eb4391ef3e8372f3892Behdad Esfahbod}
347df66028781a7609a515980e64396e6f1044d764aBehdad Esfahbod
348f7acd8df5146155b51d6f50aeb04f54f3030c1c3Behdad Esfahbod/* Returns the number of zero bits in the least significant side of number */
349f7acd8df5146155b51d6f50aeb04f54f3030c1c3Behdad Esfahbodstatic inline HB_CONST_FUNC unsigned int
350f7acd8df5146155b51d6f50aeb04f54f3030c1c3Behdad Esfahbod_hb_ctz (unsigned int number)
351f7acd8df5146155b51d6f50aeb04f54f3030c1c3Behdad Esfahbod{
352f7acd8df5146155b51d6f50aeb04f54f3030c1c3Behdad Esfahbod#if defined(__GNUC__) && (__GNUC__ >= 4) && defined(__OPTIMIZE__)
353f7acd8df5146155b51d6f50aeb04f54f3030c1c3Behdad Esfahbod  return likely (number) ? __builtin_ctz (number) : 0;
354f7acd8df5146155b51d6f50aeb04f54f3030c1c3Behdad Esfahbod#else
355a949cd329e49d2c0ad6f1e023f324790d886dafeBehdad Esfahbod  unsigned int n_bits = 0;
356f7acd8df5146155b51d6f50aeb04f54f3030c1c3Behdad Esfahbod  if (unlikely (!number)) return 0;
357f7acd8df5146155b51d6f50aeb04f54f3030c1c3Behdad Esfahbod  while (!(number & 1)) {
358f7acd8df5146155b51d6f50aeb04f54f3030c1c3Behdad Esfahbod    n_bits++;
359f7acd8df5146155b51d6f50aeb04f54f3030c1c3Behdad Esfahbod    number >>= 1;
360f7acd8df5146155b51d6f50aeb04f54f3030c1c3Behdad Esfahbod  }
361f7acd8df5146155b51d6f50aeb04f54f3030c1c3Behdad Esfahbod  return n_bits;
362f7acd8df5146155b51d6f50aeb04f54f3030c1c3Behdad Esfahbod#endif
363f7acd8df5146155b51d6f50aeb04f54f3030c1c3Behdad Esfahbod}
364f7acd8df5146155b51d6f50aeb04f54f3030c1c3Behdad Esfahbod
365080a0eb7d82d7195be72c16ece6e0a3ffed636b6Behdad Esfahbodstatic inline bool
366080a0eb7d82d7195be72c16ece6e0a3ffed636b6Behdad Esfahbod_hb_unsigned_int_mul_overflows (unsigned int count, unsigned int size)
367080a0eb7d82d7195be72c16ece6e0a3ffed636b6Behdad Esfahbod{
368080a0eb7d82d7195be72c16ece6e0a3ffed636b6Behdad Esfahbod  return (size > 0) && (count >= ((unsigned int) -1) / size);
369080a0eb7d82d7195be72c16ece6e0a3ffed636b6Behdad Esfahbod}
370080a0eb7d82d7195be72c16ece6e0a3ffed636b6Behdad Esfahbod
371080a0eb7d82d7195be72c16ece6e0a3ffed636b6Behdad Esfahbod
372852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod
373852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod/* arrays and maps */
374852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod
375852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod
376dbdbfe3d7b36613d893832dcb1884c756c20bfdaBehdad Esfahbod#define HB_PREALLOCED_ARRAY_INIT {0, 0, nullptr}
377546b1adcdce2d3592843938b0b81ff32e67b0b83Behdad Esfahbodtemplate <typename Type, unsigned int StaticSize=16>
3780e253e97af71e2a7ead153589f61fd579a247502Behdad Esfahbodstruct hb_prealloced_array_t
3790e253e97af71e2a7ead153589f61fd579a247502Behdad Esfahbod{
380852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod  unsigned int len;
381852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod  unsigned int allocated;
382852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod  Type *array;
383852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod  Type static_array[StaticSize];
384852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod
38556ef4e0c52d5b474518bf0c1e4adba80f2ae6946Behdad Esfahbod  void init (void)
38656ef4e0c52d5b474518bf0c1e4adba80f2ae6946Behdad Esfahbod  {
38756ef4e0c52d5b474518bf0c1e4adba80f2ae6946Behdad Esfahbod    len = 0;
38856ef4e0c52d5b474518bf0c1e4adba80f2ae6946Behdad Esfahbod    allocated = ARRAY_LENGTH (static_array);
38956ef4e0c52d5b474518bf0c1e4adba80f2ae6946Behdad Esfahbod    array = static_array;
39056ef4e0c52d5b474518bf0c1e4adba80f2ae6946Behdad Esfahbod  }
391efde8113258b117ec0a7fbffe6d681442d045c41Behdad Esfahbod
392265ac614ea6d26041c7d64739098b76a82bbc4f4Behdad Esfahbod  inline Type& operator [] (unsigned int i) { return array[i]; }
393265ac614ea6d26041c7d64739098b76a82bbc4f4Behdad Esfahbod  inline const Type& operator [] (unsigned int i) const { return array[i]; }
394852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod
395852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod  inline Type *push (void)
396852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod  {
397deed4a48d15d4a475f8695aa3269547adf63867aBehdad Esfahbod    if (unlikely (!resize (len + 1)))
398deed4a48d15d4a475f8695aa3269547adf63867aBehdad Esfahbod      return nullptr;
399deed4a48d15d4a475f8695aa3269547adf63867aBehdad Esfahbod
400deed4a48d15d4a475f8695aa3269547adf63867aBehdad Esfahbod    return &array[len - 1];
401deed4a48d15d4a475f8695aa3269547adf63867aBehdad Esfahbod  }
402deed4a48d15d4a475f8695aa3269547adf63867aBehdad Esfahbod
403deed4a48d15d4a475f8695aa3269547adf63867aBehdad Esfahbod  inline bool resize (unsigned int size)
404deed4a48d15d4a475f8695aa3269547adf63867aBehdad Esfahbod  {
40556ef4e0c52d5b474518bf0c1e4adba80f2ae6946Behdad Esfahbod    if (unlikely (size > allocated))
406deed4a48d15d4a475f8695aa3269547adf63867aBehdad Esfahbod    {
407deed4a48d15d4a475f8695aa3269547adf63867aBehdad Esfahbod      /* Need to reallocate */
408deed4a48d15d4a475f8695aa3269547adf63867aBehdad Esfahbod
409deed4a48d15d4a475f8695aa3269547adf63867aBehdad Esfahbod      unsigned int new_allocated = allocated;
410deed4a48d15d4a475f8695aa3269547adf63867aBehdad Esfahbod      while (size >= new_allocated)
411deed4a48d15d4a475f8695aa3269547adf63867aBehdad Esfahbod        new_allocated += (new_allocated >> 1) + 8;
412deed4a48d15d4a475f8695aa3269547adf63867aBehdad Esfahbod
413deed4a48d15d4a475f8695aa3269547adf63867aBehdad Esfahbod      Type *new_array = nullptr;
414deed4a48d15d4a475f8695aa3269547adf63867aBehdad Esfahbod
415deed4a48d15d4a475f8695aa3269547adf63867aBehdad Esfahbod      if (array == static_array) {
416deed4a48d15d4a475f8695aa3269547adf63867aBehdad Esfahbod	new_array = (Type *) calloc (new_allocated, sizeof (Type));
417deed4a48d15d4a475f8695aa3269547adf63867aBehdad Esfahbod	if (new_array)
418deed4a48d15d4a475f8695aa3269547adf63867aBehdad Esfahbod	  memcpy (new_array, array, len * sizeof (Type));
419deed4a48d15d4a475f8695aa3269547adf63867aBehdad Esfahbod      } else {
420deed4a48d15d4a475f8695aa3269547adf63867aBehdad Esfahbod	bool overflows = (new_allocated < allocated) || _hb_unsigned_int_mul_overflows (new_allocated, sizeof (Type));
421deed4a48d15d4a475f8695aa3269547adf63867aBehdad Esfahbod	if (likely (!overflows)) {
422deed4a48d15d4a475f8695aa3269547adf63867aBehdad Esfahbod	  new_array = (Type *) realloc (array, new_allocated * sizeof (Type));
423deed4a48d15d4a475f8695aa3269547adf63867aBehdad Esfahbod	}
424852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod      }
4255a5030366e40baa8d96ca67b47a52ad5af143157Behdad Esfahbod
426deed4a48d15d4a475f8695aa3269547adf63867aBehdad Esfahbod      if (unlikely (!new_array))
427deed4a48d15d4a475f8695aa3269547adf63867aBehdad Esfahbod	return false;
428deed4a48d15d4a475f8695aa3269547adf63867aBehdad Esfahbod
429deed4a48d15d4a475f8695aa3269547adf63867aBehdad Esfahbod      array = new_array;
430deed4a48d15d4a475f8695aa3269547adf63867aBehdad Esfahbod      allocated = new_allocated;
431deed4a48d15d4a475f8695aa3269547adf63867aBehdad Esfahbod    }
4325a5030366e40baa8d96ca67b47a52ad5af143157Behdad Esfahbod
433deed4a48d15d4a475f8695aa3269547adf63867aBehdad Esfahbod    len = size;
434deed4a48d15d4a475f8695aa3269547adf63867aBehdad Esfahbod    return true;
435852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod  }
436852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod
437852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod  inline void pop (void)
438852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod  {
439852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod    len--;
440639afdc690c681a302080239a1967ce735ba5be5Behdad Esfahbod  }
441639afdc690c681a302080239a1967ce735ba5be5Behdad Esfahbod
442639afdc690c681a302080239a1967ce735ba5be5Behdad Esfahbod  inline void remove (unsigned int i)
443639afdc690c681a302080239a1967ce735ba5be5Behdad Esfahbod  {
444639afdc690c681a302080239a1967ce735ba5be5Behdad Esfahbod     if (unlikely (i >= len))
445639afdc690c681a302080239a1967ce735ba5be5Behdad Esfahbod       return;
446639afdc690c681a302080239a1967ce735ba5be5Behdad Esfahbod     memmove (static_cast<void *> (&array[i]),
447639afdc690c681a302080239a1967ce735ba5be5Behdad Esfahbod	      static_cast<void *> (&array[i + 1]),
448639afdc690c681a302080239a1967ce735ba5be5Behdad Esfahbod	      (len - i - 1) * sizeof (Type));
449639afdc690c681a302080239a1967ce735ba5be5Behdad Esfahbod     len--;
450852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod  }
45144b0a4d2fc62689fc56ef57f412b4bb1e439a614Behdad Esfahbod
45244b0a4d2fc62689fc56ef57f412b4bb1e439a614Behdad Esfahbod  inline void shrink (unsigned int l)
45344b0a4d2fc62689fc56ef57f412b4bb1e439a614Behdad Esfahbod  {
45444b0a4d2fc62689fc56ef57f412b4bb1e439a614Behdad Esfahbod     if (l < len)
45544b0a4d2fc62689fc56ef57f412b4bb1e439a614Behdad Esfahbod       len = l;
45644b0a4d2fc62689fc56ef57f412b4bb1e439a614Behdad Esfahbod  }
45744b0a4d2fc62689fc56ef57f412b4bb1e439a614Behdad Esfahbod
4586843569d2c70c1771ce964e3d1a4cf91e14e7687Behdad Esfahbod  template <typename T>
4596843569d2c70c1771ce964e3d1a4cf91e14e7687Behdad Esfahbod  inline Type *find (T v) {
4606843569d2c70c1771ce964e3d1a4cf91e14e7687Behdad Esfahbod    for (unsigned int i = 0; i < len; i++)
4616843569d2c70c1771ce964e3d1a4cf91e14e7687Behdad Esfahbod      if (array[i] == v)
4626843569d2c70c1771ce964e3d1a4cf91e14e7687Behdad Esfahbod	return &array[i];
463dbdbfe3d7b36613d893832dcb1884c756c20bfdaBehdad Esfahbod    return nullptr;
4646843569d2c70c1771ce964e3d1a4cf91e14e7687Behdad Esfahbod  }
4656843569d2c70c1771ce964e3d1a4cf91e14e7687Behdad Esfahbod  template <typename T>
4666843569d2c70c1771ce964e3d1a4cf91e14e7687Behdad Esfahbod  inline const Type *find (T v) const {
4676843569d2c70c1771ce964e3d1a4cf91e14e7687Behdad Esfahbod    for (unsigned int i = 0; i < len; i++)
4686843569d2c70c1771ce964e3d1a4cf91e14e7687Behdad Esfahbod      if (array[i] == v)
4696843569d2c70c1771ce964e3d1a4cf91e14e7687Behdad Esfahbod	return &array[i];
470dbdbfe3d7b36613d893832dcb1884c756c20bfdaBehdad Esfahbod    return nullptr;
4716843569d2c70c1771ce964e3d1a4cf91e14e7687Behdad Esfahbod  }
4726843569d2c70c1771ce964e3d1a4cf91e14e7687Behdad Esfahbod
473fb8cc86ff99c08064ac58a559bb66cc340693b92Behdad Esfahbod  inline void qsort (void)
47444b0a4d2fc62689fc56ef57f412b4bb1e439a614Behdad Esfahbod  {
4750712e915b4814e350aa1d833c1dee5010cdbd8f9Behdad Esfahbod    ::qsort (array, len, sizeof (Type), Type::cmp);
47644b0a4d2fc62689fc56ef57f412b4bb1e439a614Behdad Esfahbod  }
4776843569d2c70c1771ce964e3d1a4cf91e14e7687Behdad Esfahbod
478fb8cc86ff99c08064ac58a559bb66cc340693b92Behdad Esfahbod  inline void qsort (unsigned int start, unsigned int end)
479b70c96dbe41d6512b80fe3d966a1942e1ef64a4bBehdad Esfahbod  {
4800712e915b4814e350aa1d833c1dee5010cdbd8f9Behdad Esfahbod    ::qsort (array + start, end - start, sizeof (Type), Type::cmp);
481b70c96dbe41d6512b80fe3d966a1942e1ef64a4bBehdad Esfahbod  }
482b70c96dbe41d6512b80fe3d966a1942e1ef64a4bBehdad Esfahbod
4836843569d2c70c1771ce964e3d1a4cf91e14e7687Behdad Esfahbod  template <typename T>
484db5f7ef18916abb0907bc8b569a65c9c6bbd4015Behdad Esfahbod  inline Type *bsearch (T *x)
4856843569d2c70c1771ce964e3d1a4cf91e14e7687Behdad Esfahbod  {
4865e74044b6bd78c495561eb7d2981415d2c3336f4Behdad Esfahbod    unsigned int i;
4875e74044b6bd78c495561eb7d2981415d2c3336f4Behdad Esfahbod    return bfind (x, &i) ? &array[i] : nullptr;
4886843569d2c70c1771ce964e3d1a4cf91e14e7687Behdad Esfahbod  }
4896843569d2c70c1771ce964e3d1a4cf91e14e7687Behdad Esfahbod  template <typename T>
490db5f7ef18916abb0907bc8b569a65c9c6bbd4015Behdad Esfahbod  inline const Type *bsearch (T *x) const
4916843569d2c70c1771ce964e3d1a4cf91e14e7687Behdad Esfahbod  {
4925e74044b6bd78c495561eb7d2981415d2c3336f4Behdad Esfahbod    unsigned int i;
4935e74044b6bd78c495561eb7d2981415d2c3336f4Behdad Esfahbod    return bfind (x, &i) ? &array[i] : nullptr;
4945e74044b6bd78c495561eb7d2981415d2c3336f4Behdad Esfahbod  }
4955e74044b6bd78c495561eb7d2981415d2c3336f4Behdad Esfahbod  template <typename T>
4965e74044b6bd78c495561eb7d2981415d2c3336f4Behdad Esfahbod  inline bool bfind (T *x, unsigned int *i) const
4975e74044b6bd78c495561eb7d2981415d2c3336f4Behdad Esfahbod  {
498db5f7ef18916abb0907bc8b569a65c9c6bbd4015Behdad Esfahbod    int min = 0, max = (int) this->len - 1;
499db5f7ef18916abb0907bc8b569a65c9c6bbd4015Behdad Esfahbod    while (min <= max)
500db5f7ef18916abb0907bc8b569a65c9c6bbd4015Behdad Esfahbod    {
501db5f7ef18916abb0907bc8b569a65c9c6bbd4015Behdad Esfahbod      int mid = (min + max) / 2;
502db5f7ef18916abb0907bc8b569a65c9c6bbd4015Behdad Esfahbod      int c = this->array[mid].cmp (x);
503db5f7ef18916abb0907bc8b569a65c9c6bbd4015Behdad Esfahbod      if (c < 0)
504db5f7ef18916abb0907bc8b569a65c9c6bbd4015Behdad Esfahbod        max = mid - 1;
505db5f7ef18916abb0907bc8b569a65c9c6bbd4015Behdad Esfahbod      else if (c > 0)
506db5f7ef18916abb0907bc8b569a65c9c6bbd4015Behdad Esfahbod        min = mid + 1;
507db5f7ef18916abb0907bc8b569a65c9c6bbd4015Behdad Esfahbod      else
5085e74044b6bd78c495561eb7d2981415d2c3336f4Behdad Esfahbod      {
5095e74044b6bd78c495561eb7d2981415d2c3336f4Behdad Esfahbod        *i = mid;
5105e74044b6bd78c495561eb7d2981415d2c3336f4Behdad Esfahbod	return true;
5115e74044b6bd78c495561eb7d2981415d2c3336f4Behdad Esfahbod      }
512db5f7ef18916abb0907bc8b569a65c9c6bbd4015Behdad Esfahbod    }
513deed4a48d15d4a475f8695aa3269547adf63867aBehdad Esfahbod    if (max < 0 || (max < (int) this->len && this->array[max].cmp (x) > 0))
5145e74044b6bd78c495561eb7d2981415d2c3336f4Behdad Esfahbod      max++;
5155e74044b6bd78c495561eb7d2981415d2c3336f4Behdad Esfahbod    *i = max;
5165e74044b6bd78c495561eb7d2981415d2c3336f4Behdad Esfahbod    return false;
5176843569d2c70c1771ce964e3d1a4cf91e14e7687Behdad Esfahbod  }
5186a7ac79e26e85f6781186cf708a12825c0857324Behdad Esfahbod
5196a7ac79e26e85f6781186cf708a12825c0857324Behdad Esfahbod  inline void finish (void)
5206a7ac79e26e85f6781186cf708a12825c0857324Behdad Esfahbod  {
5216a7ac79e26e85f6781186cf708a12825c0857324Behdad Esfahbod    if (array != static_array)
5226a7ac79e26e85f6781186cf708a12825c0857324Behdad Esfahbod      free (array);
523dbdbfe3d7b36613d893832dcb1884c756c20bfdaBehdad Esfahbod    array = nullptr;
5246a7ac79e26e85f6781186cf708a12825c0857324Behdad Esfahbod    allocated = len = 0;
5256a7ac79e26e85f6781186cf708a12825c0857324Behdad Esfahbod  }
526852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod};
527852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod
528c5d91f39802078fc6f6de71940739ec4d04eca07Behdad Esfahbodtemplate <typename Type>
529546b1adcdce2d3592843938b0b81ff32e67b0b83Behdad Esfahbodstruct hb_auto_array_t : hb_prealloced_array_t <Type>
530c5d91f39802078fc6f6de71940739ec4d04eca07Behdad Esfahbod{
531546b1adcdce2d3592843938b0b81ff32e67b0b83Behdad Esfahbod  hb_auto_array_t (void) { hb_prealloced_array_t<Type>::init (); }
532546b1adcdce2d3592843938b0b81ff32e67b0b83Behdad Esfahbod  ~hb_auto_array_t (void) { hb_prealloced_array_t<Type>::finish (); }
533c5d91f39802078fc6f6de71940739ec4d04eca07Behdad Esfahbod};
534c5d91f39802078fc6f6de71940739ec4d04eca07Behdad Esfahbod
535a9f24c802956d57180d71b83e96a0fb81197df4aBehdad Esfahbod
5360e253e97af71e2a7ead153589f61fd579a247502Behdad Esfahbod#define HB_LOCKABLE_SET_INIT {HB_PREALLOCED_ARRAY_INIT}
53745bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbodtemplate <typename item_t, typename lock_t>
53845bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbodstruct hb_lockable_set_t
539852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod{
54051f4d4d5cd5a0dd1a581bee5b55b3cc0a74cbea3Behdad Esfahbod  hb_prealloced_array_t <item_t, 1> items;
541852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod
542bf93b636c4963cbc32d5fba7ace1053db6719192Behdad Esfahbod  inline void init (void) { items.init (); }
543bf93b636c4963cbc32d5fba7ace1053db6719192Behdad Esfahbod
544478a42536ff7ab777a7774fbfdb9c5e51334a14eBehdad Esfahbod  template <typename T>
54533ccc77902660ed4b49184e5ec99f4fd0ef63175Behdad Esfahbod  inline item_t *replace_or_insert (T v, lock_t &l, bool replace)
546852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod  {
54745bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod    l.lock ();
5486843569d2c70c1771ce964e3d1a4cf91e14e7687Behdad Esfahbod    item_t *item = items.find (v);
54945bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod    if (item) {
55033ccc77902660ed4b49184e5ec99f4fd0ef63175Behdad Esfahbod      if (replace) {
55133ccc77902660ed4b49184e5ec99f4fd0ef63175Behdad Esfahbod	item_t old = *item;
55233ccc77902660ed4b49184e5ec99f4fd0ef63175Behdad Esfahbod	*item = v;
55333ccc77902660ed4b49184e5ec99f4fd0ef63175Behdad Esfahbod	l.unlock ();
55433ccc77902660ed4b49184e5ec99f4fd0ef63175Behdad Esfahbod	old.finish ();
55533ccc77902660ed4b49184e5ec99f4fd0ef63175Behdad Esfahbod      }
55633ccc77902660ed4b49184e5ec99f4fd0ef63175Behdad Esfahbod      else {
557dbdbfe3d7b36613d893832dcb1884c756c20bfdaBehdad Esfahbod        item = nullptr;
55833ccc77902660ed4b49184e5ec99f4fd0ef63175Behdad Esfahbod	l.unlock ();
55933ccc77902660ed4b49184e5ec99f4fd0ef63175Behdad Esfahbod      }
56045bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod    } else {
561852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod      item = items.push ();
56245bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod      if (likely (item))
56345bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod	*item = v;
56445bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod      l.unlock ();
56545bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod    }
566b45f32ee4e599c515ce93e44315283d236b073bbBehdad Esfahbod    return item;
567852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod  }
568852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod
569811482bd650fb5652a9835471ae8ecf0fb185611Behdad Esfahbod  template <typename T>
57045bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod  inline void remove (T v, lock_t &l)
571852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod  {
57245bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod    l.lock ();
5736843569d2c70c1771ce964e3d1a4cf91e14e7687Behdad Esfahbod    item_t *item = items.find (v);
57445bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod    if (item) {
57545bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod      item_t old = *item;
57645bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod      *item = items[items.len - 1];
57745bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod      items.pop ();
57845bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod      l.unlock ();
57945bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod      old.finish ();
58045bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod    } else {
58145bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod      l.unlock ();
58245bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod    }
583852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod  }
584a9f24c802956d57180d71b83e96a0fb81197df4aBehdad Esfahbod
585478a42536ff7ab777a7774fbfdb9c5e51334a14eBehdad Esfahbod  template <typename T>
58645bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod  inline bool find (T v, item_t *i, lock_t &l)
587852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod  {
58845bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod    l.lock ();
58945bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod    item_t *item = items.find (v);
59045bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod    if (item)
59145bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod      *i = *item;
59245bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod    l.unlock ();
59345bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod    return !!item;
594811482bd650fb5652a9835471ae8ecf0fb185611Behdad Esfahbod  }
595811482bd650fb5652a9835471ae8ecf0fb185611Behdad Esfahbod
596b45f32ee4e599c515ce93e44315283d236b073bbBehdad Esfahbod  template <typename T>
59745bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod  inline item_t *find_or_insert (T v, lock_t &l)
59845bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod  {
59945bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod    l.lock ();
60045bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod    item_t *item = items.find (v);
601b45f32ee4e599c515ce93e44315283d236b073bbBehdad Esfahbod    if (!item) {
602b45f32ee4e599c515ce93e44315283d236b073bbBehdad Esfahbod      item = items.push ();
603b45f32ee4e599c515ce93e44315283d236b073bbBehdad Esfahbod      if (likely (item))
604b45f32ee4e599c515ce93e44315283d236b073bbBehdad Esfahbod        *item = v;
605b45f32ee4e599c515ce93e44315283d236b073bbBehdad Esfahbod    }
60645bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod    l.unlock ();
607b45f32ee4e599c515ce93e44315283d236b073bbBehdad Esfahbod    return item;
608b45f32ee4e599c515ce93e44315283d236b073bbBehdad Esfahbod  }
609b45f32ee4e599c515ce93e44315283d236b073bbBehdad Esfahbod
61045bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod  inline void finish (lock_t &l)
61145bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod  {
6123f4764bb56bb7e42ba8859f1905810bd2f998838Behdad Esfahbod    if (!items.len) {
6133f4764bb56bb7e42ba8859f1905810bd2f998838Behdad Esfahbod      /* No need for locking. */
6143f4764bb56bb7e42ba8859f1905810bd2f998838Behdad Esfahbod      items.finish ();
6153f4764bb56bb7e42ba8859f1905810bd2f998838Behdad Esfahbod      return;
6163f4764bb56bb7e42ba8859f1905810bd2f998838Behdad Esfahbod    }
61745bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod    l.lock ();
61845bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod    while (items.len) {
61945bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod      item_t old = items[items.len - 1];
62045bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod	items.pop ();
62145bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod	l.unlock ();
62245bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod	old.finish ();
62345bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod	l.lock ();
62445bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod    }
6256a7ac79e26e85f6781186cf708a12825c0857324Behdad Esfahbod    items.finish ();
62645bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod    l.unlock ();
62745bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod  }
62845bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod
62945bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod};
63045bfa99034512e886d75b1d45a5a649647f4711fBehdad Esfahbod
631852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58Behdad Esfahbod
6324188096a7722f09ffa9319986c0286071da10a27Behdad Esfahbod/* ASCII tag/character handling */
633db5227c40e5c35fe2ffb750f32b639cb44424a1dBehdad Esfahbod
63420b817ac21147e0a8edbf23ef071c2f4ce6c2b95Behdad Esfahbodstatic inline bool ISALPHA (unsigned char c)
635153142dac8dd9abaf164bb88af07c600c17fc3a1Behdad Esfahbod{ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); }
63620b817ac21147e0a8edbf23ef071c2f4ce6c2b95Behdad Esfahbodstatic inline bool ISALNUM (unsigned char c)
637153142dac8dd9abaf164bb88af07c600c17fc3a1Behdad Esfahbod{ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'); }
63820b817ac21147e0a8edbf23ef071c2f4ce6c2b95Behdad Esfahbodstatic inline bool ISSPACE (unsigned char c)
63920b817ac21147e0a8edbf23ef071c2f4ce6c2b95Behdad Esfahbod{ return c == ' ' || c =='\f'|| c =='\n'|| c =='\r'|| c =='\t'|| c =='\v'; }
640153142dac8dd9abaf164bb88af07c600c17fc3a1Behdad Esfahbodstatic inline unsigned char TOUPPER (unsigned char c)
641153142dac8dd9abaf164bb88af07c600c17fc3a1Behdad Esfahbod{ return (c >= 'a' && c <= 'z') ? c - 'a' + 'A' : c; }
642153142dac8dd9abaf164bb88af07c600c17fc3a1Behdad Esfahbodstatic inline unsigned char TOLOWER (unsigned char c)
643153142dac8dd9abaf164bb88af07c600c17fc3a1Behdad Esfahbod{ return (c >= 'A' && c <= 'Z') ? c - 'A' + 'a' : c; }
644db5227c40e5c35fe2ffb750f32b639cb44424a1dBehdad Esfahbod
645db5227c40e5c35fe2ffb750f32b639cb44424a1dBehdad Esfahbod
64691dd11565221bdb108c138662ea013aac14bb968Behdad Esfahbod/* HB_NDEBUG disables some sanity checks that are very safe to disable and
64791dd11565221bdb108c138662ea013aac14bb968Behdad Esfahbod * should be disabled in production systems.  If NDEBUG is defined, enable
64891dd11565221bdb108c138662ea013aac14bb968Behdad Esfahbod * HB_NDEBUG; but if it's desirable that normal assert()s (which are very
64991dd11565221bdb108c138662ea013aac14bb968Behdad Esfahbod * light-weight) to be enabled, then HB_DEBUG can be defined to disable
65091dd11565221bdb108c138662ea013aac14bb968Behdad Esfahbod * the costlier checks. */
65191dd11565221bdb108c138662ea013aac14bb968Behdad Esfahbod#ifdef NDEBUG
65291dd11565221bdb108c138662ea013aac14bb968Behdad Esfahbod#define HB_NDEBUG
65391dd11565221bdb108c138662ea013aac14bb968Behdad Esfahbod#endif
65491dd11565221bdb108c138662ea013aac14bb968Behdad Esfahbod
655cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod
656cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod/* Misc */
657cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod
658a8b89a09f6d3a3466282aae07fd65e143f9f8f83Behdad Esfahbodtemplate <typename T> class hb_assert_unsigned_t;
659a8b89a09f6d3a3466282aae07fd65e143f9f8f83Behdad Esfahbodtemplate <> class hb_assert_unsigned_t<unsigned char> {};
6609e7c720100e432b43564ed5ff12f3175ca2ed74aDominik Röttschestemplate <> class hb_assert_unsigned_t<unsigned short> {};
661a8b89a09f6d3a3466282aae07fd65e143f9f8f83Behdad Esfahbodtemplate <> class hb_assert_unsigned_t<unsigned int> {};
662a8b89a09f6d3a3466282aae07fd65e143f9f8f83Behdad Esfahbodtemplate <> class hb_assert_unsigned_t<unsigned long> {};
663f60f2166c48d07f556ff83f04e95181946eb03dfBehdad Esfahbod
664b5aeb95afeb13a66177caada9f5d5ad4cddbd35fBehdad Esfahbodtemplate <typename T> static inline bool
6658f0b64fb6988f9502d2c5e39768a9af133d9a83fBehdad Esfahbodhb_in_range (T u, T lo, T hi)
6667b08b0a7f2057937dfc3ab2ec191656bf2386463Behdad Esfahbod{
667385cf37cf084198e3aedb4354a7b025938a9f11bBehdad Esfahbod  /* The sizeof() is here to force template instantiation.
668385cf37cf084198e3aedb4354a7b025938a9f11bBehdad Esfahbod   * I'm sure there are better ways to do this but can't think of
669385cf37cf084198e3aedb4354a7b025938a9f11bBehdad Esfahbod   * one right now.  Declaring a variable won't work as HB_UNUSED
67068e04afbb1e1073c47474f7a4d6d2cacf7057f6fBehdad Esfahbod   * is unusable on some platforms and unused types are less likely
671385cf37cf084198e3aedb4354a7b025938a9f11bBehdad Esfahbod   * to generate a warning than unused variables. */
672c3448e8d21963eb7fc357a37a7a426a4bf130ef3Behdad Esfahbod  static_assert ((sizeof (hb_assert_unsigned_t<T>) >= 0), "");
673385cf37cf084198e3aedb4354a7b025938a9f11bBehdad Esfahbod
674c2b151d95262a8dc2d2ce94e19ab0ef5b0c8f98dBehdad Esfahbod  /* The casts below are important as if T is smaller than int,
675c2b151d95262a8dc2d2ce94e19ab0ef5b0c8f98dBehdad Esfahbod   * the subtract results will become a signed int! */
676c2b151d95262a8dc2d2ce94e19ab0ef5b0c8f98dBehdad Esfahbod  return (T)(u - lo) <= (T)(hi - lo);
6777b08b0a7f2057937dfc3ab2ec191656bf2386463Behdad Esfahbod}
6787b08b0a7f2057937dfc3ab2ec191656bf2386463Behdad Esfahbod
6794a7f4f3e56f8f7640ae7337aa1b3324f31e0d4abBehdad Esfahbodtemplate <typename T> static inline bool
680c98b7183f7dc453d5bac1f2503017cded317a495Behdad Esfahbodhb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2)
681c98b7183f7dc453d5bac1f2503017cded317a495Behdad Esfahbod{
682c98b7183f7dc453d5bac1f2503017cded317a495Behdad Esfahbod  return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2);
683c98b7183f7dc453d5bac1f2503017cded317a495Behdad Esfahbod}
684c98b7183f7dc453d5bac1f2503017cded317a495Behdad Esfahbod
685c98b7183f7dc453d5bac1f2503017cded317a495Behdad Esfahbodtemplate <typename T> static inline bool
686093cd583263a5d427e3377b31585043fb55d2557Behdad Esfahbodhb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3)
6874a7f4f3e56f8f7640ae7337aa1b3324f31e0d4abBehdad Esfahbod{
688093cd583263a5d427e3377b31585043fb55d2557Behdad Esfahbod  return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2) || hb_in_range (u, lo3, hi3);
6894a7f4f3e56f8f7640ae7337aa1b3324f31e0d4abBehdad Esfahbod}
6904a7f4f3e56f8f7640ae7337aa1b3324f31e0d4abBehdad Esfahbod
6917b08b0a7f2057937dfc3ab2ec191656bf2386463Behdad Esfahbod
692aa7044de0ceacd71cab19212d266c3a66c03b41eBehdad Esfahbod/* Enable bitwise ops on enums marked as flags_t */
6936986208ba3b395534f4c7bcfa51df6bf9038f717Behdad Esfahbod/* To my surprise, looks like the function resolver is happy to silently cast
6946986208ba3b395534f4c7bcfa51df6bf9038f717Behdad Esfahbod * one enum to another...  So this doesn't provide the type-checking that I
695e0082ae60dbd87d433f3b2b9d2bfa64b9a4c3663Behdad Esfahbod * originally had in mind... :(.
696e0082ae60dbd87d433f3b2b9d2bfa64b9a4c3663Behdad Esfahbod *
6977c6937e7c7b62602fef10ac4b2e164d0c67c932bebraminio * For MSVC warnings, see: https://github.com/harfbuzz/harfbuzz/pull/163
698e0082ae60dbd87d433f3b2b9d2bfa64b9a4c3663Behdad Esfahbod */
699e0082ae60dbd87d433f3b2b9d2bfa64b9a4c3663Behdad Esfahbod#ifdef _MSC_VER
700e0082ae60dbd87d433f3b2b9d2bfa64b9a4c3663Behdad Esfahbod# pragma warning(disable:4200)
701e0082ae60dbd87d433f3b2b9d2bfa64b9a4c3663Behdad Esfahbod# pragma warning(disable:4800)
702167c3271778cd1a8c4433b9d2230901ce17c099eChun-wei Fan#endif
7031dc32ea4d2f294f9d1ae1c8fd19fb75f9278223bBehdad Esfahbod#define HB_MARK_AS_FLAG_T(T) \
7041dc32ea4d2f294f9d1ae1c8fd19fb75f9278223bBehdad Esfahbod	extern "C++" { \
7051dc32ea4d2f294f9d1ae1c8fd19fb75f9278223bBehdad Esfahbod	  static inline T operator | (T l, T r) { return T ((unsigned) l | (unsigned) r); } \
7061dc32ea4d2f294f9d1ae1c8fd19fb75f9278223bBehdad Esfahbod	  static inline T operator & (T l, T r) { return T ((unsigned) l & (unsigned) r); } \
7071dc32ea4d2f294f9d1ae1c8fd19fb75f9278223bBehdad Esfahbod	  static inline T operator ^ (T l, T r) { return T ((unsigned) l ^ (unsigned) r); } \
7081dc32ea4d2f294f9d1ae1c8fd19fb75f9278223bBehdad Esfahbod	  static inline T operator ~ (T r) { return T (~(unsigned int) r); } \
7091dc32ea4d2f294f9d1ae1c8fd19fb75f9278223bBehdad Esfahbod	  static inline T& operator |= (T &l, T r) { l = l | r; return l; } \
7101dc32ea4d2f294f9d1ae1c8fd19fb75f9278223bBehdad Esfahbod	  static inline T& operator &= (T& l, T r) { l = l & r; return l; } \
7111dc32ea4d2f294f9d1ae1c8fd19fb75f9278223bBehdad Esfahbod	  static inline T& operator ^= (T& l, T r) { l = l ^ r; return l; } \
7121dc32ea4d2f294f9d1ae1c8fd19fb75f9278223bBehdad Esfahbod	}
713aa7044de0ceacd71cab19212d266c3a66c03b41eBehdad Esfahbod
714aa7044de0ceacd71cab19212d266c3a66c03b41eBehdad Esfahbod
71545d6f29f15f1d2323bcaa2498aed23ff0c8a1567Behdad Esfahbod/* Useful for set-operations on small enums.
71645d6f29f15f1d2323bcaa2498aed23ff0c8a1567Behdad Esfahbod * For example, for testing "x ∈ {x1, x2, x3}" use:
7176058f98825e8f134893a1bbfb402e45d85b56ff0Behdad Esfahbod * (FLAG_UNSAFE(x) & (FLAG(x1) | FLAG(x2) | FLAG(x3)))
71845d6f29f15f1d2323bcaa2498aed23ff0c8a1567Behdad Esfahbod */
719d8adaa97fbf33071b8a4b5c05c3f2f15f2fd22eaBehdad Esfahbod#define FLAG(x) (ASSERT_STATIC_EXPR_ZERO ((unsigned int)(x) < 32) + (1U << (unsigned int)(x)))
720d8adaa97fbf33071b8a4b5c05c3f2f15f2fd22eaBehdad Esfahbod#define FLAG_UNSAFE(x) ((unsigned int)(x) < 32 ? (1U << (unsigned int)(x)) : 0)
7212c372b80f6befad69e216e3f218b38640b8cc044Behdad Esfahbod#define FLAG_RANGE(x,y) (ASSERT_STATIC_EXPR_ZERO ((x) < (y)) + FLAG(y+1) - FLAG(x))
7227b08b0a7f2057937dfc3ab2ec191656bf2386463Behdad Esfahbod
7238f0b64fb6988f9502d2c5e39768a9af133d9a83fBehdad Esfahbod
724c1e87442621beff98791ce56cfd1ccee506c4ee6Behdad Esfahbodtemplate <typename T, typename T2> static inline void
72585846b3de7491b6a07fed6a2c0c6c1b09943b249Behdad Esfahbodhb_stable_sort (T *array, unsigned int len, int(*compar)(const T *, const T *), T2 *array2)
72645d6f29f15f1d2323bcaa2498aed23ff0c8a1567Behdad Esfahbod{
72785846b3de7491b6a07fed6a2c0c6c1b09943b249Behdad Esfahbod  for (unsigned int i = 1; i < len; i++)
72885846b3de7491b6a07fed6a2c0c6c1b09943b249Behdad Esfahbod  {
72985846b3de7491b6a07fed6a2c0c6c1b09943b249Behdad Esfahbod    unsigned int j = i;
73085846b3de7491b6a07fed6a2c0c6c1b09943b249Behdad Esfahbod    while (j && compar (&array[j - 1], &array[i]) > 0)
73185846b3de7491b6a07fed6a2c0c6c1b09943b249Behdad Esfahbod      j--;
73285846b3de7491b6a07fed6a2c0c6c1b09943b249Behdad Esfahbod    if (i == j)
73385846b3de7491b6a07fed6a2c0c6c1b09943b249Behdad Esfahbod      continue;
73485846b3de7491b6a07fed6a2c0c6c1b09943b249Behdad Esfahbod    /* Move item i to occupy place for item j, shift what's in between. */
73585846b3de7491b6a07fed6a2c0c6c1b09943b249Behdad Esfahbod    {
73693099748e39740a3f6f003c83d9dec1d21660ce8Behdad Esfahbod      T t = array[i];
73785846b3de7491b6a07fed6a2c0c6c1b09943b249Behdad Esfahbod      memmove (&array[j + 1], &array[j], (i - j) * sizeof (T));
73885846b3de7491b6a07fed6a2c0c6c1b09943b249Behdad Esfahbod      array[j] = t;
73985846b3de7491b6a07fed6a2c0c6c1b09943b249Behdad Esfahbod    }
74085846b3de7491b6a07fed6a2c0c6c1b09943b249Behdad Esfahbod    if (array2)
74185846b3de7491b6a07fed6a2c0c6c1b09943b249Behdad Esfahbod    {
74293099748e39740a3f6f003c83d9dec1d21660ce8Behdad Esfahbod      T2 t = array2[i];
74385846b3de7491b6a07fed6a2c0c6c1b09943b249Behdad Esfahbod      memmove (&array2[j + 1], &array2[j], (i - j) * sizeof (T2));
74485846b3de7491b6a07fed6a2c0c6c1b09943b249Behdad Esfahbod      array2[j] = t;
74585846b3de7491b6a07fed6a2c0c6c1b09943b249Behdad Esfahbod    }
74685846b3de7491b6a07fed6a2c0c6c1b09943b249Behdad Esfahbod  }
74745d6f29f15f1d2323bcaa2498aed23ff0c8a1567Behdad Esfahbod}
74845d6f29f15f1d2323bcaa2498aed23ff0c8a1567Behdad Esfahbod
749250398b1e4f102e4e44eeb9e2aebf0cd2d397344Behdad Esfahbodtemplate <typename T> static inline void
75085846b3de7491b6a07fed6a2c0c6c1b09943b249Behdad Esfahbodhb_stable_sort (T *array, unsigned int len, int(*compar)(const T *, const T *))
75139b17837b4064d59c18cebb49c1c0b5b8cc0c117Behdad Esfahbod{
752dbdbfe3d7b36613d893832dcb1884c756c20bfdaBehdad Esfahbod  hb_stable_sort (array, len, compar, (int *) nullptr);
75339b17837b4064d59c18cebb49c1c0b5b8cc0c117Behdad Esfahbod}
75445d6f29f15f1d2323bcaa2498aed23ff0c8a1567Behdad Esfahbod
7556f3a300138f659020c21c3e08b7981c78df5f332Behdad Esfahbodstatic inline hb_bool_t
7566f3a300138f659020c21c3e08b7981c78df5f332Behdad Esfahbodhb_codepoint_parse (const char *s, unsigned int len, int base, hb_codepoint_t *out)
7576f3a300138f659020c21c3e08b7981c78df5f332Behdad Esfahbod{
7586f3a300138f659020c21c3e08b7981c78df5f332Behdad Esfahbod  /* Pain because we don't know whether s is nul-terminated. */
7596f3a300138f659020c21c3e08b7981c78df5f332Behdad Esfahbod  char buf[64];
760847794e929831750e97525137ab5e285ccd1064eBehdad Esfahbod  len = MIN (ARRAY_LENGTH (buf) - 1, len);
761847794e929831750e97525137ab5e285ccd1064eBehdad Esfahbod  strncpy (buf, s, len);
762847794e929831750e97525137ab5e285ccd1064eBehdad Esfahbod  buf[len] = '\0';
7636f3a300138f659020c21c3e08b7981c78df5f332Behdad Esfahbod
7646f3a300138f659020c21c3e08b7981c78df5f332Behdad Esfahbod  char *end;
7656f3a300138f659020c21c3e08b7981c78df5f332Behdad Esfahbod  errno = 0;
7666f3a300138f659020c21c3e08b7981c78df5f332Behdad Esfahbod  unsigned long v = strtoul (buf, &end, base);
7676f3a300138f659020c21c3e08b7981c78df5f332Behdad Esfahbod  if (errno) return false;
7686f3a300138f659020c21c3e08b7981c78df5f332Behdad Esfahbod  if (*end) return false;
7696f3a300138f659020c21c3e08b7981c78df5f332Behdad Esfahbod  *out = v;
7706f3a300138f659020c21c3e08b7981c78df5f332Behdad Esfahbod  return true;
7716f3a300138f659020c21c3e08b7981c78df5f332Behdad Esfahbod}
77245d6f29f15f1d2323bcaa2498aed23ff0c8a1567Behdad Esfahbod
773acdba3f90b232fc12fcb200dca2584481b339118Behdad Esfahbod
7747737e87ac4582d57945f3ffbbae1012f62c6b482Behdad Esfahbod/* Vectorization */
7757737e87ac4582d57945f3ffbbae1012f62c6b482Behdad Esfahbod
7767737e87ac4582d57945f3ffbbae1012f62c6b482Behdad Esfahbodstruct HbOpOr
7777737e87ac4582d57945f3ffbbae1012f62c6b482Behdad Esfahbod{
7787737e87ac4582d57945f3ffbbae1012f62c6b482Behdad Esfahbod  static const bool passthru_left = true;
7797737e87ac4582d57945f3ffbbae1012f62c6b482Behdad Esfahbod  static const bool passthru_right = true;
7807737e87ac4582d57945f3ffbbae1012f62c6b482Behdad Esfahbod  template <typename T> static void process (T &o, const T &a, const T &b) { o = a | b; }
7817737e87ac4582d57945f3ffbbae1012f62c6b482Behdad Esfahbod};
7827737e87ac4582d57945f3ffbbae1012f62c6b482Behdad Esfahbodstruct HbOpAnd
7837737e87ac4582d57945f3ffbbae1012f62c6b482Behdad Esfahbod{
7847737e87ac4582d57945f3ffbbae1012f62c6b482Behdad Esfahbod  static const bool passthru_left = false;
7857737e87ac4582d57945f3ffbbae1012f62c6b482Behdad Esfahbod  static const bool passthru_right = false;
7867737e87ac4582d57945f3ffbbae1012f62c6b482Behdad Esfahbod  template <typename T> static void process (T &o, const T &a, const T &b) { o = a & b; }
7877737e87ac4582d57945f3ffbbae1012f62c6b482Behdad Esfahbod};
7887737e87ac4582d57945f3ffbbae1012f62c6b482Behdad Esfahbodstruct HbOpMinus
7897737e87ac4582d57945f3ffbbae1012f62c6b482Behdad Esfahbod{
7907737e87ac4582d57945f3ffbbae1012f62c6b482Behdad Esfahbod  static const bool passthru_left = true;
7917737e87ac4582d57945f3ffbbae1012f62c6b482Behdad Esfahbod  static const bool passthru_right = false;
7927737e87ac4582d57945f3ffbbae1012f62c6b482Behdad Esfahbod  template <typename T> static void process (T &o, const T &a, const T &b) { o = a & ~b; }
7937737e87ac4582d57945f3ffbbae1012f62c6b482Behdad Esfahbod};
7947737e87ac4582d57945f3ffbbae1012f62c6b482Behdad Esfahbodstruct HbOpXor
7957737e87ac4582d57945f3ffbbae1012f62c6b482Behdad Esfahbod{
7967737e87ac4582d57945f3ffbbae1012f62c6b482Behdad Esfahbod  static const bool passthru_left = true;
7977737e87ac4582d57945f3ffbbae1012f62c6b482Behdad Esfahbod  static const bool passthru_right = true;
7987737e87ac4582d57945f3ffbbae1012f62c6b482Behdad Esfahbod  template <typename T> static void process (T &o, const T &a, const T &b) { o = a ^ b; }
7997737e87ac4582d57945f3ffbbae1012f62c6b482Behdad Esfahbod};
8007737e87ac4582d57945f3ffbbae1012f62c6b482Behdad Esfahbod
8017737e87ac4582d57945f3ffbbae1012f62c6b482Behdad Esfahbod/* Type behaving similar to vectorized vars defined using __attribute__((vector_size(...))). */
8027737e87ac4582d57945f3ffbbae1012f62c6b482Behdad Esfahbodtemplate <typename elt_t, unsigned int byte_size>
8037737e87ac4582d57945f3ffbbae1012f62c6b482Behdad Esfahbodstruct hb_vector_size_t
8047737e87ac4582d57945f3ffbbae1012f62c6b482Behdad Esfahbod{
8057737e87ac4582d57945f3ffbbae1012f62c6b482Behdad Esfahbod  elt_t& operator [] (unsigned int i) { return v[i]; }
8067737e87ac4582d57945f3ffbbae1012f62c6b482Behdad Esfahbod  const elt_t& operator [] (unsigned int i) const { return v[i]; }
8077737e87ac4582d57945f3ffbbae1012f62c6b482Behdad Esfahbod
8087737e87ac4582d57945f3ffbbae1012f62c6b482Behdad Esfahbod  template <class Op>
8097737e87ac4582d57945f3ffbbae1012f62c6b482Behdad Esfahbod  inline hb_vector_size_t process (const hb_vector_size_t &o) const
8107737e87ac4582d57945f3ffbbae1012f62c6b482Behdad Esfahbod  {
8117737e87ac4582d57945f3ffbbae1012f62c6b482Behdad Esfahbod    hb_vector_size_t r;
8127737e87ac4582d57945f3ffbbae1012f62c6b482Behdad Esfahbod    for (unsigned int i = 0; i < ARRAY_LENGTH (v); i++)
8137737e87ac4582d57945f3ffbbae1012f62c6b482Behdad Esfahbod      Op::process (r.v[i], v[i], o.v[i]);
8147737e87ac4582d57945f3ffbbae1012f62c6b482Behdad Esfahbod    return r;
8157737e87ac4582d57945f3ffbbae1012f62c6b482Behdad Esfahbod  }
8167737e87ac4582d57945f3ffbbae1012f62c6b482Behdad Esfahbod  inline hb_vector_size_t operator | (const hb_vector_size_t &o) const
8177737e87ac4582d57945f3ffbbae1012f62c6b482Behdad Esfahbod  { return process<HbOpOr> (o); }
8187737e87ac4582d57945f3ffbbae1012f62c6b482Behdad Esfahbod  inline hb_vector_size_t operator & (const hb_vector_size_t &o) const
8197737e87ac4582d57945f3ffbbae1012f62c6b482Behdad Esfahbod  { return process<HbOpAnd> (o); }
8207737e87ac4582d57945f3ffbbae1012f62c6b482Behdad Esfahbod  inline hb_vector_size_t operator ^ (const hb_vector_size_t &o) const
8217737e87ac4582d57945f3ffbbae1012f62c6b482Behdad Esfahbod  { return process<HbOpXor> (o); }
8227737e87ac4582d57945f3ffbbae1012f62c6b482Behdad Esfahbod  inline hb_vector_size_t operator ~ () const
8237737e87ac4582d57945f3ffbbae1012f62c6b482Behdad Esfahbod  {
8247737e87ac4582d57945f3ffbbae1012f62c6b482Behdad Esfahbod    hb_vector_size_t r;
8257737e87ac4582d57945f3ffbbae1012f62c6b482Behdad Esfahbod    for (unsigned int i = 0; i < ARRAY_LENGTH (v); i++)
8267737e87ac4582d57945f3ffbbae1012f62c6b482Behdad Esfahbod      r.v[i] = ~v[i];
8277737e87ac4582d57945f3ffbbae1012f62c6b482Behdad Esfahbod    return r;
8287737e87ac4582d57945f3ffbbae1012f62c6b482Behdad Esfahbod  }
8297737e87ac4582d57945f3ffbbae1012f62c6b482Behdad Esfahbod
8307737e87ac4582d57945f3ffbbae1012f62c6b482Behdad Esfahbod  private:
831221ce6c18f2a1e878b68eb0a97f235efa4c044d3Behdad Esfahbod  static_assert (byte_size / sizeof (elt_t) * sizeof (elt_t) == byte_size, "");
8327737e87ac4582d57945f3ffbbae1012f62c6b482Behdad Esfahbod  elt_t v[byte_size / sizeof (elt_t)];
8337737e87ac4582d57945f3ffbbae1012f62c6b482Behdad Esfahbod};
8347737e87ac4582d57945f3ffbbae1012f62c6b482Behdad Esfahbod
8357737e87ac4582d57945f3ffbbae1012f62c6b482Behdad Esfahbod/* The `vector_size' attribute was introduced in gcc 3.1. */
8367737e87ac4582d57945f3ffbbae1012f62c6b482Behdad Esfahbod#if defined( __GNUC__ ) && ( __GNUC__ >= 4 )
8377737e87ac4582d57945f3ffbbae1012f62c6b482Behdad Esfahbod#define HAVE_VECTOR_SIZE 1
8387737e87ac4582d57945f3ffbbae1012f62c6b482Behdad Esfahbod#endif
8397737e87ac4582d57945f3ffbbae1012f62c6b482Behdad Esfahbod
8407737e87ac4582d57945f3ffbbae1012f62c6b482Behdad Esfahbod
841bab02d339f39ed5168daaef9461227f78e596a2fBehdad Esfahbod/* Global runtime options. */
842bab02d339f39ed5168daaef9461227f78e596a2fBehdad Esfahbod
843bab02d339f39ed5168daaef9461227f78e596a2fBehdad Esfahbodstruct hb_options_t
844bab02d339f39ed5168daaef9461227f78e596a2fBehdad Esfahbod{
8455c87120b8178566ddae99d9825edc24f9b87ea3dBehdad Esfahbod  unsigned int initialized : 1;
8465c87120b8178566ddae99d9825edc24f9b87ea3dBehdad Esfahbod  unsigned int uniscribe_bug_compatible : 1;
847bab02d339f39ed5168daaef9461227f78e596a2fBehdad Esfahbod};
848bab02d339f39ed5168daaef9461227f78e596a2fBehdad Esfahbod
849bab02d339f39ed5168daaef9461227f78e596a2fBehdad Esfahbodunion hb_options_union_t {
8505c87120b8178566ddae99d9825edc24f9b87ea3dBehdad Esfahbod  unsigned int i;
851bab02d339f39ed5168daaef9461227f78e596a2fBehdad Esfahbod  hb_options_t opts;
852bab02d339f39ed5168daaef9461227f78e596a2fBehdad Esfahbod};
853c3448e8d21963eb7fc357a37a7a426a4bf130ef3Behdad Esfahbodstatic_assert ((sizeof (int) == sizeof (hb_options_union_t)), "");
854bab02d339f39ed5168daaef9461227f78e596a2fBehdad Esfahbod
855bab02d339f39ed5168daaef9461227f78e596a2fBehdad EsfahbodHB_INTERNAL void
856bab02d339f39ed5168daaef9461227f78e596a2fBehdad Esfahbod_hb_options_init (void);
857bab02d339f39ed5168daaef9461227f78e596a2fBehdad Esfahbod
858bab02d339f39ed5168daaef9461227f78e596a2fBehdad Esfahbodextern HB_INTERNAL hb_options_union_t _hb_options;
859bab02d339f39ed5168daaef9461227f78e596a2fBehdad Esfahbod
860bab02d339f39ed5168daaef9461227f78e596a2fBehdad Esfahbodstatic inline hb_options_t
861bab02d339f39ed5168daaef9461227f78e596a2fBehdad Esfahbodhb_options (void)
862bab02d339f39ed5168daaef9461227f78e596a2fBehdad Esfahbod{
863bab02d339f39ed5168daaef9461227f78e596a2fBehdad Esfahbod  if (unlikely (!_hb_options.i))
864bab02d339f39ed5168daaef9461227f78e596a2fBehdad Esfahbod    _hb_options_init ();
865bab02d339f39ed5168daaef9461227f78e596a2fBehdad Esfahbod
866bab02d339f39ed5168daaef9461227f78e596a2fBehdad Esfahbod  return _hb_options.opts;
867bab02d339f39ed5168daaef9461227f78e596a2fBehdad Esfahbod}
868bab02d339f39ed5168daaef9461227f78e596a2fBehdad Esfahbod
869a13b023dbfd0532e8cd74c356fbbd4453d0ffaa0Steven R. Loomis/* Size signifying variable-sized array */
870a13b023dbfd0532e8cd74c356fbbd4453d0ffaa0Steven R. Loomis#define VAR 1
871bab02d339f39ed5168daaef9461227f78e596a2fBehdad Esfahbod
872e1a37f3db4f2364e98ff057209a94aa9b23e5c9dBehdad Esfahbod
873e1a37f3db4f2364e98ff057209a94aa9b23e5c9dBehdad Esfahbod/* String type. */
874e1a37f3db4f2364e98ff057209a94aa9b23e5c9dBehdad Esfahbod
875e1a37f3db4f2364e98ff057209a94aa9b23e5c9dBehdad Esfahbodstruct hb_string_t
876e1a37f3db4f2364e98ff057209a94aa9b23e5c9dBehdad Esfahbod{
877e1a37f3db4f2364e98ff057209a94aa9b23e5c9dBehdad Esfahbod  inline hb_string_t (void) : bytes (nullptr), len (0) {}
878e1a37f3db4f2364e98ff057209a94aa9b23e5c9dBehdad Esfahbod  inline hb_string_t (const char *bytes_, unsigned int len_) : bytes (bytes_), len (len_) {}
879e1a37f3db4f2364e98ff057209a94aa9b23e5c9dBehdad Esfahbod
880e35a763c07b60da6e5fbdb6edd9d25f575cd3d8bBehdad Esfahbod  inline int cmp (const hb_string_t &a) const
881e1a37f3db4f2364e98ff057209a94aa9b23e5c9dBehdad Esfahbod  {
882e35a763c07b60da6e5fbdb6edd9d25f575cd3d8bBehdad Esfahbod    if (len != a.len)
883e35a763c07b60da6e5fbdb6edd9d25f575cd3d8bBehdad Esfahbod      return (int) a.len - (int) len;
884e1a37f3db4f2364e98ff057209a94aa9b23e5c9dBehdad Esfahbod
885e35a763c07b60da6e5fbdb6edd9d25f575cd3d8bBehdad Esfahbod    return memcmp (a.bytes, bytes, len);
886e1a37f3db4f2364e98ff057209a94aa9b23e5c9dBehdad Esfahbod  }
887e1a37f3db4f2364e98ff057209a94aa9b23e5c9dBehdad Esfahbod  static inline int cmp (const void *pa, const void *pb)
888e1a37f3db4f2364e98ff057209a94aa9b23e5c9dBehdad Esfahbod  {
889e1a37f3db4f2364e98ff057209a94aa9b23e5c9dBehdad Esfahbod    hb_string_t *a = (hb_string_t *) pa;
890e1a37f3db4f2364e98ff057209a94aa9b23e5c9dBehdad Esfahbod    hb_string_t *b = (hb_string_t *) pb;
891e35a763c07b60da6e5fbdb6edd9d25f575cd3d8bBehdad Esfahbod    return b->cmp (*a);
892e1a37f3db4f2364e98ff057209a94aa9b23e5c9dBehdad Esfahbod  }
893e1a37f3db4f2364e98ff057209a94aa9b23e5c9dBehdad Esfahbod
894e1a37f3db4f2364e98ff057209a94aa9b23e5c9dBehdad Esfahbod  const char *bytes;
895e1a37f3db4f2364e98ff057209a94aa9b23e5c9dBehdad Esfahbod  unsigned int len;
896e1a37f3db4f2364e98ff057209a94aa9b23e5c9dBehdad Esfahbod};
897e1a37f3db4f2364e98ff057209a94aa9b23e5c9dBehdad Esfahbod
898e1a37f3db4f2364e98ff057209a94aa9b23e5c9dBehdad Esfahbod
899c57d454accff66e5f2c58006e8fb40bc020b6182Behdad Esfahbod#endif /* HB_PRIVATE_HH */
900