1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef CHPP_MACROS_H_
18 #define CHPP_MACROS_H_
19 
20 #include <assert.h>
21 #include <inttypes.h>
22 #include <stddef.h>
23 #include <stdlib.h>
24 
25 #include "chpp/memory.h"
26 
27 #ifdef __cplusplus
28 extern "C" {
29 #endif
30 
31 #define MOST_SIGNIFICANT_NIBBLE 0xf0
32 #define LEAST_SIGNIFICANT_NIBBLE 0x0f
33 
34 #ifndef UNUSED_VAR
35 #define UNUSED_VAR(var) ((void)(var))
36 #endif
37 
38 #ifndef MIN
39 #define MIN(a, b) ((a) < (b) ? (a) : (b))
40 #endif
41 
42 #ifndef MAX
43 #define MAX(a, b) ((a) > (b) ? (a) : (b))
44 #endif
45 
46 #ifndef ARRAY_SIZE
47 #define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
48 #endif
49 
50 #ifndef CHPP_ASSERT
51 #define CHPP_ASSERT(var) assert(var)
52 #endif
53 
54 #ifndef CHPP_ASSERT_LOG
55 #define CHPP_ASSERT_LOG(var, fmt, ...) \
56   do {                                 \
57     if (!(var)) {                      \
58       CHPP_LOGE(fmt, ##__VA_ARGS__);   \
59       CHPP_ASSERT(false);              \
60     }                                  \
61   } while (0)
62 #endif
63 
64 #ifndef CHPP_NOT_NULL
65 #define CHPP_NOT_NULL(var) CHPP_ASSERT((var) != NULL)
66 #endif
67 
68 /**
69  * Debug assertions that are not intended to be enabled for production software.
70  */
71 #ifndef CHPP_DEBUG_ASSERT
72 #ifdef CHPP_DEBUG_ASSERT_ENABLED
73 #define CHPP_DEBUG_ASSERT(var) CHPP_ASSERT(var)
74 #else
75 #define CHPP_DEBUG_ASSERT(var) UNUSED_VAR(var)
76 #endif  // CHPP_DEBUG_ASSERT_ENABLED
77 #endif  // CHPP_DEBUG_ASSERT
78 
79 #ifndef CHPP_DEBUG_ASSERT_LOG
80 #define CHPP_DEBUG_ASSERT_LOG(var, fmt, ...) \
81   do {                                       \
82     if (!(var)) {                            \
83       CHPP_LOGE(fmt, ##__VA_ARGS__);         \
84       CHPP_DEBUG_ASSERT(false);              \
85     }                                        \
86   } while (0)
87 #endif
88 
89 #ifndef PRIu64  // Pre-C99 lacks PRIu64 support. Note that the correct
90                 // definition on pre-C99 systems would be compiler-dependent.
91 #define PRIu64 "llu"
92 #endif
93 
94 #if defined(__GNUC__) && (__STDC_VERSION__ >= 201112L)
95 #define CHPP_C11_OR_NEWER
96 #endif
97 
98 #ifdef CHPP_C11_OR_NEWER
99 #define CHPP_STATIC_ASSERT _Static_assert
100 
101 #else
102 #define CHPP_STATIC_ASSERT4(cond, var) typedef char var[(!!(cond)) * 2 - 1]
103 #define CHPP_STATIC_ASSERT3(cond, line) \
104   CHPP_STATIC_ASSERT4(cond, static_assertion_at_line_##line)
105 #define CHPP_STATIC_ASSERT2(cond, line) CHPP_STATIC_ASSERT3(cond, line)
106 #define CHPP_STATIC_ASSERT(cond, msg) CHPP_STATIC_ASSERT2(cond, __LINE__)
107 
108 #endif  // CHPP_C11_OR_NEWER
109 
110 // Time-related macros
111 #define CHPP_TIME_NONE 0
112 #define CHPP_TIME_MAX UINT64_MAX
113 #define CHPP_MSEC_PER_SEC UINT64_C(1000)
114 #define CHPP_USEC_PER_MSEC UINT64_C(1000)
115 #define CHPP_NSEC_PER_USEC UINT64_C(1000)
116 #define CHPP_USEC_PER_SEC (CHPP_USEC_PER_MSEC * CHPP_MSEC_PER_SEC)
117 #define CHPP_NSEC_PER_MSEC (CHPP_NSEC_PER_USEC * CHPP_USEC_PER_MSEC)
118 #define CHPP_NSEC_PER_SEC \
119   (CHPP_NSEC_PER_USEC * CHPP_USEC_PER_MSEC * CHPP_MSEC_PER_SEC)
120 #define CHPP_NSEC_PER_MINUTE (CHPP_NSEC_PER_SEC * 60)
121 #define CHPP_NSEC_PER_HOUR (CHPP_NSEC_PER_MINUTE * 60)
122 
123 #if defined(__GNUC__) || defined(__clang__)
124 #define check_types_match(t1, t2) ((__typeof__(t1) *)0 != (__typeof__(t2) *)0)
125 #else
126 #define check_types_match(t1, t2) 0
127 #endif
128 
129 #define container_of(ptr, type, member)                     \
130   ((type *)(void *)((char *)(ptr)-offsetof(type, member)) + \
131    check_types_match(*(ptr), ((type *)0)->member))
132 
133 #define sizeof_member(type, member) (sizeof(((type *)0)->member))
134 
135 /**
136  * Macros for defining (compiler dependent) packed structures
137  */
138 #if defined(__GNUC__) || defined(__clang__)
139 // For GCC and clang
140 #define CHPP_PACKED_START
141 #define CHPP_PACKED_END
142 #define CHPP_PACKED_ATTR __attribute__((packed))
143 
144 #elif defined(__ICCARM__) || defined(__CC_ARM)
145 // For IAR ARM and Keil MDK-ARM compilers
146 #define CHPP_PACKED_START _Pragma("pack(push, 1)")
147 #define CHPP_PACKED_END _Pragma("pack(pop)")
148 #define CHPP_PACKED_ATTR
149 
150 #elif defined(_MSC_VER)
151 // For Microsoft Visual Studio
152 #define CHPP_PACKED_START __pragma(pack(push, 1))
153 #define CHPP_PACKED_END __pragma(pack(pop))
154 #define CHPP_PACKED_ATTR
155 
156 #else
157 // Unknown compiler
158 #error Unrecognized compiler
159 #endif
160 
161 #define CHPP_FREE_AND_NULLIFY(p) \
162   do {                           \
163     chppFree(p);                 \
164     (p) = NULL;                  \
165   } while (0)
166 
167 //! Cast a const pointer to a non-const. This is necessary for removing const
168 //! with the -Wcast-qual compiler flag.
169 #define CHPP_CONST_CAST_POINTER(p) (void *)(intptr_t)(p)
170 
171 #ifdef __cplusplus
172 }
173 #endif
174 
175 #endif  // CHPP_MACROS_H_
176