struct side_arg_vec;
struct side_type_description;
+struct side_dynamic_type_description;
struct side_event_field;
+struct side_tracer_visitor_ctx;
+struct side_tracer_dynamic_map_visitor_ctx;
+struct side_tracer_dynamic_vla_visitor_ctx;
enum side_type {
SIDE_TYPE_U8,
SIDE_TYPE_S16,
SIDE_TYPE_S32,
SIDE_TYPE_S64,
+
SIDE_TYPE_STRING,
- SIDE_TYPE_DYNAMIC,
+
SIDE_TYPE_STRUCT,
SIDE_TYPE_ARRAY,
SIDE_TYPE_VLA,
SIDE_TYPE_VLA_VISITOR,
- //TODO:
- //specialized array and vla for fixed-size integers (optimization)
- //variants (discriminated unions)
+
+ SIDE_TYPE_ARRAY_U8,
+ SIDE_TYPE_ARRAY_U16,
+ SIDE_TYPE_ARRAY_U32,
+ SIDE_TYPE_ARRAY_U64,
+ SIDE_TYPE_ARRAY_S8,
+ SIDE_TYPE_ARRAY_S16,
+ SIDE_TYPE_ARRAY_S32,
+ SIDE_TYPE_ARRAY_S64,
+
+ SIDE_TYPE_VLA_U8,
+ SIDE_TYPE_VLA_U16,
+ SIDE_TYPE_VLA_U32,
+ SIDE_TYPE_VLA_U64,
+ SIDE_TYPE_VLA_S8,
+ SIDE_TYPE_VLA_S16,
+ SIDE_TYPE_VLA_S32,
+ SIDE_TYPE_VLA_S64,
+
+ SIDE_TYPE_DYNAMIC,
+};
+
+enum side_dynamic_type {
+ SIDE_DYNAMIC_TYPE_NULL,
+
+ SIDE_DYNAMIC_TYPE_U8,
+ SIDE_DYNAMIC_TYPE_U16,
+ SIDE_DYNAMIC_TYPE_U32,
+ SIDE_DYNAMIC_TYPE_U64,
+ SIDE_DYNAMIC_TYPE_S8,
+ SIDE_DYNAMIC_TYPE_S16,
+ SIDE_DYNAMIC_TYPE_S32,
+ SIDE_DYNAMIC_TYPE_S64,
+
+ SIDE_DYNAMIC_TYPE_STRING,
+
+ SIDE_DYNAMIC_TYPE_MAP_VISITOR,
+ SIDE_DYNAMIC_TYPE_VLA_VISITOR,
};
enum side_loglevel {
SIDE_VISITOR_STATUS_END = 1,
};
-typedef enum side_visitor_status (*side_visitor_begin)(void *ctx);
-typedef enum side_visitor_status (*side_visitor_end)(void *ctx);
-typedef enum side_visitor_status (*side_visitor_get_next)(void *ctx, struct side_arg_vec *sav_elem);
+typedef enum side_visitor_status (*side_visitor)(const struct side_tracer_visitor_ctx *tracer_ctx,
+ void *app_ctx);
+typedef enum side_visitor_status (*side_dynamic_map_visitor)(const struct side_tracer_dynamic_map_visitor_ctx *tracer_ctx,
+ void *app_ctx);
+typedef enum side_visitor_status (*side_dynamic_vla_visitor)(const struct side_tracer_dynamic_vla_visitor_ctx *tracer_ctx,
+ void *app_ctx);
struct side_type_description {
enum side_type type;
+ //TODO: we should add something like a list of user attributes (namespaced strings)
union {
struct {
uint32_t nr_fields;
} side_vla;
struct {
const struct side_type_description *elem_type;
- side_visitor_begin begin;
- side_visitor_end end;
- side_visitor_get_next get_next;
+ side_visitor visitor;
} side_vla_visitor;
} u;
};
const struct side_event_field *fields;
};
+struct side_arg_dynamic_vec {
+ uint32_t type; /* enum side_dynamic_type */
+ union {
+ uint8_t side_u8;
+ uint16_t side_u16;
+ uint32_t side_u32;
+ uint64_t side_u64;
+ int8_t side_s8;
+ int16_t side_s16;
+ int32_t side_s32;
+ int64_t side_s64;
+
+ const char *string;
+
+ struct {
+ void *app_dynamic_visitor_ctx;
+ side_dynamic_map_visitor visitor;
+ } side_dynamic_map_visitor;
+ struct {
+ void *app_dynamic_visitor_ctx;
+ side_dynamic_vla_visitor visitor;
+ } side_dynamic_vla_visitor;
+ } u;
+};
+
struct side_arg_vec {
uint32_t type; /* enum side_type */
union {
int16_t side_s16;
int32_t side_s32;
int64_t side_s64;
+
const char *string;
const struct side_arg_vec_description *side_struct;
const struct side_arg_vec_description *side_array;
const struct side_arg_vec_description *side_vla;
- void *side_vla_visitor_ctx;
+ void *side_vla_app_visitor_ctx;
+
+ void *side_array_fixint;
+ struct {
+ void *p;
+ uint32_t length;
+ } side_vla_fixint;
+
+ struct side_arg_dynamic_vec dynamic;
} u;
};
uint32_t len;
};
+struct side_dynamic_event_field {
+ const char *field_name;
+ const struct side_arg_dynamic_vec *elem;
+ //TODO: we should add something like a list of user attributes (namespaced strings)
+};
+
+/* The visitor pattern is a double-dispatch visitor. */
+struct side_tracer_visitor_ctx {
+ enum side_visitor_status (*write_elem)(const struct side_tracer_visitor_ctx *tracer_ctx,
+ const struct side_arg_vec *elem);
+ void *priv; /* Private tracer context. */
+};
+
+struct side_tracer_dynamic_map_visitor_ctx {
+ enum side_visitor_status (*write_field)(const struct side_tracer_dynamic_map_visitor_ctx *tracer_ctx,
+ const struct side_dynamic_event_field *field);
+ void *priv; /* Private tracer context. */
+};
+
+struct side_tracer_dynamic_vla_visitor_ctx {
+ enum side_visitor_status (*write_elem)(const struct side_tracer_dynamic_vla_visitor_ctx *tracer_ctx,
+ const struct side_arg_dynamic_vec *elem);
+ void *priv; /* Private tracer context. */
+};
+
#define side_type_decl(_type) { .type = _type }
#define side_field(_type, _name) { .field_name = _name, .side_type = side_type_decl(_type) }
.side_type = side_type_vla_decl(_elem_type), \
}
-#define side_type_vla_visitor_decl(_elem_type, _begin, _end, _get_next) \
+#define side_type_vla_visitor_decl(_elem_type, _visitor) \
{ \
.type = SIDE_TYPE_VLA_VISITOR, \
.u = { \
.side_vla_visitor = { \
- .elem_type = _elem_type, \
- .begin = _begin, \
- .end = _end, \
- .get_next = _get_next, \
+ .elem_type = SIDE_PARAM(_elem_type), \
+ .visitor = _visitor, \
}, \
}, \
}
-#define side_field_vla_visitor(_name, _elem_type, _begin, _end, _get_next) \
+#define side_field_vla_visitor(_name, _elem_type, _visitor) \
{ \
.field_name = _name, \
- .side_type = side_type_vla_visitor_decl(_elem_type, _begin, _end, _get_next), \
+ .side_type = side_type_vla_visitor_decl(SIDE_PARAM(_elem_type), _visitor), \
}
#define side_elem(...) \
- SIDE_COMPOUND_LITERAL(const struct side_type_description, side_type_decl(__VA_ARGS__))
+ SIDE_COMPOUND_LITERAL(const struct side_type_description, __VA_ARGS__)
+
+#define side_elem_type(...) \
+ side_elem(side_type_decl(__VA_ARGS__))
#define side_field_list(...) \
SIDE_COMPOUND_LITERAL(const struct side_event_field, __VA_ARGS__)
#define side_arg_struct(_side_type) { .type = SIDE_TYPE_STRUCT, .u = { .side_struct = (_side_type) } }
#define side_arg_array(_side_type) { .type = SIDE_TYPE_ARRAY, .u = { .side_array = (_side_type) } }
#define side_arg_vla(_side_type) { .type = SIDE_TYPE_VLA, .u = { .side_vla = (_side_type) } }
-#define side_arg_vla_visitor(_ctx) { .type = SIDE_TYPE_VLA_VISITOR, .u = { .side_vla_visitor_ctx = (_ctx) } }
+#define side_arg_vla_visitor(_ctx) { .type = SIDE_TYPE_VLA_VISITOR, .u = { .side_vla_app_visitor_ctx = (_ctx) } }
+
+#define side_arg_array_u8(_ptr) { .type = SIDE_TYPE_ARRAY_U8, .u = { .side_array_fixint = (_ptr) } }
+#define side_arg_array_u16(_ptr) { .type = SIDE_TYPE_ARRAY_U16, .u = { .side_array_fixint = (_ptr) } }
+#define side_arg_array_u32(_ptr) { .type = SIDE_TYPE_ARRAY_U32, .u = { .side_array_fixint = (_ptr) } }
+#define side_arg_array_u64(_ptr) { .type = SIDE_TYPE_ARRAY_U64, .u = { .side_array_fixint = (_ptr) } }
+#define side_arg_array_s8(_ptr) { .type = SIDE_TYPE_ARRAY_S8, .u = { .side_array_fixint = (_ptr) } }
+#define side_arg_array_s16(_ptr) { .type = SIDE_TYPE_ARRAY_S16, .u = { .side_array_fixint = (_ptr) } }
+#define side_arg_array_s32(_ptr) { .type = SIDE_TYPE_ARRAY_S32, .u = { .side_array_fixint = (_ptr) } }
+#define side_arg_array_s64(_ptr) { .type = SIDE_TYPE_ARRAY_S64, .u = { .side_array_fixint = (_ptr) } }
+
+#define side_arg_vla_u8(_ptr, _length) { .type = SIDE_TYPE_VLA_U8, .u = { .side_vla_fixint = { .p = (_ptr), .length = (_length) } }
+#define side_arg_vla_u16(_ptr, _length) { .type = SIDE_TYPE_VLA_U16, .u = { .side_vla_fixint = { .p = (_ptr), .length = (_length) } } }
+#define side_arg_vla_u32(_ptr, _length) { .type = SIDE_TYPE_VLA_U32, .u = { .side_vla_fixint = { .p = (_ptr), .length = (_length) } } }
+#define side_arg_vla_u64(_ptr, _length) { .type = SIDE_TYPE_VLA_U64, .u = { .side_vla_fixint = { .p = (_ptr), .length = (_length) } } }
+#define side_arg_vla_s8(_ptr, _length) { .type = SIDE_TYPE_VLA_S8, .u = { .side_vla_fixint = { .p = (_ptr), .length = (_length) } } }
+#define side_arg_vla_s16(_ptr, _length) { .type = SIDE_TYPE_VLA_S16, .u = { .side_vla_fixint = { .p = (_ptr), .length = (_length) } } }
+#define side_arg_vla_s32(_ptr, _length) { .type = SIDE_TYPE_VLA_S32, .u = { .side_vla_fixint = { .p = (_ptr), .length = (_length) } } }
+#define side_arg_vla_s64(_ptr, _length) { .type = SIDE_TYPE_VLA_S64, .u = { .side_vla_fixint = { .p = (_ptr), .length = (_length) } } }
+
+#define side_arg_dynamic(dynamic_arg_type) \
+ { \
+ .type = SIDE_TYPE_DYNAMIC, \
+ .u = { \
+ .dynamic = dynamic_arg_type, \
+ }, \
+ }
+
+#define side_arg_dynamic_null(val) { .type = SIDE_DYNAMIC_TYPE_NULL }
+
+#define side_arg_dynamic_u8(val) { .type = SIDE_DYNAMIC_TYPE_U8, .u = { .side_u8 = (val) } }
+#define side_arg_dynamic_u16(val) { .type = SIDE_DYNAMIC_TYPE_U16, .u = { .side_u16 = (val) } }
+#define side_arg_dynamic_u32(val) { .type = SIDE_DYNAMIC_TYPE_U32, .u = { .side_u32 = (val) } }
+#define side_arg_dynamic_u64(val) { .type = SIDE_DYNAMIC_TYPE_U64, .u = { .side_u64 = (val) } }
+#define side_arg_dynamic_s8(val) { .type = SIDE_DYNAMIC_TYPE_S8, .u = { .side_s8 = (val) } }
+#define side_arg_dynamic_s16(val) { .type = SIDE_DYNAMIC_TYPE_S16, .u = { .side_s16 = (val) } }
+#define side_arg_dynamic_s32(val) { .type = SIDE_DYNAMIC_TYPE_S32, .u = { .side_s32 = (val) } }
+#define side_arg_dynamic_s64(val) { .type = SIDE_DYNAMIC_TYPE_S64, .u = { .side_s64 = (val) } }
+#define side_arg_dynamic_string(val) { .type = SIDE_DYNAMIC_TYPE_STRING, .u = { .string = (val) } }
+
+#define side_arg_dynamic_vla_visitor(_dynamic_vla_visitor, _ctx) \
+ { \
+ .type = SIDE_DYNAMIC_TYPE_VLA_VISITOR, \
+ .app_dynamic_visitor_ctx = _ctx, \
+ .u = { \
+ .vla_visitor = _dynamic_vla_visitor, \
+ }, \
+ }
+
+#define side_arg_dynamic_map_visitor(_dynamic_map_visitor, _ctx) \
+ { \
+ .type = SIDE_DYNAMIC_TYPE_MAP_VISITOR, \
+ .app_dynamic_visitor_ctx = _ctx, \
+ .u = { \
+ .map_visitor = _dynamic_map_visitor, \
+ }, \
+ }
#define side_arg_define_vec(_identifier, _sav) \
const struct side_arg_vec _identifier##_vec[] = { _sav }; \