diff options
Diffstat (limited to 'libmisc')
-rw-r--r-- | libmisc/CMakeLists.txt | 3 | ||||
-rw-r--r-- | libmisc/assert.c | 23 | ||||
-rw-r--r-- | libmisc/include/libmisc/assert.h | 24 | ||||
-rw-r--r-- | libmisc/include/libmisc/endian.h | 3 | ||||
-rw-r--r-- | libmisc/include/libmisc/rand.h | 46 | ||||
-rw-r--r-- | libmisc/include/libmisc/vcall.h | 3 |
6 files changed, 100 insertions, 2 deletions
diff --git a/libmisc/CMakeLists.txt b/libmisc/CMakeLists.txt index 0c5c019..1f30906 100644 --- a/libmisc/CMakeLists.txt +++ b/libmisc/CMakeLists.txt @@ -5,4 +5,7 @@ add_library(libmisc INTERFACE) target_include_directories(libmisc SYSTEM INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/include) +target_sources(libmisc INTERFACE + assert.c +) target_compile_options(libmisc INTERFACE "$<$<COMPILE_LANGUAGE:C>:-fplan9-extensions>") diff --git a/libmisc/assert.c b/libmisc/assert.c new file mode 100644 index 0000000..7817ba3 --- /dev/null +++ b/libmisc/assert.c @@ -0,0 +1,23 @@ +/* libmisc/assert.h - More assertions + * + * Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com> + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +#include <stdio.h> /* for fprintf(), stderr */ +#include <stdlib.h> /* for abort() */ + +#include <libmisc/assert.h> + +#ifndef NDEBUG +__attribute__((__noreturn__)) void +__assert_msg_fail(const char *expr, + const char *file, unsigned int line, const char *func, + const char *msg) { + fprintf(stderr, "error: %s:%u:%s(): assertion \"%s\" failed%s%s\n", + file, line, func, + expr, + msg ? ": " : "", msg); + abort(); +} +#endif diff --git a/libmisc/include/libmisc/assert.h b/libmisc/include/libmisc/assert.h new file mode 100644 index 0000000..c2c4697 --- /dev/null +++ b/libmisc/include/libmisc/assert.h @@ -0,0 +1,24 @@ +/* libmisc/assert.h - More assertions + * + * Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com> + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +#ifndef _LIBMISC_ASSERT_H_ +#define _LIBMISC_ASSERT_H_ + +#ifdef NDEBUG +# define assert_msg(expr, msg) ((void)0) +#else +# define assert_msg(expr, msg) do { if (!(expr)) __assert_msg_fail(#expr, __FILE__, __LINE__, __func__, msg); } while (0) +__attribute__((__noreturn__)) void +__assert_msg_fail(const char *expr, + const char *file, unsigned int line, const char *func, + const char *msg); +#endif + +#define assert(expr) assert_msg(expr, NULL) /* C89, POSIX-2001 */ +#define assert_notreached(msg) do { assert_msg(0, msg); __builtin_unreachable(); } while (0) +#define static_assert _Static_assert /* C11 */ + +#endif /* _LIBMISC_ASSERT_H_ */ diff --git a/libmisc/include/libmisc/endian.h b/libmisc/include/libmisc/endian.h index 24d7d42..b1bc55c 100644 --- a/libmisc/include/libmisc/endian.h +++ b/libmisc/include/libmisc/endian.h @@ -7,9 +7,10 @@ #ifndef _LIBMISC_ENDIAN_H_ #define _LIBMISC_ENDIAN_H_ -#include <assert.h> #include <stdint.h> /* for uint{n}_t */ +#include <libmisc/assert.h> + /* Big endian *****************************************************************/ typedef struct { diff --git a/libmisc/include/libmisc/rand.h b/libmisc/include/libmisc/rand.h new file mode 100644 index 0000000..bdb0db9 --- /dev/null +++ b/libmisc/include/libmisc/rand.h @@ -0,0 +1,46 @@ +/* libmisc/rand.h - Non-crytpographic random-number utilities + * + * Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com> + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +#ifndef _LIBMISC_RAND_H_ +#define _LIBMISC_RAND_H_ + +#include <stdint.h> /* for uint{n}_t, UINT{n}_C() */ +#include <stdlib.h> /* for random() */ + +#include <libmisc/assert.h> + +/** + * Return a psuedo-random number in the half-open interval [0,cnt). + * `cnt` must not be greater than 1<<63. + */ +static inline uint64_t rand_uint63n(uint64_t cnt) { + if (cnt <= UINT64_C(1)<<31) { + uint32_t fair_cnt = ((UINT32_C(1)<<31) / cnt) * cnt; + uint32_t rnd; + do { + rnd = random(); + } while (rnd >= fair_cnt); + return rnd % cnt; + } else if (cnt <= UINT64_C(1)<<62) { + uint64_t fair_cnt = ((UINT64_C(1)<<62) / cnt) * cnt; + uint64_t rnd; + do { + rnd = (random() << 31) | random(); + } while (rnd >= fair_cnt); + return rnd % cnt; + } else if (cnt <= UINT64_C(1)<<63) { + uint64_t fair_cnt = ((UINT64_C(1)<<63) / cnt) * cnt; + uint64_t rnd; + do { + rnd = (random() << 62) | (random() << 31) | random(); + } while (rnd >= fair_cnt); + return rnd % cnt; + } else { + assert_notreached("cnt is out of bounds"); + } +} + +#endif /* _LIBMISC_RAND_H_ */ diff --git a/libmisc/include/libmisc/vcall.h b/libmisc/include/libmisc/vcall.h index ea9402e..9b54c06 100644 --- a/libmisc/include/libmisc/vcall.h +++ b/libmisc/include/libmisc/vcall.h @@ -7,9 +7,10 @@ #ifndef _LIBMISC_VCALL_H_ #define _LIBMISC_VCALL_H_ -#include <assert.h> /* for assert() and static_assert() */ #include <stddef.h> /* for offsetof() */ +#include <libmisc/assert.h> + #define VCALL(o, m, ...) \ ({ \ assert(o); \ |