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
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.
30 #include <su/config.h>
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:
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.
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
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.}
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.
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.
84 * \defgroup CONFIG SU configuration
86 * \brief Overall \SU configuration (\r{su/code.h})
88 * It reflects the chosen configuration and the build time environment.
94 /*! Whether the \SU namespace exists.
95 * If not, facilities exist in the global namespace. */
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}. */
117 # define su_PAGE_SIZE /*!< \_ */
120 /*! @} *//* CONFIG }}} */
123 * \defgroup CORE Basic infrastructure
124 * \brief Macros, POD types, and basic interfaces (\r{su/code.h})
126 * The basic infrastructure:
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()}.
134 * The latter is a precondition for \vr{su_HAVE_INLINE}.
136 * Some macros require \vr{su_FILE} to be defined to a literal.
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.
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 /*!< \_ */
162 #elif defined __CYGWIN__
164 # define su_OS_CYGWIN 1
165 #elif defined DARWIN || defined _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__
174 #elif defined __FreeBSD__
175 # undef su_OS_FREEBSD
176 # define su_OS_FREEBSD 1
177 #elif defined __linux__ || defined __linux
179 # define su_OS_LINUX 1
180 #elif defined __minix
182 # define su_OS_MINIX 1
183 #elif defined __MSDOS__
185 # define su_OS_MSDOS 1
186 #elif defined __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
198 # define su_OS_SUNOS 1
206 # define su_C_LANG 1 /*!< \_ */
207 # define su_C_DECL_BEGIN /*!< \_ */
208 # define su_C_DECL_END /*!< \_ */
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) /*!< \_ */
218 # define su_C_DECL_BEGIN extern "C" {
219 # define su_C_DECL_END }
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::
226 # define su_NSPC_BEGIN(X) /**/
227 # define su_NSPC_END(X) /**/
228 # define su_NSPC_USE(X) /**/
229 # define su_NSPC(X) /**/::
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 */
245 /* This is for the declarator only */
246 # if __cplusplus +0 < 201103L
249 # define su_OVRX override
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)
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
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. */
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))
278 # define su_EXPORT /*extern*/ /*!< \_ */
279 # define su_EXPORT_DATA extern /*!< \_ */
280 # define su_IMPORT /*extern*/ /*!< \_ */
281 # define su_IMPORT_DATA extern /*!< \_ */
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)
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) \
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__);\
310 #define su_CTAV(T) su_CTA(T, "Unexpected value of constant") /*!< \_ */
311 #define su_LCTAV(T) su_LCTA(T, "Unexpected value of constant") /*!< \_ */
313 # define su_MCTA(T,M) su_CTA(T, M);
315 # define su_MCTA(T,M)
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 /*!< \_ */
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
349 # error Unsupported __BYTE_ORDER__
353 /* __GNUC__ after some other Unix compilers which also define __GNUC__ */
354 #elif defined __PCC__ /* __clang__ */
356 # undef su_CC_VCHECK_PCC
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
370 # error Unsupported __BYTE_ORDER__
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 */
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__ */
387 # undef su_CC_VCHECK_GCC
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
401 # error Unsupported __BYTE_ORDER__
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
413 # define su_CC_EXTEN /*!< \_ */
417 # define su_CC_PACKED TODO: PACKED attribute not supported for this compiler
419 #if defined su_CC_BOM || defined 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. */
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}. */
428 #if !defined su_CC_UZ_TYPE && defined __SIZE_TYPE__
429 # define su_CC_UZ_TYPE __SIZE_TYPE__
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__
438 # define su_FUN su_empty /* Something that is not a literal */
442 #define su_HAVE_INLINE
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
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))
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))
462 # define su_INLINE static __inline
463 # define su_SINLINE static __inline
467 # define su_INLINE static /* TODO __attribute__((unused)) alike? */
468 # define su_SINLINE static /* TODO __attribute__((unused)) alike? */
469 # undef su_HAVE_INLINE
472 # define su_INLINE inline
473 # define su_SINLINE static inline
476 # undef su_HAVE_INLINE
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)
486 # define su_LIKELY(X) ((X) != 0) /*!< \_ */
487 # define su_UNLIKELY(X) ((X) != 0) /*!< \_ */
491 /* SUPPORT MACROS+ {{{ */
493 /* USECASE_XY_DISABLED for tagging unused files:
494 * git rm `git grep ^su_USECASE_MX_DISABLED` */
496 # define su_USECASE_MX_DISABLED This file is not a (valid) compilation unit
498 #ifndef su_USECASE_MX_DISABLED
499 # define su_USECASE_MX_DISABLED
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)
528 /*! \c{_Alignof()} if available, something hacky otherwise */
529 # define su_ALIGNOF(X) su_ROUND_UP2(sizeof(X), su__ZAL_L)
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) \
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) /*!< \_ */
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) \
588 su_assert(su_STRING(X), FNAME, LNNO, su_FUN, su_TRU1);\
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) \
594 su_assert(su_STRING(X), FNAME, LNNO, su_FUN, su_FAL0);\
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) \
601 su_assert(su_STRING(X), FNAME, LNNO, su_FUN, su_FAL0);\
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) \
608 su_assert(su_STRING(X), FNAME, LNNO, su_FUN, su_FAL0);\
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) \
615 su_assert(su_STRING(X), FNAME, LNNO, su_FUN, su_FAL0);\
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) \
623 su_assert(su_STRING(X), FNAME, LNNO, su_FUN, su_FAL0);\
624 Y; goto su_NYD_OU_LABEL;\
627 # define su_ASSERT_NYD(X) su_ASSERT_NYD_LOC(X, __FILE__, __LINE__)
628 # define su_ASSERT_NYD_LOC(X,FNAME,LNNO) \
630 su_assert(su_STRING(X), FNAME, LNNO, su_FUN, su_FAL0);\
631 goto su_NYD_OU_LABEL;\
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 */
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 /*!< \_ */
658 # define su_NDBG(X) X
659 # define su_DBGOR(X,Y) Y
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() \
678 su_UNUSED(su_DBG_LOC_ARGS_FILE);\
679 su_UNUSED(su_DBG_LOC_ARGS_LINE);\
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) */\
698 # define su_DVL(X) X /*!< \_ */
699 # define su_NDVL(X) /*!< \_ */
700 # define su_DVLOR(X,Y) X /*!< \_ */
703 # define su_NDVL(X) X
704 # define su_DVLOR(X,Y) Y
707 /*! To avoid files that are overall empty */
708 #define su_EMPTY_FILE() typedef int su_CONCAT(su_notempty_shall_b_, su_FILE);
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] = /*!< \_ */
716 # define su_FIELD_INITN(N)
717 # define su_FIELD_INITI(I)
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)
726 # define su_FIELD_OFFSETOF(T,F) \
727 su_S(su_uz,su_S(su_up,&(su_R(T *,0x1)->F)) - 1)
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 */
739 # define su_MT(X) X /*!< \_ */
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))
759 # define su_SMP(X) X /*!< \_ */
765 * __STDC_VERSION__ is ISO C99, so also use __STDC__, which should work */
766 #if defined __STDC__ || defined __STDC_VERSION__ || su_C_LANG || \
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
773 # define su_STRING(X) "X"
774 # define su_XSTRING STRING
775 # define su_CONCAT(S1,S2) S1/* will no work out though */S2
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))
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))
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)) || \
800 # define su_UNINIT(N,V) su_S(void,0) /*!< \_ */
801 # define su_UNINIT_DECL(V) /*!< \_ */
803 # define su_UNINIT(N,V) N = V
804 # define su_UNINIT_DECL(V) = V
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)
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))
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, */
830 #include <inttypes.h> /* TODO query infos and drop */
831 #include <limits.h> /* TODO those includes! */
834 #include <su/code-in.h>
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
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
;
867 #if !defined PRIu8 || !defined PRId8
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
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
;
890 #if !defined PRIu16 || !defined PRId16
893 # if su_U16_MAX == UINT_MAX
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
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
;
924 #if !defined PRIu32 || !defined PRId32
927 # if su_U32_MAX == ULONG_MAX
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
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
;
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
;
966 #if !defined PRIu64 || !defined PRId64 || !defined PRIX64 || !defined 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"
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
;
988 typedef size_t su_uz
; /*!< \_ */
993 #if (defined __STDC_VERSION__ && __STDC_VERSION__ +0 >= 199901L) ||\
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)!")
1012 # error SIZE_MAX is neither su_U64_MAX nor su_U32_MAX (please report this)
1014 # define su_UZ_MAX SIZE_MAX
1016 #if !defined PRIuZ && !defined DOXYGEN
1019 MCTA(sizeof(size_t) == sizeof(unsigned long),
1020 "Format string mismatch, compile with ISO C99 compiler (-std=c99)!")
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
1037 # define su_6432(X,Y) X
1038 typedef su_s64 su_sz
;
1040 # error I cannot handle this maximum value of size_t
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
; /*!< \_ */
1052 typedef su_uz su_up
;
1053 typedef su_sz su_sp
;
1055 typedef su_ul su_up
;
1056 typedef su_sl su_sp
;
1060 /*! Values for #su_boole (normally only \c{FAL0} and \c{TRU1}). */
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 {{{ */
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
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()}. */
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()}. */
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 */
1165 su__LOG_MAX
= su_LOG_DEBUG
,
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}. */
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 */
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")
1283 enum su__glock_type
{
1286 su__GLOCK_MAX
= su__GLOCK_LOG
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
1294 * Non resolvable (native) mappings will map to \ERR{NOTOBACCO},
1295 * \SU mappings with no (native) mapping will have high unsigned numbers. */
1298 su_ERR_NONE
, /*!< No error. */
1299 su_ERR_NOTOBACCO
/*!< No such errno, fallback: no mapping exists. */
1301 su__ERR_NUMBER_ENUM_C
1302 # undef su__ERR_NUMBER_ENUM_C
1306 union su__bom_union
{
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}. */
1334 # define su_BOM_IS_BIG() (su_bom == su_bom_big)
1335 # define su_BOM_IS_LITTLE() (su_bom == su_bom_little)
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
1346 * Also see \r{su_STATE_LOG_SHOW_PID}, \r{su_STATE_LOG_SHOW_LEVEL}. */
1347 EXPORT_DATA
char const *su_program
;
1351 EXPORT
void su__glock(enum su__glock_type gt
);
1352 EXPORT
void su__gunlock(enum su__glock_type gt
);
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
);
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
); )
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
1386 EXPORT s32
su_state_err(enum su_state_err_type err
, uz state
,
1387 char const *msg_or_nil
);
1390 EXPORT s32
su_err_no(void);
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
);
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
);
1409 EXPORT s32
su_err_no_via_errno(void);
1412 INLINE
enum su_log_level
su_log_get_level(void){
1413 return S(enum su_log_level
,su__state
& su__STATE_LOG_MASK
);
1417 INLINE
void su_log_set_level(enum su_log_level nlvl
){
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); )*/
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
);
1461 # define su_assert(EXPR,FILE,LINE,FUN,CRASH)
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
),
1483 /* BASIC C INTERFACE (SYMBOLS) }}} */
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>
1492 /* POD TYPE SUPPORT {{{ */
1494 // All instanceless static encapsulators.
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}. */
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")
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} */
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}. */
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
;
1595 static void *to_vp(tp_const t
) {return C(void*,S(void const*,t
));}
1597 static void const *to_const_vp(tp_const t
) {return t
;}
1600 static tp
to_tp(void const *t
) {return C(tp
,S(tp_const
,t
));}
1602 static tp_const
to_const_tp(void const *t
) {return S(tp_const
,t
);}
1605 // Some specializations
1607 class type_traits
<T
const>{ // (ugly, but required for some node based colls..)
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
);}
1626 class type_traits
<T
*>{
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
);}
1645 class type_traits
<void *>{
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
);}
1664 class type_traits
<void const *>{
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
;}
1683 class type_traits
<char *>{
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
);}
1702 class type_traits
<char const *>{
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}. */
1723 struct type_toolbox
{
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
,
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} */
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+
1760 template<class T
> inline T
get_abs(T
const &a
) {return su_ABS(a
);}
1762 /*! \copydoc{su_CLIP()} */
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()} */
1770 inline T
const &get_max(T
const &a
, T
const &b
) {return su_MAX(a
, b
);}
1772 /*! \copydoc{su_MIN()} */
1774 inline T
const &get_min(T
const &a
, T
const &b
) {return su_MIN(a
, b
);}
1776 /*! \copydoc{su_ROUND_DOWN()} */
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()} */
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()} */
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()} */
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.
1814 /*! \copydoc{su_bom} */
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
;}
1830 /*! \copydoc{su_err_number} */
1833 enone
, /*!< No error. */
1834 enotobacco
/*!< No such errno, fallback: no mapping exists. */
1836 su__CXX_ERR_NUMBER_ENUM
1837 # undef su__CXX_ERR_NUMBER_ENUM
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();}
1863 /*! \copydoc{su_log_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} */
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
){
1897 su_state_set(su_STATE_LOG_SHOW_LEVEL
);
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
){
1910 su_state_set(su_STATE_LOG_SHOW_PID
);
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();}
1941 /*! \copydoc{su_state_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} */
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} */
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) }}} */
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
2033 * \defgroup MEM Memory
2038 * \defgroup MISC Miscellaneous
2039 * \brief Miscellaneous
2044 * \brief Simultaneous Multi Processing
2046 * This covers general \r{su_HAVE_SMP}, as well as its multi-threading subset
2051 * \defgroup TEXT Text
2054 /* MORE DOXYGEN TOP GROUPS }}} */
2057 #endif /* !su_CODE_H */