From 5cec03e402aaee5fe314e03f366363a617a7d0c8 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=A9mie=20Galarneau?= Date: Thu, 14 May 2015 12:58:52 -0400 Subject: [PATCH] ir: copy variants and sequences when setting a field path MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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 --- formats/ctf/ir/event-types.c | 58 +++++++++++++++++++ formats/ctf/ir/visitor.c | 52 ++++++++++++++--- .../babeltrace/ctf-ir/event-types-internal.h | 12 ++++ 3 files changed, 114 insertions(+), 8 deletions(-) diff --git a/formats/ctf/ir/event-types.c b/formats/ctf/ir/event-types.c index 40c26da0..b336889b 100644 --- a/formats/ctf/ir/event-types.c +++ b/formats/ctf/ir/event-types.c @@ -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) { diff --git a/formats/ctf/ir/visitor.c b/formats/ctf/ir/visitor.c index 7d3e1fc0..62195b64 100644 --- a/formats/ctf/ir/visitor.c +++ b/formats/ctf/ir/visitor.c @@ -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; } diff --git a/include/babeltrace/ctf-ir/event-types-internal.h b/include/babeltrace/ctf-ir/event-types-internal.h index 48ead485..8475198b 100644 --- a/include/babeltrace/ctf-ir/event-types-internal.h +++ b/include/babeltrace/ctf-ir/event-types-internal.h @@ -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 */ -- 2.34.1