Bump S-nail v14.9.25 ("Lubimy Gorod"), 2024-06-27
[s-mailx.git] / include / su / code.h
blob38260e7b3567c17acc26f6a82c9c0e7092758013
1 /*@ Code of the basic infrastructure (POD types, macros etc.) and functions.
2 *@ And main documentation entry point, as below.
3 *@ - Reacts upon su_HAVE_DEBUG, su_HAVE_DEVEL, and NDEBUG.
4 *@ The latter is a precondition for su_HAVE_INLINE; dependent upon compiler
5 *@ __OPTIMIZE__ (and __OPTIMIZE_SIZE__) may be looked at in addition, then.
6 *@ su_HAVE_DEVEL is meant as a possibility to enable test paths with
7 *@ debugging disabled.
8 *@ - Some macros require su_FILE to be defined to a literal.
9 *@ - Define su_MASTER to inject what is to be injected once; for example,
10 *@ it enables su_M*CTA() compile time assertions.
12 * Copyright (c) 2001 - 2020 Steffen (Daode) Nurpmeso <steffen@sdaoden.eu>.
13 * SPDX-License-Identifier: ISC
15 * Permission to use, copy, modify, and/or distribute this software for any
16 * purpose with or without fee is hereby granted, provided that the above
17 * copyright notice and this permission notice appear in all copies.
19 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
20 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
21 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
22 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
23 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
24 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
25 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
27 #ifndef su_CODE_H
28 #define su_CODE_H
30 #include <su/config.h>
32 /*!
33 * \mainpage SU --- Steffen's Utilities
35 * Afters years of finding myself too busy to port my old C++ library of which
36 * i am so prowd to the C language, and because of the ever increasing
37 * necessity to have a foundation of things i like using nonetheless,
38 * i finally have started creating a minimal set of tools instead.
40 * Some introductional notes:
42 * \list{\li{
43 * The basic infrastructure of \SU is provided by the file \r{su/code.h}.
44 * Because all other \SU headers include it (thus), having it available is
45 * almost always implicit.
46 * It should be noted, however, that the \r{CORE} reacts upon a few
47 * preprocessor switches, as documented there.
48 * }\li{
49 * Datatype overflow errors and out-of-memory situations are usually detected
50 * and result in abortions (via \r{su_LOG_EMERG} logs).
51 * Alternatively all or individual \r{su_state_err_type}s will not cause
52 * hard-failures.
54 * The actual global mode of operation can be queried via \r{su_state_get()}
55 * (presence checks with \r{su_state_has()},
56 * is configurable via \r{su_state_set()} and \r{su_state_clear()}, and often
57 * the default can also be changed on a by-call or by-object basis, see
58 * \r{su_state_err_flags} and \r{su_clone_fun} for more on this.
60 * \remarks{C++ object creation failures via \c{su_MEM_NEW()} etc. will however
61 * always cause program abortion due to standard imposed execution flow.
62 * This can be worked around by using \c{su_MEM_NEW_HEAP()} as appropriate.}
63 * }\li{
64 * Most collection and string object types work on 32-bit (or even 31-bit)
65 * lengths a.k.a. counts a.k.a. sizes.
66 * For simplicity of use, and because datatype overflow is a handled case, the
67 * user interface very often uses \r{su_uz} (i.e., \c{size_t}).
68 * Other behaviour is explicitly declared with a "big" prefix, as in
69 * "biglist", but none such object does exist at the time of this writing.
70 * }\li{
71 * \SU requires an eight (8) or more byte alignment on the stack and heap.
72 * This is because some of its facilities may use the lower (up to) three
73 * bits of pointers for internal, implementation purposes.
74 * }}
77 /*!
78 * \file
79 * \ingroup CORE
80 * \brief \r{CORE}
83 /* CONFIG {{{ *//*!
84 * \defgroup CONFIG SU configuration
85 * \ingroup CORE
86 * \brief Overall \SU configuration (\r{su/code.h})
88 * It reflects the chosen configuration and the build time environment.
89 * @{
92 #ifdef DOXYGEN
93 /* Features */
94 /*! Whether the \SU namespace exists.
95 * If not, facilities exist in the global namespace. */
96 # define su_HAVE_NSPC
98 # define su_HAVE_DEBUG /*!< Debug variant, including assertions etc. */
99 /*! Test paths available in non-debug code.
100 * Also, compiler pragmas which suppress some warnings are not set, etc.*/
101 # define su_HAVE_DEVEL
102 # define su_HAVE_DOCSTRINGS /*!< Some more helpful strings. */
103 # define su_HAVE_MEM_BAG_AUTO /*!< \_ */
104 # define su_HAVE_MEM_BAG_LOFI /*!< \_ */
105 /*! Normally the debug library provides memory write boundary excess via
106 * canaries (see \r{MEM_CACHE_ALLOC} and \r{su_MEM_ALLOC_DEBUG}).
107 * Since this counteracts external memory checkers like \c{valgrind(1)} or
108 * the ASAN (address sanitizer) compiler extensions, the \SU checkers can be
109 * disabled explicitly. */
110 # define su_HAVE_MEM_CANARIES_DISABLE
111 # define su_HAVE_SMP /*!< \r{SMP} support available? */
112 /*!< Multithreading support available?
113 * This is a subfeature of \r{SMP}. */
114 # define su_HAVE_MT
116 /* Values */
117 # define su_PAGE_SIZE /*!< \_ */
118 #endif
120 /*! @} *//* CONFIG }}} */
123 * \defgroup CORE Basic infrastructure
124 * \brief Macros, POD types, and basic interfaces (\r{su/code.h})
126 * The basic infrastructure:
128 * \list{\li{
129 * Reacts upon \vr{su_HAVE_DEBUG}, \vr{su_HAVE_DEVEL}, and \vr{NDEBUG}.
130 * Whereas the former two are configuration-time constants which will create
131 * additional API and cause a different ABI, the latter will only cause
132 * preprocessor changes, for example for \r{su_ASSERT()}.
133 * }\li{
134 * The latter is a precondition for \vr{su_HAVE_INLINE}.
135 * }\li{
136 * Some macros require \vr{su_FILE} to be defined to a literal.
137 * }\li{
138 * Define \vr{su_MASTER} to inject what is to be injected once; for example,
139 * it enables \c{su_M*CTA()} compile time assertions.
140 * }}
141 * @{
144 /* OS {{{ */
146 #define su_OS_CYGWIN 0 /*!< \_ */
147 #define su_OS_DARWIN 0 /*!< \_ */
148 #define su_OS_DRAGONFLY 0 /*!< \_ */
149 #define su_OS_EMX 0 /*!< \_ */
150 #define su_OS_FREEBSD 0 /*!< \_ */
151 #define su_OS_LINUX 0 /*!< \_ */
152 #define su_OS_MINIX 0 /*!< \_ */
153 #define su_OS_MSDOS 0 /*!< \_ */
154 #define su_OS_NETBSD 0 /*!< \_ */
155 #define su_OS_OPENBSD 0 /*!< \_ */
156 #define su_OS_SOLARIS 0 /*!< \_ */
157 #define su_OS_SUNOS 0 /*!< \_ */
158 #define su_OS_WIN32 0 /*!< \_ */
159 #define su_OS_WIN64 0 /*!< \_ */
161 #if 0
162 #elif defined __CYGWIN__
163 # undef su_OS_CYGWIN
164 # define su_OS_CYGWIN 1
165 #elif defined DARWIN || defined _DARWIN
166 # undef su_OS_DARWIN
167 # define su_OS_DARWIN 1
168 #elif defined __DragonFly__
169 # undef su_OS_DRAGONFLY
170 # define su_OS_DRAGONFLY 1
171 #elif defined __EMX__
172 # undef su_OS_EMX
173 # define su_OS_EMX 1
174 #elif defined __FreeBSD__
175 # undef su_OS_FREEBSD
176 # define su_OS_FREEBSD 1
177 #elif defined __linux__ || defined __linux
178 # undef su_OS_LINUX
179 # define su_OS_LINUX 1
180 #elif defined __minix
181 # undef su_OS_MINIX
182 # define su_OS_MINIX 1
183 #elif defined __MSDOS__
184 # undef su_OS_MSDOS
185 # define su_OS_MSDOS 1
186 #elif defined __NetBSD__
187 # undef su_OS_NETBSD
188 # define su_OS_NETBSD 1
189 #elif defined __OpenBSD__
190 # undef su_OS_OPENBSD
191 # define su_OS_OPENBSD 1
192 #elif defined __solaris__ || defined __sun
193 # if defined __SVR4 || defined __svr4__
194 # undef su_OS_SOLARIS
195 # define su_OS_SOLARIS 1
196 # else
197 # undef su_OS_SUNOS
198 # define su_OS_SUNOS 1
199 # endif
200 #endif
202 /* OS }}} */
203 /* LANG {{{ */
205 #ifndef __cplusplus
206 # define su_C_LANG 1 /*!< \_ */
207 # define su_C_DECL_BEGIN /*!< \_ */
208 # define su_C_DECL_END /*!< \_ */
210 /* Casts */
211 # define su_S(T,I) ((T)(I)) /*!< \_ */
212 # define su_R(T,I) ((T)(I)) /*!< \_ */
213 # define su_C(T,I) ((T)su_R(su_up,I)) /*!< \_ */
215 # define su_NIL ((void*)0) /*!< \_ */
216 #else
217 # define su_C_LANG 0
218 # define su_C_DECL_BEGIN extern "C" {
219 # define su_C_DECL_END }
220 # ifdef su_HAVE_NSPC
221 # define su_NSPC_BEGIN(X) namespace X {
222 # define su_NSPC_END(X) }
223 # define su_NSPC_USE(X) using namespace X;
224 # define su_NSPC(X) X::
225 # else
226 # define su_NSPC_BEGIN(X) /**/
227 # define su_NSPC_END(X) /**/
228 # define su_NSPC_USE(X) /**/
229 # define su_NSPC(X) /**/::
230 # endif
232 /* Disable copy-construction and assignment of class */
233 # define su_CLASS_NO_COPY(C) private:C(C const &);C &operator=(C const &);
234 /* If C++ class inherits from a C class, and the C class "return self", we
235 * have to waste a return register even if self==this */
236 # define su_SELFTHIS_RET(X) /* return *(X); */ X; return *this
238 /* C++ only allows those at the declaration, not the definition */
239 # define su_PUB
240 # define su_PRO
241 # define su_PRI
242 # define su_STA
243 # define su_VIR
244 # define su_OVR
245 /* This is for the declarator only */
246 # if __cplusplus +0 < 201103L
247 # define su_OVRX
248 # else
249 # define su_OVRX override
250 # endif
252 /* Casts */
253 # define su_S(T,I) static_cast<T>(I)
254 # define su_R(T,I) reinterpret_cast<T>(I)
255 # define su_C(T,I) const_cast<T>(I)
257 # define su_NIL (0L)
258 #endif /* __cplusplus */
260 /*! The \r{su_state_err()} mechanism can be configured to not cause
261 * abortion in case of datatype overflow and out-of-memory situations.
262 * Most functions return error conditions to pass them to their caller,
263 * but this is impossible for, e.g., C++ copy-constructors and assignment
264 * operators.
265 * And \SU does not use exceptions.
266 * So if those errors could occur and thus be hidden, the prototype is marked
267 * with this "keyword" so that callers can decide whether they want to take
268 * alternative routes to come to the desired result or not. */
269 #define su_SHADOW
271 /* "su_EXPORT myfun()", "class su_EXPORT myclass" */
272 #if su_OS_WIN32 || su_OS_WIN64
273 # define su_EXPORT __declspec((dllexport))
274 # define su_EXPORT_DATA __declspec((dllexport))
275 # define su_IMPORT __declspec((dllimport))
276 # define su_IMPORT_DATA __declspec((dllimport))
277 #else
278 # define su_EXPORT /*extern*/ /*!< \_ */
279 # define su_EXPORT_DATA extern /*!< \_ */
280 # define su_IMPORT /*extern*/ /*!< \_ */
281 # define su_IMPORT_DATA extern /*!< \_ */
282 #endif
284 /* Compile-Time-Assert
285 * Problem is that some compilers warn on unused local typedefs, so add
286 * a special local CTA to overcome this */
287 #if (!su_C_LANG && __cplusplus +0 >= 201103L) || defined DOXYGEN
288 # define su_CTA(T,M) static_assert(T, M) /*!< \_ */
289 # define su_LCTA(T,M) static_assert(T, M) /*!< \_ */
290 #elif 0 /* unusable! */ && \
291 defined __STDC_VERSION__ && __STDC_VERSION__ +0 >= 201112L
292 # define su_CTA(T,M) _Static_assert(T, M)
293 # define su_LCTA(T,M) _Static_assert(T, M)
294 #else
295 # define su_CTA(T,M) su__CTA_1(T, su_FILE, __LINE__)
296 # define su_LCTA(T,M) su__LCTA_1(T, su_FILE, __LINE__)
298 # define su__CTA_1(T,F,L) su__CTA_2(T, F, L)
299 # define su__CTA_2(T,F,L) \
300 typedef char ASSERTION_failed_file_ ## F ## _line_ ## L[(T) ? 1 : -1]
301 # define su__LCTA_1(T,F,L) su__LCTA_2(T, F, L)
302 # define su__LCTA_2(T,F,L) \
303 do{\
304 typedef char ASSERT_failed_file_ ## F ## _line_ ## L[(T) ? 1 : -1];\
305 ASSERT_failed_file_ ## F ## _line_ ## L __i_am_unused__;\
306 su_UNUSED(__i_am_unused__);\
307 }while(0)
308 #endif
310 #define su_CTAV(T) su_CTA(T, "Unexpected value of constant") /*!< \_ */
311 #define su_LCTAV(T) su_LCTA(T, "Unexpected value of constant") /*!< \_ */
312 #ifdef su_MASTER
313 # define su_MCTA(T,M) su_CTA(T, M);
314 #else
315 # define su_MCTA(T,M)
316 #endif
318 /* LANG }}} */
319 /* CC {{{ */
321 #define su_CC_CLANG 0 /*!< \_ */
322 #define su_CC_VCHECK_CLANG(X,Y) 0 /*!< \_ */
323 #define su_CC_GCC 0 /*!< \_ */
324 #define su_CC_VCHECK_GCC(X,Y) 0 /*!< \_ */
325 #define su_CC_PCC 0 /*!< \_ */
326 #define su_CC_VCHECK_PCC(X,Y) 0 /*!< \_ */
327 #define su_CC_SUNPROC 0 /*!< \_ */
328 #define su_CC_VCHECK_SUNPROC(X,Y) 0 /*!< \_ */
329 #define su_CC_TINYC 0 /*!< \_ */
330 #define su_CC_VCHECK_TINYC(X,Y) 0 /*!< \_ */
332 #ifdef __clang__
333 # undef su_CC_CLANG
334 # undef su_CC_VCHECK_CLANG
335 # define su_CC_CLANG 1
336 # define su_CC_VCHECK_CLANG(X,Y) \
337 (__clang_major__ +0 > (X) || \
338 (__clang_major__ +0 == (X) && __clang_minor__ +0 >= (Y)))
339 # define su_CC_EXTEN __extension__
340 # define su_CC_PACKED __attribute__((packed))
341 # if !defined su_CC_BOM &&\
342 defined __BYTE_ORDER__ && defined __ORDER_LITTLE_ENDIAN__ &&\
343 defined __ORDER_BIG_ENDIAN
344 # if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
345 # define su_CC_BOM su_CC_BOM_LITTLE
346 # elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
347 # define su_CC_BOM su_CC_BOM_BIG
348 # else
349 # error Unsupported __BYTE_ORDER__
350 # endif
351 # endif
353 /* __GNUC__ after some other Unix compilers which also define __GNUC__ */
354 #elif defined __PCC__ /* __clang__ */
355 # undef su_CC_PCC
356 # undef su_CC_VCHECK_PCC
357 # define su_CC_PCC 1
358 # define su_CC_VCHECK_PCC(X,Y) \
359 (__PCC__ +0 > (X) || (__PCC__ +0 == (X) && __PCC_MINOR__ +0 >= (Y)))
360 # define su_CC_EXTEN __extension__
361 # define su_CC_PACKED __attribute__((packed))
362 # if !defined su_CC_BOM &&\
363 defined __BYTE_ORDER__ && defined __ORDER_LITTLE_ENDIAN__ &&\
364 defined __ORDER_BIG_ENDIAN
365 # if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
366 # define su_CC_BOM su_CC_BOM_LITTLE
367 # elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
368 # define su_CC_BOM su_CC_BOM_BIG
369 # else
370 # error Unsupported __BYTE_ORDER__
371 # endif
372 # endif
374 #elif defined __SUNPRO_C /* __PCC__ */
375 # undef su_CC_SUNPROC
376 # define su_CC_SUNPROC 1
377 # define su_CC_PACKED TODO: PACKED attribute not supported for SunPro C
379 #elif defined __TINYC__ /* __SUNPRO_C */
380 # undef su_CC_TINYC
381 # define su_CC_TINYC 1
382 # define su_CC_EXTEN /* __extension__ (ignored) */
383 # define su_CC_PACKED __attribute__((packed))
385 #elif defined __GNUC__ /* __TINYC__ */
386 # undef su_CC_GCC
387 # undef su_CC_VCHECK_GCC
388 # define su_CC_GCC 1
389 # define su_CC_VCHECK_GCC(X,Y) \
390 (__GNUC__ +0 > (X) || (__GNUC__ +0 == (X) && __GNUC_MINOR__ +0 >= (Y)))
391 # define su_CC_EXTEN __extension__
392 # define su_CC_PACKED __attribute__((packed))
393 # if !defined su_CC_BOM &&\
394 defined __BYTE_ORDER__ && defined __ORDER_LITTLE_ENDIAN__ &&\
395 defined __ORDER_BIG_ENDIAN
396 # if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
397 # define su_CC_BOM su_CC_BOM_LITTLE
398 # elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
399 # define su_CC_BOM su_CC_BOM_BIG
400 # else
401 # error Unsupported __BYTE_ORDER__
402 # endif
403 # endif
405 #elif !defined su_CC_IGNORE_UNKNOWN
406 # error SU: This compiler is not yet supported.
407 # error SU: To continue with your CFLAGS etc., define su_CC_IGNORE_UNKNOWN.
408 # error SU: It may be necessary to define su_CC_PACKED to a statement that
409 # error SU: enables structure packing; it may not be a #pragma, but a _Pragma
410 #endif
412 #ifndef su_CC_EXTEN
413 # define su_CC_EXTEN /*!< \_ */
414 #endif
415 #ifndef su_CC_PACKED
416 /*! \_ */
417 # define su_CC_PACKED TODO: PACKED attribute not supported for this compiler
418 #endif
419 #if defined su_CC_BOM || defined DOXYGEN
420 # ifdef DOXYGEN
421 /*! If the CC offers \r{su_BOM} classification macros, defined to either
422 * \r{su_CC_BOM_LITTLE} or \r{su_CC_BOM_BIG}, otherwise not defined. */
423 # define su_CC_BOM
424 # endif
425 # define su_CC_BOM_LITTLE 1234 /*!< Only if there is \r{su_CC_BOM}. */
426 # define su_CC_BOM_BIG 4321 /*!< Only if there is \r{su_CC_BOM}. */
427 #endif
428 #if !defined su_CC_UZ_TYPE && defined __SIZE_TYPE__
429 # define su_CC_UZ_TYPE __SIZE_TYPE__
430 #endif
432 /* Function name */
433 #if defined __STDC_VERSION__ && __STDC_VERSION__ +0 >= 199901L
434 # define su_FUN __func__ /*!< "Not a literal". */
435 #elif su_CC_CLANG || su_CC_VCHECK_GCC(3, 4) || su_CC_PCC || su_CC_TINYC
436 # define su_FUN __extension__ __FUNCTION__
437 #else
438 # define su_FUN su_empty /* Something that is not a literal */
439 #endif
441 /* inline keyword */
442 #define su_HAVE_INLINE
443 #if su_C_LANG
444 # ifdef DOXYGEN
445 # define su_INLINE inline /*!< \_ */
446 # define su_SINLINE inline /*!< \_ */
447 # elif su_CC_CLANG || su_CC_GCC || su_CC_PCC
448 # if defined __STDC_VERSION__ && __STDC_VERSION__ +0 >= 199901l
449 # if !defined NDEBUG || !defined __OPTIMIZE__
450 # define su_INLINE static inline
451 # define su_SINLINE static inline
452 # else
453 /* clang does not like inline with <-O2 */
454 # define su_INLINE inline __attribute__((always_inline))
455 # define su_SINLINE static inline __attribute__((always_inline))
456 # endif
457 # else
458 # if su_CC_VCHECK_GCC(3, 1)
459 # define su_INLINE static __inline __attribute__((always_inline))
460 # define su_SINLINE static __inline __attribute__((always_inline))
461 # else
462 # define su_INLINE static __inline
463 # define su_SINLINE static __inline
464 # endif
465 # endif
466 # else
467 # define su_INLINE static /* TODO __attribute__((unused)) alike? */
468 # define su_SINLINE static /* TODO __attribute__((unused)) alike? */
469 # undef su_HAVE_INLINE
470 # endif
471 #else
472 # define su_INLINE inline
473 # define su_SINLINE static inline
474 #endif
475 #ifndef NDEBUG
476 # undef su_HAVE_INLINE
477 #endif
479 #if defined __predict_true && defined __predict_false
480 # define su_LIKELY(X) __predict_true((X) != 0)
481 # define su_UNLIKELY(X) __predict_false((X) != 0)
482 #elif su_CC_CLANG || su_CC_VCHECK_GCC(2, 96) || su_CC_PCC || su_CC_TINYC
483 # define su_LIKELY(X) __builtin_expect((X) != 0, 1)
484 # define su_UNLIKELY(X) __builtin_expect((X) != 0, 0)
485 #else
486 # define su_LIKELY(X) ((X) != 0) /*!< \_ */
487 # define su_UNLIKELY(X) ((X) != 0) /*!< \_ */
488 #endif
490 /* CC }}} */
491 /* SUPPORT MACROS+ {{{ */
493 /* USECASE_XY_DISABLED for tagging unused files:
494 * git rm `git grep ^su_USECASE_MX_DISABLED` */
495 #ifdef su_USECASE_MX
496 # define su_USECASE_MX_DISABLED This file is not a (valid) compilation unit
497 #endif
498 #ifndef su_USECASE_MX_DISABLED
499 # define su_USECASE_MX_DISABLED
500 #endif
502 /* Basic support macros, with side effects */
503 /*! Absolute value. */
504 #define su_ABS(A) ((A) < 0 ? -(A) : (A))
505 /*! Cramp \a{X} to be in between \a{A} and \a{B}, inclusive. */
506 #define su_CLIP(X,A,B) (((X) <= (A)) ? (A) : (((X) >= (B)) ? (B) : (X)))
507 /*! Is power of two? */
508 #define su_IS_POW2(X) ((((X) - 1) & (X)) == 0)
509 /*! Maximum value. */
510 #define su_MAX(A,B) ((A) < (B) ? (B) : (A))
511 /*! Minimum value. */
512 #define su_MIN(A,B) ((A) < (B) ? (A) : (B))
513 /*! Round down \a{X} to nearest multiple of \a{BASE}. */
514 #define su_ROUND_DOWN(X,BASE) (((X) / (BASE)) * (BASE))
515 /*! Ditto, if \a{BASE} is a power of two. */
516 #define su_ROUND_DOWN2(X,BASE) ((X) & (~((BASE) - 1)))
517 /*! Round up \a{X} to nearest multiple of \a{BASE}. */
518 #define su_ROUND_UP(X,BASE) ((((X) + ((BASE) - 1)) / (BASE)) * (BASE))
519 /*! Ditto, if \a{BASE} is a power of two. */
520 #define su_ROUND_UP2(X,BASE) (((X) + ((BASE) - 1)) & (~((BASE) - 1)))
522 /* Alignment. Note: su_uz POW2 asserted in POD section below! */
523 /* Commented out: "_Alignof() applied to an expression is a GNU extension" */
524 #if 0 && defined __STDC_VERSION__ && __STDC_VERSION__ +0 >= 201112L
525 # include <stdalign.h>
526 # define su_ALIGNOF(X) _Alignof(X)
527 #else
528 /*! \c{_Alignof()} if available, something hacky otherwise */
529 # define su_ALIGNOF(X) su_ROUND_UP2(sizeof(X), su__ZAL_L)
530 #endif
532 /*! Align a pointer \a{MEM} by the \r{su_ALIGNOF()} of \a{OTYPE}, and cast
533 * the result to \a{DTYPE}. */
534 #define su_P_ALIGN(DTYPE,OTYPE,MEM) \
535 su_R(DTYPE,\
536 su_IS_POW2(su_ALIGNOF(OTYPE))\
537 ? su_ROUND_UP2(su_R(su_up,MEM), su_ALIGNOF(OTYPE))\
538 : su_ROUND_UP(su_R(su_up,MEM), su_ALIGNOF(OTYPE)))
540 /* Roundup/align an integer; Note: POW2 asserted in POD section below! */
541 /*! Overalign an integer value to a size that cannot cause just any problem
542 * for anything which does not use special alignment directives.
543 * \remarks{It is safe to assume that \r{su_P_ALIGN()} can be used to place an
544 * object into a memory region spaced with it.} */
545 #define su_Z_ALIGN_OVER(X) su_ROUND_UP2(su_S(su_uz,X), 2 * su__ZAL_L)
547 /*! Smaller than \r{su_Z_ALIGN_OVER()}, but sufficient for plain-old-data. */
548 #define su_Z_ALIGN(X) su_ROUND_UP2(su_S(su_uz,X), su__ZAL_L)
550 /*! \r{su_Z_ALIGN()}, but only for pointers and \r{su_uz}. */
551 #define su_Z_ALIGN_PZ(X) su_ROUND_UP2(su_S(su_uz,X), su__ZAL_S)
553 /* (These are below MCTA()d to be of equal size[, however].)
554 * _L must adhere to the minimum aligned claimed in the \mainpage */
555 # define su__ZAL_S su_MAX(sizeof(su_uz), sizeof(void*))
556 # define su__ZAL_L su_MAX(su__ZAL_S, sizeof(su_u64))/* XXX FP,128bit */
558 /* Variants of ASSERT */
559 #if defined NDEBUG || defined DOXYGEN
560 # define su_ASSERT_INJ(X) /*!< Injection! */
561 # define su_ASSERT_INJOR(X,Y) Y /*!< Injection! */
562 # define su_ASSERT_NB(X) ((void)0) /*!< No block. */
563 # define su_ASSERT(X) do{}while(0) /*!< \_ */
564 # define su_ASSERT_LOC(X,FNAME,LNNO) do{}while(0) /*!< \_ */
565 # define su_ASSERT_EXEC(X,S) do{}while(0) /*!< \_ */
566 # define su_ASSERT_EXEC_LOC(X,S,FNAME,LNNO) do{}while(0) /*!< \_ */
567 # define su_ASSERT_JUMP(X,L) do{}while(0) /*!< \_ */
568 # define su_ASSERT_JUMP_LOC(X,L,FNAME,LNNO) do{}while(0) /*!< \_ */
569 # define su_ASSERT_RET(X,Y) do{}while(0) /*!< \_ */
570 # define su_ASSERT_RET_LOC(X,Y,FNAME,LNNO) do{}while(0) /*!< \_ */
571 # define su_ASSERT_RET_VOID(X) do{}while(0) /*!< \_ */
572 # define su_ASSERT_RET_VOID_LOC(X,Y,FNAME,LNNO) do{}while(0) /*!< \_ */
573 # define su_ASSERT_NYD_EXEC(X,Y) do{}while(0) /*!< \_ */
574 # define su_ASSERT_NYD_EXEC_LOC(X,FNAME,LNNO) do{}while(0) /*!< \_ */
575 # define su_ASSERT_NYD(X) do{}while(0) /*!< \_ */
576 # define su_ASSERT_NYD_LOC(X,FNAME,LNNO) do{}while(0) /*!< \_ */
577 #else
578 # define su_ASSERT_INJ(X) X
579 # define su_ASSERT_INJOR(X,Y) X
581 # define su_ASSERT_NB(X) \
582 su_R(void,((X) ? su_TRU1 \
583 : su_assert(su_STRING(X), __FILE__, __LINE__, su_FUN, su_TRU1), su_FAL0))
585 # define su_ASSERT(X) su_ASSERT_LOC(X, __FILE__, __LINE__)
586 # define su_ASSERT_LOC(X,FNAME,LNNO) \
587 do if(!(X))\
588 su_assert(su_STRING(X), FNAME, LNNO, su_FUN, su_TRU1);\
589 while(0)
591 # define su_ASSERT_EXEC(X,S) su_ASSERT_EXEC_LOC(X, S, __FILE__, __LINE__)
592 # define su_ASSERT_EXEC_LOC(X,S,FNAME,LNNO) \
593 do if(!(X)){\
594 su_assert(su_STRING(X), FNAME, LNNO, su_FUN, su_FAL0);\
596 }while(0)
598 # define su_ASSERT_JUMP(X,L) su_ASSERT_JUMP_LOC(X, L, __FILE__, __LINE__)
599 # define su_ASSERT_JUMP_LOC(X,L,FNAME,LNNO) \
600 do if(!(X)){\
601 su_assert(su_STRING(X), FNAME, LNNO, su_FUN, su_FAL0);\
602 goto L;\
603 }while(0)
605 # define su_ASSERT_RET(X,Y) su_ASSERT_RET_LOC(X, Y, __FILE__, __LINE__)
606 # define su_ASSERT_RET_LOC(X,Y,FNAME,LNNO) \
607 do if(!(X)){\
608 su_assert(su_STRING(X), FNAME, LNNO, su_FUN, su_FAL0);\
609 return Y;\
610 }while(0)
612 # define su_ASSERT_RET_VOID(X) su_ASSERT_RET_VOID_LOC(X, __FILE__, __LINE__)
613 # define su_ASSERT_RET_VOID_LOC(X,FNAME,LNNO) \
614 do if(!(X)){\
615 su_assert(su_STRING(X), FNAME, LNNO, su_FUN, su_FAL0);\
616 return;\
617 }while(0)
619 # define su_ASSERT_NYD_EXEC(X,Y) \
620 su_ASSERT_NYD_EXEC_LOC(X, Y, __FILE__, __LINE__)
621 # define su_ASSERT_NYD_EXEC_LOC(X,Y,FNAME,LNNO) \
622 do if(!(X)){\
623 su_assert(su_STRING(X), FNAME, LNNO, su_FUN, su_FAL0);\
624 Y; goto su_NYD_OU_LABEL;\
625 }while(0)
627 # define su_ASSERT_NYD(X) su_ASSERT_NYD_LOC(X, __FILE__, __LINE__)
628 # define su_ASSERT_NYD_LOC(X,FNAME,LNNO) \
629 do if(!(X)){\
630 su_assert(su_STRING(X), FNAME, LNNO, su_FUN, su_FAL0);\
631 goto su_NYD_OU_LABEL;\
632 }while(0)
633 #endif /* defined NDEBUG || defined DOXYGEN */
635 /*! There are no bit-\c{enum}erations, but we use \c{enum}s as such, since the
636 * only other option for bit constants would be preprocessor macros.
637 * Since enumerations are expected to represent a single value, a normal
638 * integer is often used to store enumeration values.
639 * To be explicit, this macro is used instead, \a{X} is the pod, \a{Y} is the
640 * enumeration name that is actually meant. */
641 #define su_BITENUM_IS(X,Y) X
643 /*! Create a bit mask for the inclusive bit range \a{LO} to \a{HI}.
644 * \remarks{\a{HI} cannot use highest bit!}
645 * \remarks{Identical to \r{su_BITS_RANGE_MASK().} */
646 #define su_BITENUM_MASK(LO,HI) (((1u << ((HI) + 1)) - 1) & ~((1u << (LO)) - 1))
648 /*! For injection macros like su_DBG(), NDBG, DBGOR, 64, 32, 6432 */
649 #define su_COMMA ,
651 /* Debug injections */
652 #if defined su_HAVE_DEBUG && !defined NDEBUG
653 # define su_DBG(X) X /*!< \_ */
654 # define su_NDBG(X) /*!< \_ */
655 # define su_DBGOR(X,Y) X /*!< \_ */
656 #else
657 # define su_DBG(X)
658 # define su_NDBG(X) X
659 # define su_DBGOR(X,Y) Y
660 #endif
662 /* Debug file location arguments. (For an usage example see su/mem.h.) */
663 #if defined su_HAVE_DEVEL || defined su_HAVE_DEBUG
664 # define su_HAVE_DBG_LOC_ARGS
665 # define su_DBG_LOC_ARGS_FILE su__dbg_loc_args_file
666 # define su_DBG_LOC_ARGS_LINE su__dbg_loc_args_line
668 # define su_DBG_LOC_ARGS_DECL_SOLE \
669 char const *su_DBG_LOC_ARGS_FILE, su_u32 su_DBG_LOC_ARGS_LINE
670 # define su_DBG_LOC_ARGS_DECL , su_DBG_LOC_ARGS_DECL_SOLE
671 # define su_DBG_LOC_ARGS_INJ_SOLE __FILE__, __LINE__
672 # define su_DBG_LOC_ARGS_INJ , su_DBG_LOC_ARGS_INJ_SOLE
673 # define su_DBG_LOC_ARGS_USE_SOLE su_DBG_LOC_ARGS_FILE, su_DBG_LOC_ARGS_LINE
674 # define su_DBG_LOC_ARGS_USE , su_DBG_LOC_ARGS_USE_SOLE
675 # define su_DBG_LOC_ARGS_ORUSE su_DBG_LOC_ARGS_FILE, su_DBG_LOC_ARGS_LINE
676 # define su_DBG_LOC_ARGS_UNUSED() \
677 do{\
678 su_UNUSED(su_DBG_LOC_ARGS_FILE);\
679 su_UNUSED(su_DBG_LOC_ARGS_LINE);\
680 }while(0)
681 #else
682 # define su_DBG_LOC_ARGS_FILE "unused"
683 # define su_DBG_LOC_ARGS_LINE 0
685 # define su_DBG_LOC_ARGS_DECL_SOLE
686 # define su_DBG_LOC_ARGS_DECL
687 # define su_DBG_LOC_ARGS_INJ_SOLE
688 # define su_DBG_LOC_ARGS_INJ
689 # define su_DBG_LOC_ARGS_USE_SOLE
690 # define su_DBG_LOC_ARGS_USE
691 # define su_DBG_LOC_ARGS_ORUSE su_DBG_LOC_ARGS_FILE, su_DBG_LOC_ARGS_LINE
692 # define su_DBG_LOC_ARGS_UNUSED() do{}while(0)
693 #endif /* su_HAVE_DEVEL || su_HAVE_DEBUG */
695 /* Development injections */
696 #if defined su_HAVE_DEVEL || defined su_HAVE_DEBUG /* Not: !defined NDEBUG) */\
697 || defined DOXYGEN
698 # define su_DVL(X) X /*!< \_ */
699 # define su_NDVL(X) /*!< \_ */
700 # define su_DVLOR(X,Y) X /*!< \_ */
701 #else
702 # define su_DVL(X)
703 # define su_NDVL(X) X
704 # define su_DVLOR(X,Y) Y
705 #endif
707 /*! To avoid files that are overall empty */
708 #define su_EMPTY_FILE() typedef int su_CONCAT(su_notempty_shall_b_, su_FILE);
710 /* C field init */
711 #if (su_C_LANG && defined __STDC_VERSION__ && \
712 __STDC_VERSION__ +0 >= 199901L) || defined DOXYGEN
713 # define su_FIELD_INITN(N) .N = /*!< \_ */
714 # define su_FIELD_INITI(I) [I] = /*!< \_ */
715 #else
716 # define su_FIELD_INITN(N)
717 # define su_FIELD_INITI(I)
718 #endif
720 /* XXX offsetof+: clang,pcc check faked! */
721 #if su_CC_VCHECK_CLANG(5, 0) || su_CC_VCHECK_GCC(4, 1) ||\
722 su_CC_VCHECK_PCC(1, 2) || defined DOXYGEN
723 /*! The offset of field \a{F} in the type \a{T}. */
724 # define su_FIELD_OFFSETOF(T,F) __builtin_offsetof(T, F)
725 #else
726 # define su_FIELD_OFFSETOF(T,F) \
727 su_S(su_uz,su_S(su_up,&(su_R(T *,0x1)->F)) - 1)
728 #endif
730 /*! Distance in between the fields \a{S}tart and \a{E}end in type \a{T}. */
731 #define su_FIELD_RANGEOF(T,S,E) \
732 (su_FIELD_OFFSETOF(T, E) - su_FIELD_OFFSETOF(T, S))
734 /*! sizeof() for member fields */
735 #define su_FIELD_SIZEOF(T,F) sizeof(su_S(T *,su_NIL)->F)
737 /* Multithread injections */
738 #ifdef su_HAVE_MT
739 # define su_MT(X) X /*!< \_ */
740 #else
741 # define su_MT(X)
742 #endif
744 /*! Members in constant array */
745 #define su_NELEM(A) (sizeof(A) / sizeof((A)[0]))
747 /*! NYD comes from code-{in,ou}.h (support function below).
748 * Instrumented functions will always have one label for goto: purposes. */
749 #define su_NYD_OU_LABEL su__nydou
751 /*! Pointer to size_t */
752 #define su_P2UZ(X) su_S(su_uz,(su_up)(X))
754 /*! Pointer comparison */
755 #define su_PCMP(A,C,B) (su_R(su_up,A) C su_R(su_up,B))
757 /* SMP injections */
758 #ifdef su_HAVE_SMP
759 # define su_SMP(X) X /*!< \_ */
760 #else
761 # define su_SMP(X)
762 #endif
764 /* String stuff.
765 * __STDC_VERSION__ is ISO C99, so also use __STDC__, which should work */
766 #if defined __STDC__ || defined __STDC_VERSION__ || su_C_LANG || \
767 defined DOXYGEN
768 # define su_STRING(X) #X /*!< \_ */
769 # define su_XSTRING(X) su_STRING(X) /*!< \_ */
770 # define su_CONCAT(S1,S2) su__CONCAT_1(S1, S2) /*!< \_ */
771 # define su__CONCAT_1(S1,S2) S1 ## S2
772 #else
773 # define su_STRING(X) "X"
774 # define su_XSTRING STRING
775 # define su_CONCAT(S1,S2) S1/* will no work out though */S2
776 #endif
778 #if su_C_LANG || defined DOXYGEN
779 /*! Compare (maybe mixed-signed) integers cases to \a{T} bits, unsigned,
780 * \a{T} is one of our homebrew integers, e.g.,
781 * \c{UCMP(32, su_ABS(n), >, wleft)}.
782 * \remarks{Does not sign-extend correctly, this is up to the caller.} */
783 # define su_UCMP(T,A,C,B) (su_S(su_ ## u ## T,A) C su_S(su_ ## u ## T,B))
784 #else
785 # define su_UCMP(T,A,C,B) \
786 (su_S(su_NSPC(su) u ## T,A) C su_S(su_NSPC(su) u ## T,B))
787 #endif
789 /*! Casts-away (*NOT* cast-away) */
790 #define su_UNCONST(T,P) su_R(T,su_R(su_up,su_S(void const*,P)))
791 /*! Casts-away (*NOT* cast-away) */
792 #define su_UNVOLATILE(T,P) su_R(T,su_R(su_up,su_S(void volatile*,P)))
793 /*! To avoid warnings with modern compilers for "char*i; *(s32_t*)i=;" */
794 #define su_UNALIGN(T,P) su_R(T,su_R(su_up,P))
795 #define su_UNXXX(T,C,P) su_R(T,su_R(su_up,su_S(C,P)))
797 /* Avoid "may be used uninitialized" warnings */
798 #if (defined NDEBUG && !(defined su_HAVE_DEBUG || defined su_HAVE_DEVEL)) || \
799 defined DOYGEN
800 # define su_UNINIT(N,V) su_S(void,0) /*!< \_ */
801 # define su_UNINIT_DECL(V) /*!< \_ */
802 #else
803 # define su_UNINIT(N,V) N = V
804 # define su_UNINIT_DECL(V) = V
805 #endif
807 /*! Avoid "unused" warnings */
808 #define su_UNUSED(X) ((void)(X))
810 #if (su_C_LANG && defined __STDC_VERSION__ && \
811 __STDC_VERSION__ +0 >= 199901L) || defined DOXYGEN
812 /*! Variable-type size (with byte array at end) */
813 # define su_VFIELD_SIZE(X)
814 /*! Variable-type size (with byte array at end) */
815 # define su_VSTRUCT_SIZEOF(T,F) sizeof(T)
816 #else
817 # define su_VFIELD_SIZE(X) \
818 ((X) == 0 ? sizeof(su_uz) \
819 : (su_S(su_sz,X) < 0 ? sizeof(su_uz) - su_ABS(X) : su_S(su_uz,X)))
820 # define su_VSTRUCT_SIZEOF(T,F) (sizeof(T) - su_FIELD_SIZEOF(T, F))
821 #endif
823 /* SUPPORT MACROS+ }}} */
825 /* We are ready to start using our own style */
826 #ifndef su_CC_SIZE_TYPE
827 # include <sys/types.h> /* TODO create config time script, */
828 #endif
830 #include <inttypes.h> /* TODO query infos and drop */
831 #include <limits.h> /* TODO those includes! */
833 #define su_HEADER
834 #include <su/code-in.h>
835 C_DECL_BEGIN
837 /* POD TYPE SUPPORT TODO maybe configure-time, from a su/config.h?! {{{ */
838 /* TODO Note: the PRI* series will go away once we have FormatCtx! */
840 /* First some shorter aliases for "normal" integers */
841 typedef unsigned long su_ul; /*!< \_ */
842 typedef unsigned int su_ui; /*!< \_ */
843 typedef unsigned short su_us; /*!< \_ */
844 typedef unsigned char su_uc; /*!< \_ */
846 typedef signed long su_sl; /*!< \_ */
847 typedef signed int su_si; /*!< \_ */
848 typedef signed short su_ss; /*!< \_ */
849 typedef signed char su_sc; /*!< \_ */
851 #if defined UINT8_MAX || defined DOXYGEN
852 # define su_U8_MAX UINT8_MAX /*!< \_ */
853 # define su_S8_MIN INT8_MIN /*!< \_ */
854 # define su_S8_MAX INT8_MAX /*!< \_ */
855 typedef uint8_t su_u8; /*!< \_ */
856 typedef int8_t su_s8; /*!< \_ */
857 #elif UCHAR_MAX != 255
858 # error UCHAR_MAX must be 255
859 #else
860 # define su_U8_MAX UCHAR_MAX
861 # define su_S8_MIN CHAR_MIN
862 # define su_S8_MAX CHAR_MAX
863 typedef unsigned char su_u8;
864 typedef signed char su_s8;
865 #endif
867 #if !defined PRIu8 || !defined PRId8
868 # undef PRIu8
869 # undef PRId8
870 # define PRIu8 "hhu"
871 # define PRId8 "hhd"
872 #endif
874 #if defined UINT16_MAX || defined DOXYGEN
875 # define su_U16_MAX UINT16_MAX /*!< \_ */
876 # define su_S16_MIN INT16_MIN /*!< \_ */
877 # define su_S16_MAX INT16_MAX /*!< \_ */
878 typedef uint16_t su_u16; /*!< \_ */
879 typedef int16_t su_s16; /*!< \_ */
880 #elif USHRT_MAX != 0xFFFFu
881 # error USHRT_MAX must be 0xFFFF
882 #else
883 # define su_U16_MAX USHRT_MAX
884 # define su_S16_MIN SHRT_MIN
885 # define su_S16_MAX SHRT_MAX
886 typedef unsigned short su_u16;
887 typedef signed short su_s16;
888 #endif
890 #if !defined PRIu16 || !defined PRId16
891 # undef PRIu16
892 # undef PRId16
893 # if su_U16_MAX == UINT_MAX
894 # define PRIu16 "u"
895 # define PRId16 "d"
896 # else
897 # define PRIu16 "hu"
898 # define PRId16 "hd"
899 # endif
900 #endif
902 #if defined UINT32_MAX || defined DOXYGEN
903 # define su_U32_MAX UINT32_MAX /*!< \_ */
904 # define su_S32_MIN INT32_MIN /*!< \_ */
905 # define su_S32_MAX INT32_MAX /*!< \_ */
906 typedef uint32_t su_u32; /*!< \_ */
907 typedef int32_t su_s32; /*!< \_ */
908 #elif ULONG_MAX == 0xFFFFFFFFu
909 # define su_U32_MAX ULONG_MAX
910 # define su_S32_MIN LONG_MIN
911 # define su_S32_MAX LONG_MAX
912 typedef unsigned long int su_u32;
913 typedef signed long int su_s32;
914 #elif UINT_MAX != 0xFFFFFFFFu
915 # error UINT_MAX must be 0xFFFFFFFF
916 #else
917 # define su_U32_MAX UINT_MAX
918 # define su_S32_MIN INT_MIN
919 # define su_S32_MAX INT_MAX
920 typedef unsigned int su_u32;
921 typedef signed int su_s32;
922 #endif
924 #if !defined PRIu32 || !defined PRId32
925 # undef PRIu32
926 # undef PRId32
927 # if su_U32_MAX == ULONG_MAX
928 # define PRIu32 "lu"
929 # define PRId32 "ld"
930 # else
931 # define PRIu32 "u"
932 # define PRId32 "d"
933 # endif
934 #endif
936 #if defined UINT64_MAX || defined DOXYGEN
937 # define su_U64_MAX UINT64_MAX /*!< \_ */
938 # define su_S64_MIN INT64_MIN /*!< \_ */
939 # define su_S64_MAX INT64_MAX /*!< \_ */
940 # define su_S64_C(C) INT64_C(C) /*!< \_ */
941 # define su_U64_C(C) UINT64_C(C) /*!< \_ */
942 typedef uint64_t su_u64; /*!< \_ */
943 typedef int64_t su_s64; /*!< \_ */
944 #elif ULONG_MAX <= 0xFFFFFFFFu
945 # if !defined ULLONG_MAX
946 # error We need a 64 bit integer
947 # else
948 # define su_U64_MAX ULLONG_MAX
949 # define su_S64_MIN LLONG_MIN
950 # define su_S64_MAX LLONG_MAX
951 # define su_S64_C(C) su_CONCAT(C, ll)
952 # define su_U64_C(C) su_CONCAT(C, ull)
953 su_CC_EXTEN typedef unsigned long long su_u64;
954 su_CC_EXTEN typedef signed long long su_s64;
955 # endif
956 #else
957 # define su_U64_MAX ULONG_MAX
958 # define su_S64_MIN LONG_MIN
959 # define su_S64_MAX LONG_MAX
960 # define su_S64_C(C) su_CONCAT(C, l)
961 # define su_U64_C(C) su_CONCAT(C, ul)
962 typedef unsigned long su_u64;
963 typedef signed long su_s64;
964 #endif
966 #if !defined PRIu64 || !defined PRId64 || !defined PRIX64 || !defined PRIo64
967 # undef PRIu64
968 # undef PRId64
969 # undef PRIX64
970 # undef PRIo64
971 # if defined ULLONG_MAX && su_U64_MAX == ULLONG_MAX
972 # define PRIu64 "llu"
973 # define PRId64 "lld"
974 # define PRIX64 "llX"
975 # define PRIo64 "llo"
976 # else
977 # define PRIu64 "lu"
978 # define PRId64 "ld"
979 # define PRIX64 "lX"
980 # define PRIo64 "lo"
981 # endif
982 #endif
984 /* (So that we can use UCMP() for size_t comparison, too) */
985 #ifdef su_CC_SIZE_TYPE
986 typedef su_CC_SIZE_TYPE su_uz;
987 #else
988 typedef size_t su_uz; /*!< \_ */
989 #endif
991 #undef PRIuZ
992 #undef PRIdZ
993 #if (defined __STDC_VERSION__ && __STDC_VERSION__ +0 >= 199901L) ||\
994 defined DOXYGEN
995 # define PRIuZ "zu"
996 # define PRIdZ "zd"
997 # define su_UZ_MAX SIZE_MAX /*!< \_ */
998 #elif defined SIZE_MAX
999 /* UnixWare has size_t as unsigned as required but uses a signed limit
1000 * constant (which is thus false!) */
1001 # if SIZE_MAX == su_U64_MAX || SIZE_MAX == su_S64_MAX
1002 # define PRIuZ PRIu64
1003 # define PRIdZ PRId64
1004 MCTA(sizeof(size_t) == sizeof(u64),
1005 "Format string mismatch, compile with ISO C99 compiler (-std=c99)!")
1006 # elif SIZE_MAX == su_U32_MAX || SIZE_MAX == su_S32_MAX
1007 # define PRIuZ PRIu32
1008 # define PRIdZ PRId32
1009 MCTA(sizeof(size_t) == sizeof(u32),
1010 "Format string mismatch, compile with ISO C99 compiler (-std=c99)!")
1011 # else
1012 # error SIZE_MAX is neither su_U64_MAX nor su_U32_MAX (please report this)
1013 # endif
1014 # define su_UZ_MAX SIZE_MAX
1015 #endif
1016 #if !defined PRIuZ && !defined DOXYGEN
1017 # define PRIuZ "lu"
1018 # define PRIdZ "ld"
1019 MCTA(sizeof(size_t) == sizeof(unsigned long),
1020 "Format string mismatch, compile with ISO C99 compiler (-std=c99)!")
1021 #endif
1022 /* The signed equivalence is not really compliant to the standard */
1023 #if su_UZ_MAX == su_U32_MAX || su_UZ_MAX == su_S32_MAX || defined DOXYGEN
1024 # define su_SZ_MIN su_S32_MIN /*!< \_ */
1025 # define su_SZ_MAX su_S32_MAX /*!< \_ */
1026 # define su_UZ_BITS 32u /*!< \_ */
1027 # define su_64(X) /*!< \_ */
1028 # define su_32(X) X /*!< \_ */
1029 # define su_6432(X,Y) Y /*!< \_ */
1030 typedef su_s32 su_sz; /*!< \_ */
1031 #elif su_UZ_MAX == su_U64_MAX
1032 # define su_SZ_MIN su_S64_MIN
1033 # define su_SZ_MAX su_S64_MAX
1034 # define su_UZ_BITS 64u
1035 # define su_64(X) X
1036 # define su_32(X)
1037 # define su_6432(X,Y) X
1038 typedef su_s64 su_sz;
1039 #else
1040 # error I cannot handle this maximum value of size_t
1041 #endif
1043 MCTA(sizeof(su_uz) == sizeof(void*),
1044 "SU cannot handle sizeof(su_uz) != sizeof(void*)")
1046 /* Regardless of P2UZ provide this one; only use it rarely */
1047 #if defined UINTPTR_MAX || defined DOXYGEN
1048 typedef uintptr_t su_up; /*!< \_ */
1049 typedef intptr_t su_sp; /*!< \_ */
1050 #else
1051 # ifdef SIZE_MAX
1052 typedef su_uz su_up;
1053 typedef su_sz su_sp;
1054 # else
1055 typedef su_ul su_up;
1056 typedef su_sl su_sp;
1057 # endif
1058 #endif
1060 /*! Values for #su_boole (normally only \c{FAL0} and \c{TRU1}). */
1061 enum{
1062 su_FAL0, /*!< 0 (no bits set). */
1063 su_TRU1, /*!< The value 1. */
1064 su_TRU2, /*!< The value 2. */
1065 su_TRUM1 = -1 /*!< All bits set. */
1067 typedef su_s8 su_boole; /*!< The \SU boolean type (see \FAL0 etc.). */
1069 /* POD TYPE SUPPORT }}} */
1070 /* BASIC TYPE TRAITS {{{ */
1072 struct su_toolbox;
1073 /* plus PTF typedefs */
1075 /*! Create a new default instance of an object type, return it or \NIL.
1076 * See \r{su_clone_fun} for the meaning of \a{estate}. */
1077 typedef void *(*su_new_fun)(u32 estate);
1079 /*! Create a clone of \a{t}, and return it.
1080 * \a{estate} might be set to some \r{su_state_err_type}s to be turned to
1081 * non-fatal errors, and contain \r{su_state_err_flags} with additional
1082 * control requests.
1083 * Otherwise (\a{estate} is 0) \NIL can still be returned for
1084 * \r{su_STATE_ERR_NOMEM} or \r{su_STATE_ERR_OVERFLOW}, dependent on the
1085 * global \r{su_state_get()} / \r{su_state_has()} setting,
1086 * as well as for other errors and with other \r{su_err_number}s, of course.
1087 * Also see \r{su_STATE_ERR_NIL_IS_VALID_OBJECT}. */
1088 typedef void *(*su_clone_fun)(void const *t, u32 estate);
1090 /*! Delete an instance returned by \r{su_new_fun} or \r{su_clone_fun} (or
1091 * \r{su_assign_fun}). */
1092 typedef void (*su_delete_fun)(void *self);
1094 /*! Assign \a{t}; see \r{su_clone_fun} for the meaning of \a{estate}.
1095 * In-place update of \SELF is (and should) not (be) assumed, but instead the
1096 * return value has to be used, with the exception as follows.
1097 * First all resources of \a{self} should be released (an operation which is
1098 * not supposed to fail), then the assignment be performed.
1099 * If this fails, \a{self} should be turned to cleared state again,
1100 * and \NIL should be returned.
1102 * \remarks{This function is not used by (object owning) \r{COLL} unless
1103 * \r{su_STATE_ERR_NIL_IS_VALID_OBJECT} is set. Regardless, if \NIL is
1104 * returned to indicate error then the caller which passed a non-\NIL object
1105 * is responsible for deletion or taking other appropriate steps.}
1107 * \remarks{If \a{self} and \a{t} are \r{COLL}, then if assignment fails then
1108 * whereas \a{self} will not manage any elements, it has been assigned \a{t}'s
1109 * possible existent \r{su_toolbox} as well as other attributes.
1110 * Some \r{COLL} will provide an additional \c{assign_elems()} function.} */
1111 typedef void *(*su_assign_fun)(void *self, void const *t, u32 estate);
1113 /*! Compare \a{a} and \a{b}, and return a value less than 0 if \a{a} is "less
1114 * than \a{b}", 0 on equality, and a value greater than 0 if \a{a} is
1115 * "greate than \a{b}". */
1116 typedef su_sz (*su_compare_fun)(void const *a, void const *b);
1118 /*! Create a hash that reproducibly represents \SELF. */
1119 typedef su_uz (*su_hash_fun)(void const *self);
1121 /* Needs to be binary compatible with \c{su::{toolbox,type_toolbox<T>}}! */
1122 /*! A toolbox provides object handling knowledge to \r{COLL}.
1123 * Also see \r{su_TOOLBOX_I9R()}. */
1124 struct su_toolbox{
1125 su_clone_fun tb_clone; /*!< \copydoc{su_clone_fun}. */
1126 su_delete_fun tb_delete; /*!< \copydoc{su_delete_fun}. */
1127 su_assign_fun tb_assign; /*!< \copydoc{su_assign_fun}. */
1128 su_compare_fun tb_compare; /*!< \copydoc{su_compare_fun}. */
1129 su_hash_fun tb_hash; /*!< \copydoc{su_hash_fun}. */
1132 /* Use C-style casts, not and ever su_R()! */
1133 /*! Initialize a \r{su_toolbox}. */
1134 #define su_TOOLBOX_I9R(CLONE,DELETE,ASSIGN,COMPARE,HASH) \
1136 su_FIELD_INITN(tb_clone) (su_clone_fun)(CLONE),\
1137 su_FIELD_INITN(tb_delete) (su_delete_fun)(DELETE),\
1138 su_FIELD_INITN(tb_assign) (su_assign_fun)(ASSIGN),\
1139 su_FIELD_INITN(tb_compare) (su_compare_fun)(COMPARE),\
1140 su_FIELD_INITN(tb_hash) (su_hash_fun)(HASH)\
1143 /* BASIC TYPE TRAITS }}} */
1144 /* BASIC C INTERFACE (SYMBOLS) {{{ */
1146 /*! Byte order mark macro; there are also \r{su_bom}, \r{su_BOM_IS_BIG()} and
1147 * \r{su_BOM_IS_LITTLE()}. */
1148 #define su_BOM 0xFEFFu
1150 /* su_state.. machinery: first byte: global log instance.. */
1152 /*! Log priorities, for simplicity of use without _LEVEL or _LVL prefix,
1153 * for \r{su_log_set_level()}. */
1154 enum su_log_level{
1155 su_LOG_EMERG, /*!< System is unusable (abort()s the program) */
1156 su_LOG_ALERT, /*!< Action must be taken immediately */
1157 su_LOG_CRIT, /*!< Critical conditions */
1158 su_LOG_ERR, /*!< Error conditions */
1159 su_LOG_WARN, /*!< Warning conditions */
1160 su_LOG_NOTICE, /*!< Normal but significant condition */
1161 su_LOG_INFO, /*!< Informational */
1162 su_LOG_DEBUG /*!< Debug-level message */
1164 enum{
1165 su__LOG_MAX = su_LOG_DEBUG,
1166 su__LOG_SHIFT = 8,
1167 su__LOG_MASK = (1u << su__LOG_SHIFT) - 1
1169 MCTA(1u<<su__LOG_SHIFT > su__LOG_MAX, "Bit ranges may not overlap")
1171 /*! Flags that can be ORd to \r{su_log_level}. */
1172 enum su_log_flags{
1173 /*! In environments where \r{su_log_write()} is (also) hooked to an output
1174 * channel, do not log the message through that. */
1175 su_LOG_F_CORE = 1u<<(su__LOG_SHIFT+0)
1178 /*! Adjustment possibilities for the global log domain (e.g,
1179 * \r{su_log_write()}), to be set via \r{su_state_set()}, to be queried via
1180 * \r{su_state_has()}. */
1181 enum su_state_log_flags{
1182 /*! Prepend a messages \r{su_log_level}. */
1183 su_STATE_LOG_SHOW_LEVEL = 1u<<4,
1184 /*! Show the PID (Process IDentification number).
1185 * This flag is only honoured if \r{su_program} set to non-\NIL. */
1186 su_STATE_LOG_SHOW_PID = 1u<<5
1189 /* ..second byte: hardening errors.. */
1191 /*! Global hardening for out-of-memory and integer etc. overflow: types.
1192 * By default out-of-memory situations, or container and string etc.
1193 * insertions etc. which cause count/offset datatype overflow result in
1194 * \r{su_LOG_EMERG}s, and thus program abortion.
1196 * This global default can be changed by including the corresponding
1197 * \c{su_state_err_type} (\r{su_STATE_ERR_NOMEM} and
1198 * \r{su_STATE_ERR_OVERFLOW}, respectively), in the global \SU state machine
1199 * via \r{su_state_set()}, in which case logging uses \r{su_LOG_ALERT} level,
1200 * a corresponding \r{su_err_number} will be assigned for \r{su_err_no()}, and
1201 * the failed function will return error.
1203 * Often functions and object allow additional control over the global on
1204 * a by-call or by-object basis, taking a state argument which consists of
1205 * \c{su_state_err_type} and \r{su_state_err_flags} bits.
1206 * In order to support this these values do not form an enumeration, but
1207 * rather are combinable bits. */
1208 enum su_state_err_type{
1209 su_STATE_ERR_NOMEM = 1u<<8, /*!< Out-of-memory. */
1210 su_STATE_ERR_OVERFLOW = 1u<<9 /*!< Integer/xy domain overflow. */
1213 /*! Hardening for out-of-memory and integer etc. overflow: adjustment flags.
1214 * Many functions offer the possibility to adjust the global \r{su_state_get()}
1215 * (\r{su_state_has()}) \r{su_state_err_type} default on a per-call level, and
1216 * object types (can) do so on a per-object basis.
1218 * If so, the global state can (selectively) be bypassed by adding in
1219 * \r{su_state_err_type}s to be ignored to an (optional) function argument,
1220 * or object control function or field.
1221 * It is also possible to instead enforce program abortion regardless of
1222 * a global ignorance policy, and pass other control flags. */
1223 enum su_state_err_flags{
1224 /*! A mask containing all \r{su_state_err_type} bits. */
1225 su_STATE_ERR_TYPE_MASK = su_STATE_ERR_NOMEM | su_STATE_ERR_OVERFLOW,
1226 /*! Allow passing of all errors.
1227 * This is just a better name alias for \r{su_STATE_ERR_TYPE_MASK}. */
1228 su_STATE_ERR_PASS = su_STATE_ERR_TYPE_MASK,
1229 /*! Regardless of global (and additional local) policy, if this flag is
1230 * set, an actual error causes a hard program abortion. */
1231 su_STATE_ERR_NOPASS = 1u<<12,
1232 /*! If this flag is set and no abortion is about to happen, a corresponding
1233 * \r{su_err_number} will not be assigned to \r{su_err_no()}. */
1234 su_STATE_ERR_NOERRNO = 1u<<13,
1235 /*! This is special in that it plays no role in the global state machine.
1236 * However, many types or functions which provide \a{estate} arguments and
1237 * use (NOT) \r{su_STATE_ERR_MASK} to overload that with meaning, adding
1238 * support for owning \r{COLL} (for \r{su_toolbox} users, to be exact)
1239 * actually made sense: if this bit is set it indicates that \NIL values
1240 * returned by \r{su_toolbox} members are acceptible values (and thus do not
1241 * cause actions like insertion, replacement etc. to fail). */
1242 su_STATE_ERR_NIL_IS_VALID_OBJECT = 1u<<14,
1243 /*! Alias for \r{su_STATE_ERR_NIL_IS_VALID_OBJECT}. */
1244 su_STATE_ERR_NILISVALO = su_STATE_ERR_NIL_IS_VALID_OBJECT,
1245 /*! Handy mask for the entire family of error \SU error bits,
1246 * \r{su_state_err_type} and \r{su_state_err_flags}.
1247 * It can be used by functions or methods which allow fine-tuning of error
1248 * behaviour to strip down an user argument.
1250 * \remarks{This mask itself is covered by the mask \c{0xFF00}.
1251 * This condition is compile-time asserted.} */
1252 su_STATE_ERR_MASK = su_STATE_ERR_TYPE_MASK |
1253 su_STATE_ERR_PASS | su_STATE_ERR_NOPASS | su_STATE_ERR_NOERRNO |
1254 su_STATE_ERR_NIL_IS_VALID_OBJECT
1257 /* ..third byte: misc flags */
1259 /*! \_ */
1260 enum su_state_flags{
1261 su_STATE_NONE, /*!< No flag: this is 0. */
1262 su_STATE_DEBUG = 1u<<16, /*!< \_ */
1263 su_STATE_VERBOSE = 1u<<17, /*!< \_ */
1264 /*! Reproducible behaviour switch.
1265 * See \r{su_reproducible_build},
1266 * and \xln{https://reproducible-builds.org}. */
1267 su_STATE_REPRODUCIBLE = 1u<<18
1270 enum su__state_flags{
1271 /* enum su_log_level is first "member" */
1272 su__STATE_LOG_MASK = 0x0Fu,
1273 su__STATE_D_V = su_STATE_DEBUG | su_STATE_VERBOSE,
1274 /* What is not allowed in the global state machine */
1275 su__STATE_GLOBAL_MASK = 0x00FFFFFFu & ~(su__STATE_LOG_MASK |
1276 (su_STATE_ERR_MASK & ~su_STATE_ERR_TYPE_MASK))
1278 MCTA(S(uz,su_LOG_DEBUG) <= S(uz,su__STATE_LOG_MASK),
1279 "Bit ranges may not overlap")
1280 MCTA((S(uz,su_STATE_ERR_MASK) & ~0xFF00) == 0, "Bits excess documented bounds")
1282 #ifdef su_HAVE_MT
1283 enum su__glock_type{
1284 su__GLOCK_STATE,
1285 su__GLOCK_LOG,
1286 su__GLOCK_MAX = su__GLOCK_LOG
1288 #endif
1290 /*! The \SU error number constants.
1291 * In order to achieve a 1:1 mapping of the \SU and the host value, e.g.,
1292 * of \ERR{INTR} and \c{EINTR}, the actual values will be detected at
1293 * compilation time.
1294 * Non resolvable (native) mappings will map to \ERR{NOTOBACCO},
1295 * \SU mappings with no (native) mapping will have high unsigned numbers. */
1296 enum su_err_number{
1297 #ifdef DOXYGEN
1298 su_ERR_NONE, /*!< No error. */
1299 su_ERR_NOTOBACCO /*!< No such errno, fallback: no mapping exists. */
1300 #else
1301 su__ERR_NUMBER_ENUM_C
1302 # undef su__ERR_NUMBER_ENUM_C
1303 #endif
1306 union su__bom_union{
1307 char bu_buf[2];
1308 u16 bu_val;
1311 /* Known endianness bom versions, see su_bom_little, su_bom_big */
1312 EXPORT_DATA union su__bom_union const su__bom_little;
1313 EXPORT_DATA union su__bom_union const su__bom_big;
1315 /* (Not yet) Internal enum su_state_* bit carrier */
1316 EXPORT_DATA uz su__state;
1318 /*! The byte order mark \r{su_BOM} in host, \r{su_bom_little} and
1319 * \r{su_bom_big} byte order.
1320 * The latter two are macros which access constant union data.
1321 * We also define two helpers \r{su_BOM_IS_BIG()} and \r{su_BOM_IS_LITTLE()},
1322 * which will expand to preprocessor statements if possible (by using
1323 * \r{su_CC_BOM}, \r{su_CC_BOM_LITTLE} and \r{su_CC_BOM_BIG}), but otherwise
1324 * to comparisons of the external constants. */
1325 EXPORT_DATA u16 const su_bom;
1327 #define su_bom_little su__bom_little.bu_val /*!< \_ */
1328 #define su_bom_big su__bom_big.bu_val /*!< \_ */
1330 #if defined su_CC_BOM || defined DOXYGEN
1331 # define su_BOM_IS_BIG() (su_CC_BOM == su_CC_BOM_BIG) /*!< \r{su_bom}. */
1332 # define su_BOM_IS_LITTLE() (su_CC_BOM == su_CC_BOM_LITTLE) /*!< \r{su_bom}. */
1333 #else
1334 # define su_BOM_IS_BIG() (su_bom == su_bom_big)
1335 # define su_BOM_IS_LITTLE() (su_bom == su_bom_little)
1336 #endif
1338 /*! The empty string. */
1339 EXPORT_DATA char const su_empty[1];
1341 /*! The string \c{reproducible_build}, see \r{su_STATE_REPRODUCIBLE}. */
1342 EXPORT_DATA char const su_reproducible_build[];
1344 /*! Can be set to the name of the program to, e.g., create a common log
1345 * message prefix.
1346 * Also see \r{su_STATE_LOG_SHOW_PID}, \r{su_STATE_LOG_SHOW_LEVEL}. */
1347 EXPORT_DATA char const *su_program;
1349 /**/
1350 #ifdef su_HAVE_MT
1351 EXPORT void su__glock(enum su__glock_type gt);
1352 EXPORT void su__gunlock(enum su__glock_type gt);
1353 #endif
1355 /*! Interaction with the SU library (global) state machine.
1356 * This covers \r{su_state_log_flags}, \r{su_state_err_type},
1357 * and \r{su_state_flags} flags and values. */
1358 INLINE u32 su_state_get(void){
1359 return (su__state & su__STATE_GLOBAL_MASK);
1362 /*! Interaction with the SU library (global) state machine:
1363 * test whether all (not any) of \a{flags} are set in \r{su_state_get()}. */
1364 INLINE boole su_state_has(uz flags){
1365 flags &= su__STATE_GLOBAL_MASK;
1366 return ((su__state & flags) == flags);
1369 /*! \_ */
1370 INLINE void su_state_set(uz flags){
1371 MT( su__glock(su__GLOCK_STATE); )
1372 su__state |= flags & su__STATE_GLOBAL_MASK;
1373 MT( su__gunlock(su__GLOCK_STATE); )
1376 /*! \_ */
1377 INLINE void su_state_clear(uz flags){
1378 MT( su__glock(su__GLOCK_STATE); )
1379 su__state &= ~(flags & su__STATE_GLOBAL_MASK);
1380 MT( su__gunlock(su__GLOCK_STATE); )
1383 /*! Notify an error to the \SU (global) state machine.
1384 * If the function is allowd to return a corresponding \r{su_err_number} will
1385 * be returned. */
1386 EXPORT s32 su_state_err(enum su_state_err_type err, uz state,
1387 char const *msg_or_nil);
1389 /*! \_ */
1390 EXPORT s32 su_err_no(void);
1392 /*! \_ */
1393 EXPORT s32 su_err_set_no(s32 eno);
1395 /*! Return string(s) describing C error number \a{eno}.
1396 * Effectively identical to \r{su_err_name()} if either the compile-time
1397 * option \r{su_HAVE_DOCSTRINGS} is missing (always), or when
1398 * \r{su_state_has()} \r{su_STATE_REPRODUCIBLE} set. */
1399 EXPORT char const *su_err_doc(s32 eno);
1401 /*! \_ */
1402 EXPORT char const *su_err_name(s32 eno);
1404 /*! Try to map an error name to an error number.
1405 * Returns the fallback error as a negative value if none found */
1406 EXPORT s32 su_err_from_name(char const *name);
1408 /*! \_ */
1409 EXPORT s32 su_err_no_via_errno(void);
1411 /*! \_ */
1412 INLINE enum su_log_level su_log_get_level(void){
1413 return S(enum su_log_level,su__state & su__STATE_LOG_MASK);
1416 /*! \_ */
1417 INLINE void su_log_set_level(enum su_log_level nlvl){
1418 uz lvl;
1419 /*MT( su__glock(su__GLOCK_STATE); )*/
1420 lvl = S(uz,nlvl) & su__STATE_LOG_MASK;
1421 su__state = (su__state & su__STATE_GLOBAL_MASK) | lvl;
1422 /*MT( su__gunlock(su__GLOCK_STATE); )*/
1425 /*! \_ */
1426 INLINE boole su_log_would_write(enum su_log_level lvl){
1427 return ((S(u32,lvl) & su__LOG_MASK) <= (su__state & su__STATE_LOG_MASK) ||
1428 (su__state & su__STATE_D_V));
1431 /*! Log functions of various sort.
1432 * \a{lvl} is a bitmix of a \r{su_log_level} and \r{su_log_flags}.
1433 * Regardless of the level these also log if \c{STATE_DEBUG|STATE_VERBOSE}.
1434 * If \r{su_program} is set, it will be prepended to messages. */
1435 EXPORT void su_log_write(BITENUM_IS(u32,su_log_level) lvl,
1436 char const *fmt, ...);
1438 /*! See \r{su_log_write()}. The \a{vp} is a \c{&va_list}. */
1439 EXPORT void su_log_vwrite(BITENUM_IS(u32,su_log_level) lvl,
1440 char const *fmt, void *vp);
1442 /*! Like perror(3). */
1443 EXPORT void su_perr(char const *msg, s32 eno_or_0);
1445 /*! SMP lock the global log domain. */
1446 INLINE void su_log_lock(void){
1447 MT( su__glock(su__GLOCK_LOG); )
1450 /*! SMP unlock the global log domain. */
1451 INLINE void su_log_unlock(void){
1452 MT( su__gunlock(su__GLOCK_LOG); )
1455 #if !defined su_ASSERT_EXPAND_NOTHING || defined DOXYGEN
1456 /*! With a \FAL0 crash this only logs.
1457 * In order to get rid of linkage define \c{su_ASSERT_EXPAND_NOTHING}. */
1458 EXPORT void su_assert(char const *expr, char const *file, u32 line,
1459 char const *fun, boole crash);
1460 #else
1461 # define su_assert(EXPR,FILE,LINE,FUN,CRASH)
1462 #endif
1464 #if DVLOR(1, 0)
1465 /*! When \a{disabled}, \r{su_nyd_chirp()} will return quick. */
1466 EXPORT void su_nyd_set_disabled(boole disabled);
1468 /*! In event-loop driven software that uses long jumps it may be desirable to
1469 * reset the recursion level at times. \a{nlvl} is only honoured when smaller
1470 * than the current recursion level. */
1471 EXPORT void su_nyd_reset_level(u32 nlvl);
1473 /*! Not-yet-dead chirp.
1474 * Normally used from the support macros in code-{in,ou}.h. */
1475 EXPORT void su_nyd_chirp(u8 act, char const *file, u32 line, char const *fun);
1477 /*! Dump all existing not-yet-dead entries via \a{ptf}.
1478 * \a{buf} is NUL terminated despite \a{blen} being passed, too. */
1479 EXPORT void su_nyd_dump(void (*ptf)(up cookie, char const *buf, uz blen),
1480 up cookie);
1481 #endif
1483 /* BASIC C INTERFACE (SYMBOLS) }}} */
1485 C_DECL_END
1486 #include <su/code-ou.h>
1487 #if !su_C_LANG || defined CXX_DOXYGEN
1488 # define su_CXX_HEADER
1489 # include <su/code-in.h>
1490 NSPC_BEGIN(su)
1492 /* POD TYPE SUPPORT {{{ */
1494 // All instanceless static encapsulators.
1495 class min;
1496 class max;
1498 // Define in-namespace wrappers for C types. code-in/ou do not define short
1499 // names for POD when used from within C++
1500 typedef su_ul ul; /*!< \_ */
1501 typedef su_ui ui; /*!< \_ */
1502 typedef su_us us; /*!< \_ */
1503 typedef su_uc uc; /*!< \_ */
1505 typedef su_sl sl; /*!< \_ */
1506 typedef su_si si; /*!< \_ */
1507 typedef su_ss ss; /*!< \_ */
1508 typedef su_sc sc; /*!< \_ */
1510 typedef su_u8 u8; /*!< \_ */
1511 typedef su_s8 s8; /*!< \_ */
1512 typedef su_u16 u16; /*!< \_ */
1513 typedef su_s16 s16; /*!< \_ */
1514 typedef su_u32 u32; /*!< \_ */
1515 typedef su_s32 s32; /*!< \_ */
1516 typedef su_u64 u64; /*!< \_ */
1517 typedef su_s64 s64; /*!< \_ */
1519 typedef su_uz uz; /*!< \_ */
1520 typedef su_sz sz; /*!< \_ */
1522 typedef su_up up; /*!< \_ */
1523 typedef su_sp sp; /*!< \_ */
1525 typedef su_boole boole; /*!< \_ */
1526 /*! Values for \r{su_boole}. */
1527 enum{
1528 FAL0 = su_FAL0, /*!< \_ */
1529 TRU1 = su_TRU1, /*!< \_ */
1530 TRU2 = su_TRU2, /*!< \_ */
1531 TRUM1 = su_TRUM1 /*!< All bits set. */
1534 /* Place the mentioned alignment CTAs */
1535 MCTA(IS_POW2(sizeof(uz)), "Must be power of two")
1536 MCTA(IS_POW2(su__ZAL_S), "Must be power of two")
1537 MCTA(IS_POW2(su__ZAL_L), "Must be power of two")
1539 /*! \_ */
1540 class min{
1541 public:
1542 static NSPC(su)s8 const s8 = su_S8_MIN; /*!< \copydoc{su_S8_MIN} */
1543 static NSPC(su)s16 const s16 = su_S16_MIN; /*!< \copydoc{su_S16_MIN} */
1544 static NSPC(su)s32 const s32 = su_S32_MIN; /*!< \copydoc{su_S32_MIN} */
1545 static NSPC(su)s64 const s64 = su_S64_MIN; /*!< \copydoc{su_S64_MIN} */
1546 static NSPC(su)sz const sz = su_SZ_MIN; /*!< \copydoc{su_SZ_MIN} */
1549 /*! \_ */
1550 class max{
1551 public:
1552 static NSPC(su)s8 const s8 = su_S8_MAX; /*!< \copydoc{su_S8_MAX} */
1553 static NSPC(su)s16 const s16 = su_S16_MAX; /*!< \copydoc{su_S16_MAX} */
1554 static NSPC(su)s32 const s32 = su_S32_MAX; /*!< \copydoc{su_S32_MAX} */
1555 static NSPC(su)s64 const s64 = su_S64_MAX; /*!< \copydoc{su_S64_MAX} */
1556 static NSPC(su)sz const sz = su_SZ_MAX; /*!< \copydoc{su_SZ_MAX} */
1558 static NSPC(su)u8 const u8 = su_U8_MAX; /*!< \copydoc{su_U8_MAX} */
1559 static NSPC(su)u16 const u16 = su_U16_MAX; /*!< \copydoc{su_U16_MAX} */
1560 static NSPC(su)u32 const u32 = su_U32_MAX; /*!< \copydoc{su_U32_MAX} */
1561 static NSPC(su)u64 const u64 = su_U64_MAX; /*!< \copydoc{su_U64_MAX} */
1562 static NSPC(su)uz const uz = su_UZ_MAX; /*!< \copydoc{su_UZ_MAX} */
1565 /* POD TYPE SUPPORT }}} */
1566 /* BASIC TYPE TRAITS {{{ */
1568 template<class T> class type_traits;
1569 template<class T> struct type_toolbox;
1570 // Plus C wrapper typedef
1572 // External forward, defined in a-t-t.h.
1573 template<class T> class auto_type_toolbox;
1575 typedef su_toolbox toolbox; /*!< See \r{type_toolbox}, \r{COLL}. */
1577 /*! See \r{type_toolbox}, \r{COLL}. */
1578 template<class T>
1579 class type_traits{
1580 public:
1581 typedef T type; /*!< \_ */
1582 typedef T *tp; /*!< \_ */
1583 typedef T const type_const; /*!< \_ */
1584 typedef T const *tp_const; /*!< \_ */
1586 typedef NSPC(su)type_toolbox<type> type_toolbox; /*!< \_ */
1587 typedef NSPC(su)auto_type_toolbox<type> auto_type_toolbox; /*!< \_ */
1589 /*! Non-pointer types are by default own-guessed, pointer based ones not. */
1590 static boole const ownguess = TRU1;
1591 /*! Ditto, associative collections, keys. */
1592 static boole const ownguess_key = TRU1;
1594 /*! \_ */
1595 static void *to_vp(tp_const t) {return C(void*,S(void const*,t));}
1596 /*! \_ */
1597 static void const *to_const_vp(tp_const t) {return t;}
1599 /*! \_ */
1600 static tp to_tp(void const *t) {return C(tp,S(tp_const,t));}
1601 /*! \_ */
1602 static tp_const to_const_tp(void const *t) {return S(tp_const,t);}
1605 // Some specializations
1606 template<class T>
1607 class type_traits<T const>{ // (ugly, but required for some node based colls..)
1608 public:
1609 typedef T type;
1610 typedef T *tp;
1611 typedef T const type_const;
1612 typedef T const *tp_const;
1613 typedef NSPC(su)type_toolbox<type> type_toolbox;
1614 typedef NSPC(su)auto_type_toolbox<type> auto_type_toolbox;
1616 static boole const ownguess = FAL0;
1617 static boole const ownguess_key = TRU1;
1619 static void *to_vp(tp_const t) {return C(tp,t);}
1620 static void const *to_const_vp(tp_const t) {return t;}
1621 static tp to_tp(void const *t) {return C(tp,S(tp_const,t));}
1622 static tp_const to_const_tp(void const *t) {return S(tp_const,t);}
1625 template<class T>
1626 class type_traits<T *>{
1627 public:
1628 typedef T type;
1629 typedef T *tp;
1630 typedef T const type_const;
1631 typedef T const *tp_const;
1632 typedef NSPC(su)type_toolbox<type> type_toolbox;
1633 typedef NSPC(su)auto_type_toolbox<type> auto_type_toolbox;
1635 static boole const ownguess = FAL0;
1636 static boole const ownguess_key = TRU1;
1638 static void *to_vp(tp_const t) {return C(tp,t);}
1639 static void const *to_const_vp(tp_const t) {return t;}
1640 static tp to_tp(void const *t) {return C(tp,S(tp_const,t));}
1641 static tp_const to_const_tp(void const *t) {return S(tp_const,t);}
1644 template<>
1645 class type_traits<void *>{
1646 public:
1647 typedef void *type;
1648 typedef void *tp;
1649 typedef void const *type_const;
1650 typedef void const *tp_const;
1651 typedef NSPC(su)toolbox type_toolbox;
1652 typedef NSPC(su)auto_type_toolbox<void *> auto_type_toolbox;
1654 static boole const ownguess = FAL0;
1655 static boole const ownguess_key = FAL0;
1657 static void *to_vp(tp_const t) {return C(tp,t);}
1658 static void const *to_const_vp(tp_const t) {return t;}
1659 static tp to_tp(void const *t) {return C(tp,S(tp_const,t));}
1660 static tp_const to_const_tp(void const *t) {return S(tp_const,t);}
1663 template<>
1664 class type_traits<void const *>{
1665 public:
1666 typedef void const *type;
1667 typedef void const *tp;
1668 typedef void const *type_const;
1669 typedef void const *tp_const;
1670 typedef NSPC(su)toolbox type_toolbox;
1671 typedef NSPC(su)auto_type_toolbox<void const *> auto_type_toolbox;
1673 static boole const ownguess = FAL0;
1674 static boole const ownguess_key = FAL0;
1676 static void *to_vp(tp_const t) {return C(void*,t);}
1677 static void const *to_const_vp(tp_const t) {return t;}
1678 static tp to_tp(void const *t) {return C(void*,t);}
1679 static tp_const to_const_tp(void const *t) {return t;}
1682 template<>
1683 class type_traits<char *>{
1684 public:
1685 typedef char *type;
1686 typedef char *tp;
1687 typedef char const *type_const;
1688 typedef char const *tp_const;
1689 typedef NSPC(su)type_toolbox<type> type_toolbox;
1690 typedef NSPC(su)auto_type_toolbox<type> auto_type_toolbox;
1692 static boole const ownguess = FAL0;
1693 static boole const ownguess_key = TRU1;
1695 static void *to_vp(tp_const t) {return C(tp,t);}
1696 static void const *to_const_vp(tp_const t) {return t;}
1697 static tp to_tp(void const *t) {return C(tp,S(tp_const,t));}
1698 static tp_const to_const_tp(void const *t) {return S(tp_const,t);}
1701 template<>
1702 class type_traits<char const *>{
1703 public:
1704 typedef char const *type;
1705 typedef char const *tp;
1706 typedef char const *type_const;
1707 typedef char const *tp_const;
1708 typedef NSPC(su)type_toolbox<type> type_toolbox;
1709 typedef NSPC(su)auto_type_toolbox<type> auto_type_toolbox;
1711 static boole const ownguess = FAL0;
1712 static boole const ownguess_key = TRU1;
1714 static void *to_vp(tp_const t) {return C(char*,t);}
1715 static void const *to_const_vp(tp_const t) {return t;}
1716 static tp to_tp(void const *t) {return C(char*,S(tp_const,t));}
1717 static tp_const to_const_tp(void const *t) {return S(tp_const,t);}
1720 /*! This is binary compatible with \r{toolbox} (and \r{su_toolbox})!
1721 * Also see \r{COLL}. */
1722 template<class T>
1723 struct type_toolbox{
1724 /*! \_ */
1725 typedef NSPC(su)type_traits<T> type_traits;
1727 /*! \copydoc{su_clone_fun} */
1728 typedef typename type_traits::tp (*clone_fun)(
1729 typename type_traits::tp_const t, u32 estate);
1730 /*! \copydoc{su_delete_fun} */
1731 typedef void (*delete_fun)(typename type_traits::tp self);
1732 /*! \copydoc{su_assign_fun} */
1733 typedef typename type_traits::tp (*assign_fun)(
1734 typename type_traits::tp self, typename type_traits::tp_const t,
1735 u32 estate);
1736 /*! \copydoc{su_compare_fun} */
1737 typedef sz (*compare_fun)(typename type_traits::tp_const self,
1738 typename type_traits::tp_const t);
1739 /*! \copydoc{su_hash_fun} */
1740 typedef uz (*hash_fun)(typename type_traits::tp_const self);
1742 /*! \r{#clone_fun} */
1743 clone_fun ttb_clone;
1744 /*! \r{#delete_fun} */
1745 delete_fun ttb_delete;
1746 /*! \r{#assign_fun} */
1747 assign_fun ttb_assign;
1748 /*! \r{#compare_fun} */
1749 compare_fun ttb_compare;
1750 /*! \r{#hash_fun} */
1751 hash_fun ttb_hash;
1754 /*! Initialize a \r{type_toolbox}. */
1755 #define su_TYPE_TOOLBOX_I9R(CLONE,DELETE,ASSIGN,COMPARE,HASH) \
1756 { CLONE, DELETE, ASSIGN, COMPARE, HASH }
1758 // abc,clip,max,min,pow2 -- the C macros are in SUPPORT MACROS+
1759 /*! \_ */
1760 template<class T> inline T get_abs(T const &a) {return su_ABS(a);}
1762 /*! \copydoc{su_CLIP()} */
1763 template<class T>
1764 inline T const &get_clip(T const &a, T const &min, T const &max){
1765 return su_CLIP(a, min, max);
1768 /*! \copydoc{su_MAX()} */
1769 template<class T>
1770 inline T const &get_max(T const &a, T const &b) {return su_MAX(a, b);}
1772 /*! \copydoc{su_MIN()} */
1773 template<class T>
1774 inline T const &get_min(T const &a, T const &b) {return su_MIN(a, b);}
1776 /*! \copydoc{su_ROUND_DOWN()} */
1777 template<class T>
1778 inline T const &get_round_down(T const &a, T const &b){
1779 return su_ROUND_DOWN(a, b);
1782 /*! \copydoc{su_ROUND_DOWN2()} */
1783 template<class T>
1784 inline T const &get_round_down2(T const &a, T const &b){
1785 return su_ROUND_DOWN2(a, b);
1788 /*! \copydoc{su_ROUND_UP()} */
1789 template<class T>
1790 inline T const &get_round_up(T const &a, T const &b){
1791 return su_ROUND_UP(a, b);
1794 /*! \copydoc{su_ROUND_UP2()} */
1795 template<class T>
1796 inline T const &get_round_up2(T const &a, T const &b){
1797 return su_ROUND_UP2(a, b);
1800 /*! \copydoc{su_IS_POW2()} */
1801 template<class T> inline int is_pow2(T const &a) {return su_IS_POW2(a);}
1803 /* BASIC TYPE TRAITS }}} */
1804 /* BASIC C++ INTERFACE (SYMBOLS) {{{ */
1806 // FIXME C++ does not yet expose the public C EXPORT_DATA symbols
1808 // All instanceless static encapsulators.
1809 class bom;
1810 class err;
1811 class log;
1812 class state;
1814 /*! \copydoc{su_bom} */
1815 class bom{
1816 public:
1817 /*! \copydoc{su_BOM} */
1818 static u16 host(void) {return su_BOM;}
1820 /*! \copydoc{su_bom_little} */
1821 static u16 little(void) {return su_bom_little;}
1823 /*! \copydoc{su_bom_big} */
1824 static u16 big(void) {return su_bom_big;}
1827 /*! \_ */
1828 class err{
1829 public:
1830 /*! \copydoc{su_err_number} */
1831 enum err_number{
1832 #ifdef DOXYGEN
1833 enone, /*!< No error. */
1834 enotobacco /*!< No such errno, fallback: no mapping exists. */
1835 #else
1836 su__CXX_ERR_NUMBER_ENUM
1837 # undef su__CXX_ERR_NUMBER_ENUM
1838 #endif
1841 /*! \copydoc{su_err_no()} */
1842 static s32 no(void) {return su_err_no();}
1844 /*! \copydoc{su_err_set_no()} */
1845 static void set_no(s32 eno) {su_err_set_no(eno);}
1847 /*! \copydoc{su_err_doc()} */
1848 static char const *doc(s32 eno) {return su_err_doc(eno);}
1850 /*! \copydoc{su_err_name()} */
1851 static char const *name(s32 eno) {return su_err_name(eno);}
1853 /*! \copydoc{su_err_from_name()} */
1854 static s32 from_name(char const *name) {return su_err_from_name(name);}
1856 /*! \copydoc{su_err_no_via_errno()} */
1857 static s32 no_via_errno(void) {return su_err_no_via_errno();}
1860 /*! \_ */
1861 class log{
1862 public:
1863 /*! \copydoc{su_log_level} */
1864 enum level{
1865 emerg = su_LOG_EMERG, /*!< \copydoc{su_LOG_EMERG} */
1866 alert = su_LOG_ALERT, /*!< \copydoc{su_LOG_ALERT} */
1867 crit = su_LOG_CRIT, /*!< \copydoc{su_LOG_CRIT} */
1868 err = su_LOG_ERR, /*!< \copydoc{su_LOG_ERR} */
1869 warn = su_LOG_WARN, /*!< \copydoc{su_LOG_WARN} */
1870 notice = su_LOG_NOTICE, /*!< \copydoc{su_LOG_NOTICE} */
1871 info = su_LOG_INFO, /*!< \copydoc{su_LOG_INFO} */
1872 debug = su_LOG_DEBUG /*!< \copydoc{su_LOG_DEBUG} */
1875 /*! \copydoc{su_log_flags} */
1876 enum flags{
1877 f_core = su_LOG_F_CORE, /*!< \copydoc{su_LOG_F_CORE} */
1880 // Log functions of various sort.
1881 // Regardless of the level these also log if state_debug|state_verbose.
1882 // The vp is a &va_list
1883 /*! \copydoc{su_log_get_level()} */
1884 static level get_level(void) {return S(level,su_log_get_level());}
1886 /*! \copydoc{su_log_set_level()} */
1887 static void set_level(level lvl) {su_log_set_level(S(su_log_level,lvl));}
1889 /*! \copydoc{su_STATE_LOG_SHOW_LEVEL} */
1890 static boole get_show_level(void){
1891 return su_state_has(su_STATE_LOG_SHOW_LEVEL);
1894 /*! \copydoc{su_STATE_LOG_SHOW_LEVEL} */
1895 static void set_show_level(boole on){
1896 if(on)
1897 su_state_set(su_STATE_LOG_SHOW_LEVEL);
1898 else
1899 su_state_clear(su_STATE_LOG_SHOW_LEVEL);
1902 /*! \copydoc{su_STATE_LOG_SHOW_PID} */
1903 static boole get_show_pid(void){
1904 return su_state_has(su_STATE_LOG_SHOW_PID);
1907 /*! \copydoc{su_STATE_LOG_SHOW_PID} */
1908 static void set_show_pid(boole on){
1909 if(on)
1910 su_state_set(su_STATE_LOG_SHOW_PID);
1911 else
1912 su_state_clear(su_STATE_LOG_SHOW_PID);
1915 /*! \copydoc{su_log_would_write()} */
1916 static boole would_write(level lvl){
1917 return su_log_would_write(S(su_log_level,lvl));
1920 /*! \copydoc{su_log_write()} */
1921 static void write(BITENUM_IS(u32,level) lvl, char const *fmt, ...);
1923 /*! \copydoc{su_log_vwrite()} */
1924 static void vwrite(BITENUM_IS(u32,level) lvl, char const *fmt, void *vp){
1925 su_log_vwrite(lvl, fmt, vp);
1928 /*! \copydoc{su_perr()} */
1929 static void perr(char const *msg, s32 eno_or_0) {su_perr(msg, eno_or_0);}
1931 /*! \copydoc{su_log_lock()} */
1932 static void lock(void) {su_log_lock();}
1934 /*! \copydoc{su_log_unlock()} */
1935 static void unlock(void) {su_log_unlock();}
1938 /*! \_ */
1939 class state{
1940 public:
1941 /*! \copydoc{su_state_err_type} */
1942 enum err_type{
1943 /*! \copydoc{su_STATE_ERR_NOMEM} */
1944 err_nomem = su_STATE_ERR_NOMEM,
1945 /*! \copydoc{su_STATE_ERR_OVERFLOW} */
1946 err_overflow = su_STATE_ERR_OVERFLOW
1949 /*! \copydoc{su_state_err_flags} */
1950 enum err_flags{
1951 /*! \copydoc{su_STATE_ERR_TYPE_MASK} */
1952 err_type_mask = su_STATE_ERR_TYPE_MASK,
1953 /*! \copydoc{su_STATE_ERR_PASS} */
1954 err_pass = su_STATE_ERR_PASS,
1955 /*! \copydoc{su_STATE_ERR_NOPASS} */
1956 err_nopass = su_STATE_ERR_NOPASS,
1957 /*! \copydoc{su_STATE_ERR_NOERRNO} */
1958 err_noerrno = su_STATE_ERR_NOERRNO,
1959 /*! \copydoc{su_STATE_ERR_MASK} */
1960 err_mask = su_STATE_ERR_MASK
1963 /*! \copydoc{su_state_flags} */
1964 enum flags{
1965 /*! \copydoc{su_STATE_NONE} */
1966 none = su_STATE_NONE,
1967 /*! \copydoc{su_STATE_DEBUG} */
1968 debug = su_STATE_DEBUG,
1969 /*! \copydoc{su_STATE_VERBOSE} */
1970 verbose = su_STATE_VERBOSE,
1971 /*! \copydoc{su_STATE_REPRODUCIBLE} */
1972 reproducible = su_STATE_REPRODUCIBLE
1975 /*! \copydoc{su_program} */
1976 static char const *get_program(void) {return su_program;}
1978 /*! \copydoc{su_program} */
1979 static void set_program(char const *name) {su_program = name;}
1981 /*! \copydoc{su_state_get()} */
1982 static boole get(void) {return su_state_get();}
1984 /*! \copydoc{su_state_has()} */
1985 static boole has(uz state) {return su_state_has(state);}
1987 /*! \copydoc{su_state_set()} */
1988 static void set(uz state) {su_state_set(state);}
1990 /*! \copydoc{su_state_clear()} */
1991 static void clear(uz state) {su_state_clear(state);}
1993 /*! \copydoc{su_state_err()} */
1994 static s32 err(err_type err, uz state, char const *msg_or_nil=NIL){
1995 return su_state_err(S(su_state_err_type,err), state, msg_or_nil);
1999 /* BASIC C++ INTERFACE (SYMBOLS) }}} */
2001 NSPC_END(su)
2002 #include <su/code-ou.h>
2003 #endif /* !C_LANG || CXX_DOXYGEN */
2005 /* MORE DOXYGEN TOP GROUPS {{{ */
2007 * \defgroup COLL Collections
2008 * \brief Collections
2010 * In \SU, and by default, collections learn how to deal with managed objects
2011 * through \r{su_toolbox} objects.
2012 * The C++ variants deduce many more things, and automatically, through
2013 * (specializations of) \r{type_traits}, \r{type_toolbox}, and
2014 * \r{auto_type_toolbox}.
2016 * Because the C++ versions are template wrappers around their \c{void*} based
2017 * C "supertypes", it is inefficient or even impossible to use \SU collections
2018 * for plain-old-data; to overcome this restriction (some) specializations to
2019 * work with POD exist.
2023 * \defgroup IO Input/Output
2024 * \brief Input and Output
2028 * \defgroup NET Network
2029 * \brief Network
2033 * \defgroup MEM Memory
2034 * \brief Memory
2038 * \defgroup MISC Miscellaneous
2039 * \brief Miscellaneous
2043 * \defgroup SMP SMP
2044 * \brief Simultaneous Multi Processing
2046 * This covers general \r{su_HAVE_SMP}, as well as its multi-threading subset
2047 * \r{su_HAVE_MT}.
2051 * \defgroup TEXT Text
2052 * \brief Text
2054 /* MORE DOXYGEN TOP GROUPS }}} */
2056 /*! @} */
2057 #endif /* !su_CODE_H */
2058 /* s-it-mode */