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