ir: copy variants and sequences when setting a field path
authorJérémie Galarneau <jeremie.galarneau@efficios.com>
Thu, 14 May 2015 16:58:52 +0000 (12:58 -0400)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Thu, 14 May 2015 16:58:52 +0000 (12:58 -0400)
Variants and sequences might be used in multiple structures. Therefore,
they are replaced by a copy with the path to their tag or sequence
length field set.

This is done on freeze, hence a user should not expect to be able
to modify a sequence's or variant's attributes subsequently.

Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
formats/ctf/ir/event-types.c
formats/ctf/ir/visitor.c
include/babeltrace/ctf-ir/event-types-internal.h

index 40c26da01d47cbed5966f1318712dc2529007d8e..b336889b029efb208c525a17fb32e44b4301f048 100644 (file)
@@ -2128,6 +2128,35 @@ end:
        return ret;
 }
 
+BT_HIDDEN
+int bt_ctf_field_type_structure_set_field_index(struct bt_ctf_field_type *type,
+               struct bt_ctf_field_type *field, int index)
+{
+       int ret = 0;
+       struct bt_ctf_field_type_structure *structure;
+
+       if (!type || !field || type->frozen ||
+               bt_ctf_field_type_get_type_id(type) != CTF_TYPE_STRUCT) {
+               ret = -1;
+               goto end;
+       }
+
+       structure = container_of(type, struct bt_ctf_field_type_structure,
+               parent);
+       if (index < 0 || index >= structure->fields->len) {
+               ret = -1;
+               goto end;
+       }
+
+       bt_ctf_field_type_get(field);
+       bt_ctf_field_type_put(((struct structure_field *)
+               g_ptr_array_index(structure->fields, index))->type);
+       ((struct structure_field *) structure->fields->pdata[index])->type =
+               field;
+end:
+       return ret;
+}
+
 BT_HIDDEN
 int bt_ctf_field_type_variant_get_field_name_index(
                struct bt_ctf_field_type *type, const char *name)
@@ -2231,6 +2260,35 @@ end:
        return ret;
 }
 
