UNIXworkcode

1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 * 4 * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 /** 30 * @file common.h 31 * 32 * @brief Common definitions and feature checks. 33 * 34 * @author Mike Becker 35 * @author Olaf Wintermann 36 * @copyright 2-Clause BSD License 37 * 38 * @mainpage UAP Common Extensions 39 * Library with common and useful functions, macros and data structures. 40 * <p> 41 * Latest available source:<br> 42 * <a href="https://sourceforge.net/projects/ucx/files/">https://sourceforge.net/projects/ucx/files/</a> 43 * </p> 44 * 45 * <p> 46 * Repositories:<br> 47 * <a href="https://sourceforge.net/p/ucx/code">https://sourceforge.net/p/ucx/code</a> 48 * -&nbsp;or&nbsp;- 49 * <a href="https://develop.uap-core.de/hg/ucx">https://develop.uap-core.de/hg/ucx</a> 50 * </p> 51 * 52 * <h2>LICENCE</h2> 53 * 54 * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved. 55 * 56 * Redistribution and use in source and binary forms, with or without 57 * modification, are permitted provided that the following conditions are met: 58 * 59 * 1. Redistributions of source code must retain the above copyright 60 * notice, this list of conditions and the following disclaimer. 61 * 62 * 2. Redistributions in binary form must reproduce the above copyright 63 * notice, this list of conditions and the following disclaimer in the 64 * documentation and/or other materials provided with the distribution. 65 * 66 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 67 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 68 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 69 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 70 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 71 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 72 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 73 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 74 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 75 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 76 * POSSIBILITY OF SUCH DAMAGE. 77 */ 78 79 #ifndef UCX_COMMON_H 80 #define UCX_COMMON_H 81 82 /** Major UCX version as integer constant. */ 83 #define UCX_VERSION_MAJOR 3 84 85 /** Minor UCX version as integer constant. */ 86 #define UCX_VERSION_MINOR 1 87 88 /** Version constant which ensures to increase monotonically. */ 89 #define UCX_VERSION (((UCX_VERSION_MAJOR)<<16)|UCX_VERSION_MINOR) 90 91 // --------------------------------------------------------------------------- 92 // Common includes 93 // --------------------------------------------------------------------------- 94 95 #include <stdlib.h> 96 #include <stddef.h> 97 #include <stdbool.h> 98 #include <stdint.h> 99 #include <sys/types.h> 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 // 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 289 /** 290 * Function pointer compatible with fwrite-like functions. 291 */ 292 typedef size_t (*cx_write_func)( 293 const void *, 294 size_t, 295 size_t, 296 void * 297 ); 298 299 /** 300 * Function pointer compatible with fread-like functions. 301 */ 302 typedef size_t (*cx_read_func)( 303 void *, 304 size_t, 305 size_t, 306 void * 307 ); 308 309 // --------------------------------------------------------------------------- 310 // Utility macros 311 // --------------------------------------------------------------------------- 312 313 /** 314 * Determines the number of members in a static C array. 315 * 316 * @attention never use this to determine the size of a dynamically allocated 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 // --------------------------------------------------------------------------- 366 367 #ifdef _MSC_VER 368 // fix missing ssize_t definition 369 #include <BaseTsd.h> 370 typedef SSIZE_T ssize_t; 371 372 // fix missing _Thread_local support 373 #define _Thread_local __declspec(thread) 374 #endif // _MSC_VER 375 376 #endif // UCX_COMMON_H 377