PipeWire
1.7.0
Toggle main menu visibility
Loading...
Searching...
No Matches
defs.h
Go to the documentation of this file.
1
/* Simple Plugin API */
2
/* SPDX-FileCopyrightText: Copyright © 2018 Wim Taymans */
3
/* SPDX-License-Identifier: MIT */
4
5
#ifndef SPA_UTILS_DEFS_H
6
#define SPA_UTILS_DEFS_H
7
8
#include <inttypes.h>
9
#include <signal.h>
10
#include <stdlib.h>
11
#include <
string.h
>
12
#include <stddef.h>
13
#include <limits.h>
14
#include <stdio.h>
15
16
#ifdef __cplusplus
17
extern
"C"
{
18
# if __cplusplus >= 201103L
19
# define SPA_STATIC_ASSERT_IMPL(expr, msg, ...) static_assert(expr, msg)
20
# define SPA_ALIGNOF alignof
21
# endif
22
#elif __STDC_VERSION__ >= 202311L
23
# define SPA_STATIC_ASSERT_IMPL(expr, msg, ...) static_assert(expr, msg)
24
# define SPA_ALIGNOF alignof
25
#else
26
# include <stdbool.h>
27
# if __STDC_VERSION__ >= 201112L
28
# define SPA_STATIC_ASSERT_IMPL(expr, msg, ...) _Static_assert(expr, msg)
29
# define SPA_ALIGNOF _Alignof
30
# endif
31
#endif
32
#ifndef SPA_STATIC_ASSERT_IMPL
33
#define SPA_STATIC_ASSERT_IMPL(expr, ...) \
34
((void)sizeof(struct { int spa_static_assertion_failed : 2 * !!(expr) - 1; }))
35
#endif
36
#ifndef SPA_ALIGNOF
37
#define SPA_ALIGNOF __alignof__
38
#endif
39
40
#define SPA_STATIC_ASSERT(expr, ...) SPA_STATIC_ASSERT_IMPL(expr, ## __VA_ARGS__, "`" #expr "` evaluated to false")
41
42
#define SPA_CONCAT_NOEXPAND(a, b) a ## b
43
#define SPA_CONCAT(a, b) SPA_CONCAT_NOEXPAND(a, b)
44
49
54
70
#if defined(__clang__) && defined(__cplusplus) && __cplusplus >= 201103L
71
/* clang's fallthrough annotations are only available starting in C++11. */
72
# define SPA_FALLTHROUGH [[clang::fallthrough]];
73
#elif __GNUC__ >= 7 || __clang_major__ >= 10
74
# define SPA_FALLTHROUGH __attribute__ ((fallthrough));
75
#else
76
# define SPA_FALLTHROUGH
/* FALLTHROUGH */
77
#endif
78
79
#define SPA_FLAG_MASK(field,mask,flag) (((field) & (mask)) == (flag))
80
#define SPA_FLAG_IS_SET(field,flag) SPA_FLAG_MASK(field, flag, flag)
81
82
#define SPA_FLAG_SET(field,flag) ((field) |= (flag))
83
#define SPA_FLAG_CLEAR(field, flag) \
84
({ \
85
SPA_STATIC_ASSERT(__builtin_constant_p(flag) ? \
86
(__typeof__(flag))(__typeof__(field))(__typeof__(flag))(flag) == (flag) : \
87
sizeof(field) >= sizeof(flag), \
88
"truncation problem when masking " #field \
89
" with ~" #flag); \
90
((field) &= ~(__typeof__(field))(flag)); \
91
})
92
#define SPA_FLAG_UPDATE(field,flag,val) ((val) ? SPA_FLAG_SET((field),(flag)) : SPA_FLAG_CLEAR((field),(flag)))
93
94
enum
spa_direction
{
95
SPA_DIRECTION_INPUT
= 0,
96
SPA_DIRECTION_OUTPUT
= 1,
97
};
98
99
#define SPA_DIRECTION_REVERSE(d) ((d) ^ 1)
100
101
#define SPA_RECTANGLE(width,height) ((struct spa_rectangle){ (width), (height) })
102
struct
spa_rectangle
{
103
uint32_t
width
;
104
uint32_t
height
;
105
};
106
107
#define SPA_POINT(x,y) ((struct spa_point){ (x), (y) })
108
struct
spa_point
{
109
int32_t
x
;
110
int32_t
y
;
111
};
112
113
#define SPA_REGION(x,y,width,height) ((struct spa_region){ SPA_POINT(x,y), SPA_RECTANGLE(width,height) })
114
struct
spa_region
{
115
struct
spa_point
position
;
116
struct
spa_rectangle
size
;
117
};
118
119
#define SPA_FRACTION(num,denom) ((struct spa_fraction){ (num), (denom) })
120
struct
spa_fraction
{
121
uint32_t
num
;
122
uint32_t
denom
;
123
};
124
125
#define SPA_N_ELEMENTS(arr) (sizeof(arr) / sizeof((arr)[0]))
128
131
* SPA_FOR_EACH_ELEMENT(array, f) {
132
* f->bar = baz;
133
* }
134
* ```
135
*/
136
#define SPA_FOR_EACH_ELEMENT(arr, ptr) \
137
for ((ptr) = arr; (ptr) < (arr) + SPA_N_ELEMENTS(arr); (ptr)++)
138
139
#define SPA_FOR_EACH_ELEMENT_VAR(arr, var) \
140
for (__typeof__((arr)[0])* var = arr; (var) < (arr) + SPA_N_ELEMENTS(arr); (var)++)
141
142
#define SPA_ABS(a) \
143
({ \
144
__typeof__(a) _a = (a); \
145
SPA_LIKELY(_a >= 0) ? _a : -_a; \
146
})
147
#define SPA_MIN(a,b) \
148
({ \
149
__typeof__(a) _min_a = (a); \
150
__typeof__(b) _min_b = (b); \
151
SPA_LIKELY(_min_a <= _min_b) ? _min_a : _min_b; \
152
})
153
#define SPA_MAX(a,b) \
154
({ \
155
__typeof__(a) _max_a = (a); \
156
__typeof__(b) _max_b = (b); \
157
SPA_LIKELY(_max_a >= _max_b) ? _max_a : _max_b; \
158
})
159
#define SPA_CLAMP(v,low,high) \
160
({ \
161
__typeof__(v) _v = (v); \
162
__typeof__(low) _low = (low); \
163
__typeof__(high) _high = (high); \
164
SPA_MIN(SPA_MAX(_v, _low), _high); \
165
})
166
167
#define SPA_CLAMPF(v,low,high) \
168
({ \
169
fminf(fmaxf(v, low), high); \
170
})
171
#define SPA_CLAMPD(v,low,high) \
172
({ \
173
fmin(fmax(v, low), high); \
174
})
175
176
177
#define SPA_SWAP(a,b) \
178
({ \
179
__typeof__(a) _t = (a); \
180
(a) = b; (b) = _t; \
181
})
182
183
#define SPA_TYPECHECK(type,x) \
184
({ type _dummy; \
185
typeof(x) _dummy2; \
186
(void)(&_dummy == &_dummy2); \
187
x; \
188
})
189
190
190
/** 3-way comparison. NaN > NaN and NaN > finite numbers */
191
#define SPA_CMP(a, b) \
192
({ \
193
__typeof__(a) _a = (a); \
194
__typeof__(b) _b = (b); \
195
(_a > _b) ? 1 : (_a == _b) ? 0 : (_a < _b) ? -1 \
196
: (_a == _a) ? -1 : (_b == _b) ? 1 \
197
: 1; \
198
})
199
201
202
*/
203
#define SPA_PTROFF(ptr_,offset_,type_) ((type_*)((uintptr_t)(ptr_) + (ptrdiff_t)(offset_)))
204
#define SPA_PTROFF_ALIGN(ptr_,offset_,alignment_,type_) \
205
SPA_PTR_ALIGN(SPA_PTROFF(ptr_,offset_,type_),alignment_,type_)
206
208
210
#define SPA_MEMBER(b,o,t) SPA_PTROFF(b,o,t)
211
#define SPA_MEMBER_ALIGN(b,o,a,t) SPA_PTROFF_ALIGN(b,o,a,t)
212
213
#define SPA_CONTAINER_OF(p,t,m) ((t*)((uintptr_t)(p) - offsetof(t,m)))
214
215
#define SPA_PTRDIFF(p1,p2) ((intptr_t)(p1) - (intptr_t)(p2))
216
217
#define SPA_PTR_TO_UINT32(p) ((uint32_t) ((uintptr_t) (p)))
218
#define SPA_UINT32_TO_PTR(u) ((void*) ((uintptr_t) (u)))
219
220
#define SPA_TIME_INVALID ((int64_t)INT64_MIN)
221
#define SPA_IDX_INVALID ((unsigned int)-1)
222
#define SPA_ID_INVALID ((uint32_t)0xffffffff)
223
224
#define SPA_NSEC_PER_SEC (1000000000LL)
225
#define SPA_NSEC_PER_MSEC (1000000ll)
226
#define SPA_NSEC_PER_USEC (1000ll)
227
#define SPA_USEC_PER_SEC (1000000ll)
228
#define SPA_USEC_PER_MSEC (1000ll)
229
#define SPA_MSEC_PER_SEC (1000ll)
230
231
#define SPA_TIMESPEC_TO_NSEC(ts) ((ts)->tv_sec * SPA_NSEC_PER_SEC + (ts)->tv_nsec)
232
#define SPA_TIMESPEC_TO_USEC(ts) ((ts)->tv_sec * SPA_USEC_PER_SEC + (ts)->tv_nsec / SPA_NSEC_PER_USEC)
233
#define SPA_TIMEVAL_TO_NSEC(tv) ((tv)->tv_sec * SPA_NSEC_PER_SEC + (tv)->tv_usec * SPA_NSEC_PER_USEC)
234
#define SPA_TIMEVAL_TO_USEC(tv) ((tv)->tv_sec * SPA_USEC_PER_SEC + (tv)->tv_usec)
235
236
#ifdef __GNUC__
237
#define SPA_PRINTF_FUNC(fmt, arg1) __attribute__((format(printf, fmt, arg1)))
238
#define SPA_FORMAT_ARG_FUNC(arg1) __attribute__((format_arg(arg1)))
239
#define SPA_ALIGNED(align) __attribute__((aligned(align)))
240
#define SPA_DEPRECATED __attribute__ ((deprecated))
241
#define SPA_EXPORT __attribute__((visibility("default")))
242
#define SPA_SENTINEL __attribute__((__sentinel__))
243
#define SPA_UNUSED __attribute__ ((unused))
244
#define SPA_NORETURN __attribute__ ((noreturn))
245
#define SPA_WARN_UNUSED_RESULT __attribute__ ((warn_unused_result))
246
#define SPA_BARRIER __asm__ __volatile__("": : :"memory")
247
#else
248
#define SPA_PRINTF_FUNC(fmt, arg1)
249
#define SPA_FORMAT_ARG_FUNC(arg1)
250
#define SPA_ALIGNED(align)
251
#define SPA_DEPRECATED
252
#define SPA_EXPORT
253
#define SPA_SENTINEL
254
#define SPA_UNUSED
255
#define SPA_NORETURN
256
#define SPA_WARN_UNUSED_RESULT
257
#define SPA_BARRIER
258
#endif
259
260
#ifndef SPA_API_IMPL
261
#define SPA_API_PROTO static inline
262
#define SPA_API_IMPL static inline
263
#endif
264
265
#ifndef SPA_API_UTILS_DEFS
266
#ifdef SPA_API_IMPL
267
#define SPA_API_UTILS_DEFS SPA_API_IMPL
268
#else
269
#define SPA_API_UTILS_DEFS static inline
270
#endif
271
#endif
272
273
274
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
275
#define SPA_RESTRICT restrict
276
#elif defined(__GNUC__) && __GNUC__ >= 4
277
#define SPA_RESTRICT __restrict__
278
#else
279
#define SPA_RESTRICT
280
#endif
281
282
#define SPA_ROUND_DOWN(num,value) \
283
({ \
284
__typeof__(num) _num = (num); \
285
((_num) - ((_num) % (value))); \
286
})
287
#define SPA_ROUND_UP(num,value) \
288
({ \
289
__typeof__(value) _v = (value); \
290
((((num) + (_v) - 1) / (_v)) * (_v)); \
291
})
292
293
#define SPA_ROUND_MASK(num,mask) ((__typeof__(num))((mask)-1))
294
295
#define SPA_ROUND_DOWN_N(num,align) ((num) & ~SPA_ROUND_MASK(num, align))
296
#define SPA_ROUND_UP_N(num,align) ((((num)-1) | SPA_ROUND_MASK(num, align))+1)
297
298
#define SPA_SCALE32(val,num,denom) \
299
({ \
300
uint64_t _val = (val); \
301
uint64_t _denom = (denom); \
302
(uint32_t)(((_val) * (num)) / (_denom)); \
303
})
304
305
#define SPA_SCALE32_UP(val,num,denom) \
306
({ \
307
uint64_t _val = (val); \
308
uint64_t _denom = (denom); \
309
(uint32_t)(((_val) * (num) + (_denom)-1) / (_denom)); \
310
})
311
312
/* Macros for getting the next highest power of two, for 32 and 64 bit
313
* unsigned integers. If the integers are already a power of two, the
314
* result is unchanged. Source:
315
* https://graphics.stanford.edu/%7Eseander/bithacks.html#RoundUpPowerOf2 */
316
317
#define SPA_ROUND_UP_POW2_32(num) \
318
({ \
319
uint32_t _n = (uint32_t)(num) - 1; \
320
_n |= _n >> 1; \
321
_n |= _n >> 2; \
322
_n |= _n >> 4; \
323
_n |= _n >> 8; \
324
_n |= _n >> 16; \
325
_n + 1; \
326
})
327
328
#define SPA_ROUND_UP_POW2_64(num) \
329
({ \
330
uint64_t _n = (uint64_t)(num) - 1; \
331
_n |= _n >> 1; \
332
_n |= _n >> 2; \
333
_n |= _n >> 4; \
334
_n |= _n >> 8; \
335
_n |= _n >> 16; \
336
_n |= _n >> 32; \
337
_n + 1; \
338
})
339
340
/* The vast majority of real world machines use a two's complement method.
341
* However, it is still prudent to check for that instead of just assuming.
342
* Fortunately, it is simple to check for this by negating INT_MAX and
343
* subtracting 1 from that. In two's complement, there is one more negative
344
* integer than there are positive integers (due to two's complement having
345
* only one zero representation), and this check exploits that particular
346
* asymmetry.
347
* It is very important to make sure limits.h is included for this to work,
348
* since otherwise, INT_MIN and INT_MAX will be missing, and this will _not_
349
* cause a preprocessor error - instead, the #if check here silently fails,
350
* as if the machine used something other than a two's complement method. */
351
#if INT_MIN == (-(INT_MAX) - 1)
352
#define SPA_MACHINE_USES_TWOS_COMPLEMENT
353
#endif
354
355
356
#define SPA_PTR_ALIGNMENT(p,align) ((uintptr_t)(p) & ((align)-1))
357
#define SPA_IS_ALIGNED(p,align) (SPA_PTR_ALIGNMENT(p,align) == 0)
358
#define SPA_PTR_ALIGN(p,align,type) ((type*)SPA_ROUND_UP_N((intptr_t)(p), (intptr_t)(align)))
359
360
#ifndef SPA_LIKELY
361
#ifdef __GNUC__
362
#define SPA_LIKELY(x) (__builtin_expect(!!(x),1))
363
#define SPA_UNLIKELY(x) (__builtin_expect(!!(x),0))
364
#else
365
#define SPA_LIKELY(x) (x)
366
#define SPA_UNLIKELY(x) (x)
367
#endif
368
#endif
369
370
SPA_API_UTILS_DEFS
bool
spa_ptrinside
(
const
void
*p1,
size_t
s1,
const
void
*p2,
size_t
s2,
371
size_t
*remaining)
372
{
373
if
(
SPA_LIKELY
((uintptr_t)p1 <= (uintptr_t)p2 && s2 <= s1 &&
374
(uintptr_t)p2 - (uintptr_t)p1 <= s1 - s2)) {
375
if
(remaining != NULL)
376
*remaining = ((uintptr_t)p1 + s1) - ((uintptr_t)p2 + s2);
377
return
true
;
378
}
else
{
379
if
(remaining != NULL)
380
*remaining = 0;
381
return
false
;
382
}
383
}
384
385
SPA_API_UTILS_DEFS
bool
spa_ptr_inside_and_aligned
(
const
void
*p1,
size_t
s1,
386
const
void
*p2,
size_t
s2,
size_t
align,
387
size_t
*remaining)
388
{
389
if
(
SPA_IS_ALIGNED
(p2, align)) {
390
return
spa_ptrinside
(p1, s1, p2, s2, remaining);
391
}
else
{
392
if
(remaining != NULL)
393
*remaining = 0;
394
return
false
;
395
}
396
}
397
398
#define spa_ptr_type_inside(p1, s1, p2, type, remaining) \
399
spa_ptr_inside_and_aligned(p1, s1, p2, sizeof(type), SPA_ALIGNOF(type), remaining)
400
401
#define SPA_PTR_TO_INT(p) ((int) ((intptr_t) (p)))
402
#define SPA_INT_TO_PTR(u) ((void*) ((intptr_t) (u)))
403
404
#define SPA_STRINGIFY_1(...) #__VA_ARGS__
405
#define SPA_STRINGIFY(...) SPA_STRINGIFY_1(__VA_ARGS__)
406
407
struct
spa_error_location
{
408
int
line
;
409
int
col
;
410
size_t
len
;
411
const
char
*
location
;
412
const
char
*
reason
;
413
};
414
415
#define spa_return_if_fail(expr) \
416
do { \
417
if (SPA_UNLIKELY(!(expr))) { \
418
fprintf(stderr, "'%s' failed at %s:%u %s()\n", \
419
#expr , __FILE__, __LINE__, __func__); \
420
return; \
421
} \
422
} while(false)
423
424
#define spa_return_val_if_fail(expr, val) \
425
do { \
426
if (SPA_UNLIKELY(!(expr))) { \
427
fprintf(stderr, "'%s' failed at %s:%u %s()\n", \
428
#expr , __FILE__, __LINE__, __func__); \
429
return (val); \
430
} \
431
} while(false)
432
433
#define spa_goto_if_fail(expr, label) \
434
do { \
435
if (SPA_UNLIKELY(!(expr))) { \
436
fprintf(stderr, "'%s' failed at %s:%u %s()\n", \
437
#expr , __FILE__, __LINE__, __func__); \
438
goto label; \
439
} \
440
} while(false)
441
442
443
/* spa_assert_se() is an assert which guarantees side effects of x,
444
* i.e. is never optimized away, regardless of NDEBUG or FASTPATH. */
445
#ifndef __COVERITY__
446
#define spa_assert_se(expr) \
447
do { \
448
if (SPA_UNLIKELY(!(expr))) { \
449
fprintf(stderr, "'%s' failed at %s:%u %s()\n", \
450
#expr , __FILE__, __LINE__, __func__); \
451
abort(); \
452
} \
453
} while (false)
454
#else
455
#define spa_assert_se(expr) \
456
do { \
457
int _unique_var = (expr); \
458
if (!_unique_var) \
459
abort(); \
460
} while (false)
461
#endif
462
463
/* Does exactly nothing */
464
#define spa_nop() do {} while (false)
465
466
#ifdef NDEBUG
467
#define spa_assert(expr) spa_nop()
468
#elif defined (FASTPATH)
469
#define spa_assert(expr) spa_assert_se(expr)
470
#else
471
#define spa_assert(expr) spa_assert_se(expr)
472
#endif
473
474
#ifdef NDEBUG
475
#define spa_assert_not_reached() abort()
476
#else
477
#define spa_assert_not_reached() \
478
do { \
479
fprintf(stderr, "Code should not be reached at %s:%u %s()\n", \
480
__FILE__, __LINE__, __func__); \
481
abort(); \
482
} while (false)
483
#endif
484
485
#define spa_memzero(x,l) (memset((x), 0, (l)))
486
#define spa_zero(x) (spa_memzero(&(x), sizeof(x)))
487
488
#ifdef SPA_DEBUG_MEMCPY
489
#define spa_memcpy(d,s,n) \
490
({ \
491
fprintf(stderr, "%s:%u %s() memcpy(%p, %p, %zd)\n", \
492
__FILE__, __LINE__, __func__, (d), (s), (size_t)(n)); \
493
memcpy(d,s,n); \
494
})
495
#define spa_memmove(d,s,n) \
496
({ \
497
fprintf(stderr, "%s:%u %s() memmove(%p, %p, %zd)\n", \
498
__FILE__, __LINE__, __func__, (d), (s), (size_t)(n)); \
499
memmove(d,s,n); \
500
})
501
#else
502
#define spa_memcpy(d,s,n) memcpy(d,s,n)
503
#define spa_memmove(d,s,n) memmove(d,s,n)
504
#endif
505
506
#define spa_aprintf(_fmt, ...) \
507
({ \
508
char *_strp; \
509
if (asprintf(&(_strp), (_fmt), ## __VA_ARGS__ ) == -1) \
510
_strp = NULL; \
511
_strp; \
512
})
513
514
#define spa_alloca(n, size, max_size) \
515
({ \
516
void *_res = NULL; \
517
if ((size_t)n > (size_t)max_size / (size_t)size) \
518
errno = ENOMEM; \
519
else \
520
_res = alloca((size_t)n * (size_t)size); \
521
_res; \
522
})
523
527
528
#ifdef __cplusplus
529
}
/* extern "C" */
530
#endif
531
532
#endif
/* SPA_UTILS_DEFS_H */
spa_ptr_inside_and_aligned
SPA_API_UTILS_DEFS bool spa_ptr_inside_and_aligned(const void *p1, size_t s1, const void *p2, size_t s2, size_t align, size_t *remaining)
Definition
defs.h:462
SPA_API_UTILS_DEFS
#define SPA_API_UTILS_DEFS
Definition
defs.h:329
SPA_LIKELY
#define SPA_LIKELY(x)
Definition
defs.h:441
spa_direction
spa_direction
Definition
defs.h:107
spa_ptrinside
SPA_API_UTILS_DEFS bool spa_ptrinside(const void *p1, size_t s1, const void *p2, size_t s2, size_t *remaining)
Definition
defs.h:447
SPA_IS_ALIGNED
#define SPA_IS_ALIGNED(p, align)
Definition
defs.h:429
SPA_DIRECTION_INPUT
@ SPA_DIRECTION_INPUT
Definition
defs.h:108
SPA_DIRECTION_OUTPUT
@ SPA_DIRECTION_OUTPUT
Definition
defs.h:109
string.h
spa/utils/string.h
spa_error_location
Definition
defs.h:488
spa_error_location::line
int line
Definition
defs.h:489
spa_error_location::location
const char * location
Definition
defs.h:492
spa_error_location::col
int col
Definition
defs.h:490
spa_error_location::len
size_t len
Definition
defs.h:491
spa_error_location::reason
const char * reason
Definition
defs.h:493
spa_fraction
Definition
defs.h:138
spa_fraction::num
uint32_t num
Definition
defs.h:139
spa_fraction::denom
uint32_t denom
Definition
defs.h:140
spa_point
Definition
defs.h:124
spa_point::y
int32_t y
Definition
defs.h:126
spa_point::x
int32_t x
Definition
defs.h:125
spa_rectangle
Definition
defs.h:117
spa_rectangle::width
uint32_t width
Definition
defs.h:118
spa_rectangle::height
uint32_t height
Definition
defs.h:119
spa_region
Definition
defs.h:131
spa_region::position
struct spa_point position
Definition
defs.h:132
spa_region::size
struct spa_rectangle size
Definition
defs.h:133
spa
utils
defs.h
Generated by
1.18.0