summaryrefslogtreecommitdiff
path: root/include/al/macros.h
blob: 715718a778265f6f1003f58ecf7b9fbc9bbe3683 (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
#ifndef _AL_MACROS_H
#define _AL_MACROS_H

#define AL_MACRO_WRAP do {
#define AL_MACRO_END } while(0)

#define AL_PASTER_EVALUATOR(X, Y) X##_##Y
#define AL_PASTER(X, Y) AL_PASTER_EVALUATOR(X, Y)

#if defined LIKELY || defined UNLIKELY
#error "Conflicting definitions for LIKELY/UNLIKELY"
#endif

#ifdef AL_HAVE_BUILTIN_EXPECT
#define LIKELY(x) __builtin_expect((x), 1)
#else
#define LIKELY(x) x
#endif

#ifdef AL_HAVE_BUILTIN_EXPECT
#define UNLIKELY(x) __builtin_expect((x), 0)
#else
#define UNLIKELY(x) x
#endif

#if defined MAX || defined MIN || defined CLAMP || defined SWAP || defined ARRAY_SIZE || defined BOOLSTR
#error "Conflicting definitions for common macros"
#endif

#ifdef AL_HAVE_GNU_EXTENSIONS
#define MIN(a, b)          \
({                         \
    __typeof__(a) _a = a;  \
    __typeof__(b) _b = b;  \
    (void)(&_a == &_b);    \
    _a < _b ? _a : _b;     \
})
#define MAX(a, b)          \
({                         \
    __typeof__(a) _a = a;  \
    __typeof__(b) _b = b;  \
    (void)(&_a == &_b);    \
    _a > _b ? _a : _b;     \
})
#define CLAMP(n, lo, hi) MIN(hi, MAX(lo, n))
#else
// Compatible/Pedantic min/max.
/*
#error "MIN/MAX/CLAMP should not be used in this mode as they\
 differ in behavior without support for statement expressions"
*/
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#define MAX(a,b) ((a) > (b) ? (a) : (b))
#define CLAMP(n, lo, hi) MIN(hi, MAX(lo, n))
#endif

#define SWAP(a, b) \
AL_MACRO_WRAP \
{ \
    __typeof__(a) tmp = a; \
    a = b; \
    b = tmp; \
} AL_MACRO_END

#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))

#define BOOLSTR(b) ((b) ? "true" : "false")

#if defined KB || defined MB || defined GB || defined TB
#error "Conflicting definitions for byte size macros"
#endif

#define KB(n) ((n) << 10)
#define MB(n) ((n) << 20)
#define GB(n) ((n) << 30)
#define TB(n) (((u64)n) << 40)

#if defined __counted_by || defined __sized_by
#error "Conflicting definitions for common attributes"
#endif

// https://github.com/google/double-conversion/pull/131/files
#ifdef __has_attribute
#define AL_HAS_ATTRIBUTE(x) __has_attribute(x)
#else
#define AL_HAS_ATTRIBUTE(x) 0
#endif

#if AL_HAS_ATTRIBUTE(__counted_by__)
#define __counted_by(member) __attribute__((__counted_by__(member)))
#else
#define __counted_by(member)
#endif

#if AL_HAS_ATTRIBUTE(__sized_by__)
#define __sized_by(member) __attribute__((__sized_by__(member)))
#else
#define __sized_by(member)
#endif

#ifdef _MSC_VER
#define __thread __declspec(thread)
#endif

#endif // _AL_MACROS_H