25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
26 * POSSIBILITY OF SUCH DAMAGE. |
26 * POSSIBILITY OF SUCH DAMAGE. |
27 */ |
27 */ |
28 |
28 |
29 /** |
29 /** |
30 * \file common.h |
30 * @file common.h |
31 * |
31 * |
32 * \brief Common definitions and feature checks. |
32 * @brief Common definitions and feature checks. |
33 * |
33 * |
34 * \author Mike Becker |
34 * @author Mike Becker |
35 * \author Olaf Wintermann |
35 * @author Olaf Wintermann |
36 * \version 3.0 |
36 * @copyright 2-Clause BSD License |
37 * \copyright 2-Clause BSD License |
37 * |
38 * |
38 * @mainpage UAP Common Extensions |
39 * \mainpage UAP Common Extensions |
|
40 * Library with common and useful functions, macros and data structures. |
39 * Library with common and useful functions, macros and data structures. |
41 * <p> |
40 * <p> |
42 * Latest available source:<br> |
41 * Latest available source:<br> |
43 * <a href="https://sourceforge.net/projects/ucx/files/">https://sourceforge.net/projects/ucx/files/</a> |
42 * <a href="https://sourceforge.net/projects/ucx/files/">https://sourceforge.net/projects/ucx/files/</a> |
44 * </p> |
43 * </p> |
45 * |
44 * |
46 * <p> |
45 * <p> |
47 * Repositories:<br> |
46 * Repositories:<br> |
48 * <a href="https://sourceforge.net/p/ucx/code">https://sourceforge.net/p/ucx/code</a> |
47 * <a href="https://sourceforge.net/p/ucx/code">https://sourceforge.net/p/ucx/code</a> |
49 * - or - |
48 * - or - |
50 * <a href="https://develop.uap-core.de/hg/ucx">https://develop.uap-core.de/hg/ucx</a> |
49 * <a href="https://uap-core.de/hg/ucx">https://uap-core.de/hg/ucx</a> |
51 * </p> |
50 * </p> |
52 * |
51 * |
53 * <h2>LICENCE</h2> |
52 * <h2>LICENCE</h2> |
54 * |
53 * |
55 * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved. |
54 * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved. |
82 |
81 |
83 /** Major UCX version as integer constant. */ |
82 /** Major UCX version as integer constant. */ |
84 #define UCX_VERSION_MAJOR 3 |
83 #define UCX_VERSION_MAJOR 3 |
85 |
84 |
86 /** Minor UCX version as integer constant. */ |
85 /** Minor UCX version as integer constant. */ |
87 #define UCX_VERSION_MINOR 0 |
86 #define UCX_VERSION_MINOR 1 |
88 |
87 |
89 /** Version constant which ensures to increase monotonically. */ |
88 /** Version constant which ensures to increase monotonically. */ |
90 #define UCX_VERSION (((UCX_VERSION_MAJOR)<<16)|UCX_VERSION_MINOR) |
89 #define UCX_VERSION (((UCX_VERSION_MAJOR)<<16)|UCX_VERSION_MINOR) |
91 |
90 |
92 // Common Includes |
91 // --------------------------------------------------------------------------- |
|
92 // Common includes |
|
93 // --------------------------------------------------------------------------- |
93 |
94 |
94 #include <stdlib.h> |
95 #include <stdlib.h> |
95 #include <stddef.h> |
96 #include <stddef.h> |
96 #include <stdbool.h> |
97 #include <stdbool.h> |
97 #include <stdint.h> |
98 #include <stdint.h> |
98 #include <sys/types.h> |
99 #include <sys/types.h> |
99 |
100 |
|
101 // --------------------------------------------------------------------------- |
|
102 // Architecture Detection |
|
103 // --------------------------------------------------------------------------- |
|
104 |
|
105 #ifndef INTPTR_MAX |
|
106 #error Missing INTPTR_MAX definition |
|
107 #endif |
|
108 #if INTPTR_MAX == INT64_MAX |
|
109 /** |
|
110 * The address width in bits on this platform. |
|
111 */ |
|
112 #define CX_WORDSIZE 64 |
|
113 #elif INTPTR_MAX == INT32_MAX |
|
114 /** |
|
115 * The address width in bits on this platform. |
|
116 */ |
|
117 #define CX_WORDSIZE 32 |
|
118 #else |
|
119 #error Unknown pointer size or missing size macros! |
|
120 #endif |
|
121 |
|
122 // --------------------------------------------------------------------------- |
|
123 // Attribute definitions |
|
124 // --------------------------------------------------------------------------- |
|
125 |
|
126 #ifndef __GNUC__ |
|
127 /** |
|
128 * Removes GNU C attributes where they are not supported. |
|
129 */ |
|
130 #define __attribute__(x) |
|
131 #endif |
|
132 |
|
133 /** |
|
134 * All pointer arguments must be non-NULL. |
|
135 */ |
|
136 #define cx_attr_nonnull __attribute__((__nonnull__)) |
|
137 |
|
138 /** |
|
139 * The specified pointer arguments must be non-NULL. |
|
140 */ |
|
141 #define cx_attr_nonnull_arg(...) __attribute__((__nonnull__(__VA_ARGS__))) |
|
142 |
|
143 /** |
|
144 * The returned value is guaranteed to be non-NULL. |
|
145 */ |
|
146 #define cx_attr_returns_nonnull __attribute__((__returns_nonnull__)) |
|
147 |
|
148 /** |
|
149 * The attributed function always returns freshly allocated memory. |
|
150 */ |
|
151 #define cx_attr_malloc __attribute__((__malloc__)) |
|
152 |
|
153 #ifndef __clang__ |
|
154 /** |
|
155 * The pointer returned by the attributed function is supposed to be freed |
|
156 * by @p freefunc. |
|
157 * |
|
158 * @param freefunc the function that shall be used to free the memory |
|
159 * @param freefunc_arg the index of the pointer argument in @p freefunc |
|
160 */ |
|
161 #define cx_attr_dealloc(freefunc, freefunc_arg) \ |
|
162 __attribute__((__malloc__(freefunc, freefunc_arg))) |
|
163 #else |
|
164 /** |
|
165 * Not supported in clang. |
|
166 */ |
|
167 #define cx_attr_dealloc(...) |
|
168 #endif // __clang__ |
|
169 |
|
170 /** |
|
171 * Shortcut to specify #cxFree() as deallocator. |
|
172 */ |
|
173 #define cx_attr_dealloc_ucx cx_attr_dealloc(cxFree, 2) |
|
174 |
|
175 /** |
|
176 * Specifies the parameters from which the allocation size is calculated. |
|
177 */ |
|
178 #define cx_attr_allocsize(...) __attribute__((__alloc_size__(__VA_ARGS__))) |
|
179 |
|
180 |
|
181 #ifdef __clang__ |
|
182 /** |
|
183 * No support for @c null_terminated_string_arg in clang or GCC below 14. |
|
184 */ |
|
185 #define cx_attr_cstr_arg(idx) |
|
186 /** |
|
187 * No support for access attribute in clang. |
|
188 */ |
|
189 #define cx_attr_access(mode, ...) |
|
190 #else |
|
191 #if __GNUC__ < 10 |
|
192 /** |
|
193 * No support for access attribute in GCC < 10. |
|
194 */ |
|
195 #define cx_attr_access(mode, ...) |
|
196 #else |
|
197 /** |
|
198 * Helper macro to define access macros. |
|
199 */ |
|
200 #define cx_attr_access(mode, ...) __attribute__((__access__(mode, __VA_ARGS__))) |
|
201 #endif // __GNUC__ < 10 |
|
202 #if __GNUC__ < 14 |
|
203 /** |
|
204 * No support for @c null_terminated_string_arg in clang or GCC below 14. |
|
205 */ |
|
206 #define cx_attr_cstr_arg(idx) |
|
207 #else |
|
208 /** |
|
209 * The specified argument is expected to be a zero-terminated string. |
|
210 * |
|
211 * @param idx the index of the argument |
|
212 */ |
|
213 #define cx_attr_cstr_arg(idx) \ |
|
214 __attribute__((__null_terminated_string_arg__(idx))) |
|
215 #endif // __GNUC__ < 14 |
|
216 #endif // __clang__ |
|
217 |
|
218 |
|
219 /** |
|
220 * Specifies that the function will only read through the given pointer. |
|
221 * |
|
222 * Takes one or two arguments: the index of the pointer and (optionally) the |
|
223 * index of another argument specifying the maximum number of accessed bytes. |
|
224 */ |
|
225 #define cx_attr_access_r(...) cx_attr_access(__read_only__, __VA_ARGS__) |
|
226 |
|
227 /** |
|
228 * Specifies that the function will read and write through the given pointer. |
|
229 * |
|
230 * Takes one or two arguments: the index of the pointer and (optionally) the |
|
231 * index of another argument specifying the maximum number of accessed bytes. |
|
232 */ |
|
233 #define cx_attr_access_rw(...) cx_attr_access(__read_write__, __VA_ARGS__) |
|
234 |
|
235 /** |
|
236 * Specifies that the function will only write through the given pointer. |
|
237 * |
|
238 * Takes one or two arguments: the index of the pointer and (optionally) the |
|
239 * index of another argument specifying the maximum number of accessed bytes. |
|
240 */ |
|
241 #define cx_attr_access_w(...) cx_attr_access(__write_only__, __VA_ARGS__) |
|
242 |
|
243 #if __STDC_VERSION__ >= 202300L |
|
244 |
|
245 /** |
|
246 * Do not warn about unused variable. |
|
247 */ |
|
248 #define cx_attr_unused [[maybe_unused]] |
|
249 |
|
250 /** |
|
251 * Warn about discarded return value. |
|
252 */ |
|
253 #define cx_attr_nodiscard [[nodiscard]] |
|
254 |
|
255 #else // no C23 |
|
256 |
|
257 /** |
|
258 * Do not warn about unused variable. |
|
259 */ |
|
260 #define cx_attr_unused __attribute__((__unused__)) |
|
261 |
|
262 /** |
|
263 * Warn about discarded return value. |
|
264 */ |
|
265 #define cx_attr_nodiscard __attribute__((__warn_unused_result__)) |
|
266 |
|
267 #endif // __STDC_VERSION__ |
|
268 |
|
269 |
|
270 // --------------------------------------------------------------------------- |
|
271 // MSVC specifics |
|
272 // --------------------------------------------------------------------------- |
|
273 |
|
274 #ifdef _MSC_VER |
|
275 // fix missing _Thread_local support |
|
276 #define _Thread_local __declspec(thread) |
|
277 #endif // _MSC_VER |
|
278 |
|
279 #if defined(CX_WINDLL_EXPORT) |
|
280 #define cx_attr_export __declspec(dllexport) |
|
281 #elif defined(CX_WINDLL) |
|
282 #define cx_attr_export __declspec(dllimport) |
|
283 #else |
|
284 /** Only used for building Windows DLLs. */ |
|
285 #define cx_attr_export |
|
286 #endif // CX_WINDLL / CX_WINDLL_EXPORT |
|
287 |
|
288 // --------------------------------------------------------------------------- |
|
289 // Useful function pointers |
|
290 // --------------------------------------------------------------------------- |
|
291 |
100 /** |
292 /** |
101 * Function pointer compatible with fwrite-like functions. |
293 * Function pointer compatible with fwrite-like functions. |
102 */ |
294 */ |
103 typedef size_t (*cx_write_func)( |
295 typedef size_t (*cx_write_func)( |
104 void const *, |
296 const void *, |
105 size_t, |
297 size_t, |
106 size_t, |
298 size_t, |
107 void * |
299 void * |
108 ); |
300 ); |
109 |
301 |
115 size_t, |
307 size_t, |
116 size_t, |
308 size_t, |
117 void * |
309 void * |
118 ); |
310 ); |
119 |
311 |
120 |
312 // --------------------------------------------------------------------------- |
121 // Compiler specific stuff |
313 // Utility macros |
122 |
314 // --------------------------------------------------------------------------- |
123 #ifndef __GNUC__ |
315 |
124 /** |
316 /** |
125 * Removes GNU C attributes where they are not supported. |
317 * Determines the number of members in a static C array. |
126 */ |
318 * |
127 #define __attribute__(x) |
319 * @attention never use this to determine the size of a dynamically allocated |
|
320 * array. |
|
321 * |
|
322 * @param arr the array identifier |
|
323 * @return the number of elements |
|
324 */ |
|
325 #define cx_nmemb(arr) (sizeof(arr)/sizeof((arr)[0])) |
|
326 |
|
327 // --------------------------------------------------------------------------- |
|
328 // szmul implementation |
|
329 // --------------------------------------------------------------------------- |
|
330 |
|
331 #if (__GNUC__ >= 5 || defined(__clang__)) && !defined(CX_NO_SZMUL_BUILTIN) |
|
332 #define CX_SZMUL_BUILTIN |
|
333 #define cx_szmul(a, b, result) __builtin_mul_overflow(a, b, result) |
|
334 #else // no GNUC or clang bultin |
|
335 /** |
|
336 * Performs a multiplication of size_t values and checks for overflow. |
|
337 * |
|
338 * @param a (@c size_t) first operand |
|
339 * @param b (@c size_t) second operand |
|
340 * @param result (@c size_t*) a pointer to a variable, where the result should |
|
341 * be stored |
|
342 * @retval zero success |
|
343 * @retval non-zero the multiplication would overflow |
|
344 */ |
|
345 #define cx_szmul(a, b, result) cx_szmul_impl(a, b, result) |
|
346 |
|
347 /** |
|
348 * Implementation of cx_szmul() when no compiler builtin is available. |
|
349 * |
|
350 * Do not use in application code. |
|
351 * |
|
352 * @param a first operand |
|
353 * @param b second operand |
|
354 * @param result a pointer to a variable, where the result should |
|
355 * be stored |
|
356 * @retval zero success |
|
357 * @retval non-zero the multiplication would overflow |
|
358 */ |
|
359 #if __cplusplus |
|
360 extern "C" |
128 #endif |
361 #endif |
129 |
362 cx_attr_export int cx_szmul_impl(size_t a, size_t b, size_t *result); |
130 #ifdef _MSC_VER |
363 #endif // cx_szmul |
131 |
364 |
132 // fix missing ssize_t definition |
365 |
133 #include <BaseTsd.h> |
|
134 typedef SSIZE_T ssize_t; |
|
135 |
|
136 // fix missing _Thread_local support |
|
137 #define _Thread_local __declspec(thread) |
|
138 |
|
139 #endif |
|
140 |
366 |
141 #endif // UCX_COMMON_H |
367 #endif // UCX_COMMON_H |