+BT_HIDDEN
+int bt_ctf_field_type_variant_set_field_index(struct bt_ctf_field_type *type,
+               struct bt_ctf_field_type *field, int index)
+{
+       int ret = 0;
+       struct bt_ctf_field_type_variant *variant;
+
+       if (!type || !field || type->frozen ||
+               bt_ctf_field_type_get_type_id(type) != CTF_TYPE_VARIANT) {
+               ret = -1;
+               goto end;
+       }
+
+       variant = container_of(type, struct bt_ctf_field_type_variant,
+               parent);
+       if (index < 0 || index >= variant->fields->len) {
+               ret = -1;
+               goto end;
+       }
+
+       bt_ctf_field_type_get(field);
+       bt_ctf_field_type_put(((struct structure_field *)
+               g_ptr_array_index(variant->fields, index))->type);
+       ((struct structure_field *) variant->fields->pdata[index])->type =
+               field;
+end:
+       return ret;
+}
+
 static
 void bt_ctf_field_type_integer_destroy(struct bt_ctf_ref *ref)
 {
index 7d3e1fc0732b9d232911e1abf6b15dffbfdba0f9..62195b64adb6f3e7561b88e585686c287f29efb3 100644 (file)
@@ -95,20 +95,37 @@ static inline
 struct bt_ctf_field_type *get_type_field(struct bt_ctf_field_type *type, int i)
 {
        struct bt_ctf_field_type *field = NULL;
-       const char *unused_name;
        enum ctf_type_id type_id = bt_ctf_field_type_get_type_id(type);
 
        if (type_id == CTF_TYPE_STRUCT) {
-               bt_ctf_field_type_structure_get_field(type, &unused_name,
+               bt_ctf_field_type_structure_get_field(type, NULL,
                        &field, i);
        } else if (type_id == CTF_TYPE_VARIANT) {
                bt_ctf_field_type_variant_get_field(type,
-                       &unused_name, &field, i);
+                       NULL, &field, i);
        }
 
        return field;
 }
 
+static inline
+int set_type_field(struct bt_ctf_field_type *type,
+               struct bt_ctf_field_type *field, int i)
+{
+       int ret = -1;
+       enum ctf_type_id type_id = bt_ctf_field_type_get_type_id(type);
+
+       if (type_id == CTF_TYPE_STRUCT) {
+               ret = bt_ctf_field_type_structure_set_field_index(
+                       type, field, i);
+       } else if (type_id == CTF_TYPE_VARIANT) {
+               ret = bt_ctf_field_type_variant_set_field_index(
+                       type, field, i);
+       }
+
+       return ret;
+}
+
 static inline
 int get_type_field_index(struct bt_ctf_field_type *type, const char *name)
 {
@@ -750,6 +767,8 @@ int type_resolve_func(struct bt_ctf_field_type *type,
        const char *field_name = NULL;
        struct bt_ctf_field_path *field_path = NULL;
        struct bt_ctf_field_type *resolved_type = NULL;
+       struct bt_ctf_field_type *type_copy = NULL;
+       struct ctf_type_stack_frame *frame;
 
        if (type_id != CTF_TYPE_SEQUENCE &&
                type_id != CTF_TYPE_VARIANT) {
@@ -775,7 +794,18 @@ int type_resolve_func(struct bt_ctf_field_type *type,
        /* Print path if in verbose mode */
        print_path(field_name, resolved_type, field_path);
 
-       /* Set type's path */
+       /*
+        * Set field type's path.
+        *
+        * The original field is copied since it may have been reused
+        * in multiple structures which would cause a conflict.
+        */
+       type_copy = bt_ctf_field_type_copy(type);
+       if (!type_copy) {
+               ret = -1;
+               goto end;
+       }
+
        if (type_id == CTF_TYPE_VARIANT) {
                if (bt_ctf_field_type_get_type_id(resolved_type) !=
                        CTF_TYPE_ENUM) {
@@ -783,12 +813,13 @@ int type_resolve_func(struct bt_ctf_field_type *type,
                        ret = -1;
                        goto end;
                }
-               ret = bt_ctf_field_type_variant_set_tag(type, resolved_type);
+               ret = bt_ctf_field_type_variant_set_tag(
+                       type_copy, resolved_type);
                if (ret) {
                        goto end;
                }
 
-               ret = bt_ctf_field_type_variant_set_tag_field_path(type,
+               ret = bt_ctf_field_type_variant_set_tag_field_path(type_copy,
                        field_path);
                if (ret) {
                        goto end;
@@ -808,12 +839,17 @@ int type_resolve_func(struct bt_ctf_field_type *type,
                        goto end;
                }
 
-               ret = bt_ctf_field_type_sequence_set_length_field_path(type,
-                       field_path);
+               ret = bt_ctf_field_type_sequence_set_length_field_path(
+                       type_copy, field_path);
                if (ret) {
                        goto end;
                }
        }
+
+       /* Replace the original field */
+       frame = ctf_type_stack_peek(context->stack);
+       ret = set_type_field(frame->type, type_copy, frame->index);
+       bt_ctf_field_type_put(type_copy);
 end:
        return ret;
 }
index 48ead4858033f9d7543b7cc7e6e8d59d53b135cb..8475198be676bc0f1860059c68807f98140c668f 100644 (file)
@@ -201,6 +201,12 @@ BT_HIDDEN
 int bt_ctf_field_type_structure_get_field_name_index(
                struct bt_ctf_field_type *structure, const char *name);
 
+/* Replace an existing field's type in a structure */
+BT_HIDDEN
+int bt_ctf_field_type_structure_set_field_index(
+               struct bt_ctf_field_type *structure,
+               struct bt_ctf_field_type *field, int index);
+
 BT_HIDDEN
 int bt_ctf_field_type_variant_get_field_name_index(
                struct bt_ctf_field_type *variant, const char *name);
@@ -218,4 +224,10 @@ BT_HIDDEN
 int bt_ctf_field_type_variant_set_tag(struct bt_ctf_field_type *type,
                struct bt_ctf_field_type *tag);
 
+/* Replace an existing field's type in a variant */
+BT_HIDDEN
+int bt_ctf_field_type_variant_set_field_index(
+               struct bt_ctf_field_type *variant,
+               struct bt_ctf_field_type *field, int index);
+
 #endif /* BABELTRACE_CTF_IR_EVENT_TYPES_INTERNAL_H */
This page took 0.028368 seconds and 4 git commands to generate.