| 86 #define UCX_VERSION_MINOR 1 |
86 #define UCX_VERSION_MINOR 1 |
| 87 |
87 |
| 88 /** Version constant which ensures to increase monotonically. */ |
88 /** Version constant which ensures to increase monotonically. */ |
| 89 #define UCX_VERSION (((UCX_VERSION_MAJOR)<<16)|UCX_VERSION_MINOR) |
89 #define UCX_VERSION (((UCX_VERSION_MAJOR)<<16)|UCX_VERSION_MINOR) |
| 90 |
90 |
| 91 // Common Includes |
91 // --------------------------------------------------------------------------- |
| |
92 // Common includes |
| |
93 // --------------------------------------------------------------------------- |
| 92 |
94 |
| 93 #include <stdlib.h> |
95 #include <stdlib.h> |
| 94 #include <stddef.h> |
96 #include <stddef.h> |
| 95 #include <stdbool.h> |
97 #include <stdbool.h> |
| 96 #include <stdint.h> |
98 #include <stdint.h> |
| 97 #include <sys/types.h> |
99 #include <sys/types.h> |
| 98 |
100 |
| 99 #ifndef UCX_TEST_H |
101 // --------------------------------------------------------------------------- |
| |
102 // Architecture Detection |
| |
103 // --------------------------------------------------------------------------- |
| |
104 |
| |
105 #if INTPTR_MAX == INT64_MAX |
| |
106 /** |
| |
107 * The address width in bits on this platform. |
| |
108 */ |
| |
109 #define CX_WORDSIZE 64 |
| |
110 #elif INTPTR_MAX == INT32_MAX |
| |
111 /** |
| |
112 * The address width in bits on this platform. |
| |
113 */ |
| |
114 #define CX_WORDSIZE 32 |
| |
115 #else |
| |
116 #error Unknown pointer size or missing size macros! |
| |
117 #endif |
| |
118 |
| |
119 // --------------------------------------------------------------------------- |
| |
120 // Missing Defines |
| |
121 // --------------------------------------------------------------------------- |
| |
122 |
| |
123 #ifndef SSIZE_MAX // not defined in glibc since C23 and MSVC |
| |
124 #if CX_WORDSIZE == 64 |
| |
125 #define SSIZE_MAX 0x7fffffffffffffffll |
| |
126 #else |
| |
127 #define SSIZE_MAX 0x7fffffffl |
| |
128 #endif |
| |
129 #endif |
| |
130 |
| |
131 |
| |
132 // --------------------------------------------------------------------------- |
| |
133 // Attribute definitions |
| |
134 // --------------------------------------------------------------------------- |
| |
135 |
| |
136 #ifndef __GNUC__ |
| |
137 /** |
| |
138 * Removes GNU C attributes where they are not supported. |
| |
139 */ |
| |
140 #define __attribute__(x) |
| |
141 #endif |
| |
142 |
| |
143 /** |
| |
144 * All pointer arguments must be non-NULL. |
| |
145 */ |
| |
146 #define cx_attr_nonnull __attribute__((__nonnull__)) |
| |
147 |
| |
148 /** |
| |
149 * The specified pointer arguments must be non-NULL. |
| |
150 */ |
| |
151 #define cx_attr_nonnull_arg(...) __attribute__((__nonnull__(__VA_ARGS__))) |
| |
152 |
| |
153 /** |
| |
154 * The returned value is guaranteed to be non-NULL. |
| |
155 */ |
| |
156 #define cx_attr_returns_nonnull __attribute__((__returns_nonnull__)) |
| |
157 |
| |
158 /** |
| |
159 * The attributed function always returns freshly allocated memory. |
| |
160 */ |
| |
161 #define cx_attr_malloc __attribute__((__malloc__)) |
| |
162 |
| |
163 #ifndef __clang__ |
| |
164 /** |
| |
165 * The pointer returned by the attributed function is supposed to be freed |
| |
166 * by \p freefunc. |
| |
167 * |
| |
168 * @param freefunc the function that shall be used to free the memory |
| |
169 * @param freefunc_arg the index of the pointer argument in \p freefunc |
| |
170 */ |
| |
171 #define cx_attr_dealloc(freefunc, freefunc_arg) \ |
| |
172 __attribute__((__malloc__(freefunc, freefunc_arg))) |
| |
173 #else |
| |
174 /** |
| |
175 * Not supported in clang. |
| |
176 */ |
| |
177 #define cx_attr_dealloc(...) |
| |
178 #endif // __clang__ |
| |
179 |
| |
180 /** |
| |
181 * Shortcut to specify #cxFree() as deallocator. |
| |
182 */ |
| |
183 #define cx_attr_dealloc_ucx cx_attr_dealloc(cxFree, 2) |
| |
184 |
| |
185 /** |
| |
186 * Specifies the parameters from which the allocation size is calculated. |
| |
187 */ |
| |
188 #define cx_attr_allocsize(...) __attribute__((__alloc_size__(__VA_ARGS__))) |
| |
189 |
| |
190 |
| |
191 #ifdef __clang__ |
| |
192 /** |
| |
193 * No support for \c null_terminated_string_arg in clang or GCC below 14. |
| |
194 */ |
| |
195 #define cx_attr_cstr_arg(idx) |
| |
196 /** |
| |
197 * No support for access attribute in clang. |
| |
198 */ |
| |
199 #define cx_attr_access(mode, ...) |
| |
200 #else |
| |
201 #if __GNUC__ < 10 |
| |
202 /** |
| |
203 * No support for access attribute in GCC < 10. |
| |
204 */ |
| |
205 #define cx_attr_access(mode, ...) |
| |
206 #else |
| |
207 /** |
| |
208 * Helper macro to define access macros. |
| |
209 */ |
| |
210 #define cx_attr_access(mode, ...) __attribute__((__access__(mode, __VA_ARGS__))) |
| |
211 #endif // __GNUC__ < 10 |
| |
212 #if __GNUC__ < 14 |
| |
213 /** |
| |
214 * No support for \c null_terminated_string_arg in clang or GCC below 14. |
| |
215 */ |
| |
216 #define cx_attr_cstr_arg(idx) |
| |
217 #else |
| |
218 /** |
| |
219 * The specified argument is expected to be a zero-terminated string. |
| |
220 * |
| |
221 * @param idx the index of the argument |
| |
222 */ |
| |
223 #define cx_attr_cstr_arg(idx) \ |
| |
224 __attribute__((__null_terminated_string_arg__(idx))) |
| |
225 #endif // __GNUC__ < 14 |
| |
226 #endif // __clang__ |
| |
227 |
| |
228 |
| |
229 /** |
| |
230 * Specifies that the function will only read through the given pointer. |
| |
231 * |
| |
232 * Takes one or two arguments: the index of the pointer and (optionally) the |
| |
233 * index of another argument specifying the maximum number of accessed bytes. |
| |
234 */ |
| |
235 #define cx_attr_access_r(...) cx_attr_access(__read_only__, __VA_ARGS__) |
| |
236 |
| |
237 /** |
| |
238 * Specifies that the function will read and write through the given pointer. |
| |
239 * |
| |
240 * Takes one or two arguments: the index of the pointer and (optionally) the |
| |
241 * index of another argument specifying the maximum number of accessed bytes. |
| |
242 */ |
| |
243 #define cx_attr_access_rw(...) cx_attr_access(__read_write__, __VA_ARGS__) |
| |
244 |
| |
245 /** |
| |
246 * Specifies that the function will only write through the given pointer. |
| |
247 * |
| |
248 * Takes one or two arguments: the index of the pointer and (optionally) the |
| |
249 * index of another argument specifying the maximum number of accessed bytes. |
| |
250 */ |
| |
251 #define cx_attr_access_w(...) cx_attr_access(__write_only__, __VA_ARGS__) |
| |
252 |
| |
253 #if __STDC_VERSION__ >= 202300L |
| |
254 |
| |
255 /** |
| |
256 * Do not warn about unused variable. |
| |
257 */ |
| |
258 #define cx_attr_unused [[maybe_unused]] |
| |
259 |
| |
260 /** |
| |
261 * Warn about discarded return value. |
| |
262 */ |
| |
263 #define cx_attr_nodiscard [[nodiscard]] |
| |
264 |
| |
265 #else // no C23 |
| |
266 |
| |
267 /** |
| |
268 * Do not warn about unused variable. |
| |
269 */ |
| |
270 #define cx_attr_unused __attribute__((__unused__)) |
| |
271 |
| |
272 /** |
| |
273 * Warn about discarded return value. |
| |
274 */ |
| |
275 #define cx_attr_nodiscard __attribute__((__warn_unused_result__)) |
| |
276 |
| |
277 #endif // __STDC_VERSION__ |
| |
278 |
| |
279 // --------------------------------------------------------------------------- |
| |
280 // Useful function pointers |
| |
281 // --------------------------------------------------------------------------- |
| |
282 |
| 100 /** |
283 /** |
| 101 * Function pointer compatible with fwrite-like functions. |
284 * Function pointer compatible with fwrite-like functions. |
| 102 */ |
285 */ |
| 103 typedef size_t (*cx_write_func)( |
286 typedef size_t (*cx_write_func)( |
| 104 void const *, |
287 const void *, |
| 105 size_t, |
288 size_t, |
| 106 size_t, |
289 size_t, |
| 107 void * |
290 void * |
| 108 ); |
291 ) cx_attr_nonnull; |
| 109 #endif // UCX_TEST_H |
|
| 110 |
292 |
| 111 /** |
293 /** |
| 112 * Function pointer compatible with fread-like functions. |
294 * Function pointer compatible with fread-like functions. |
| 113 */ |
295 */ |
| 114 typedef size_t (*cx_read_func)( |
296 typedef size_t (*cx_read_func)( |
| 115 void *, |
297 void *, |
| 116 size_t, |
298 size_t, |
| 117 size_t, |
299 size_t, |
| 118 void * |
300 void * |
| 119 ); |
301 ) cx_attr_nonnull; |
| 120 |
302 |
| 121 |
303 // --------------------------------------------------------------------------- |
| 122 // Compiler specific stuff |
304 // Utility macros |
| 123 |
305 // --------------------------------------------------------------------------- |
| 124 #ifndef __GNUC__ |
306 |
| 125 /** |
307 /** |
| 126 * Removes GNU C attributes where they are not supported. |
308 * Determines the number of members in a static C array. |
| 127 */ |
309 * |
| 128 #define __attribute__(x) |
310 * @attention never use this to determine the size of a dynamically allocated |
| 129 #endif |
311 * array. |
| |
312 * |
| |
313 * @param arr the array identifier |
| |
314 * @return the number of elements |
| |
315 */ |
| |
316 #define cx_nmemb(arr) (sizeof(arr)/sizeof((arr)[0])) |
| |
317 |
| |
318 // --------------------------------------------------------------------------- |
| |
319 // szmul implementation |
| |
320 // --------------------------------------------------------------------------- |
| |
321 |
| |
322 #if (__GNUC__ >= 5 || defined(__clang__)) && !defined(CX_NO_SZMUL_BUILTIN) |
| |
323 #define CX_SZMUL_BUILTIN |
| |
324 |
| |
325 /** |
| |
326 * Alias for \c __builtin_mul_overflow. |
| |
327 * |
| |
328 * Performs a multiplication of size_t values and checks for overflow. |
| |
329 * |
| |
330 * @param a first operand |
| |
331 * @param b second operand |
| |
332 * @param result a pointer to a size_t, where the result should |
| |
333 * be stored |
| |
334 * @return zero, if no overflow occurred and the result is correct, non-zero |
| |
335 * otherwise |
| |
336 */ |
| |
337 #define cx_szmul(a, b, result) __builtin_mul_overflow(a, b, result) |
| |
338 |
| |
339 #else // no GNUC or clang bultin |
| |
340 |
| |
341 /** |
| |
342 * Performs a multiplication of size_t values and checks for overflow. |
| |
343 * |
| |
344 * @param a first operand |
| |
345 * @param b second operand |
| |
346 * @param result a pointer to a size_t, where the result should |
| |
347 * be stored |
| |
348 * @return zero, if no overflow occurred and the result is correct, non-zero |
| |
349 * otherwise |
| |
350 */ |
| |
351 #define cx_szmul(a, b, result) cx_szmul_impl(a, b, result) |
| |
352 |
| |
353 /** |
| |
354 * Performs a multiplication of size_t values and checks for overflow. |
| |
355 * |
| |
356 * This is a custom implementation in case there is no compiler builtin |
| |
357 * available. |
| |
358 * |
| |
359 * @param a first operand |
| |
360 * @param b second operand |
| |
361 * @param result a pointer to a size_t where the result should be stored |
| |
362 * @return zero, if no overflow occurred and the result is correct, non-zero |
| |
363 * otherwise |
| |
364 */ |
| |
365 #if __cplusplus |
| |
366 extern "C" |
| |
367 #endif |
| |
368 int cx_szmul_impl(size_t a, size_t b, size_t *result); |
| |
369 |
| |
370 #endif // cx_szmul |
| |
371 |
| |
372 |
| |
373 // --------------------------------------------------------------------------- |
| |
374 // Fixes for MSVC incompatibilities |
| |
375 // --------------------------------------------------------------------------- |
| 130 |
376 |
| 131 #ifdef _MSC_VER |
377 #ifdef _MSC_VER |
| 132 |
|
| 133 // fix missing ssize_t definition |
378 // fix missing ssize_t definition |
| 134 #include <BaseTsd.h> |
379 #include <BaseTsd.h> |
| 135 typedef SSIZE_T ssize_t; |
380 typedef SSIZE_T ssize_t; |
| 136 |
381 |
| 137 // fix missing _Thread_local support |
382 // fix missing _Thread_local support |
| 138 #define _Thread_local __declspec(thread) |
383 #define _Thread_local __declspec(thread) |
| 139 |
384 #endif // _MSC_VER |
| 140 #endif |
|
| 141 |
385 |
| 142 #endif // UCX_COMMON_H |
386 #endif // UCX_COMMON_H |