libacfutils
A general purpose library of utility functions designed to make it easier to develop addons for the X-Plane flight simulator.
Loading...
Searching...
No Matches
sysmacros.h
Go to the documentation of this file.
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license in the file COPYING
10 * or http://www.opensource.org/licenses/CDDL-1.0.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file COPYING.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22/*
23 * Copyright 2018 Saso Kiselkov. All rights reserved.
24 */
29#ifndef _ACF_UTILS_SYSMACROS_H_
30#define _ACF_UTILS_SYSMACROS_H_
31
32#if IBM
33#include <windows.h>
34#endif /* IBM */
35
36#include "types.h"
37
38#ifdef __cplusplus
39extern "C" {
40#endif
41
42#define NO_ACF_TYPE 0
43#define FF_A320_ACF_TYPE 1
44
45#if IBM
46#define DIRSEP '\\'
47#define DIRSEP_S "\\" /* DIRSEP as a string */
48#else /* !IBM */
49#define DIRSEP '/'
50#define DIRSEP_S "/" /* DIRSEP as a string */
51#ifndef MAX_PATH
52#define MAX_PATH 512
53#endif
54#endif /* !IBM */
55
56#if defined(__GNUC__) || defined(__clang__)
57#define DEPRECATED_FUNC(f) f __attribute__((deprecated))
58#define DEPRECATED_ATTR __attribute__((deprecated))
59#define PRINTF_ATTR(x) __attribute__((format(printf, x, x + 1)))
60#define PRINTF_ATTR2(x,y) __attribute__((format(printf, x, y)))
61#define PRINTF_FORMAT(f) f
62#define SENTINEL_ATTR __attribute__((sentinel))
63#define HOT_ATTR __attribute__((hot))
64#define PURE_ATTR __attribute__((pure))
65#define ALWAYS_INLINE_ATTR __attribute__((always_inline))
66#define ALIGN_ATTR(x) __attribute__((aligned(x)))
67
68#ifndef BSWAP32
69#define BSWAP16(x) __builtin_bswap16((x))
70#define BSWAP32(x) __builtin_bswap32((x))
71#define BSWAP64(x) __builtin_bswap64((x))
72#endif /* BSWAP32 */
73
74#define COND_LIKELY(x) __builtin_expect(x, 1)
75#define COND_UNLIKELY(x) __builtin_expect(x, 0)
76
77#else /* !__GNUC__ && !__clang__ */
78
79#define DEPRECATED_ATTR
80#define PRINTF_ATTR(x)
81#define PRINTF_ATTR2(x,y)
82#define SENTINEL_ATTR
83#define HOT_ATTR
84#define PURE_ATTR
85#define ALWAYS_INLINE_ATTR
86
87#define COND_LIKELY(x) x
88#define COND_UNLIKELY(x) x
89
90#if defined(_MSC_VER)
91#define ALIGN_ATTR(x) __declspec(align(x))
92#else
93#define ALIGN_ATTR(x)
94#endif
95
96#if _MSC_VER >= 1400
97# define DEPRECATED_FUNC(f) __declspec(deprecated) f
98# include <sal.h>
99# if _MSC_VER > 1400
100# define PRINTF_FORMAT(f) _Printf_format_string_ f
101# else /* _MSC_VER == 1400 */
102# define PRINTF_FORMAT(f) __format_string f
103# endif /* FORMAT_STRING */
104#else /* _MSC_VER < 1400 */
105# define PRINTF_FORMAT(f) f
106#endif /* _MSC_VER */
107
108#ifndef BSWAP32
109#define BSWAP16(x) \
110 ((((x) & 0xff00u) >> 8) | \
111 (((x) & 0x00ffu) << 8))
112#define BSWAP32(x) \
113 ((((x) & 0xff000000u) >> 24) | \
114 (((x) & 0x00ff0000u) >> 8) | \
115 (((x) & 0x0000ff00u) << 8) | \
116 (((x) & 0x000000ffu) << 24))
117#define BSWAP64(x) \
118 ((((x) & 0x00000000000000ffllu) >> 56) | \
119 (((x) & 0x000000000000ff00llu) << 40) | \
120 (((x) & 0x0000000000ff0000llu) << 24) | \
121 (((x) & 0x00000000ff000000llu) << 8) | \
122 (((x) & 0x000000ff00000000llu) >> 8) | \
123 (((x) & 0x0000ff0000000000llu) >> 24) | \
124 (((x) & 0x00ff000000000000llu) >> 40) | \
125 (((x) & 0xff00000000000000llu) << 56))
126#endif /* BSWAP32 */
127#endif /* !__GNUC__ && !__clang__ */
128
129#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
130#define BE64(x) (x)
131#define BE32(x) (x)
132#define BE16(x) (x)
133#else /* __BYTE_ORDER__ != __ORDER_BIG_ENDIAN__ */
134#define BE64(x) BSWAP64(x)
135#define BE32(x) BSWAP32(x)
136#define BE16(x) BSWAP16(x)
137#endif /* __BYTE_ORDER__ != __ORDER_BIG_ENDIAN__ */
138
139#define DESTROY(x) do { free(x); (x) = NULL; } while (0)
140#define DESTROY_OP(var, zero_val, destroy_op) \
141 do { \
142 if ((var) != (zero_val)) { \
143 destroy_op; \
144 (var) = (zero_val); \
145 } \
146 } while (0)
147
148#ifdef WINDOWS
149#define PATHSEP "\\"
150#else
151#define PATHSEP "/"
152#endif
153
154/* Minimum/Maximum allowable elevation AMSL of anything */
155#define MIN_ELEV -2000.0
156#define MAX_ELEV 30000.0
157
158/* Minimum/Maximum allowable altitude AMSL of anything */
159#define MIN_ALT -2000.0
160#define MAX_ALT 100000.0
161
162/* Maximum valid speed of anything */
163#define MAX_SPD 1000.0
164
165/* Minimum/Maximum allowable arc radius on any procedure */
166#define MIN_ARC_RADIUS 0.1
167#define MAX_ARC_RADIUS 100.0
168
169/*
170 * Compile-time assertion. The condition 'x' must be constant.
171 * TYPE_ASSERT is a compile-time assertion, but which checks that
172 * the type of `x' is `type'.
173 */
174#if __STDC_VERSION__ >= 201112L && \
175 (!defined(__GNUC__) || __GNUC__ > 7 || defined(__clang__))
176#define CTASSERT(x) _Static_assert((x), #x)
177#define TYPE_ASSERT(x, type) \
178 CTASSERT(_Generic((x), type: 1, default: 0) != 0)
179#define NOT_TYPE_ASSERT(x, type) \
180 CTASSERT(_Generic((x), type: 0, default: 1) != 0)
181#else /* __STDC_VERSION__ < 201112L */
182#define TYPE_ASSERT(x, type)
183#define NOT_TYPE_ASSERT(x, type)
184#if defined(__GNUC__) || defined(__clang__)
185#define CTASSERT(x) _CTASSERT(x, __LINE__)
186#define _CTASSERT(x, y) __CTASSERT(x, y)
187#define __CTASSERT(x, y) \
188 typedef char __compile_time_assertion__ ## y [(x) ? 1 : -1] \
189 __attribute__((unused))
190#else /* !defined(__GNUC__) && !defined(__clang__) */
191#define CTASSERT(x)
192#endif /* !defined(__GNUC__) && !defined(__clang__) */
193#endif /* __STDC_VERSION__ < 201112L */
194
195#if defined(__GNUC__) || defined(__clang__)
196
197#define highbit64(x) (64 - __builtin_clzll(x) - 1)
198#define highbit32(x) (32 - __builtin_clzll(x) - 1)
199
200#elif defined(_MSC_VER)
201
202static inline unsigned
203highbit32(unsigned int x)
204{
205 unsigned long idx;
206 _BitScanReverse(&idx, x);
207 return (idx);
208}
209
210static inline unsigned
211highbit64(unsigned long long x)
212{
213 unsigned long idx;
214 _BitScanReverse64(&idx, x);
215 return (idx);
216}
217#else
218#error "Compiler platform unsupported, please add highbit definition"
219#endif
220
221#ifndef MIN
222#define MIN(x, y) ((x) < (y) ? (x) : (y))
223#endif
224#ifndef MAX
225#define MAX(x, y) ((x) > (y) ? (x) : (y))
226#endif
227#ifndef AVG
228#define AVG(x, y) (((x) + (y)) / 2.0)
229#endif
230#if defined(_MSC_VER)
231#define FILTER_IN_TYPE(x) double
232#else
233#define FILTER_IN_TYPE(x) __typeof__(x)
234#endif
235/*
236 * Provides a gradual method of integrating an old value until it approaches
237 * a new target value. This is used in iterative processes by calling the
238 * FILTER_IN macro repeatedly a certain time intervals (d_t = delta-time).
239 * As time progresses, old_val will gradually be made to approach new_val.
240 * The lag serves to make the approach slower or faster (e.g. a value of
241 * '2' and d_t in seconds makes old_val approach new_val with a ramp that
242 * is approximately 2 seconds long).
243 */
244#define FILTER_IN(old_val, new_val, d_t, lag) \
245 do { \
246 FILTER_IN_TYPE(old_val) o = (old_val); \
247 FILTER_IN_TYPE(new_val) n = (new_val); \
248 ASSERT(!isnan(o)); \
249 (old_val) += (n - o) * ((d_t) / (lag)); \
250 /* Prevent an overshoot */ \
251 if ((o < n && (old_val) > n) || \
252 (o > n && (old_val) < n)) \
253 (old_val) = n; \
254 } while (0)
255/*
256 * Same as FILTER_IN, but handles NAN values for old_val and new_val properly.
257 * If new_val is NAN, old_val is set to NAN. Otherwise if old_val is NAN,
258 * it is set to new_val directly (without gradual filtering). Otherwise this
259 * simply calls the FILTER_IN macro as normal.
260 */
261#define FILTER_IN_NAN(old_val, new_val, d_t, lag) \
262 do { \
263 FILTER_IN_TYPE(old_val) o = (old_val); \
264 FILTER_IN_TYPE(new_val) n = (new_val); \
265 if (isnan(n)) \
266 (old_val) = NAN; \
267 else if (isnan(o)) \
268 (old_val) = (new_val); \
269 else \
270 FILTER_IN(old_val, new_val, d_t, lag); \
271 } while (0)
272
273/*
274 * Linearly interpolates old_val until it is equal to tgt. The current
275 * time delta is d_t (in seconds). The interpolation speed is step/second.
276 */
277#define FILTER_IN_LIN(old_val, tgt, d_t, step) \
278 do { \
279 double o = (old_val); \
280 double t = (tgt); \
281 double s; \
282 if (isnan(o)) \
283 o = t; \
284 if (o < t) \
285 s = (d_t) * (step); \
286 else \
287 s = (d_t) * (-(step)); \
288 if ((o <= t && o + s > t) || (o >= t && o + s < t)) \
289 (old_val) = t; \
290 else \
291 (old_val) += s; \
292 } while (0)
293
294#define SCANF_STR_AUTOLEN_IMPL(_str_) #_str_
295#define SCANF_STR_AUTOLEN(_str_) SCANF_STR_AUTOLEN_IMPL(_str_)
296
330#ifndef REQ_PTR
331#if __STDC_VERSION__ >= 201112L
332#define REQ_PTR(x) x[static 1]
333#else
334#define REQ_PTR(x) *x
335#endif
336#endif // !defined(REQ_PTR)
337
371#ifndef REQ_ARR
372#if __STDC_VERSION__ >= 201112L
373#define REQ_ARR(x, n) x[static (n)]
374#else
375#define REQ_ARR(x) x[n]
376#endif
377#endif // !defined(REQ_ARR)
378
414#ifndef ENUM_BIT_WIDTH_CHECK
415#define ENUM_BIT_WIDTH_CHECK(enum_type, num_bits, ...) \
416 do { \
417 enum_type __enum_check_value__ = 0; \
418 CTASSERT(num_bits > 0); \
419 enum { __enum_check_max_value__ = (1 << (num_bits)) - 1 }; \
420 switch (__enum_check_value__) { \
421 __VA_ARGS__ \
422 } \
423 } while (0)
424#define ENUM_BIT_WIDTH_CHECK_VARIANT(variant_name) \
425 case variant_name: { \
426 CTASSERT((int)variant_name >= 0); \
427 CTASSERT((unsigned long long)variant_name <= \
428 (unsigned long long)__enum_check_max_value__); \
429 } \
430 break
431#endif // !defined(ENUM_BIT_WIDTH_CHECK)
432
433#ifdef __cplusplus
434}
435#endif
436
437#endif /* _ACF_UTILS_SYSMACROS_H_ */