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