ucx/cx/common.h

changeset 852
83fdf679df99
parent 816
839fefbdedc7
equal deleted inserted replaced
850:bbe2925eb590 852:83fdf679df99
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 * \copyright 2-Clause BSD License 36 * @copyright 2-Clause BSD License
37 * 37 *
38 * \mainpage UAP Common Extensions 38 * @mainpage UAP Common Extensions
39 * Library with common and useful functions, macros and data structures. 39 * Library with common and useful functions, macros and data structures.
40 * <p> 40 * <p>
41 * Latest available source:<br> 41 * Latest available source:<br>
42 * <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>
43 * </p> 43 * </p>
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

mercurial