Implement variant type
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Tue, 6 Dec 2022 19:52:32 +0000 (14:52 -0500)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Tue, 6 Dec 2022 21:36:28 +0000 (16:36 -0500)
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
include/side/trace.h
src/tracer.c
tests/unit/test.c

index f03b4fcb14bff61aec94b409c2ea60c13b78f3e6..e341047af5a14fcf9d8ec4194d779d8e4867edb5 100644 (file)
@@ -82,6 +82,7 @@ struct side_tracer_dynamic_struct_visitor_ctx;
 struct side_event_description;
 struct side_arg_dynamic_struct;
 struct side_events_register_handle;
+struct side_arg_variant;
 
 enum side_type_label {
        /* Stack-copy basic types */
@@ -107,6 +108,7 @@ enum side_type_label {
 
        /* Stack-copy compound types */
        SIDE_TYPE_STRUCT,
+       SIDE_TYPE_VARIANT,
        SIDE_TYPE_ARRAY,
        SIDE_TYPE_VLA,
        SIDE_TYPE_VLA_VISITOR,
@@ -471,6 +473,7 @@ struct side_type {
                struct side_type_vla side_vla;
                struct side_type_vla_visitor side_vla_visitor;
                const struct side_type_struct *side_struct;
+               const struct side_type_variant *side_variant;
 
                /* Stack-copy enumeration types */
                struct side_type_enum side_enum;
@@ -481,6 +484,20 @@ struct side_type {
        } SIDE_PACKED u;
 } SIDE_PACKED;
 
+struct side_variant_option {
+       int64_t range_begin;
+       int64_t range_end;
+       const struct side_type side_type;
+} SIDE_PACKED;
+
+struct side_type_variant {
+       const struct side_type selector;
+       const struct side_variant_option *options;
+       const struct side_attr *attr;
+       uint32_t nr_options;
+       uint32_t nr_attr;
+} SIDE_PACKED;
+
 struct side_event_field {
        const char *field_name;
        struct side_type side_type;
@@ -513,6 +530,7 @@ struct side_arg_static {
 
        /* Stack-copy compound types */
        const struct side_arg_vec *side_struct;
+       const struct side_arg_variant *side_variant;
        const struct side_arg_vec *side_array;
        const struct side_arg_vec *side_vla;
        void *side_vla_app_visitor_ctx;
@@ -601,6 +619,11 @@ struct side_arg {
        } SIDE_PACKED u;
 } SIDE_PACKED;
 
+struct side_arg_variant {
+       struct side_arg selector;
+       struct side_arg option;
+} SIDE_PACKED;
+
 struct side_arg_vec {
        const struct side_arg *sav;
        uint32_t len;
@@ -845,6 +868,16 @@ struct side_event_description {
                .side_type = _type, \
        }
 
+#define side_option_range(_range_begin, _range_end, _type) \
+       { \
+               .range_begin = _range_begin, \
+               .range_end = _range_end, \
+               .side_type = _type, \
+       }
+
+#define side_option(_value, _type) \
+       side_option_range(_value, _value, SIDE_PARAM(_type))
+
 /* Host endian */
 #define side_type_u8(_attr)                            _side_type_integer(SIDE_TYPE_U8, false, SIDE_TYPE_BYTE_ORDER_HOST, sizeof(uint8_t), 0, SIDE_PARAM(_attr))
 #define side_type_u16(_attr)                           _side_type_integer(SIDE_TYPE_U16, false, SIDE_TYPE_BYTE_ORDER_HOST, sizeof(uint16_t), 0, SIDE_PARAM(_attr))
@@ -993,6 +1026,33 @@ struct side_event_description {
        SIDE_COMPOUND_LITERAL(const struct side_type_struct, \
                _side_type_struct_define(SIDE_PARAM(_fields), SIDE_PARAM(_attr)))
 
+#define side_type_variant(_variant) \
+       { \
+               .type = SIDE_TYPE_VARIANT, \
+               .u = { \
+                       .side_variant = _variant, \
+               }, \
+       }
+#define side_field_variant(_name, _variant) \
+       _side_field(_name, side_type_variant(SIDE_PARAM(_variant)))
+
+#define _side_type_variant_define(_selector, _options, _attr) \
+       { \
+               .selector = _selector, \
+               .options = _options, \
+               .attr = _attr, \
+               .nr_options = SIDE_ARRAY_SIZE(SIDE_PARAM(_options)), \
+               .nr_attr  = SIDE_ARRAY_SIZE(SIDE_PARAM(_attr)), \
+       }
+
+#define side_define_variant(_identifier, _selector, _options, _attr) \
+       const struct side_type_variant _identifier = \
+               _side_type_variant_define(SIDE_PARAM(_selector), SIDE_PARAM(_options), SIDE_PARAM(_attr))
+
+#define side_variant_literal(_selector, _options, _attr) \
+       SIDE_COMPOUND_LITERAL(const struct side_type_variant, \
+               _side_type_variant_define(SIDE_PARAM(_selector), SIDE_PARAM(_options), SIDE_PARAM(_attr)))
+
 #define side_type_array(_elem_type, _length, _attr) \
        { \
                .type = SIDE_TYPE_ARRAY, \
@@ -1350,6 +1410,9 @@ struct side_event_description {
 #define side_field_list(...) \
        SIDE_COMPOUND_LITERAL(const struct side_event_field, __VA_ARGS__)
 
+#define side_option_list(...) \
+       SIDE_COMPOUND_LITERAL(const struct side_variant_option, __VA_ARGS__)
+
 /* Stack-copy field arguments */
 
 #define side_arg_null(_val)            { .type = SIDE_TYPE_NULL }
@@ -1374,6 +1437,22 @@ struct side_event_description {
 #define side_arg_float_binary128(_val) { .type = SIDE_TYPE_FLOAT_BINARY128, .u = { .side_static = { .float_value = { .side_float_binary128 = (_val) } } } }
 
 #define side_arg_struct(_side_type)    { .type = SIDE_TYPE_STRUCT, .u = { .side_static = { .side_struct = (_side_type) } } }
+
+#define side_arg_define_variant(_identifier, _selector_val, _option) \
+       const struct side_arg_variant _identifier = { \
+               .selector = _selector_val, \
+               .option = _option, \
+       }
+#define side_arg_variant(_side_variant) \
+       { \
+               .type = SIDE_TYPE_VARIANT, \
+               .u = { \
+                       .side_static = { \
+                               .side_variant = (_side_variant), \
+                       }, \
+               }, \
+       }
+
 #define side_arg_array(_side_type)     { .type = SIDE_TYPE_ARRAY, .u = { .side_static = { .side_array = (_side_type) } } }
 #define side_arg_vla(_side_type)       { .type = SIDE_TYPE_VLA, .u = { .side_static = { .side_vla = (_side_type) } } }
 #define side_arg_vla_visitor(_ctx)     { .type = SIDE_TYPE_VLA_VISITOR, .u = { .side_static = { .side_vla_app_visitor_ctx = (_ctx) } } }
index 8dd938807912af54f86fe2bb00b805e1b900795f..32e49697976a2411e6b2e8bbc1772cfc530b9fdf 100644 (file)
@@ -30,6 +30,8 @@ static struct side_tracer_handle *tracer_handle;
 static
 void tracer_print_struct(const struct side_type *type_desc, const struct side_arg_vec *side_arg_vec);
 static
+void tracer_print_variant(const struct side_type *type_desc, const struct side_arg_variant *side_arg_variant);
+static
 void tracer_print_array(const struct side_type *type_desc, const struct side_arg_vec *side_arg_vec);
 static
 void tracer_print_vla(const struct side_type *type_desc, const struct side_arg_vec *side_arg_vec);
@@ -951,6 +953,9 @@ void tracer_print_type(const struct side_type *type_desc, const struct side_arg
        case SIDE_TYPE_STRUCT:
                tracer_print_struct(type_desc, item->u.side_static.side_struct);
                break;
+       case SIDE_TYPE_VARIANT:
+               tracer_print_variant(type_desc, item->u.side_static.side_variant);
+               break;
        case SIDE_TYPE_ARRAY:
                tracer_print_array(type_desc, item->u.side_static.side_array);
                break;
@@ -1058,6 +1063,46 @@ void tracer_print_struct(const struct side_type *type_desc, const struct side_ar
        printf(" }");
 }
 
+static
+void tracer_print_variant(const struct side_type *type_desc, const struct side_arg_variant *side_arg_variant)
+{
+       const struct side_type_variant *side_type_variant = type_desc->u.side_variant;
+       const struct side_type *selector_type = &side_type_variant->selector;
+       union int64_value v64;
+       uint32_t i;
+
+       if (selector_type->type != side_arg_variant->selector.type) {
+               fprintf(stderr, "ERROR: Unexpected variant selector type\n");
+               abort();
+       }
+       switch (selector_type->type) {
+       case SIDE_TYPE_U8:
+       case SIDE_TYPE_U16:
+       case SIDE_TYPE_U32:
+       case SIDE_TYPE_U64:
+       case SIDE_TYPE_S8:
+       case SIDE_TYPE_S16:
+       case SIDE_TYPE_S32:
+       case SIDE_TYPE_S64:
+               break;
+       default:
+               fprintf(stderr, "ERROR: Expecting integer variant selector type\n");
+               abort();
+       }
+       v64 = tracer_load_integer_value(&selector_type->u.side_integer,
+                       &side_arg_variant->selector.u.side_static.integer_value, 0, NULL);
+       for (i = 0; i < side_type_variant->nr_options; i++) {
+               const struct side_variant_option *option = &side_type_variant->options[i];
+
+               if (v64.s >= option->range_begin && v64.s <= option->range_end) {
+                       tracer_print_type(&option->side_type, &side_arg_variant->option);
+                       return;
+               }
+       }
+       fprintf(stderr, "ERROR: Variant selector value unknown %" PRId64 "\n", v64.s);
+       abort();
+}
+
 static
 void tracer_print_array(const struct side_type *type_desc, const struct side_arg_vec *side_arg_vec)
 {
index f258a37eb19b31257a229e14b6189722d3eb5cd3..8c41f8bd0499e4fa86abfe514ad3fbbfe10e68ef 100644 (file)
@@ -2209,6 +2209,41 @@ void test_string_utf(void)
        );
 }
 
+static side_define_variant(myvariantdef,
+       side_type_u32(side_attr_list()),
+       side_option_list(
+               side_option_range(1, 3, side_type_u16(side_attr_list())),
+               side_option(5, side_type_string(side_attr_list())),
+       ),
+       side_attr_list()
+);
+
+side_static_event(my_provider_event_variant, "myprovider", "myeventvariant", SIDE_LOGLEVEL_DEBUG,
+       side_field_list(
+               side_field_variant("variant1", &myvariantdef),
+               side_field_variant("variant2", &myvariantdef),
+               side_field_u8("z", side_attr_list()),
+       ),
+       side_attr_list()
+);
+
+static
+void test_variant(void)
+{
+       side_event_cond(my_provider_event_variant) {
+               side_arg_define_variant(myvariant1, side_arg_u32(2), side_arg_u16(4));
+               side_arg_define_variant(myvariant2, side_arg_u32(5), side_arg_string("abc"));
+
+               side_event_call(my_provider_event_variant,
+                       side_arg_list(
+                               side_arg_variant(&myvariant1),
+                               side_arg_variant(&myvariant2),
+                               side_arg_u8(55),
+                       )
+               );
+       }
+}
+
 int main()
 {
        test_fields();
@@ -2260,5 +2295,6 @@ int main()
        test_gather_enum();
        test_gather_string();
        test_string_utf();
+       test_variant();
        return 0;
 }
This page took 0.036146 seconds and 4 git commands to generate.