so://phie

orb

Multi-purpose module system
git clone git://soophie.de/orb

blob: 9860981471c416806c5cd8b869bab9b9fe15993c (2605 bytes)[raw]

1#pragma once

2

3#include <stddef.h>

4#include <stdbool.h>

5

6#define ORB_RC_INIT ((orb_rc_t) { .code = 0, .is_fatal = false })

7#define ORB_OK ORB_RC_INIT

8

9#define ORB_MODULE(module) { \

10 orb_module_run(module, DUC_OUT); \

11}

12

13#define ORB_MODULE_DEF(type, param_list) { \

14 orb_module_t module = orb_module_create(&type, param_list); \

15 ORB_MODULE(&module) \

16}

17

18typedef struct {

19 int code;

20 bool is_fatal;

21} orb_rc_t;

22

23typedef struct orb_module orb_module_t;

24

25typedef 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;

32

33struct orb_module {

34 const orb_module_type_t *type;

35 void *param_list;

36 void *data;

37};

38

39typedef struct {

40 void *out;

41 orb_module_t *module;

42 orb_rc_t rc;

43} orb_ctx_t;

44

45orb_rc_t ORB_ERR(int code);

46orb_rc_t ORB_FATAL(int code);

47orb_ctx_t orb_ctx_create(void *out);

48orb_module_t orb_module_create(const orb_module_type_t *type, void *param_list);

49void orb_module_run(orb_module_t *self, orb_ctx_t *ctx);

50

51#ifdef ORB_IMPL

52

53#include <stdlib.h>

54

55orb_rc_t ORB_ERR(int code) {

56 return (orb_rc_t) { .code = code, .is_fatal = false };

57}

58

59orb_rc_t ORB_FATAL(int code) {

60 return (orb_rc_t) { .code = code, .is_fatal = true };

61}

62

63orb_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}

70

71orb_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}

78

79static void _orb_module_init(orb_module_t *self) {

80 if (self->type->size == 0) return;

81 self->data = calloc(1, self->type->size);

82}

83

84static void _orb_module_cleanup(orb_module_t *self) {

85 if (self->data) {

86 free(self->data);

87 self->data = NULL;

88 }

89}

90

91void 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}

118

119#endif // ORB_IMPL