summaryrefslogtreecommitdiff
path: root/libmisc
diff options
context:
space:
mode:
Diffstat (limited to 'libmisc')
-rw-r--r--libmisc/error.c9
-rw-r--r--libmisc/fmt.c6
-rw-r--r--libmisc/include/libmisc/alloc.h7
-rw-r--r--libmisc/include/libmisc/error.h1
-rw-r--r--libmisc/include/libmisc/obj.h97
-rw-r--r--libmisc/log.c3
-rw-r--r--libmisc/tests/test_obj.c8
-rw-r--r--libmisc/tests/test_obj_autobox.c14
-rw-r--r--libmisc/tests/test_obj_nest.c14
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);