Multi-purpose module system
git clone git://soophie.de/orb
blob: 9860981471c416806c5cd8b869bab9b9fe15993c (2605 bytes)[raw]
1
#pragma once3
#include <stddef.h>4
#include <stdbool.h>6
#define ORB_RC_INIT ((orb_rc_t) { .code = 0, .is_fatal = false })7
#define ORB_OK ORB_RC_INIT9
#define ORB_MODULE(module) { \10
orb_module_run(module, DUC_OUT); \11
}13
#define ORB_MODULE_DEF(type, param_list) { \14
orb_module_t module = orb_module_create(&type, param_list); \15
ORB_MODULE(&module) \16
}18
typedef struct {19
int code;20
bool is_fatal;21
} orb_rc_t;23
typedef struct orb_module orb_module_t;25
typedef struct {26
size_t size;27
orb_rc_t (*init)(orb_module_t *self);28
orb_rc_t (*fetch)(orb_module_t *self);29
orb_rc_t (*render)(orb_module_t *self, void *out);30
void (*cleanup)(orb_module_t *self);31
} orb_module_type_t;33
struct orb_module {34
const orb_module_type_t *type;35
void *param_list;36
void *data;37
};39
typedef struct {40
void *out;41
orb_module_t *module;42
orb_rc_t rc;43
} orb_ctx_t;45
orb_rc_t ORB_ERR(int code);46
orb_rc_t ORB_FATAL(int code);47
orb_ctx_t orb_ctx_create(void *out);48
orb_module_t orb_module_create(const orb_module_type_t *type, void *param_list);49
void orb_module_run(orb_module_t *self, orb_ctx_t *ctx);51
#ifdef ORB_IMPL53
#include <stdlib.h>55
orb_rc_t ORB_ERR(int code) {56
return (orb_rc_t) { .code = code, .is_fatal = false };57
}59
orb_rc_t ORB_FATAL(int code) {60
return (orb_rc_t) { .code = code, .is_fatal = true };61
}63
orb_ctx_t orb_ctx_create(void *out) {64
return (orb_ctx_t) {65
.out = out,66
.module = NULL,67
.rc = ORB_RC_INIT,68
};69
}71
orb_module_t orb_module_create(const orb_module_type_t *type, void *param_list) {72
return (orb_module_t) {73
.type = type,74
.param_list = param_list,75
.data = NULL,76
};77
}79
static void _orb_module_init(orb_module_t *self) {80
if (self->type->size == 0) return;81
self->data = calloc(1, self->type->size);82
}84
static void _orb_module_cleanup(orb_module_t *self) {85
if (self->data) {86
free(self->data);87
self->data = NULL;88
}89
}91
void orb_module_run(orb_module_t *self, orb_ctx_t *ctx) {92
orb_ctx_t sub_ctx = {93
.out = ctx->out,94
.module = self,95
.rc = ORB_RC_INIT,96
};97
_orb_module_init(self);98
if (self->type->init) {99
sub_ctx.rc = self->type->init(self);100
if (sub_ctx.rc.is_fatal) goto cleanup;101
}102
if (self->type->fetch) {103
sub_ctx.rc = self->type->fetch(self);104
if (sub_ctx.rc.is_fatal) goto cleanup;105
}106
if (self->type->render) {107
orb_rc_t rc = self->type->render(self, &sub_ctx);108
if (rc.code != 0) sub_ctx.rc = rc;109
if (sub_ctx.rc.is_fatal) goto cleanup;110
}111
cleanup:112
if (self->type->cleanup) {113
self->type->cleanup(self);114
}115
_orb_module_cleanup(self);116
ctx->rc = sub_ctx.rc;117
}119
#endif // ORB_IMPL