1/*
2 * Copyright © 2007,2008,2009 Red Hat, Inc.
3 * Copyright © 2011,2012 Google, Inc.
4 *
5 * This is part of HarfBuzz, a text shaping library.
6 *
7 * Permission is hereby granted, without written agreement and without
8 * license or royalty fees, to use, copy, modify, and distribute this
9 * software and its documentation for any purpose, provided that the
10 * above copyright notice and the following two paragraphs appear in
11 * all copies of this software.
12 *
13 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
14 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
15 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
16 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
17 * DAMAGE.
18 *
19 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
20 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
21 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
22 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
23 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
24 *
25 * Red Hat Author(s): Behdad Esfahbod
26 * Google Author(s): Behdad Esfahbod
27 */
28
29#ifndef HB_HH
30#define HB_HH
31
32#define _GNU_SOURCE 1
33
34#ifdef HAVE_CONFIG_H
35#include "config.h"
36#endif
37
38#include "hb.h"
39#define HB_H_IN
40#ifdef HAVE_OT
41#include "hb-ot.h"
42#define HB_OT_H_IN
43#endif
44
45#include <math.h>
46#include <stdlib.h>
47#include <stddef.h>
48#include <string.h>
49#include <assert.h>
50#include <errno.h>
51#include <stdio.h>
52#include <stdarg.h>
53
54#if (defined(_MSC_VER) && _MSC_VER >= 1500) || defined(__MINGW32__)
55#include <intrin.h>
56#endif
57
58#define HB_PASTE1(a,b) a##b
59#define HB_PASTE(a,b) HB_PASTE1(a,b)
60
61
62/* Compile-time custom allocator support. */
63
64#if defined(hb_malloc_impl) \
65 && defined(hb_calloc_impl) \
66 && defined(hb_realloc_impl) \
67 && defined(hb_free_impl)
68extern "C" void* hb_malloc_impl(size_t size);
69extern "C" void* hb_calloc_impl(size_t nmemb, size_t size);
70extern "C" void* hb_realloc_impl(void *ptr, size_t size);
71extern "C" void hb_free_impl(void *ptr);
72#define malloc hb_malloc_impl
73#define calloc hb_calloc_impl
74#define realloc hb_realloc_impl
75#define free hb_free_impl
76
77#if defined(hb_memalign_impl)
78extern "C" int hb_memalign_impl(void **memptr, size_t alignment, size_t size);
79#define posix_memalign hb_memalign_impl
80#else
81#undef HAVE_POSIX_MEMALIGN
82#endif
83
84#endif
85
86
87/*
88 * Compiler attributes
89 */
90
91#if __cplusplus < 201103L
92
93#ifndef nullptr
94#define nullptr NULL
95#endif
96
97#ifndef constexpr
98#define constexpr const
99#endif
100
101#ifndef static_assert
102#define static_assert(e, msg) \
103 HB_UNUSED typedef int HB_PASTE(static_assertion_failed_at_line_, __LINE__) [(e) ? 1 : -1]
104#endif // static_assert
105
106#ifdef __GNUC__
107#if (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 8))
108#define thread_local __thread
109#endif
110#else
111#define thread_local
112#endif
113
114template <typename T>
115struct _hb_alignof
116{
117 struct s
118 {
119 char c;
120 T t;
121 };
122 static constexpr size_t value = offsetof (s, t);
123};
124#ifndef alignof
125#define alignof(x) (_hb_alignof<x>::value)
126#endif
127
128/* https://github.com/harfbuzz/harfbuzz/issues/1127 */
129#ifndef explicit_operator
130#define explicit_operator
131#endif
132
133#else /* __cplusplus >= 201103L */
134
135/* https://github.com/harfbuzz/harfbuzz/issues/1127 */
136#ifndef explicit_operator
137#define explicit_operator explicit
138#endif
139
140#endif /* __cplusplus < 201103L */
141
142
143#if (defined(__GNUC__) || defined(__clang__)) && defined(__OPTIMIZE__)
144#define likely(expr) (__builtin_expect (!!(expr), 1))
145#define unlikely(expr) (__builtin_expect (!!(expr), 0))
146#else
147#define likely(expr) (expr)
148#define unlikely(expr) (expr)
149#endif
150
151#if !defined(__GNUC__) && !defined(__clang__)
152#undef __attribute__
153#define __attribute__(x)
154#endif
155
156#if __GNUC__ >= 3
157#define HB_PURE_FUNC __attribute__((pure))
158#define HB_CONST_FUNC __attribute__((const))
159#define HB_PRINTF_FUNC(format_idx, arg_idx) __attribute__((__format__ (__printf__, format_idx, arg_idx)))
160#else
161#define HB_PURE_FUNC
162#define HB_CONST_FUNC
163#define HB_PRINTF_FUNC(format_idx, arg_idx)
164#endif
165#if __GNUC__ >= 4
166#define HB_UNUSED __attribute__((unused))
167#elif defined(_MSC_VER) /* https://github.com/harfbuzz/harfbuzz/issues/635 */
168#define HB_UNUSED __pragma(warning(suppress: 4100 4101))
169#else
170#define HB_UNUSED
171#endif
172
173#ifndef HB_INTERNAL
174# if !defined(HB_NO_VISIBILITY) && !defined(__MINGW32__) && !defined(__CYGWIN__) && !defined(_MSC_VER) && !defined(__SUNPRO_CC)
175# define HB_INTERNAL __attribute__((__visibility__("hidden")))
176# elif defined(__MINGW32__)
177 /* We use -export-symbols on mingw32, since it does not support visibility
178 * attribute. */
179# define HB_INTERNAL
180#else
181# define HB_INTERNAL
182# define HB_NO_VISIBILITY 1
183# endif
184#endif
185
186#if __GNUC__ >= 3
187#define HB_FUNC __PRETTY_FUNCTION__
188#elif defined(_MSC_VER)
189#define HB_FUNC __FUNCSIG__
190#else
191#define HB_FUNC __func__
192#endif
193
194#if defined(__SUNPRO_CC) && (__SUNPRO_CC < 0x5140)
195/* https://github.com/harfbuzz/harfbuzz/issues/630 */
196#define __restrict
197#endif
198
199/*
200 * Borrowed from https://bugzilla.mozilla.org/show_bug.cgi?id=1215411
201 * HB_FALLTHROUGH is an annotation to suppress compiler warnings about switch
202 * cases that fall through without a break or return statement. HB_FALLTHROUGH
203 * is only needed on cases that have code:
204 *
205 * switch (foo) {
206 * case 1: // These cases have no code. No fallthrough annotations are needed.
207 * case 2:
208 * case 3:
209 * foo = 4; // This case has code, so a fallthrough annotation is needed:
210 * HB_FALLTHROUGH;
211 * default:
212 * return foo;
213 * }
214 */
215#if defined(__clang__) && __cplusplus >= 201103L
216 /* clang's fallthrough annotations are only available starting in C++11. */
217# define HB_FALLTHROUGH [[clang::fallthrough]]
218#elif __GNUC__ >= 7
219 /* GNU fallthrough attribute is available from GCC7 */
220# define HB_FALLTHROUGH __attribute__((fallthrough))
221#elif defined(_MSC_VER)
222 /*
223 * MSVC's __fallthrough annotations are checked by /analyze (Code Analysis):
224 * https://msdn.microsoft.com/en-us/library/ms235402%28VS.80%29.aspx
225 */
226# include <sal.h>
227# define HB_FALLTHROUGH __fallthrough
228#else
229# define HB_FALLTHROUGH /* FALLTHROUGH */
230#endif
231
232#if defined(_WIN32) || defined(__CYGWIN__)
233 /* We need Windows Vista for both Uniscribe backend and for
234 * MemoryBarrier. We don't support compiling on Windows XP,
235 * though we run on it fine. */
236# if defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0600
237# undef _WIN32_WINNT
238# endif
239# ifndef _WIN32_WINNT
240# define _WIN32_WINNT 0x0600
241# endif
242# ifndef WIN32_LEAN_AND_MEAN
243# define WIN32_LEAN_AND_MEAN 1
244# endif
245# ifndef STRICT
246# define STRICT 1
247# endif
248
249# if defined(_WIN32_WCE)
250 /* Some things not defined on Windows CE. */
251# define vsnprintf _vsnprintf
252# define getenv(Name) nullptr
253# if _WIN32_WCE < 0x800
254# define setlocale(Category, Locale) "C"
255static int errno = 0; /* Use something better? */
256# endif
257# elif defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP)
258# define getenv(Name) nullptr
259# endif
260# if defined(_MSC_VER) && _MSC_VER < 1900
261# define snprintf _snprintf
262# endif
263#endif
264
265#if HAVE_ATEXIT
266/* atexit() is only safe to be called from shared libraries on certain
267 * platforms. Whitelist.
268 * https://bugs.freedesktop.org/show_bug.cgi?id=82246 */
269# if defined(__linux) && defined(__GLIBC_PREREQ)
270# if __GLIBC_PREREQ(2,3)
271/* From atexit() manpage, it's safe with glibc 2.2.3 on Linux. */
272# define HB_USE_ATEXIT 1
273# endif
274# elif defined(_MSC_VER) || defined(__MINGW32__)
275/* For MSVC:
276 * https://msdn.microsoft.com/en-us/library/tze57ck3.aspx
277 * https://msdn.microsoft.com/en-us/library/zk17ww08.aspx
278 * mingw32 headers say atexit is safe to use in shared libraries.
279 */
280# define HB_USE_ATEXIT 1
281# elif defined(__ANDROID__)
282/* This is available since Android NKD r8 or r8b:
283 * https://issuetracker.google.com/code/p/android/issues/detail?id=6455
284 */
285# define HB_USE_ATEXIT 1
286# elif defined(__APPLE__)
287/* For macOS and related platforms, the atexit man page indicates
288 * that it will be invoked when the library is unloaded, not only
289 * at application exit.
290 */
291# define HB_USE_ATEXIT 1
292# endif
293#endif
294#ifdef HB_NO_ATEXIT
295# undef HB_USE_ATEXIT
296#endif
297
298#define HB_STMT_START do
299#define HB_STMT_END while (0)
300
301/* Static-assert as expression. */
302template <unsigned int cond> class hb_assert_constant_t;
303template <> class hb_assert_constant_t<1> {};
304#define ASSERT_STATIC_EXPR_ZERO(_cond) (0 * (unsigned int) sizeof (hb_assert_constant_t<_cond>))
305
306/* Lets assert int types. Saves trouble down the road. */
307static_assert ((sizeof (int8_t) == 1), "");
308static_assert ((sizeof (uint8_t) == 1), "");
309static_assert ((sizeof (int16_t) == 2), "");
310static_assert ((sizeof (uint16_t) == 2), "");
311static_assert ((sizeof (int32_t) == 4), "");
312static_assert ((sizeof (uint32_t) == 4), "");
313static_assert ((sizeof (int64_t) == 8), "");
314static_assert ((sizeof (uint64_t) == 8), "");
315static_assert ((sizeof (hb_codepoint_t) == 4), "");
316static_assert ((sizeof (hb_position_t) == 4), "");
317static_assert ((sizeof (hb_mask_t) == 4), "");
318static_assert ((sizeof (hb_var_int_t) == 4), "");
319
320
321/* We like our types POD */
322
323#define _ASSERT_TYPE_POD1(_line, _type) union _type_##_type##_on_line_##_line##_is_not_POD { _type instance; }
324#define _ASSERT_TYPE_POD0(_line, _type) _ASSERT_TYPE_POD1 (_line, _type)
325#define ASSERT_TYPE_POD(_type) _ASSERT_TYPE_POD0 (__LINE__, _type)
326
327#ifdef __GNUC__
328# define _ASSERT_INSTANCE_POD1(_line, _instance) \
329 HB_STMT_START { \
330 typedef __typeof__(_instance) _type_##_line; \
331 _ASSERT_TYPE_POD1 (_line, _type_##_line); \
332 } HB_STMT_END
333#else
334# define _ASSERT_INSTANCE_POD1(_line, _instance) typedef int _assertion_on_line_##_line##_not_tested
335#endif
336# define _ASSERT_INSTANCE_POD0(_line, _instance) _ASSERT_INSTANCE_POD1 (_line, _instance)
337# define ASSERT_INSTANCE_POD(_instance) _ASSERT_INSTANCE_POD0 (__LINE__, _instance)
338
339/* Check _assertion in a method environment */
340#define _ASSERT_POD1(_line) \
341 HB_UNUSED inline void _static_assertion_on_line_##_line (void) const \
342 { _ASSERT_INSTANCE_POD1 (_line, *this); /* Make sure it's POD. */ }
343# define _ASSERT_POD0(_line) _ASSERT_POD1 (_line)
344# define ASSERT_POD() _ASSERT_POD0 (__LINE__)
345
346
347#define HB_DISALLOW_COPY_AND_ASSIGN(TypeName) \
348 TypeName(const TypeName&); \
349 void operator=(const TypeName&)
350
351
352/*
353 * Compiler-assisted vectorization parameters.
354 */
355
356/*
357 * Disable vectorization for now. To correctly use them, we should
358 * use posix_memalign() to allocate in hb_vector_t. Otherwise, can
359 * cause misaligned access.
360 *
361 * https://bugs.chromium.org/p/chromium/issues/detail?id=860184
362 */
363#if !defined(HB_VECTOR_SIZE)
364# define HB_VECTOR_SIZE 0
365#endif
366
367/* The `vector_size' attribute was introduced in gcc 3.1. */
368#if !defined(HB_VECTOR_SIZE)
369# if defined( __GNUC__ ) && ( __GNUC__ >= 4 )
370# define HB_VECTOR_SIZE 128
371# else
372# define HB_VECTOR_SIZE 0
373# endif
374#endif
375static_assert (0 == (HB_VECTOR_SIZE & (HB_VECTOR_SIZE - 1)), "HB_VECTOR_SIZE is not power of 2.");
376static_assert (0 == (HB_VECTOR_SIZE % 64), "HB_VECTOR_SIZE is not multiple of 64.");
377#if HB_VECTOR_SIZE
378typedef uint64_t hb_vector_size_impl_t __attribute__((vector_size (HB_VECTOR_SIZE / 8)));
379#else
380typedef uint64_t hb_vector_size_impl_t;
381#endif
382
383
384/* HB_NDEBUG disables some sanity checks that are very safe to disable and
385 * should be disabled in production systems. If NDEBUG is defined, enable
386 * HB_NDEBUG; but if it's desirable that normal assert()s (which are very
387 * light-weight) to be enabled, then HB_DEBUG can be defined to disable
388 * the costlier checks. */
389#ifdef NDEBUG
390#define HB_NDEBUG 1
391#endif
392
393
394/* Flags */
395
396/* Enable bitwise ops on enums marked as flags_t */
397/* To my surprise, looks like the function resolver is happy to silently cast
398 * one enum to another... So this doesn't provide the type-checking that I
399 * originally had in mind... :(.
400 *
401 * For MSVC warnings, see: https://github.com/harfbuzz/harfbuzz/pull/163
402 */
403#ifdef _MSC_VER
404# pragma warning(disable:4200)
405# pragma warning(disable:4800)
406#endif
407#define HB_MARK_AS_FLAG_T(T) \
408 extern "C++" { \
409 static inline T operator | (T l, T r) { return T ((unsigned) l | (unsigned) r); } \
410 static inline T operator & (T l, T r) { return T ((unsigned) l & (unsigned) r); } \
411 static inline T operator ^ (T l, T r) { return T ((unsigned) l ^ (unsigned) r); } \
412 static inline T operator ~ (T r) { return T (~(unsigned int) r); } \
413 static inline T& operator |= (T &l, T r) { l = l | r; return l; } \
414 static inline T& operator &= (T& l, T r) { l = l & r; return l; } \
415 static inline T& operator ^= (T& l, T r) { l = l ^ r; return l; } \
416 }
417
418/* Useful for set-operations on small enums.
419 * For example, for testing "x ∈ {x1, x2, x3}" use:
420 * (FLAG_UNSAFE(x) & (FLAG(x1) | FLAG(x2) | FLAG(x3)))
421 */
422#define FLAG(x) (ASSERT_STATIC_EXPR_ZERO ((unsigned int)(x) < 32) + (1U << (unsigned int)(x)))
423#define FLAG_UNSAFE(x) ((unsigned int)(x) < 32 ? (1U << (unsigned int)(x)) : 0)
424#define FLAG_RANGE(x,y) (ASSERT_STATIC_EXPR_ZERO ((x) < (y)) + FLAG(y+1) - FLAG(x))
425
426
427/* Size signifying variable-sized array */
428#define VAR 1
429
430
431/* fallback for round() */
432static inline double
433_hb_round (double x)
434{
435 if (x >= 0)
436 return floor (x + 0.5);
437 else
438 return ceil (x - 0.5);
439}
440#if !defined (HAVE_ROUND) && !defined (HAVE_DECL_ROUND)
441#define round(x) _hb_round(x)
442#endif
443
444
445/* fallback for posix_memalign() */
446static inline int
447_hb_memalign(void **memptr, size_t alignment, size_t size)
448{
449 if (unlikely (0 != (alignment & (alignment - 1)) ||
450 !alignment ||
451 0 != (alignment & (sizeof (void *) - 1))))
452 return EINVAL;
453
454 char *p = (char *) malloc (size + alignment - 1);
455 if (unlikely (!p))
456 return ENOMEM;
457
458 size_t off = (size_t) p & (alignment - 1);
459 if (off)
460 p += alignment - off;
461
462 *memptr = (void *) p;
463
464 return 0;
465}
466#if !defined(posix_memalign) && !defined(HAVE_POSIX_MEMALIGN)
467#define posix_memalign _hb_memalign
468#endif
469
470
471/* Headers we include for everyone. Keep sorted. They express dependency amongst
472 * themselves, but no other file should include them.*/
473#include "hb-atomic.hh"
474#include "hb-debug.hh"
475#include "hb-dsalgs.hh"
476#include "hb-mutex.hh"
477#include "hb-null.hh"
478#include "hb-object.hh"
479
480#endif /* HB_HH */
481