From ac2e8f5a15a968f236387ed98e34b4a9250c9a92 Mon Sep 17 00:00:00 2001 From: Bruce Hill Date: Fri, 6 Aug 2021 17:52:20 -0700 Subject: Improved, cleaner/faster/more flexible return value checks --- utils.h | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) (limited to 'utils.h') diff --git a/utils.h b/utils.h index b645817..04df47a 100644 --- a/utils.h +++ b/utils.h @@ -4,6 +4,8 @@ #ifndef UTILS__H #define UTILS__H +#include +#include #include #include #include @@ -16,10 +18,34 @@ #define S2(x) S1(x) #define __LOCATION__ __FILE__ ":" S2(__LINE__) +#define DEFINE_CHECK_TYPE(t, name, var, expr) \ +static inline t _check_##name(t var, const char *fmt, ...) { \ + if (!(expr)) {\ + va_list args;\ + va_start(args, fmt);\ + verrx(1, fmt, args);\ + va_end(args);\ + }\ + return var;\ +} +DEFINE_CHECK_TYPE(void*, ptr, p, p); +DEFINE_CHECK_TYPE(int, int, i, i >= 0); +DEFINE_CHECK_TYPE(ssize_t, ssize_t, i, i >= 0); +DEFINE_CHECK_TYPE(char, char, c, c); +DEFINE_CHECK_TYPE(_Bool, bool, b, b); + +#define PP_ARG_N(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,N,...) N +#define PP_NARG(...) PP_ARG_N(__VA_ARGS__,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0) + +#define _require_fmt(e, ...) _Generic((e), _Bool: _check_bool, int: _check_int, ssize_t: _check_ssize_t, char: _check_char, void*: _check_ptr, default: _check_ptr)((e), ""__VA_ARGS__) +#define require(e, ...) (PP_NARG(e,##__VA_ARGS__) > 1 ? _require_fmt((e), __LOCATION__": "__VA_ARGS__) : _require_fmt((e), __LOCATION__": `%s` failed", #e)) +#define require_true(e, ...) (PP_NARG(e,##__VA_ARGS__) > 1 ? _require_fmt((_Bool)(e), __LOCATION__": "__VA_ARGS__) : _require_fmt((_Bool)(e), __LOCATION__": `%s` is not true", #e)) + +#define new(t) _check_ptr(calloc(1, sizeof(t)), "`new(" #t ")` allocation failure") +#define checked_strdup(s) _check_ptr(strdup(s), "`checked_strdup(" #s ")` allocation failure") +#define grow(arr,n) _check_ptr(realloc(arr,sizeof(arr[0])*(n)), "`grow(" #arr ", " #n ")` allocation failure") + #define streq(a, b) (strcmp(a, b) == 0) -#define new(t) check_nonnull(calloc(1, sizeof(t)), __LOCATION__ ": `new(" #t ")` allocation failure") -#define checked_strdup(s) check_nonnull(strdup(s), __LOCATION__ ": `checked_strdup(" #s ")` allocation failure") -#define grow(arr,n) check_nonnull(realloc(arr,sizeof(arr[0])*(n)), __LOCATION__ ": `groaw(" #arr ", " #n ")` allocation failure") __attribute__((nonnull(1))) char unescapechar(const char *escaped, const char **end); @@ -31,9 +57,6 @@ __attribute__((nonnull)) bool matchchar(const char **str, char c, bool skip_nl); __attribute__((nonnull)) bool matchstr(const char **str, const char *target, bool skip_nl); -__attribute__((returns_nonnull)) -void *check_nonnull(void *p, const char *err_msg, ...); -int check_nonnegative(int i, const char *err_msg, ...); __attribute__((nonnull)) int memicmp(const void *s1, const void *s2, size_t n); __attribute__((nonnull)) -- cgit v1.2.3