summaryrefslogtreecommitdiff
path: root/src/hb-private.h
blob: 9130b04642d2d419e35340abfc63cff90a76d1fd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
/*
 * Copyright (C) 2007,2008,2009  Red Hat, Inc.
 *
 *  This is part of HarfBuzz, a text shaping library.
 *
 * Permission is hereby granted, without written agreement and without
 * license or royalty fees, to use, copy, modify, and distribute this
 * software and its documentation for any purpose, provided that the
 * above copyright notice and the following two paragraphs appear in
 * all copies of this software.
 *
 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
 * DAMAGE.
 *
 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 *
 * Red Hat Author(s): Behdad Esfahbod
 */

#ifndef HB_PRIVATE_H
#define HB_PRIVATE_H

#if HAVE_CONFIG_H
#include "config.h"
#endif

#include "hb-common.h"

#include <stdlib.h>
#include <string.h>
#include <assert.h>

/* We only use these two for debug output.  However, the debug code is
 * always seen by the compiler (and optimized out in non-debug builds.
 * If including these becomes a problem, we can start thinking about
 * someway around that. */
#include <stdio.h>
#include <errno.h>


/* Essentials */

#ifndef NULL
# define NULL ((void *) 0)
#endif

#undef FALSE
#define FALSE 0

#undef TRUE
#define TRUE 1


/* Basics */

#undef MIN
#define MIN(a,b) ((a) < (b) ? (a) : (b))

#undef MAX
#define MAX(a,b) ((a) > (b) ? (a) : (b))

#ifndef HB_INTERNAL
# define HB_INTERNAL extern
#endif

#undef  ARRAY_LENGTH
#define ARRAY_LENGTH(__array) ((signed int) (sizeof (__array) / sizeof (__array[0])))

#define HB_STMT_START do
#define HB_STMT_END   while (0)

#define _ASSERT_STATIC1(_line, _cond) typedef int _static_assert_on_line_##_line##_failed[(_cond)?1:-1]
#define _ASSERT_STATIC0(_line, _cond) _ASSERT_STATIC1 (_line, (_cond))
#define ASSERT_STATIC(_cond) _ASSERT_STATIC0 (__LINE__, (_cond))


/* Misc */

#define ASSERT_SIZE(_type, _size) ASSERT_STATIC (sizeof (_type) == (_size))

/* Size signifying variable-sized array */
#define VAR 1

#define VAR0 (VAR+0)
#define ASSERT_SIZE_VAR(_type, _size, _var_type) \
	ASSERT_STATIC (sizeof (_type) == (_size) + VAR0 * sizeof (_var_type))
#define ASSERT_SIZE_VAR2(_type, _size, _var_type1, _var_type2) \
	ASSERT_STATIC (sizeof (_type) == (_size) + VAR0 * sizeof (_var_type1) + VAR0 * sizeof (_var_type2))

#if defined(__GNUC__) && (__GNUC__ > 2) && defined(__OPTIMIZE__)
#define _HB_BOOLEAN_EXPR(expr) \
  __extension__ ({ \
     int _hb_boolean_var_; \
     if (expr) \
	_hb_boolean_var_ = 1; \
     else \
	_hb_boolean_var_ = 0; \
     _hb_boolean_var_; \
  })
#define HB_LIKELY(expr) (__builtin_expect (_HB_BOOLEAN_EXPR(expr), 1))
#define HB_UNLIKELY(expr) (__builtin_expect (_HB_BOOLEAN_EXPR(expr), 0))
#else
#define HB_LIKELY(expr) (expr)
#define HB_UNLIKELY(expr) (expr)
#endif

#ifndef __GNUC__
#undef __attribute__
#define __attribute__(x)
#endif

#if __GNUC__ >= 3
#define HB_PURE_FUNC	__attribute__((pure))
#define HB_CONST_FUNC	__attribute__((const))
#else
#define HB_PURE_FUNC
#define HB_CONST_FUNC
#endif
#if __GNUC__ >= 4
#define HB_UNUSED	__attribute__((unused))
#else
#define HB_UNUSED
#endif


#if (defined(__WIN32__) && !defined(__WINE__)) || defined(_MSC_VER)
#define snprintf _snprintf
#endif

#ifdef _MSC_VER
#undef inline
#define inline __inline
#endif

#ifdef __STRICT_ANSI__
#undef inline
#define inline __inline__
#endif


