X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=formats%2Fctf%2Fir%2Fevent-fields.c;h=1092dc314d9d8ac08ab39476f39a5afcd1f16daa;hb=8c1aa858878b64d103166be4c02f110af87669df;hp=ed2cf489fc4e82b535c27885793afe8ecb30ee57;hpb=9773681407e4e8fce40f247132dc99fabe306bfe;p=babeltrace.git diff --git a/formats/ctf/ir/event-fields.c b/formats/ctf/ir/event-fields.c index ed2cf489..1092dc31 100644 --- a/formats/ctf/ir/event-fields.c +++ b/formats/ctf/ir/event-fields.c @@ -1,7 +1,7 @@ /* * event-fields.c * - * Babeltrace CTF Writer + * Babeltrace CTF IR - Event Fields * * Copyright 2013, 2014 Jérémie Galarneau * @@ -29,6 +29,8 @@ #include #include #include +#include +#include #include #define PACKET_LEN_INCREMENT (getpagesize() * 8 * CHAR_BIT) @@ -57,7 +59,7 @@ static struct bt_ctf_field *bt_ctf_field_string_create(struct bt_ctf_field_type *); static -void bt_ctf_field_destroy(struct bt_ctf_ref *); +void bt_ctf_field_destroy(struct bt_object *); static void bt_ctf_field_integer_destroy(struct bt_ctf_field *); static @@ -76,17 +78,32 @@ static void bt_ctf_field_string_destroy(struct bt_ctf_field *); static -int bt_ctf_field_generic_validate(struct bt_ctf_field *field); +int bt_ctf_field_generic_validate(struct bt_ctf_field *); static -int bt_ctf_field_structure_validate(struct bt_ctf_field *field); +int bt_ctf_field_structure_validate(struct bt_ctf_field *); static -int bt_ctf_field_variant_validate(struct bt_ctf_field *field); +int bt_ctf_field_variant_validate(struct bt_ctf_field *); static -int bt_ctf_field_enumeration_validate(struct bt_ctf_field *field); +int bt_ctf_field_enumeration_validate(struct bt_ctf_field *); static -int bt_ctf_field_array_validate(struct bt_ctf_field *field); +int bt_ctf_field_array_validate(struct bt_ctf_field *); static -int bt_ctf_field_sequence_validate(struct bt_ctf_field *field); +int bt_ctf_field_sequence_validate(struct bt_ctf_field *); + +static +int bt_ctf_field_generic_reset(struct bt_ctf_field *); +static +int bt_ctf_field_structure_reset(struct bt_ctf_field *); +static +int bt_ctf_field_variant_reset(struct bt_ctf_field *); +static +int bt_ctf_field_enumeration_reset(struct bt_ctf_field *); +static +int bt_ctf_field_array_reset(struct bt_ctf_field *); +static +int bt_ctf_field_sequence_reset(struct bt_ctf_field *); +static +int bt_ctf_field_string_reset(struct bt_ctf_field *); static int bt_ctf_field_integer_serialize(struct bt_ctf_field *, @@ -113,11 +130,29 @@ static int bt_ctf_field_string_serialize(struct bt_ctf_field *, struct ctf_stream_pos *); +static +int bt_ctf_field_integer_copy(struct bt_ctf_field *, struct bt_ctf_field *); +static +int bt_ctf_field_enumeration_copy(struct bt_ctf_field *, struct bt_ctf_field *); +static +int bt_ctf_field_floating_point_copy(struct bt_ctf_field *, + struct bt_ctf_field *); +static +int bt_ctf_field_structure_copy(struct bt_ctf_field *, struct bt_ctf_field *); +static +int bt_ctf_field_variant_copy(struct bt_ctf_field *, struct bt_ctf_field *); +static +int bt_ctf_field_array_copy(struct bt_ctf_field *, struct bt_ctf_field *); +static +int bt_ctf_field_sequence_copy(struct bt_ctf_field *, struct bt_ctf_field *); +static +int bt_ctf_field_string_copy(struct bt_ctf_field *, struct bt_ctf_field *); + static int increase_packet_size(struct ctf_stream_pos *pos); static -struct bt_ctf_field *(*field_create_funcs[])( +struct bt_ctf_field *(* const field_create_funcs[])( struct bt_ctf_field_type *) = { [CTF_TYPE_INTEGER] = bt_ctf_field_integer_create, [CTF_TYPE_ENUM] = bt_ctf_field_enumeration_create, @@ -131,7 +166,7 @@ struct bt_ctf_field *(*field_create_funcs[])( }; static -void (*field_destroy_funcs[])(struct bt_ctf_field *) = { +void (* const field_destroy_funcs[])(struct bt_ctf_field *) = { [CTF_TYPE_INTEGER] = bt_ctf_field_integer_destroy, [CTF_TYPE_ENUM] = bt_ctf_field_enumeration_destroy, [CTF_TYPE_FLOAT] = @@ -144,7 +179,7 @@ void (*field_destroy_funcs[])(struct bt_ctf_field *) = { }; static -int (*field_validate_funcs[])(struct bt_ctf_field *) = { +int (* const field_validate_funcs[])(struct bt_ctf_field *) = { [CTF_TYPE_INTEGER] = bt_ctf_field_generic_validate, [CTF_TYPE_ENUM] = bt_ctf_field_enumeration_validate, [CTF_TYPE_FLOAT] = bt_ctf_field_generic_validate, @@ -156,7 +191,19 @@ int (*field_validate_funcs[])(struct bt_ctf_field *) = { }; static -int (*field_serialize_funcs[])(struct bt_ctf_field *, +int (* const field_reset_funcs[])(struct bt_ctf_field *) = { + [CTF_TYPE_INTEGER] = bt_ctf_field_generic_reset, + [CTF_TYPE_ENUM] = bt_ctf_field_enumeration_reset, + [CTF_TYPE_FLOAT] = bt_ctf_field_generic_reset, + [CTF_TYPE_STRUCT] = bt_ctf_field_structure_reset, + [CTF_TYPE_VARIANT] = bt_ctf_field_variant_reset, + [CTF_TYPE_ARRAY] = bt_ctf_field_array_reset, + [CTF_TYPE_SEQUENCE] = bt_ctf_field_sequence_reset, + [CTF_TYPE_STRING] = bt_ctf_field_string_reset, +}; + +static +int (* const field_serialize_funcs[])(struct bt_ctf_field *, struct ctf_stream_pos *) = { [CTF_TYPE_INTEGER] = bt_ctf_field_integer_serialize, [CTF_TYPE_ENUM] = bt_ctf_field_enumeration_serialize, @@ -169,6 +216,19 @@ int (*field_serialize_funcs[])(struct bt_ctf_field *, [CTF_TYPE_STRING] = bt_ctf_field_string_serialize, }; +static +int (* const field_copy_funcs[])(struct bt_ctf_field *, + struct bt_ctf_field *) = { + [CTF_TYPE_INTEGER] = bt_ctf_field_integer_copy, + [CTF_TYPE_ENUM] = bt_ctf_field_enumeration_copy, + [CTF_TYPE_FLOAT] = bt_ctf_field_floating_point_copy, + [CTF_TYPE_STRUCT] = bt_ctf_field_structure_copy, + [CTF_TYPE_VARIANT] = bt_ctf_field_variant_copy, + [CTF_TYPE_ARRAY] = bt_ctf_field_array_copy, + [CTF_TYPE_SEQUENCE] = bt_ctf_field_sequence_copy, + [CTF_TYPE_STRING] = bt_ctf_field_string_copy, +}; + struct bt_ctf_field *bt_ctf_field_create(struct bt_ctf_field_type *type) { struct bt_ctf_field *field = NULL; @@ -191,8 +251,8 @@ struct bt_ctf_field *bt_ctf_field_create(struct bt_ctf_field_type *type) /* The type's declaration can't change after this point */ bt_ctf_field_type_freeze(type); - bt_ctf_field_type_get(type); - bt_ctf_ref_init(&field->ref_count); + bt_get(type); + bt_object_init(field, bt_ctf_field_destroy); field->type = type; error: return field; @@ -200,16 +260,12 @@ error: void bt_ctf_field_get(struct bt_ctf_field *field) { - if (field) { - bt_ctf_ref_get(&field->ref_count); - } + bt_get(field); } void bt_ctf_field_put(struct bt_ctf_field *field) { - if (field) { - bt_ctf_ref_put(&field->ref_count, bt_ctf_field_destroy); - } + bt_put(field); } struct bt_ctf_field_type *bt_ctf_field_get_type(struct bt_ctf_field *field) @@ -221,11 +277,64 @@ struct bt_ctf_field_type *bt_ctf_field_get_type(struct bt_ctf_field *field) } ret = field->type; - bt_ctf_field_type_get(ret); + bt_get(ret); end: return ret; } +enum ctf_type_id bt_ctf_field_get_type_id(struct bt_ctf_field *field) +{ + enum ctf_type_id ret = CTF_TYPE_UNKNOWN; + + if (!field) { + goto end; + } + + ret = bt_ctf_field_type_get_type_id(field->type); +end: + return ret; +} + +int bt_ctf_field_is_integer(struct bt_ctf_field *field) +{ + return bt_ctf_field_get_type_id(field) == CTF_TYPE_INTEGER; +} + +int bt_ctf_field_is_floating_point(struct bt_ctf_field *field) +{ + return bt_ctf_field_get_type_id(field) == CTF_TYPE_FLOAT; +} + +int bt_ctf_field_is_enumeration(struct bt_ctf_field *field) +{ + return bt_ctf_field_get_type_id(field) == CTF_TYPE_ENUM; +} + +int bt_ctf_field_is_string(struct bt_ctf_field *field) +{ + return bt_ctf_field_get_type_id(field) == CTF_TYPE_STRING; +} + +int bt_ctf_field_is_structure(struct bt_ctf_field *field) +{ + return bt_ctf_field_get_type_id(field) == CTF_TYPE_STRUCT; +} + +int bt_ctf_field_is_array(struct bt_ctf_field *field) +{ + return bt_ctf_field_get_type_id(field) == CTF_TYPE_ARRAY; +} + +int bt_ctf_field_is_sequence(struct bt_ctf_field *field) +{ + return bt_ctf_field_get_type_id(field) == CTF_TYPE_SEQUENCE; +} + +int bt_ctf_field_is_variant(struct bt_ctf_field *field) +{ + return bt_ctf_field_get_type_id(field) == CTF_TYPE_VARIANT; +} + struct bt_ctf_field *bt_ctf_field_sequence_get_length( struct bt_ctf_field *field) { @@ -243,7 +352,7 @@ struct bt_ctf_field *bt_ctf_field_sequence_get_length( sequence = container_of(field, struct bt_ctf_field_sequence, parent); ret = sequence->length; - bt_ctf_field_get(ret); + bt_get(ret); end: return ret; } @@ -281,7 +390,7 @@ int bt_ctf_field_sequence_set_length(struct bt_ctf_field *field, sequence = container_of(field, struct bt_ctf_field_sequence, parent); if (sequence->elements) { g_ptr_array_free(sequence->elements, TRUE); - bt_ctf_field_put(sequence->length); + bt_put(sequence->length); } sequence->elements = g_ptr_array_sized_new((size_t)sequence_length); @@ -291,9 +400,9 @@ int bt_ctf_field_sequence_set_length(struct bt_ctf_field *field, } g_ptr_array_set_free_func(sequence->elements, - (GDestroyNotify)bt_ctf_field_put); - g_ptr_array_set_size(sequence->elements, (size_t)sequence_length); - bt_ctf_field_get(length_field); + (GDestroyNotify) bt_put); + g_ptr_array_set_size(sequence->elements, (size_t) sequence_length); + bt_get(length_field); sequence->length = length_field; end: return ret; @@ -336,16 +445,16 @@ struct bt_ctf_field *bt_ctf_field_structure_get_field( structure->fields->pdata[index] = new_field; end: - bt_ctf_field_get(new_field); + bt_get(new_field); error: if (field_type) { - bt_ctf_field_type_put(field_type); + bt_put(field_type); } return new_field; } struct bt_ctf_field *bt_ctf_field_structure_get_field_by_index( - struct bt_ctf_field *field, size_t index) + struct bt_ctf_field *field, int index) { int ret; const char *field_name; @@ -377,7 +486,7 @@ struct bt_ctf_field *bt_ctf_field_structure_get_field_by_index( ret = bt_ctf_field_type_structure_get_field(structure_type, &field_name, &field_type, index); - bt_ctf_field_type_put(structure_type); + bt_put(structure_type); if (ret) { goto error; } @@ -389,11 +498,9 @@ struct bt_ctf_field *bt_ctf_field_structure_get_field_by_index( structure->fields->pdata[index] = ret_field; end: - bt_ctf_field_get(ret_field); + bt_get(ret_field); error: - if (field_type) { - bt_ctf_field_type_put(field_type); - } + bt_put(field_type); return ret_field; } @@ -430,14 +537,14 @@ int bt_ctf_field_structure_set_field(struct bt_ctf_field *field, } if (structure->fields->pdata[index]) { - bt_ctf_field_put(structure->fields->pdata[index]); + bt_put(structure->fields->pdata[index]); } structure->fields->pdata[index] = value; - bt_ctf_field_get(value); + bt_get(value); end: if (expected_field_type) { - bt_ctf_field_type_put(expected_field_type); + bt_put(expected_field_type); } return ret; } @@ -466,11 +573,13 @@ struct bt_ctf_field *bt_ctf_field_array_get_field(struct bt_ctf_field *field, } new_field = bt_ctf_field_create(field_type); - bt_ctf_field_get(new_field); array->elements->pdata[(size_t)index] = new_field; end: if (field_type) { - bt_ctf_field_type_put(field_type); + bt_put(field_type); + } + if (new_field) { + bt_get(new_field); } return new_field; } @@ -493,17 +602,19 @@ struct bt_ctf_field *bt_ctf_field_sequence_get_field(struct bt_ctf_field *field, } field_type = bt_ctf_field_type_sequence_get_element_type(field->type); - if (sequence->elements->pdata[(size_t)index]) { - new_field = sequence->elements->pdata[(size_t)index]; + if (sequence->elements->pdata[(size_t) index]) { + new_field = sequence->elements->pdata[(size_t) index]; goto end; } new_field = bt_ctf_field_create(field_type); - bt_ctf_field_get(new_field); - sequence->elements->pdata[(size_t)index] = new_field; + sequence->elements->pdata[(size_t) index] = new_field; end: if (field_type) { - bt_ctf_field_type_put(field_type); + bt_put(field_type); + } + if (new_field) { + bt_get(new_field); } return new_field; } @@ -538,11 +649,36 @@ struct bt_ctf_field *bt_ctf_field_variant_get_field(struct bt_ctf_field *field, tag_enum_integer = container_of(tag_enum, struct bt_ctf_field_integer, parent); - if (!bt_ctf_field_validate(variant->tag)) { + if (bt_ctf_field_validate(tag_field) < 0) { goto end; } tag_enum_value = tag_enum_integer->definition.value._signed; + + /* + * If the variant currently has a tag and a payload, and if the + * requested tag value is the same as the current one, return + * the current payload instead of creating a fresh one. + */ + if (variant->tag && variant->payload) { + struct bt_ctf_field *cur_tag_container = NULL; + struct bt_ctf_field_integer *cur_tag_enum_integer; + int64_t cur_tag_value; + + cur_tag_container = + bt_ctf_field_enumeration_get_container(variant->tag); + cur_tag_enum_integer = container_of(cur_tag_container, + struct bt_ctf_field_integer, parent); + bt_put(cur_tag_container); + cur_tag_value = cur_tag_enum_integer->definition.value._signed; + + if (cur_tag_value == tag_enum_value) { + new_field = variant->payload; + bt_get(new_field); + goto end; + } + } + field_type = bt_ctf_field_type_variant_get_field_type_signed( variant_type, tag_enum_value); if (!field_type) { @@ -554,17 +690,42 @@ struct bt_ctf_field *bt_ctf_field_variant_get_field(struct bt_ctf_field *field, goto end; } - bt_ctf_field_put(variant->tag); - bt_ctf_field_put(variant->payload); - bt_ctf_field_get(new_field); - bt_ctf_field_get(tag_field); + bt_put(variant->tag); + bt_put(variant->payload); + bt_get(new_field); + bt_get(tag_field); variant->tag = tag_field; variant->payload = new_field; end: - bt_ctf_field_put(tag_enum); + bt_put(tag_enum); return new_field; } +struct bt_ctf_field *bt_ctf_field_variant_get_current_field( + struct bt_ctf_field *variant_field) +{ + struct bt_ctf_field *current_field = NULL; + struct bt_ctf_field_variant *variant; + + if (!variant_field || + bt_ctf_field_type_get_type_id(variant_field->type) != + CTF_TYPE_VARIANT) { + goto end; + } + + variant = container_of(variant_field, struct bt_ctf_field_variant, + parent); + + if (variant->payload) { + current_field = variant->payload; + bt_get(current_field); + goto end; + } + +end: + return current_field; +} + struct bt_ctf_field *bt_ctf_field_enumeration_get_container( struct bt_ctf_field *field) { @@ -587,7 +748,7 @@ struct bt_ctf_field *bt_ctf_field_enumeration_get_container( } container = enumeration->payload; - bt_ctf_field_get(container); + bt_get(container); end: return container; } @@ -640,9 +801,9 @@ const char *bt_ctf_field_enumeration_get_mapping_name( } error_put_container_type: - bt_ctf_field_type_put(container_type); + bt_put(container_type); error_put_container: - bt_ctf_field_put(container); + bt_put(container); end: return name; } @@ -861,6 +1022,72 @@ end: return ret; } +int bt_ctf_field_string_append(struct bt_ctf_field *field, + const char *value) +{ + int ret = 0; + struct bt_ctf_field_string *string_field; + + if (!field || !value || + bt_ctf_field_type_get_type_id(field->type) != + CTF_TYPE_STRING) { + ret = -1; + goto end; + } + + string_field = container_of(field, struct bt_ctf_field_string, parent); + + if (string_field->payload) { + g_string_append(string_field->payload, value); + } else { + string_field->payload = g_string_new(value); + } + + string_field->parent.payload_set = 1; + +end: + return ret; +} + +int bt_ctf_field_string_append_len(struct bt_ctf_field *field, + const char *value, unsigned int length) +{ + int i; + int ret = 0; + unsigned int effective_length = length; + struct bt_ctf_field_string *string_field; + + if (!field || !value || + bt_ctf_field_type_get_type_id(field->type) != + CTF_TYPE_STRING) { + ret = -1; + goto end; + } + + string_field = container_of(field, struct bt_ctf_field_string, parent); + + /* make sure no null bytes are appended */ + for (i = 0; i < length; ++i) { + if (value[i] == '\0') { + effective_length = i; + break; + } + } + + if (string_field->payload) { + g_string_append_len(string_field->payload, value, + effective_length); + } else { + string_field->payload = g_string_new_len(value, + effective_length); + } + + string_field->parent.payload_set = 1; + +end: + return ret; +} + BT_HIDDEN int bt_ctf_field_validate(struct bt_ctf_field *field) { @@ -883,6 +1110,28 @@ end: return ret; } +BT_HIDDEN +int bt_ctf_field_reset(struct bt_ctf_field *field) +{ + int ret = 0; + enum ctf_type_id type_id; + + if (!field) { + ret = -1; + goto end; + } + + type_id = bt_ctf_field_type_get_type_id(field->type); + if (type_id <= CTF_TYPE_UNKNOWN || type_id >= NR_CTF_TYPES) { + ret = -1; + goto end; + } + + ret = field_reset_funcs[type_id](field); +end: + return ret; +} + BT_HIDDEN int bt_ctf_field_serialize(struct bt_ctf_field *field, struct ctf_stream_pos *pos) @@ -906,6 +1155,36 @@ end: return ret; } +struct bt_ctf_field *bt_ctf_field_copy(struct bt_ctf_field *field) +{ + int ret; + struct bt_ctf_field *copy = NULL; + enum ctf_type_id type_id; + + if (!field) { + goto end; + } + + type_id = bt_ctf_field_type_get_type_id(field->type); + if (type_id <= CTF_TYPE_UNKNOWN || type_id >= NR_CTF_TYPES) { + goto end; + } + + copy = bt_ctf_field_create(field->type); + if (!copy) { + goto end; + } + + copy->payload_set = field->payload_set; + ret = field_copy_funcs[type_id](field, copy); + if (ret) { + bt_put(copy); + copy = NULL; + } +end: + return copy; +} + static struct bt_ctf_field *bt_ctf_field_integer_create(struct bt_ctf_field_type *type) { @@ -978,7 +1257,7 @@ struct bt_ctf_field *bt_ctf_field_structure_create( struct bt_ctf_field_structure, 1); struct bt_ctf_field *field = NULL; - if (!structure || !structure_type->fields->len) { + if (!structure) { goto end; } @@ -1045,17 +1324,13 @@ struct bt_ctf_field *bt_ctf_field_string_create(struct bt_ctf_field_type *type) } static -void bt_ctf_field_destroy(struct bt_ctf_ref *ref) +void bt_ctf_field_destroy(struct bt_object *obj) { struct bt_ctf_field *field; struct bt_ctf_field_type *type; enum ctf_type_id type_id; - if (!ref) { - return; - } - - field = container_of(ref, struct bt_ctf_field, ref_count); + field = container_of(obj, struct bt_ctf_field, base); type = field->type; type_id = bt_ctf_field_type_get_type_id(type); if (type_id <= CTF_TYPE_UNKNOWN || @@ -1064,9 +1339,7 @@ void bt_ctf_field_destroy(struct bt_ctf_ref *ref) } field_destroy_funcs[type_id](field); - if (type) { - bt_ctf_field_type_put(type); - } + bt_put(type); } static @@ -1093,7 +1366,7 @@ void bt_ctf_field_enumeration_destroy(struct bt_ctf_field *field) enumeration = container_of(field, struct bt_ctf_field_enumeration, parent); - bt_ctf_field_put(enumeration->payload); + bt_put(enumeration->payload); g_free(enumeration); } @@ -1135,8 +1408,8 @@ void bt_ctf_field_variant_destroy(struct bt_ctf_field *field) } variant = container_of(field, struct bt_ctf_field_variant, parent); - bt_ctf_field_put(variant->tag); - bt_ctf_field_put(variant->payload); + bt_put(variant->tag); + bt_put(variant->payload); g_free(variant); } @@ -1164,8 +1437,10 @@ void bt_ctf_field_sequence_destroy(struct bt_ctf_field *field) } sequence = container_of(field, struct bt_ctf_field_sequence, parent); - g_ptr_array_free(sequence->elements, TRUE); - bt_ctf_field_put(sequence->length); + if (sequence->elements) { + g_ptr_array_free(sequence->elements, TRUE); + } + bt_put(sequence->length); g_free(sequence); } @@ -1178,7 +1453,9 @@ void bt_ctf_field_string_destroy(struct bt_ctf_field *field) } string = container_of(field, struct bt_ctf_field_string, parent); - g_string_free(string->payload, TRUE); + if (string->payload) { + g_string_free(string->payload, TRUE); + } g_free(string); } @@ -1297,6 +1574,185 @@ end: return ret; } +static +int bt_ctf_field_generic_reset(struct bt_ctf_field *field) +{ + int ret = 0; + + if (!field) { + ret = -1; + goto end; + } + + field->payload_set = 0; +end: + return ret; +} + +static +int bt_ctf_field_enumeration_reset(struct bt_ctf_field *field) +{ + int ret = 0; + struct bt_ctf_field_enumeration *enumeration; + + if (!field) { + ret = -1; + goto end; + } + + enumeration = container_of(field, struct bt_ctf_field_enumeration, + parent); + if (!enumeration->payload) { + goto end; + } + + ret = bt_ctf_field_reset(enumeration->payload); +end: + return ret; +} + +static +int bt_ctf_field_structure_reset(struct bt_ctf_field *field) +{ + size_t i; + int ret = 0; + struct bt_ctf_field_structure *structure; + + if (!field) { + ret = -1; + goto end; + } + + structure = container_of(field, struct bt_ctf_field_structure, parent); + for (i = 0; i < structure->fields->len; i++) { + struct bt_ctf_field *member = structure->fields->pdata[i]; + + if (!member) { + /* + * Structure members are lazily initialized; skip if + * this member has not been allocated yet. + */ + continue; + } + + ret = bt_ctf_field_reset(member); + if (ret) { + goto end; + } + } +end: + return ret; +} + +static +int bt_ctf_field_variant_reset(struct bt_ctf_field *field) +{ + int ret = 0; + struct bt_ctf_field_variant *variant; + + if (!field) { + ret = -1; + goto end; + } + + variant = container_of(field, struct bt_ctf_field_variant, parent); + if (variant->payload) { + ret = bt_ctf_field_reset(variant->payload); + } +end: + return ret; +} + +static +int bt_ctf_field_array_reset(struct bt_ctf_field *field) +{ + size_t i; + int ret = 0; + struct bt_ctf_field_array *array; + + if (!field) { + ret = -1; + goto end; + } + + array = container_of(field, struct bt_ctf_field_array, parent); + for (i = 0; i < array->elements->len; i++) { + struct bt_ctf_field *member = array->elements->pdata[i]; + + if (!member) { + /* + * Array elements are lazily initialized; skip if + * this member has not been allocated yet. + */ + continue; + } + + ret = bt_ctf_field_reset(member); + if (ret) { + goto end; + } + } +end: + return ret; +} + +static +int bt_ctf_field_sequence_reset(struct bt_ctf_field *field) +{ + size_t i; + int ret = 0; + struct bt_ctf_field_sequence *sequence; + + if (!field) { + ret = -1; + goto end; + } + + sequence = container_of(field, struct bt_ctf_field_sequence, parent); + for (i = 0; i < sequence->elements->len; i++) { + struct bt_ctf_field *member = sequence->elements->pdata[i]; + + if (!member) { + /* + * Sequence elements are lazily initialized; skip if + * this member has not been allocated yet. + */ + continue; + } + + ret = bt_ctf_field_reset(member); + if (ret) { + goto end; + } + } +end: + return ret; +} + +static +int bt_ctf_field_string_reset(struct bt_ctf_field *field) +{ + int ret = 0; + struct bt_ctf_field_string *string; + + if (!field) { + ret = -1; + goto end; + } + + ret = bt_ctf_field_generic_reset(field); + if (ret) { + goto end; + } + + string = container_of(field, struct bt_ctf_field_string, parent); + if (string->payload) { + g_string_truncate(string->payload, 0); + } +end: + return ret; +} + static int bt_ctf_field_integer_serialize(struct bt_ctf_field *field, struct ctf_stream_pos *pos) @@ -1468,8 +1924,237 @@ int bt_ctf_field_string_serialize(struct bt_ctf_field *field, } } end: - bt_ctf_field_put(character); - bt_ctf_field_type_put(character_type); + bt_put(character); + bt_put(character_type); + return ret; +} + +static +int bt_ctf_field_integer_copy(struct bt_ctf_field *src, + struct bt_ctf_field *dst) +{ + struct bt_ctf_field_integer *integer_src, *integer_dst; + + integer_src = container_of(src, struct bt_ctf_field_integer, parent); + integer_dst = container_of(dst, struct bt_ctf_field_integer, parent); + + memcpy(&integer_dst->definition, &integer_src->definition, + sizeof(struct definition_integer)); + return 0; +} + +static +int bt_ctf_field_enumeration_copy(struct bt_ctf_field *src, + struct bt_ctf_field *dst) +{ + int ret = 0; + struct bt_ctf_field_enumeration *enum_src, *enum_dst; + + enum_src = container_of(src, struct bt_ctf_field_enumeration, parent); + enum_dst = container_of(dst, struct bt_ctf_field_enumeration, parent); + + if (enum_src->payload) { + enum_dst->payload = bt_ctf_field_copy(enum_src->payload); + if (!enum_dst->payload) { + ret = -1; + goto end; + } + } +end: + return ret; +} + +static +int bt_ctf_field_floating_point_copy( + struct bt_ctf_field *src, struct bt_ctf_field *dst) +{ + struct bt_ctf_field_floating_point *float_src, *float_dst; + + float_src = container_of(src, struct bt_ctf_field_floating_point, + parent); + float_dst = container_of(dst, struct bt_ctf_field_floating_point, + parent); + + memcpy(&float_dst->definition, &float_src->definition, + sizeof(struct definition_float)); + memcpy(&float_dst->sign, &float_src->sign, + sizeof(struct definition_integer)); + memcpy(&float_dst->mantissa, &float_src->mantissa, + sizeof(struct definition_integer)); + memcpy(&float_dst->exp, &float_src->exp, + sizeof(struct definition_integer)); + return 0; +} + +static +int bt_ctf_field_structure_copy(struct bt_ctf_field *src, + struct bt_ctf_field *dst) +{ + int ret = 0, i; + struct bt_ctf_field_structure *struct_src, *struct_dst; + + struct_src = container_of(src, struct bt_ctf_field_structure, parent); + struct_dst = container_of(dst, struct bt_ctf_field_structure, parent); + + /* This field_name_to_index HT is owned by the structure field type */ + struct_dst->field_name_to_index = struct_src->field_name_to_index; + g_ptr_array_set_size(struct_dst->fields, struct_src->fields->len); + + for (i = 0; i < struct_src->fields->len; i++) { + struct bt_ctf_field *field = + g_ptr_array_index(struct_src->fields, i); + struct bt_ctf_field *field_copy = NULL; + + if (field) { + field_copy = bt_ctf_field_copy(field); + + if (!field_copy) { + ret = -1; + goto end; + } + } + + g_ptr_array_index(struct_dst->fields, i) = field_copy; + } +end: + return ret; +} + +static +int bt_ctf_field_variant_copy(struct bt_ctf_field *src, + struct bt_ctf_field *dst) +{ + int ret = 0; + struct bt_ctf_field_variant *variant_src, *variant_dst; + + variant_src = container_of(src, struct bt_ctf_field_variant, parent); + variant_dst = container_of(dst, struct bt_ctf_field_variant, parent); + + if (variant_src->tag) { + variant_dst->tag = bt_ctf_field_copy(variant_src->tag); + if (!variant_dst->tag) { + ret = -1; + goto end; + } + } + if (variant_src->payload) { + variant_dst->payload = bt_ctf_field_copy(variant_src->payload); + if (!variant_dst->payload) { + ret = -1; + goto end; + } + } +end: + return ret; +} + +static +int bt_ctf_field_array_copy(struct bt_ctf_field *src, + struct bt_ctf_field *dst) +{ + int ret = 0, i; + struct bt_ctf_field_array *array_src, *array_dst; + + array_src = container_of(src, struct bt_ctf_field_array, parent); + array_dst = container_of(dst, struct bt_ctf_field_array, parent); + + g_ptr_array_set_size(array_dst->elements, array_src->elements->len); + for (i = 0; i < array_src->elements->len; i++) { + struct bt_ctf_field *field = + g_ptr_array_index(array_src->elements, i); + struct bt_ctf_field *field_copy = NULL; + + if (field) { + field_copy = bt_ctf_field_copy(field); + + if (!field_copy) { + ret = -1; + goto end; + } + } + + g_ptr_array_index(array_dst->elements, i) = field_copy; + } +end: + return ret; +} + +static +int bt_ctf_field_sequence_copy(struct bt_ctf_field *src, + struct bt_ctf_field *dst) +{ + int ret = 0, i; + struct bt_ctf_field_sequence *sequence_src, *sequence_dst; + struct bt_ctf_field *src_length; + struct bt_ctf_field *dst_length; + + sequence_src = container_of(src, struct bt_ctf_field_sequence, parent); + sequence_dst = container_of(dst, struct bt_ctf_field_sequence, parent); + + src_length = bt_ctf_field_sequence_get_length(src); + + if (!src_length) { + /* no length set yet: keep destination sequence empty */ + goto end; + } + + /* copy source length */ + dst_length = bt_ctf_field_copy(src_length); + bt_put(src_length); + + if (!dst_length) { + ret = -1; + goto end; + } + + /* this will initialize the destination sequence's internal array */ + ret = bt_ctf_field_sequence_set_length(dst, dst_length); + bt_put(dst_length); + + if (ret) { + goto end; + } + + assert(sequence_dst->elements->len == sequence_src->elements->len); + + for (i = 0; i < sequence_src->elements->len; i++) { + struct bt_ctf_field *field = + g_ptr_array_index(sequence_src->elements, i); + struct bt_ctf_field *field_copy = NULL; + + if (field) { + field_copy = bt_ctf_field_copy(field); + + if (!field_copy) { + ret = -1; + goto end; + } + } + + g_ptr_array_index(sequence_dst->elements, i) = field_copy; + } +end: + return ret; +} + +static +int bt_ctf_field_string_copy(struct bt_ctf_field *src, + struct bt_ctf_field *dst) +{ + int ret = 0; + struct bt_ctf_field_string *string_src, *string_dst; + + string_src = container_of(src, struct bt_ctf_field_string, parent); + string_dst = container_of(dst, struct bt_ctf_field_string, parent); + + if (string_src->payload) { + string_dst->payload = g_string_new(string_src->payload->str); + if (!string_dst->payload) { + ret = -1; + goto end; + } + } +end: return ret; }