ucx/cx/common.h

changeset 11
0aa8cbd7912e
parent 0
1a157da63d7c
child 16
04c9f8d8f03b
equal deleted inserted replaced
10:80f9d007cb52 11:0aa8cbd7912e
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

mercurial