diff options
Diffstat (limited to 'libmisc')
-rw-r--r-- | libmisc/error.c | 9 | ||||
-rw-r--r-- | libmisc/fmt.c | 6 | ||||
-rw-r--r-- | libmisc/include/libmisc/alloc.h | 7 | ||||
-rw-r--r-- | libmisc/include/libmisc/error.h | 1 | ||||
-rw-r--r-- | libmisc/include/libmisc/obj.h | 97 | ||||
-rw-r--r-- | libmisc/log.c | 3 | ||||
-rw-r--r-- | libmisc/tests/test_obj.c | 8 | ||||
-rw-r--r-- | libmisc/tests/test_obj_autobox.c | 14 | ||||
-rw-r--r-- | libmisc/tests/test_obj_nest.c | 14 |
9 files changed, 84 insertions, 75 deletions
diff --git a/libmisc/error.c b/libmisc/error.c index dfe4e80..345755c 100644 --- a/libmisc/error.c +++ b/libmisc/error.c @@ -4,6 +4,8 @@ * SPDX-License-Identifier: AGPL-3.0-or-later */ +#include <string.h> /* for strdup() */ + #include <libmisc/error.h> const char *error_msg(error err) { @@ -12,6 +14,13 @@ const char *error_msg(error err) { : _errnum_str_msg(err.num); } +error error_dup(error err) { + return (error){ + .num = err.num, + ._msg = err._msg ? strdup(err._msg) : NULL, + }; +} + void error_cleanup(error *errptr) { if (!errptr) return; diff --git a/libmisc/fmt.c b/libmisc/fmt.c index 7c18ef5..175ad60 100644 --- a/libmisc/fmt.c +++ b/libmisc/fmt.c @@ -253,14 +253,14 @@ declare(16, 64); /* fmt_buf ********************************************************************/ -LO_IMPLEMENTATION_C(fmt_dest, struct fmt_buf, fmt_buf, static); +LO_IMPLEMENTATION_C(fmt_dest, struct fmt_buf, fmt_buf); -static void fmt_buf_putb(struct fmt_buf *buf, uint8_t b) { +void fmt_buf_putb(struct fmt_buf *buf, uint8_t b) { if (buf->len < buf->cap) ((uint8_t *)(buf->dat))[buf->len] = b; buf->len++; } -static size_t fmt_buf_tell(struct fmt_buf *buf) { +size_t fmt_buf_tell(struct fmt_buf *buf) { return buf->len; } diff --git a/libmisc/include/libmisc/alloc.h b/libmisc/include/libmisc/alloc.h index afddbce..34becdb 100644 --- a/libmisc/include/libmisc/alloc.h +++ b/libmisc/include/libmisc/alloc.h @@ -23,4 +23,11 @@ #define heap_alloc(N, TYP) ((TYP *)calloc(N, sizeof(TYP))) +static inline void heap_cleanup(void **ptrptr) { + if (!ptrptr) + return; + free(*ptrptr); + *ptrptr = NULL; +} + #endif /* _LIBMISC_ALLOC_H_ */ diff --git a/libmisc/include/libmisc/error.h b/libmisc/include/libmisc/error.h index 4110626..c9b53dd 100644 --- a/libmisc/include/libmisc/error.h +++ b/libmisc/include/libmisc/error.h @@ -136,6 +136,7 @@ typedef struct { #define ERROR_IS_NULL(err) ((err).num == 0 && (err)._msg == NULL) const char *error_msg(error err); +error error_dup(error err); void error_cleanup(error *errptr); void fmt_print_error(lo_interface fmt_dest w, error err); diff --git a/libmisc/include/libmisc/obj.h b/libmisc/include/libmisc/obj.h index 3467d5b..c00e512 100644 --- a/libmisc/include/libmisc/obj.h +++ b/libmisc/include/libmisc/obj.h @@ -119,57 +119,62 @@ (_ARG_obj).vtable->_ARG_meth((_ARG_obj).self __VA_OPT__(,) __VA_ARGS__) /** - * Use `LO_IMPLEMENTATION_H(iface_name, impl_type, impl_name)` in a .h - * file to declare that `{impl_type}` implements the `{iface_name}` - * interface with functions named `{impl_name}_{method_name}`. + * `LO_IMPLEMENTATION_{H,C,STATIC}` declare that `{impl_type}` + * implements the `{iface_name}` interface with functions named + * `{impl_name}_{method_name}`. * - * This will also define a `lo_box_{impl_name}_as_{iface_name}(obj)` - * const-expr macro. + * Either use _H and _C in the .h file and .c file respectively, or + * use _STATIC in just a .c file. * - * You must also call the LO_IMPLEMENTATION_C in a single .c file. + * These define: + * - The vtable symbol + * - The prototypes for the `{impl_name}_{method_name}` method + * functions. + * - A `lo_box_{impl_name}_as_{iface_name}(obj)` const-expr macro. */ -#define LO_IMPLEMENTATION_H(_ARG_iface_name, _ARG_impl_type, _ARG_impl_name) \ - /* Vtable. */ \ - extern const struct _lo_##_ARG_iface_name##_vtable \ - _lo_##_ARG_impl_name##_##_ARG_iface_name##_vtable; \ - /* Boxing. */ \ - LM_DEFAPPEND(_LO_REGISTRY_##_ARG_iface_name, \ - (_ARG_impl_type *, _ARG_impl_name)); \ - LM_DEFAPPEND(lo_box_##_ARG_impl_name##_as_##_ARG_iface_name(_ARG_self), ( \ - (lo_interface _ARG_iface_name){ \ - .self = (_ARG_self), \ - .vtable = &_lo_##_ARG_impl_name##_##_ARG_iface_name##_vtable, \ - } \ - )); \ +#define LO_IMPLEMENTATION_H( iface_name, impl_type, impl_name) _LO_IMPL_H(extern, iface_name, impl_type, impl_name) +#define LO_IMPLEMENTATION_C( iface_name, impl_type, impl_name) _LO_IMPL_C(extern, iface_name, impl_type, impl_name) +#define LO_IMPLEMENTATION_STATIC(iface_name, impl_type, impl_name) _LO_IMPL_H(static, iface_name, impl_type, impl_name); \ + _LO_IMPL_C(static, iface_name, impl_type, impl_name) + +#define _LO_IMPL_H(_ARG_visibility, _ARG_iface_name, _ARG_impl_type, _ARG_impl_name) \ + /* Vtable. */ \ + _LO_h_vis_vtable_##_ARG_visibility const struct _lo_##_ARG_iface_name##_vtable \ + _lo_##_ARG_impl_name##_##_ARG_iface_name##_vtable; \ + /* Method prototypes. */ \ + LM_FOREACH_TUPLE(_ARG_iface_name##_LO_IFACE, \ + _LO_IMPL_PROTO, _LO_h_vis_fn_##_ARG_visibility, _ARG_impl_type, _ARG_impl_name) \ + /* Boxing. */ \ + LM_DEFAPPEND(_LO_REGISTRY_##_ARG_iface_name, \ + (_ARG_impl_type *, _ARG_impl_name)); \ + LM_DEFAPPEND(lo_box_##_ARG_impl_name##_as_##_ARG_iface_name(_ARG_self), ( \ + (lo_interface _ARG_iface_name){ \ + .self = (_ARG_self), \ + .vtable = &_lo_##_ARG_impl_name##_##_ARG_iface_name##_vtable, \ + } \ + )); \ LM_FORCE_SEMICOLON +#define _LO_h_vis_vtable_extern extern +#define _LO_h_vis_vtable_static static +#define _LO_h_vis_fn_extern +#define _LO_h_vis_fn_static static + +#define _LO_IMPL_PROTO( _ARG_quals, _ARG_impl_type, _ARG_impl_name, _tuple_typ, ...) _LO_IMPL_PROTO_##_tuple_typ(_ARG_quals, _ARG_impl_type, _ARG_impl_name, __VA_ARGS__) +#define _LO_IMPL_PROTO_lo_nest(_ARG_quals, _ARG_impl_type, _ARG_impl_name, _ARG_child_iface_name) /* empty */ +#define _LO_IMPL_PROTO_lo_func(_ARG_quals, _ARG_impl_type, _ARG_impl_name, _ARG_ret_type, _ARG_func_name, ...) _ARG_quals _ARG_ret_type _ARG_impl_name##_##_ARG_func_name(_ARG_impl_type * __VA_OPT__(,) __VA_ARGS__); + +#define _LO_IMPL_C(_ARG_visibility, _ARG_iface_name, _ARG_impl_type, _ARG_impl_name) \ + /* Vtable. */ \ + _LO_c_vis_vtable_##_ARG_visibility const struct _lo_##_ARG_iface_name##_vtable \ + _lo_##_ARG_impl_name##_##_ARG_iface_name##_vtable = { \ + LM_FOREACH_TUPLE(_ARG_iface_name##_LO_IFACE, \ + _LO_IMPL_VTABLE, _ARG_impl_name) \ + }; \ + LM_FORCE_SEMICOLON +#define _LO_c_vis_vtable_extern +#define _LO_c_vis_vtable_static [[maybe_unused]] static -/** - * Use `LO_IMPLEMENTATION_C(iface_name, impl_type, impl_name[, static])` in a .c - * file to declare that `{impl_type}` implements the `{iface_name}` interface - * with functions named `{impl_name}_{method_name}`. - * - * You must also call the LO_IMPLEMENTATION_H in the corresponding .h file. - * - * If `iface_name` contains a nested interface, then the - * implementation of the nested interfaces must be declared with - * `LO_IMPLEMENTATION_C` first. - */ -#define LO_IMPLEMENTATION_C(_ARG_iface_name, _ARG_impl_type, _ARG_impl_name, ...) \ - /* Method prototypes. */ \ - LM_FOREACH_TUPLE(_ARG_iface_name##_LO_IFACE, \ - _LO_IMPL_PROTO, _ARG_impl_type, _ARG_impl_name, __VA_ARGS__) \ - /* Vtable. */ \ - const struct _lo_##_ARG_iface_name##_vtable \ - _lo_##_ARG_impl_name##_##_ARG_iface_name##_vtable = { \ - LM_FOREACH_TUPLE(_ARG_iface_name##_LO_IFACE, \ - _LO_IMPL_VTABLE, _ARG_impl_name) \ - } - -#define _LO_IMPL_PROTO( _ARG_impl_type, _ARG_impl_name, _ARG_quals, _tuple_typ, ...) _LO_IMPL_PROTO_##_tuple_typ(_ARG_impl_type, _ARG_impl_name, _ARG_quals, __VA_ARGS__) -#define _LO_IMPL_PROTO_lo_nest(_ARG_impl_type, _ARG_impl_name, _ARG_quals, _ARG_child_iface_name) /* empty */ -#define _LO_IMPL_PROTO_lo_func(_ARG_impl_type, _ARG_impl_name, _ARG_quals, _ARG_ret_type, _ARG_func_name, ...) _ARG_quals _ARG_ret_type _ARG_impl_name##_##_ARG_func_name(_ARG_impl_type * __VA_OPT__(,) __VA_ARGS__); - -#define _LO_IMPL_VTABLE(_ARG_impl_name, _tuple_typ, ...) _LO_IMPL_VTABLE_##_tuple_typ(_ARG_impl_name, __VA_ARGS__) +#define _LO_IMPL_VTABLE( _ARG_impl_name, _tuple_typ, ...) _LO_IMPL_VTABLE_##_tuple_typ(_ARG_impl_name, __VA_ARGS__) #define _LO_IMPL_VTABLE_lo_nest(_ARG_impl_name, _ARG_child_iface_name) ._lo_##_ARG_child_iface_name##_vtable = &_lo_##_ARG_impl_name##_##_ARG_child_iface_name##_vtable, LM_FOREACH_TUPLE2(_ARG_child_iface_name##_LO_IFACE, _LO_IMPL_VTABLE2, _ARG_impl_name) #define _LO_IMPL_VTABLE_lo_func(_ARG_impl_name, _ARG_ret_type, _ARG_func_name, ...) ._ARG_func_name = (void*)_ARG_impl_name##_##_ARG_func_name, diff --git a/libmisc/log.c b/libmisc/log.c index 7e917c6..96e9ca4 100644 --- a/libmisc/log.c +++ b/libmisc/log.c @@ -12,8 +12,7 @@ #include <libmisc/log.h> struct log_stdout {}; -LO_IMPLEMENTATION_H(fmt_dest, struct log_stdout, log_stdout); -LO_IMPLEMENTATION_C(fmt_dest, struct log_stdout, log_stdout, static); +LO_IMPLEMENTATION_STATIC(fmt_dest, struct log_stdout, log_stdout); static size_t log_bytes = 0; diff --git a/libmisc/tests/test_obj.c b/libmisc/tests/test_obj.c index 687ad4e..c3c6786 100644 --- a/libmisc/tests/test_obj.c +++ b/libmisc/tests/test_obj.c @@ -28,19 +28,19 @@ LO_IMPLEMENTATION_H(frobber, struct myclass, myclass); /* `struct myclass` implementation ********************************************/ -LO_IMPLEMENTATION_C(frobber, struct myclass, myclass, static); +LO_IMPLEMENTATION_C(frobber, struct myclass, myclass); -static int myclass_frob(struct myclass *self) { +int myclass_frob(struct myclass *self) { test_assert(self); return self->a; } -static int myclass_frob1(struct myclass *self, int arg) { +int myclass_frob1(struct myclass *self, int arg) { test_assert(self); return arg; } -static void myclass_frob0(struct myclass *self) { +void myclass_frob0(struct myclass *self) { test_assert(self); } diff --git a/libmisc/tests/test_obj_autobox.c b/libmisc/tests/test_obj_autobox.c index 1110639..394f716 100644 --- a/libmisc/tests/test_obj_autobox.c +++ b/libmisc/tests/test_obj_autobox.c @@ -26,21 +26,15 @@ LO_INTERFACE(writer); LO_NEST(writer) LO_INTERFACE(read_writer); -/* implementation header ******************************************************/ +/* implementation *************************************************************/ struct myclass { size_t len; char buf[512]; }; -LO_IMPLEMENTATION_H(reader, struct myclass, myclass); -LO_IMPLEMENTATION_H(writer, struct myclass, myclass); -LO_IMPLEMENTATION_H(read_writer, struct myclass, myclass); - -/* implementation main ********************************************************/ - -LO_IMPLEMENTATION_C(reader, struct myclass, myclass, static); -LO_IMPLEMENTATION_C(writer, struct myclass, myclass, static); -LO_IMPLEMENTATION_C(read_writer, struct myclass, myclass, static); +LO_IMPLEMENTATION_STATIC(reader, struct myclass, myclass); +LO_IMPLEMENTATION_STATIC(writer, struct myclass, myclass); +LO_IMPLEMENTATION_STATIC(read_writer, struct myclass, myclass); static size_t myclass_read(struct myclass *self, void *buf, size_t count) { test_assert(self); diff --git a/libmisc/tests/test_obj_nest.c b/libmisc/tests/test_obj_nest.c index 20ffe4a..b52cd7b 100644 --- a/libmisc/tests/test_obj_nest.c +++ b/libmisc/tests/test_obj_nest.c @@ -25,21 +25,15 @@ LO_INTERFACE(writer); LO_NEST(writer) LO_INTERFACE(read_writer); -/* implementation header ******************************************************/ +/* implementation *************************************************************/ struct myclass { size_t len; char buf[512]; }; -LO_IMPLEMENTATION_H(reader, struct myclass, myclass); -LO_IMPLEMENTATION_H(writer, struct myclass, myclass); -LO_IMPLEMENTATION_H(read_writer, struct myclass, myclass); - -/* implementation main ********************************************************/ - -LO_IMPLEMENTATION_C(reader, struct myclass, myclass, static); -LO_IMPLEMENTATION_C(writer, struct myclass, myclass, static); -LO_IMPLEMENTATION_C(read_writer, struct myclass, myclass, static); +LO_IMPLEMENTATION_STATIC(reader, struct myclass, myclass); +LO_IMPLEMENTATION_STATIC(writer, struct myclass, myclass); +LO_IMPLEMENTATION_STATIC(read_writer, struct myclass, myclass); static size_t myclass_read(struct myclass *self, void *buf, size_t count) { test_assert(self); |