#if __GNUC__ >= 3
#define HB_FUNC __PRETTY_FUNCTION__
#elif defined(_MSC_VER)
#define HB_FUNC __FUNCSIG__
#else
#define HB_FUNC __func__
#endif


/* Return the number of 1 bits in mask.
 *
 * GCC 3.4 supports a "population count" builtin, which on many targets is
 * implemented with a single instruction. There is a fallback definition
 * in libgcc in case a target does not have one, which should be just as
 * good as the open-coded solution below, (which is "HACKMEM 169").
 */
static HB_UNUSED inline unsigned int
_hb_popcount32 (uint32_t mask)
{
#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
    return __builtin_popcount (mask);
#else
    register uint32_t y;

    y = (mask >> 1) &033333333333;
    y = mask - y - ((y >>1) & 033333333333);
    return (((y + (y >> 3)) & 030707070707) % 077);
#endif
}


/* Multiplies a 16dot16 value by another value, then truncates the result */
#define _hb_16dot16_mul_round(A,B) (((int64_t) (A) * (B) + 0x8000) / 0x10000)


/* We need external help for these */

#ifdef HAVE_GLIB

#include <glib.h>

typedef int hb_atomic_int_t;
#define hb_atomic_int_fetch_and_add(AI, V)	g_atomic_int_exchange_and_add (&(AI), V)
#define hb_atomic_int_get(AI)			g_atomic_int_get (&(AI))
#define hb_atomic_int_set(AI, V)		g_atomic_int_set (&(AI), V)

typedef GStaticMutex hb_mutex_t;
#define HB_MUTEX_INIT			G_STATIC_MUTEX_INIT
#define hb_mutex_init(M)		g_static_mutex_init (&M)
#define hb_mutex_lock(M)		g_static_mutex_lock (&M)
#define hb_mutex_trylock(M)		g_static_mutex_trylock (&M)
#define hb_mutex_unlock(M)		g_static_mutex_unlock (&M)

#else

#ifdef _MSC_VER
#pragma message(__LOC__"Could not find any system to define platform macros, library will NOT be thread-safe")
#else
#warning "Could not find any system to define platform macros, library will NOT be thread-safe"
#endif

typedef int hb_atomic_int_t;
#define hb_atomic_int_fetch_and_add(AI, V)	((AI) += (V), (AI) - (V))
#define hb_atomic_int_get(AI)			(AI)
#define hb_atomic_int_set(AI, V)		HB_STMT_START { (AI) = (V); } HB_STMT_END

typedef int hb_mutex_t;
#define HB_MUTEX_INIT				0
#define hb_mutex_init(M)			HB_STMT_START { (M) = 0; } HB_STMT_END
#define hb_mutex_lock(M)			HB_STMT_START { (M) = 1; } HB_STMT_END
#define hb_mutex_trylock(M)			((M) = 1, 1)
#define hb_mutex_unlock(M)			HB_STMT_START { (M) = 0; } HB_STMT_END

#endif


/* Big-endian handling */

#define hb_be_uint16(v)		((uint16_t) ((((const uint8_t *)&(v))[0] << 8) + (((const uint8_t *)&(v))[1])))

#define hb_be_uint16_put(v,V)	HB_STMT_START { v[0] = (V>>8); v[1] = (V); } HB_STMT_END
#define hb_be_uint16_get(v)	(uint16_t) ((v[0] << 8) + v[1])
#define hb_be_uint16_cmp(a,b)	(a[0] == b[0] && a[1] == b[1])

#define hb_be_uint32_put(v,V)	HB_STMT_START { v[0] = (V>>24); v[1] = (V>>16); v[2] = (V>>8); v[3] = (V); } HB_STMT_END
#define hb_be_uint32_get(v)	(uint32_t) ((v[0] << 24) + (v[1] << 16) + (v[2] << 8) + v[3])
#define hb_be_uint32_cmp(a,b)	(a[0] == b[0] && a[1] == b[1] && a[2] == b[2] && a[3] == b[3])


/* Debug */

#ifndef HB_DEBUG
#define HB_DEBUG 0
#endif

static HB_UNUSED inline hb_bool_t /* always returns TRUE */
_hb_trace (const char *what,
	   const char *function,
	   const void *obj,
	   unsigned int depth,
	   unsigned int max_depth)
{
  if (depth < max_depth)
    fprintf (stderr, "%s(%p) %-*d-> %s\n", what, obj, depth, depth, function);
  return TRUE;
}


#include "hb-object-private.h"

#endif /* HB_PRIVATE_H */