X-Git-Url: http://git.efficios.com/?p=babeltrace.git;a=blobdiff_plain;f=lib%2Fctf-ir%2Ffields.c;h=5c9ff0b667cd4ae7e482f0b983a042bf42134b19;hp=9c4297bcaa0f6052994c127428c2732b1f43cb18;hb=312c056ae3d374b253fa0cfe5ed576c0b0e5e569;hpb=d990a4fbda94b71e59a8865802c3172f0d141906 diff --git a/lib/ctf-ir/fields.c b/lib/ctf-ir/fields.c index 9c4297bc..5c9ff0b6 100644 --- a/lib/ctf-ir/fields.c +++ b/lib/ctf-ir/fields.c @@ -29,3153 +29,1213 @@ #define BT_LOG_TAG "FIELDS" #include +#include #include #include -#include #include #include #include #include #include +#include #include -static -struct bt_ctf_field *bt_ctf_field_integer_create(struct bt_ctf_field_type *); -static -struct bt_ctf_field *bt_ctf_field_enumeration_create( - struct bt_ctf_field_type *); -static -struct bt_ctf_field *bt_ctf_field_floating_point_create( - struct bt_ctf_field_type *); -static -struct bt_ctf_field *bt_ctf_field_structure_create( - struct bt_ctf_field_type *); -static -struct bt_ctf_field *bt_ctf_field_variant_create( - struct bt_ctf_field_type *); -static -struct bt_ctf_field *bt_ctf_field_array_create( - struct bt_ctf_field_type *); -static -struct bt_ctf_field *bt_ctf_field_sequence_create( - struct bt_ctf_field_type *); -static -struct bt_ctf_field *bt_ctf_field_string_create(struct bt_ctf_field_type *); +#define BT_ASSERT_PRE_FIELD_IS_INT_OR_ENUM(_field, _name) \ + BT_ASSERT_PRE((_field)->type->id == BT_FIELD_TYPE_ID_INTEGER || \ + (_field)->type->id == BT_FIELD_TYPE_ID_ENUM, \ + _name " is not an integer or an enumeration field: " \ + "%!+f", (_field)) + +static struct bt_field_common_methods bt_field_integer_methods = { + .set_is_frozen = bt_field_common_generic_set_is_frozen, + .validate = bt_field_common_generic_validate, + .copy = NULL, + .is_set = bt_field_common_generic_is_set, + .reset = bt_field_common_generic_reset, +}; -static -void bt_ctf_field_destroy(struct bt_object *); -static -void bt_ctf_field_integer_destroy(struct bt_ctf_field *); -static -void bt_ctf_field_enumeration_destroy(struct bt_ctf_field *); -static -void bt_ctf_field_floating_point_destroy(struct bt_ctf_field *); -static -void bt_ctf_field_structure_destroy(struct bt_ctf_field *); -static -void bt_ctf_field_variant_destroy(struct bt_ctf_field *); -static -void bt_ctf_field_array_destroy(struct bt_ctf_field *); -static -void bt_ctf_field_sequence_destroy(struct bt_ctf_field *); -static -void bt_ctf_field_string_destroy(struct bt_ctf_field *); +static struct bt_field_common_methods bt_field_floating_point_methods = { + .set_is_frozen = bt_field_common_generic_set_is_frozen, + .validate = bt_field_common_generic_validate, + .copy = NULL, + .is_set = bt_field_common_generic_is_set, + .reset = bt_field_common_generic_reset, +}; -static -int bt_ctf_field_generic_validate(struct bt_ctf_field *); -static -int bt_ctf_field_structure_validate(struct bt_ctf_field *); -static -int bt_ctf_field_variant_validate(struct bt_ctf_field *); -static -int bt_ctf_field_enumeration_validate(struct bt_ctf_field *); -static -int bt_ctf_field_array_validate(struct bt_ctf_field *); -static -int bt_ctf_field_sequence_validate(struct bt_ctf_field *); +static struct bt_field_common_methods bt_field_enumeration_methods = { + .set_is_frozen = bt_field_common_generic_set_is_frozen, + .validate = bt_field_common_generic_validate, + .copy = NULL, + .is_set = bt_field_common_generic_is_set, + .reset = bt_field_common_generic_reset, +}; -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 struct bt_field_common_methods bt_field_string_methods = { + .set_is_frozen = bt_field_common_generic_set_is_frozen, + .validate = bt_field_common_generic_validate, + .copy = NULL, + .is_set = bt_field_common_generic_is_set, + .reset = bt_field_common_string_reset, +}; -static -int bt_ctf_field_integer_serialize(struct bt_ctf_field *, - struct bt_ctf_stream_pos *, enum bt_ctf_byte_order); -static -int bt_ctf_field_enumeration_serialize(struct bt_ctf_field *, - struct bt_ctf_stream_pos *, enum bt_ctf_byte_order); -static -int bt_ctf_field_floating_point_serialize(struct bt_ctf_field *, - struct bt_ctf_stream_pos *, enum bt_ctf_byte_order); -static -int bt_ctf_field_structure_serialize(struct bt_ctf_field *, - struct bt_ctf_stream_pos *, enum bt_ctf_byte_order); -static -int bt_ctf_field_variant_serialize(struct bt_ctf_field *, - struct bt_ctf_stream_pos *, enum bt_ctf_byte_order); -static -int bt_ctf_field_array_serialize(struct bt_ctf_field *, - struct bt_ctf_stream_pos *, enum bt_ctf_byte_order); -static -int bt_ctf_field_sequence_serialize(struct bt_ctf_field *, - struct bt_ctf_stream_pos *, enum bt_ctf_byte_order); -static -int bt_ctf_field_string_serialize(struct bt_ctf_field *, - struct bt_ctf_stream_pos *, enum bt_ctf_byte_order); +static struct bt_field_common_methods bt_field_structure_methods = { + .set_is_frozen = bt_field_common_structure_set_is_frozen_recursive, + .validate = bt_field_common_structure_validate_recursive, + .copy = NULL, + .is_set = bt_field_common_structure_is_set_recursive, + .reset = bt_field_common_structure_reset_recursive, +}; -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 struct bt_field_common_methods bt_field_sequence_methods = { + .set_is_frozen = bt_field_common_sequence_set_is_frozen_recursive, + .validate = bt_field_common_sequence_validate_recursive, + .copy = NULL, + .is_set = bt_field_common_sequence_is_set_recursive, + .reset = bt_field_common_sequence_reset_recursive, +}; + +static struct bt_field_common_methods bt_field_array_methods = { + .set_is_frozen = bt_field_common_array_set_is_frozen_recursive, + .validate = bt_field_common_array_validate_recursive, + .copy = NULL, + .is_set = bt_field_common_array_is_set_recursive, + .reset = bt_field_common_array_reset_recursive, +}; + +static struct bt_field_common_methods bt_field_variant_methods = { + .set_is_frozen = bt_field_common_variant_set_is_frozen_recursive, + .validate = bt_field_common_variant_validate_recursive, + .copy = NULL, + .is_set = bt_field_common_variant_is_set_recursive, + .reset = bt_field_common_variant_reset_recursive, +}; static -void generic_field_freeze(struct bt_ctf_field *); -static -void bt_ctf_field_enumeration_freeze(struct bt_ctf_field *); -static -void bt_ctf_field_structure_freeze(struct bt_ctf_field *); -static -void bt_ctf_field_variant_freeze(struct bt_ctf_field *); +struct bt_field *bt_field_integer_create(struct bt_field_type *); + static -void bt_ctf_field_array_freeze(struct bt_ctf_field *); +struct bt_field *bt_field_enumeration_create(struct bt_field_type *); + static -void bt_ctf_field_sequence_freeze(struct bt_ctf_field *); +struct bt_field *bt_field_floating_point_create(struct bt_field_type *); static -bt_bool bt_ctf_field_generic_is_set(struct bt_ctf_field *); +struct bt_field *bt_field_structure_create(struct bt_field_type *); + static -bt_bool bt_ctf_field_structure_is_set(struct bt_ctf_field *); +struct bt_field *bt_field_variant_create(struct bt_field_type *); + static -bt_bool bt_ctf_field_variant_is_set(struct bt_ctf_field *); +struct bt_field *bt_field_array_create(struct bt_field_type *); + static -bt_bool bt_ctf_field_enumeration_is_set(struct bt_ctf_field *); +struct bt_field *bt_field_sequence_create(struct bt_field_type *); + static -bt_bool bt_ctf_field_array_is_set(struct bt_ctf_field *); +struct bt_field *bt_field_string_create(struct bt_field_type *); + static -bt_bool bt_ctf_field_sequence_is_set(struct bt_ctf_field *); +struct bt_field *(* const field_create_funcs[])(struct bt_field_type *) = { + [BT_FIELD_TYPE_ID_INTEGER] = bt_field_integer_create, + [BT_FIELD_TYPE_ID_ENUM] = bt_field_enumeration_create, + [BT_FIELD_TYPE_ID_FLOAT] = bt_field_floating_point_create, + [BT_FIELD_TYPE_ID_STRUCT] = bt_field_structure_create, + [BT_FIELD_TYPE_ID_VARIANT] = bt_field_variant_create, + [BT_FIELD_TYPE_ID_ARRAY] = bt_field_array_create, + [BT_FIELD_TYPE_ID_SEQUENCE] = bt_field_sequence_create, + [BT_FIELD_TYPE_ID_STRING] = bt_field_string_create, +}; static -int increase_packet_size(struct bt_ctf_stream_pos *pos); +void bt_field_integer_destroy(struct bt_field *field); static -struct bt_ctf_field *(* const field_create_funcs[])( - struct bt_ctf_field_type *) = { - [BT_CTF_FIELD_TYPE_ID_INTEGER] = bt_ctf_field_integer_create, - [BT_CTF_FIELD_TYPE_ID_ENUM] = bt_ctf_field_enumeration_create, - [BT_CTF_FIELD_TYPE_ID_FLOAT] = - bt_ctf_field_floating_point_create, - [BT_CTF_FIELD_TYPE_ID_STRUCT] = bt_ctf_field_structure_create, - [BT_CTF_FIELD_TYPE_ID_VARIANT] = bt_ctf_field_variant_create, - [BT_CTF_FIELD_TYPE_ID_ARRAY] = bt_ctf_field_array_create, - [BT_CTF_FIELD_TYPE_ID_SEQUENCE] = bt_ctf_field_sequence_create, - [BT_CTF_FIELD_TYPE_ID_STRING] = bt_ctf_field_string_create, -}; +void bt_field_enumeration_destroy(struct bt_field *field); static -void (* const field_destroy_funcs[])(struct bt_ctf_field *) = { - [BT_CTF_FIELD_TYPE_ID_INTEGER] = bt_ctf_field_integer_destroy, - [BT_CTF_FIELD_TYPE_ID_ENUM] = bt_ctf_field_enumeration_destroy, - [BT_CTF_FIELD_TYPE_ID_FLOAT] = - bt_ctf_field_floating_point_destroy, - [BT_CTF_FIELD_TYPE_ID_STRUCT] = bt_ctf_field_structure_destroy, - [BT_CTF_FIELD_TYPE_ID_VARIANT] = bt_ctf_field_variant_destroy, - [BT_CTF_FIELD_TYPE_ID_ARRAY] = bt_ctf_field_array_destroy, - [BT_CTF_FIELD_TYPE_ID_SEQUENCE] = bt_ctf_field_sequence_destroy, - [BT_CTF_FIELD_TYPE_ID_STRING] = bt_ctf_field_string_destroy, -}; +void bt_field_floating_point_destroy(struct bt_field *field); static -int (* const field_validate_funcs[])(struct bt_ctf_field *) = { - [BT_CTF_FIELD_TYPE_ID_INTEGER] = bt_ctf_field_generic_validate, - [BT_CTF_FIELD_TYPE_ID_ENUM] = bt_ctf_field_enumeration_validate, - [BT_CTF_FIELD_TYPE_ID_FLOAT] = bt_ctf_field_generic_validate, - [BT_CTF_FIELD_TYPE_ID_STRUCT] = bt_ctf_field_structure_validate, - [BT_CTF_FIELD_TYPE_ID_VARIANT] = bt_ctf_field_variant_validate, - [BT_CTF_FIELD_TYPE_ID_ARRAY] = bt_ctf_field_array_validate, - [BT_CTF_FIELD_TYPE_ID_SEQUENCE] = bt_ctf_field_sequence_validate, - [BT_CTF_FIELD_TYPE_ID_STRING] = bt_ctf_field_generic_validate, -}; +void bt_field_structure_destroy_recursive(struct bt_field *field); static -int (* const field_reset_funcs[])(struct bt_ctf_field *) = { - [BT_CTF_FIELD_TYPE_ID_INTEGER] = bt_ctf_field_generic_reset, - [BT_CTF_FIELD_TYPE_ID_ENUM] = bt_ctf_field_enumeration_reset, - [BT_CTF_FIELD_TYPE_ID_FLOAT] = bt_ctf_field_generic_reset, - [BT_CTF_FIELD_TYPE_ID_STRUCT] = bt_ctf_field_structure_reset, - [BT_CTF_FIELD_TYPE_ID_VARIANT] = bt_ctf_field_variant_reset, - [BT_CTF_FIELD_TYPE_ID_ARRAY] = bt_ctf_field_array_reset, - [BT_CTF_FIELD_TYPE_ID_SEQUENCE] = bt_ctf_field_sequence_reset, - [BT_CTF_FIELD_TYPE_ID_STRING] = bt_ctf_field_string_reset, -}; +void bt_field_variant_destroy_recursive(struct bt_field *field); static -int (* const field_serialize_funcs[])(struct bt_ctf_field *, - struct bt_ctf_stream_pos *, enum bt_ctf_byte_order) = { - [BT_CTF_FIELD_TYPE_ID_INTEGER] = bt_ctf_field_integer_serialize, - [BT_CTF_FIELD_TYPE_ID_ENUM] = bt_ctf_field_enumeration_serialize, - [BT_CTF_FIELD_TYPE_ID_FLOAT] = - bt_ctf_field_floating_point_serialize, - [BT_CTF_FIELD_TYPE_ID_STRUCT] = bt_ctf_field_structure_serialize, - [BT_CTF_FIELD_TYPE_ID_VARIANT] = bt_ctf_field_variant_serialize, - [BT_CTF_FIELD_TYPE_ID_ARRAY] = bt_ctf_field_array_serialize, - [BT_CTF_FIELD_TYPE_ID_SEQUENCE] = bt_ctf_field_sequence_serialize, - [BT_CTF_FIELD_TYPE_ID_STRING] = bt_ctf_field_string_serialize, -}; +void bt_field_array_destroy_recursive(struct bt_field *field); static -int (* const field_copy_funcs[])(struct bt_ctf_field *, - struct bt_ctf_field *) = { - [BT_CTF_FIELD_TYPE_ID_INTEGER] = bt_ctf_field_integer_copy, - [BT_CTF_FIELD_TYPE_ID_ENUM] = bt_ctf_field_enumeration_copy, - [BT_CTF_FIELD_TYPE_ID_FLOAT] = bt_ctf_field_floating_point_copy, - [BT_CTF_FIELD_TYPE_ID_STRUCT] = bt_ctf_field_structure_copy, - [BT_CTF_FIELD_TYPE_ID_VARIANT] = bt_ctf_field_variant_copy, - [BT_CTF_FIELD_TYPE_ID_ARRAY] = bt_ctf_field_array_copy, - [BT_CTF_FIELD_TYPE_ID_SEQUENCE] = bt_ctf_field_sequence_copy, - [BT_CTF_FIELD_TYPE_ID_STRING] = bt_ctf_field_string_copy, -}; +void bt_field_sequence_destroy_recursive(struct bt_field *field); static -void (* const field_freeze_funcs[])(struct bt_ctf_field *) = { - [BT_CTF_FIELD_TYPE_ID_INTEGER] = generic_field_freeze, - [BT_CTF_FIELD_TYPE_ID_FLOAT] = generic_field_freeze, - [BT_CTF_FIELD_TYPE_ID_STRING] = generic_field_freeze, - [BT_CTF_FIELD_TYPE_ID_ENUM] = bt_ctf_field_enumeration_freeze, - [BT_CTF_FIELD_TYPE_ID_STRUCT] = bt_ctf_field_structure_freeze, - [BT_CTF_FIELD_TYPE_ID_VARIANT] = bt_ctf_field_variant_freeze, - [BT_CTF_FIELD_TYPE_ID_ARRAY] = bt_ctf_field_array_freeze, - [BT_CTF_FIELD_TYPE_ID_SEQUENCE] = bt_ctf_field_sequence_freeze, -}; +void bt_field_string_destroy(struct bt_field *field); static -bt_bool (* const field_is_set_funcs[])(struct bt_ctf_field *) = { - [BT_CTF_FIELD_TYPE_ID_INTEGER] = bt_ctf_field_generic_is_set, - [BT_CTF_FIELD_TYPE_ID_ENUM] = bt_ctf_field_enumeration_is_set, - [BT_CTF_FIELD_TYPE_ID_FLOAT] = bt_ctf_field_generic_is_set, - [BT_CTF_FIELD_TYPE_ID_STRUCT] = bt_ctf_field_structure_is_set, - [BT_CTF_FIELD_TYPE_ID_VARIANT] = bt_ctf_field_variant_is_set, - [BT_CTF_FIELD_TYPE_ID_ARRAY] = bt_ctf_field_array_is_set, - [BT_CTF_FIELD_TYPE_ID_SEQUENCE] = bt_ctf_field_sequence_is_set, - [BT_CTF_FIELD_TYPE_ID_STRING] = bt_ctf_field_generic_is_set, +void (* const field_destroy_funcs[])(struct bt_field *) = { + [BT_FIELD_TYPE_ID_INTEGER] = bt_field_integer_destroy, + [BT_FIELD_TYPE_ID_ENUM] = bt_field_enumeration_destroy, + [BT_FIELD_TYPE_ID_FLOAT] = bt_field_floating_point_destroy, + [BT_FIELD_TYPE_ID_STRUCT] = bt_field_structure_destroy_recursive, + [BT_FIELD_TYPE_ID_VARIANT] = bt_field_variant_destroy_recursive, + [BT_FIELD_TYPE_ID_ARRAY] = bt_field_array_destroy_recursive, + [BT_FIELD_TYPE_ID_SEQUENCE] = bt_field_sequence_destroy_recursive, + [BT_FIELD_TYPE_ID_STRING] = bt_field_string_destroy, }; -struct bt_ctf_field *bt_ctf_field_create(struct bt_ctf_field_type *type) +BT_HIDDEN +struct bt_field *bt_field_create_recursive(struct bt_field_type *type) { - struct bt_ctf_field *field = NULL; - enum bt_ctf_field_type_id type_id; - int ret; - - if (!type) { - BT_LOGW_STR("Invalid parameter: field type is NULL."); - goto error; - } - - type_id = bt_ctf_field_type_get_type_id(type); - if (type_id <= BT_CTF_FIELD_TYPE_ID_UNKNOWN || - type_id >= BT_CTF_NR_TYPE_IDS) { - BT_LOGW("Invalid parameter: unknown field type ID: " - "ft-addr=%p, ft-id=%d", type, type_id); - goto error; - } - - /* Field class MUST be valid */ - ret = bt_ctf_field_type_validate(type); - if (ret) { - /* Invalid */ - BT_LOGW("Invalid parameter: field type is invalid: " - "ft-addr=%p", type); - goto error; - } + struct bt_field *field = NULL; + enum bt_field_type_id type_id; + BT_ASSERT_PRE_NON_NULL(type, "Field type"); + BT_ASSERT(field_type_common_has_known_id((void *) type)); + BT_ASSERT_PRE(bt_field_type_common_validate((void *) type) == 0, + "Field type is invalid: %!+F", type); + type_id = bt_field_type_get_type_id(type); field = field_create_funcs[type_id](type); if (!field) { - goto error; + goto end; } - /* The type's declaration can't change after this point */ - bt_ctf_field_type_freeze(type); - bt_get(type); - bt_object_init(field, bt_ctf_field_destroy); - field->type = type; -error: + bt_object_set_is_shared((void *) field, false); + bt_field_type_freeze(type); + +end: return field; } -/* Pre-2.0 CTF writer backward compatibility */ -void bt_ctf_field_get(struct bt_ctf_field *field) +struct bt_field_type *bt_field_borrow_type(struct bt_field *field) { - bt_get(field); + return (void *) bt_field_common_borrow_type((void *) field); } -/* Pre-2.0 CTF writer backward compatibility */ -void bt_ctf_field_put(struct bt_ctf_field *field) +enum bt_field_type_id bt_field_get_type_id(struct bt_field *field) { - bt_put(field); + struct bt_field_common *field_common = (void *) field; + + BT_ASSERT_PRE_NON_NULL(field, "Field"); + return field_common->type->id; } -struct bt_ctf_field_type *bt_ctf_field_get_type(struct bt_ctf_field *field) +bt_bool bt_field_is_integer(struct bt_field *field) { - struct bt_ctf_field_type *ret = NULL; - - if (!field) { - BT_LOGW_STR("Invalid parameter: field is NULL."); - goto end; - } - - ret = field->type; - bt_get(ret); -end: - return ret; + return bt_field_get_type_id(field) == BT_FIELD_TYPE_ID_INTEGER; } -enum bt_ctf_field_type_id bt_ctf_field_get_type_id(struct bt_ctf_field *field) +bt_bool bt_field_is_floating_point(struct bt_field *field) { - enum bt_ctf_field_type_id ret = BT_CTF_FIELD_TYPE_ID_UNKNOWN; - - if (!field) { - BT_LOGW_STR("Invalid parameter: field is NULL."); - goto end; - } - - ret = bt_ctf_field_type_get_type_id(field->type); -end: - return ret; + return bt_field_get_type_id(field) == BT_FIELD_TYPE_ID_FLOAT; } -bt_bool bt_ctf_field_is_integer(struct bt_ctf_field *field) +bt_bool bt_field_is_enumeration(struct bt_field *field) { - return bt_ctf_field_get_type_id(field) == BT_CTF_FIELD_TYPE_ID_INTEGER; + return bt_field_get_type_id(field) == BT_FIELD_TYPE_ID_ENUM; } -bt_bool bt_ctf_field_is_floating_point(struct bt_ctf_field *field) +bt_bool bt_field_is_string(struct bt_field *field) { - return bt_ctf_field_get_type_id(field) == BT_CTF_FIELD_TYPE_ID_FLOAT; + return bt_field_get_type_id(field) == BT_FIELD_TYPE_ID_STRING; } -bt_bool bt_ctf_field_is_enumeration(struct bt_ctf_field *field) +bt_bool bt_field_is_structure(struct bt_field *field) { - return bt_ctf_field_get_type_id(field) == BT_CTF_FIELD_TYPE_ID_ENUM; + return bt_field_get_type_id(field) == BT_FIELD_TYPE_ID_STRUCT; } -bt_bool bt_ctf_field_is_string(struct bt_ctf_field *field) +bt_bool bt_field_is_array(struct bt_field *field) { - return bt_ctf_field_get_type_id(field) == BT_CTF_FIELD_TYPE_ID_STRING; + return bt_field_get_type_id(field) == BT_FIELD_TYPE_ID_ARRAY; } -bt_bool bt_ctf_field_is_structure(struct bt_ctf_field *field) +bt_bool bt_field_is_sequence(struct bt_field *field) { - return bt_ctf_field_get_type_id(field) == BT_CTF_FIELD_TYPE_ID_STRUCT; + return bt_field_get_type_id(field) == BT_FIELD_TYPE_ID_SEQUENCE; } -bt_bool bt_ctf_field_is_array(struct bt_ctf_field *field) +bt_bool bt_field_is_variant(struct bt_field *field) { - return bt_ctf_field_get_type_id(field) == BT_CTF_FIELD_TYPE_ID_ARRAY; + return bt_field_get_type_id(field) == BT_FIELD_TYPE_ID_VARIANT; } -bt_bool bt_ctf_field_is_sequence(struct bt_ctf_field *field) +int64_t bt_field_sequence_get_length(struct bt_field *field) { - return bt_ctf_field_get_type_id(field) == BT_CTF_FIELD_TYPE_ID_SEQUENCE; + return bt_field_common_sequence_get_length((void *) field); } -bt_bool bt_ctf_field_is_variant(struct bt_ctf_field *field) +int bt_field_sequence_set_length(struct bt_field *field, uint64_t length) { - return bt_ctf_field_get_type_id(field) == BT_CTF_FIELD_TYPE_ID_VARIANT; + return bt_field_common_sequence_set_length((void *) field, + length, (bt_field_common_create_func) bt_field_create_recursive); } -struct bt_ctf_field *bt_ctf_field_sequence_get_length( - struct bt_ctf_field *field) +struct bt_field *bt_field_structure_borrow_field_by_index( + struct bt_field *field, uint64_t index) { - struct bt_ctf_field *ret = NULL; - struct bt_ctf_field_sequence *sequence; - - if (!field) { - BT_LOGW_STR("Invalid parameter: field is NULL."); - goto end; - } - - if (bt_ctf_field_type_get_type_id(field->type) != - BT_CTF_FIELD_TYPE_ID_SEQUENCE) { - BT_LOGW("Invalid parameter: field's type is not a sequence field type: " - "field-addr=%p, ft-addr=%p, ft-id=%s", field, - field->type, - bt_ctf_field_type_id_string(field->type->id)); - goto end; - } - - sequence = container_of(field, struct bt_ctf_field_sequence, parent); - ret = sequence->length; - bt_get(ret); -end: - return ret; + return (void *) bt_field_common_structure_borrow_field_by_index( + (void *) field, index); } -int bt_ctf_field_sequence_set_length(struct bt_ctf_field *field, - struct bt_ctf_field *length_field) +struct bt_field *bt_field_structure_borrow_field_by_name( + struct bt_field *field, const char *name) { - int ret = 0; - struct bt_ctf_field_type_integer *length_type; - struct bt_ctf_field_integer *length; - struct bt_ctf_field_sequence *sequence; - uint64_t sequence_length; - - if (!field) { - BT_LOGW_STR("Invalid parameter: field is NULL."); - ret = -1; - goto end; - } - - if (!length_field) { - BT_LOGW_STR("Invalid parameter: length field is NULL."); - ret = -1; - goto end; - } - - if (field->frozen) { - BT_LOGW("Invalid parameter: field is frozen: addr=%p", - field); - ret = -1; - goto end; - } - - if (bt_ctf_field_type_get_type_id(length_field->type) != - BT_CTF_FIELD_TYPE_ID_INTEGER) { - BT_LOGW("Invalid parameter: length field's type is not an integer field type: " - "field-addr=%p, length-field-addr=%p, length-ft-addr=%p, length-ft-id=%s", - field, length_field, length_field->type, - bt_ctf_field_type_id_string(length_field->type->id)); - ret = -1; - goto end; - } - - length_type = container_of(length_field->type, - struct bt_ctf_field_type_integer, parent); - /* The length field must be unsigned */ - if (length_type->is_signed) { - BT_LOGW("Invalid parameter: length field's type is signed: " - "field-addr=%p, length-field-addr=%p, " - "length-field-ft-addr=%p", field, length_field, - length_field->type); - ret = -1; - goto end; - } - - length = container_of(length_field, struct bt_ctf_field_integer, - parent); - sequence_length = length->payload.unsignd; - sequence = container_of(field, struct bt_ctf_field_sequence, parent); - if (sequence->elements) { - g_ptr_array_free(sequence->elements, TRUE); - bt_put(sequence->length); - } - - sequence->elements = g_ptr_array_sized_new((size_t)sequence_length); - if (!sequence->elements) { - BT_LOGE_STR("Failed to allocate a GPtrArray."); - ret = -1; - goto end; - } - - g_ptr_array_set_free_func(sequence->elements, - (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; + return (void *) bt_field_common_structure_borrow_field_by_name( + (void *) field, name); } -struct bt_ctf_field *bt_ctf_field_structure_get_field_by_name( - struct bt_ctf_field *field, const char *name) +struct bt_field *bt_field_array_borrow_field( + struct bt_field *field, uint64_t index) { - struct bt_ctf_field *new_field = NULL; - GQuark field_quark; - struct bt_ctf_field_structure *structure; - struct bt_ctf_field_type *field_type = NULL; - size_t index; - - if (!field) { - BT_LOGW_STR("Invalid parameter: field is NULL."); - goto error; - } - - if (!name) { - BT_LOGW_STR("Invalid parameter: field name is NULL."); - goto error; - } - - if (bt_ctf_field_type_get_type_id(field->type) != - BT_CTF_FIELD_TYPE_ID_STRUCT) { - BT_LOGW("Invalid parameter: field's type is not a structure field type: " - "field-addr=%p, ft-addr=%p, ft-id=%s", field, - field->type, - bt_ctf_field_type_id_string(field->type->id)); - goto error; - } + return (void *) bt_field_common_array_borrow_field((void *) field, + index); +} - field_quark = g_quark_from_string(name); - structure = container_of(field, struct bt_ctf_field_structure, parent); - field_type = - bt_ctf_field_type_structure_get_field_type_by_name(field->type, - name); - if (!g_hash_table_lookup_extended(structure->field_name_to_index, - GUINT_TO_POINTER(field_quark), - NULL, (gpointer *)&index)) { - BT_LOGV("Invalid parameter: no such field in structure field's type: " - "struct-field-addr=%p, struct-ft-addr=%p, " - "field-ft-addr=%p, name=\"%s\"", - field, field->type, field_type, name); - goto error; - } +struct bt_field *bt_field_sequence_borrow_field( + struct bt_field *field, uint64_t index) +{ + return (void *) bt_field_common_sequence_borrow_field((void *) field, + index); +} - if (structure->fields->pdata[index]) { - new_field = structure->fields->pdata[index]; - goto end; - } +struct bt_field *bt_field_variant_borrow_current_field( + struct bt_field *variant_field) +{ + return (void *) bt_field_common_variant_borrow_current_field( + (void *) variant_field); +} - /* We don't want to modify this field if it's frozen */ - if (field->frozen) { - /* - * Not logging a warning here because the user could - * legitimately check if a structure field is set with - * this function: if the preconditions are satisfied, - * a NULL return value means this. - */ - BT_LOGV("Not creating a field because structure field is frozen: " - "struct-field-addr=%p, name=\"%s\"", field, name); - goto end; - } +int bt_field_variant_set_tag_signed(struct bt_field *variant_field, + int64_t tag) +{ + return bt_field_variant_common_set_tag((void *) variant_field, + (uint64_t) tag, true); +} - new_field = bt_ctf_field_create(field_type); - if (!new_field) { - BT_LOGW("Cannot create field: " - "struct-field-addr=%p, struct-ft-addr=%p, " - "field-ft-addr=%p, name=\"%s\"", - field, field->type, field_type, name); - goto error; - } +int bt_field_variant_set_tag_unsigned(struct bt_field *variant_field, + uint64_t tag) +{ + return bt_field_variant_common_set_tag((void *) variant_field, + (uint64_t) tag, false); +} - structure->fields->pdata[index] = new_field; -end: - bt_get(new_field); -error: - if (field_type) { - bt_put(field_type); - } - return new_field; +int bt_field_variant_get_tag_signed(struct bt_field *variant_field, + int64_t *tag) +{ + return bt_field_common_variant_get_tag_signed((void *) variant_field, tag); } -struct bt_ctf_field *bt_ctf_field_structure_get_field_by_index( - struct bt_ctf_field *field, uint64_t index) +int bt_field_variant_get_tag_unsigned(struct bt_field *variant_field, + uint64_t *tag) { - int ret; - const char *field_name; - struct bt_ctf_field_structure *structure; - struct bt_ctf_field_type *structure_type; - struct bt_ctf_field_type *field_type = NULL; - struct bt_ctf_field *ret_field = NULL; + return bt_field_common_variant_get_tag_unsigned((void *) variant_field, tag); +} - if (!field) { - BT_LOGW_STR("Invalid parameter: field is NULL."); - goto end; - } +struct bt_field_type_enumeration_mapping_iterator * +bt_field_enumeration_get_mappings(struct bt_field *field) +{ + struct bt_field_enumeration *enum_field = (void *) field; - if (bt_ctf_field_type_get_type_id(field->type) != - BT_CTF_FIELD_TYPE_ID_STRUCT) { - BT_LOGW("Invalid parameter: field's type is not a structure field type: " - "field-addr=%p, ft-addr=%p, ft-id=%s", field, - field->type, - bt_ctf_field_type_id_string(field->type->id)); - goto end; - } + BT_ASSERT_PRE_NON_NULL(field, "Enumeration field"); + BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID((struct bt_field_common *) field, + BT_FIELD_TYPE_ID_ENUM, "Field"); + BT_ASSERT_PRE_FIELD_COMMON_IS_SET((struct bt_field_common *) field, + "Enumeration field"); + return bt_field_common_enumeration_get_mappings((void *) field, + (bt_field_common_create_func) bt_field_create_recursive, + enum_field->common.payload.unsignd); +} - structure = container_of(field, struct bt_ctf_field_structure, parent); - if (index >= structure->fields->len) { - BT_LOGW("Invalid parameter: index is out of bounds: " - "addr=%p, index=%" PRIu64 ", count=%u", - field, index, structure->fields->len); - goto error; - } +BT_ASSERT_PRE_FUNC +static inline +struct bt_field_type_common_integer *get_int_enum_int_ft( + struct bt_field *field) +{ + struct bt_field_common_integer *int_field = (void *) field; + struct bt_field_type_common_integer *int_ft = NULL; - ret_field = structure->fields->pdata[index]; - if (ret_field) { - goto end; + if (int_field->common.type->id == BT_FIELD_TYPE_ID_INTEGER) { + int_ft = BT_FROM_COMMON(int_field->common.type); + } else if (int_field->common.type->id == BT_FIELD_TYPE_ID_ENUM) { + struct bt_field_type_common_enumeration *enum_ft = + BT_FROM_COMMON(int_field->common.type); + int_ft = enum_ft->container_ft; } - /* We don't want to modify this field if it's frozen */ - if (field->frozen) { - /* - * Not logging a warning here because the user could - * legitimately check if a structure field is set with - * this function: if the preconditions are satisfied, - * a NULL return value means this. - */ - BT_LOGV("Not creating a field because structure field is frozen: " - "struct-field-addr=%p, index=%" PRIu64, field, index); - goto end; - } + BT_ASSERT(int_ft); + return int_ft; +} - /* Field has not been instanciated yet, create it */ - structure_type = bt_ctf_field_get_type(field); - assert(structure_type); - ret = bt_ctf_field_type_structure_get_field(structure_type, - &field_name, &field_type, index); - assert(ret == 0); - bt_put(structure_type); - ret_field = bt_ctf_field_create(field_type); - if (!ret_field) { - BT_LOGW("Cannot create field: " - "struct-field-addr=%p, struct-ft-addr=%p, " - "field-ft-addr=%p, index=%" PRIu64, - field, field->type, field_type, index); - goto error; - } +int bt_field_integer_signed_get_value(struct bt_field *field, int64_t *value) +{ + struct bt_field_common_integer *integer = (void *) field; - structure->fields->pdata[index] = ret_field; -end: - bt_get(ret_field); -error: - bt_put(field_type); - return ret_field; + BT_ASSERT_PRE_NON_NULL(field, "Integer/enumeration field"); + BT_ASSERT_PRE_NON_NULL(value, "Value"); + BT_ASSERT_PRE_FIELD_COMMON_IS_SET(BT_TO_COMMON(integer), + "Integer/enumeration field"); + BT_ASSERT_PRE_FIELD_IS_INT_OR_ENUM(BT_TO_COMMON(integer), "Field"); + BT_ASSERT_PRE(bt_field_type_common_integer_is_signed( + BT_TO_COMMON(get_int_enum_int_ft(field))), + "Field's type is unsigned: %!+f", field); + *value = integer->payload.signd; + return 0; } -int bt_ctf_field_structure_set_field_by_name(struct bt_ctf_field *field, - const char *name, struct bt_ctf_field *value) +int bt_field_integer_signed_set_value(struct bt_field *field, int64_t value) { int ret = 0; - GQuark field_quark; - struct bt_ctf_field_structure *structure; - struct bt_ctf_field_type *expected_field_type = NULL; - size_t index; - - if (!field) { - BT_LOGW_STR("Invalid parameter: structure field is NULL."); - ret = -1; - goto end; - } + struct bt_field_common_integer *integer = (void *) field; + + BT_ASSERT_PRE_NON_NULL(field, "Integer field"); + BT_ASSERT_PRE_FIELD_COMMON_HOT(BT_TO_COMMON(integer), "Integer field"); + BT_ASSERT_PRE_FIELD_IS_INT_OR_ENUM(BT_TO_COMMON(integer), "Field"); + BT_ASSERT_PRE(bt_field_type_common_integer_is_signed( + BT_FROM_COMMON(get_int_enum_int_ft(field))), + "Field's type is unsigned: %!+f", field); + BT_ASSERT_PRE(value_is_in_range_signed( + get_int_enum_int_ft(field)->size, value), + "Value is out of bounds: value=%" PRId64 ", %![field-]+f", + value, field); + integer->payload.signd = value; + bt_field_set(field, true); + return ret; +} - if (!name) { - BT_LOGW_STR("Invalid parameter: field name is NULL."); - ret = -1; - goto end; - } +int bt_field_integer_unsigned_get_value(struct bt_field *field, uint64_t *value) +{ + struct bt_field_common_integer *integer = (void *) field; - if (!value) { - BT_LOGW_STR("Invalid parameter: field is NULL."); - ret = -1; - goto end; - } + BT_ASSERT_PRE_NON_NULL(field, "Integer field"); + BT_ASSERT_PRE_NON_NULL(value, "Value"); + BT_ASSERT_PRE_FIELD_COMMON_IS_SET(BT_TO_COMMON(integer), "Integer field"); + BT_ASSERT_PRE_FIELD_IS_INT_OR_ENUM(BT_TO_COMMON(integer), "Field"); + BT_ASSERT_PRE(!bt_field_type_common_integer_is_signed( + BT_FROM_COMMON(get_int_enum_int_ft(field))), + "Field's type is signed: %!+f", field); + *value = integer->payload.unsignd; + return 0; +} - if (bt_ctf_field_type_get_type_id(field->type) != - BT_CTF_FIELD_TYPE_ID_STRUCT) { - BT_LOGW("Invalid parameter: field's type is not a structure field type: " - "field-addr=%p, ft-addr=%p, ft-id=%s", field, - field->type, - bt_ctf_field_type_id_string(field->type->id)); - ret = -1; - goto end; - } +int bt_field_integer_unsigned_set_value(struct bt_field *field, + uint64_t value) +{ + struct bt_field_common_integer *integer = (void *) field; + + BT_ASSERT_PRE_NON_NULL(field, "Integer field"); + BT_ASSERT_PRE_FIELD_COMMON_HOT(BT_TO_COMMON(integer), "Integer field"); + BT_ASSERT_PRE_FIELD_IS_INT_OR_ENUM(BT_TO_COMMON(integer), "Field"); + BT_ASSERT_PRE(!bt_field_type_common_integer_is_signed( + BT_FROM_COMMON(get_int_enum_int_ft(field))), + "Field's type is signed: %!+f", field); + BT_ASSERT_PRE(value_is_in_range_unsigned( + get_int_enum_int_ft(field)->size, value), + "Value is out of bounds: value=%" PRIu64 ", %![field-]+f", + value, field); + integer->payload.unsignd = value; + bt_field_set(field, true); + return 0; +} - field_quark = g_quark_from_string(name); - structure = container_of(field, struct bt_ctf_field_structure, parent); - expected_field_type = - bt_ctf_field_type_structure_get_field_type_by_name(field->type, - name); - - if (bt_ctf_field_type_compare(expected_field_type, value->type)) { - BT_LOGW("Invalid parameter: field type of field to set is different from the expected field type: " - "struct-field-addr=%p, field-addr=%p, " - "field-ft-addr=%p, expected-ft-addr=%p", - field, value, value->type, expected_field_type); - ret = -1; - goto end; - } +int bt_field_floating_point_get_value(struct bt_field *field, + double *value) +{ + return bt_field_common_floating_point_get_value((void *) field, value); +} - if (!g_hash_table_lookup_extended(structure->field_name_to_index, - GUINT_TO_POINTER(field_quark), NULL, (gpointer *) &index)) { - BT_LOGV("Invalid parameter: no such field in structure field's type: " - "struct-field-addr=%p, struct-ft-addr=%p, " - "field-ft-addr=%p, name=\"%s\"", - field, field->type, value->type, name); - ret = -1; - goto end; - } +int bt_field_floating_point_set_value(struct bt_field *field, + double value) +{ + return bt_field_common_floating_point_set_value((void *) field, value); +} - if (structure->fields->pdata[index]) { - bt_put(structure->fields->pdata[index]); - } +const char *bt_field_string_get_value(struct bt_field *field) +{ + return bt_field_common_string_get_value((void *) field); +} - structure->fields->pdata[index] = value; - bt_get(value); -end: - if (expected_field_type) { - bt_put(expected_field_type); - } - return ret; +int bt_field_string_set_value(struct bt_field *field, const char *value) +{ + return bt_field_common_string_set_value((void *) field, value); } -struct bt_ctf_field *bt_ctf_field_array_get_field(struct bt_ctf_field *field, - uint64_t index) +int bt_field_string_append(struct bt_field *field, const char *value) { - struct bt_ctf_field *new_field = NULL; - struct bt_ctf_field_type *field_type = NULL; - struct bt_ctf_field_array *array; + return bt_field_common_string_append((void *) field, value); +} - if (!field) { - BT_LOGW_STR("Invalid parameter: field is NULL."); - goto end; - } +int bt_field_string_append_len(struct bt_field *field, + const char *value, unsigned int length) +{ + return bt_field_common_string_append_len((void *) field, value, length); +} - if (bt_ctf_field_type_get_type_id(field->type) != - BT_CTF_FIELD_TYPE_ID_ARRAY) { - BT_LOGW("Invalid parameter: field's type is not an array field type: " - "field-addr=%p, ft-addr=%p, ft-id=%s", field, - field->type, - bt_ctf_field_type_id_string(field->type->id)); - goto end; - } +int bt_field_string_clear(struct bt_field *string_field) +{ + return bt_field_common_string_clear((void *) string_field); +} - array = container_of(field, struct bt_ctf_field_array, parent); - if (index >= array->elements->len) { - BT_LOGW("Invalid parameter: index is out of bounds: " - "addr=%p, index=%" PRIu64 ", count=%u", - field, index, array->elements->len); - goto end; - } +BT_HIDDEN +struct bt_field_common *bt_field_common_copy(struct bt_field_common *field) +{ + struct bt_field_common *copy = NULL; - field_type = bt_ctf_field_type_array_get_element_type(field->type); - if (array->elements->pdata[(size_t)index]) { - new_field = array->elements->pdata[(size_t)index]; + BT_ASSERT_PRE_NON_NULL(field, "Field"); + BT_ASSERT(field_type_common_has_known_id(field->type)); + BT_ASSERT(field->methods->copy); + copy = field->methods->copy(field); + if (!copy) { + BT_LOGW("Cannot create field: ft-addr=%p", field->type); goto end; - } - - /* We don't want to modify this field if it's frozen */ - if (field->frozen) { - /* - * Not logging a warning here because the user could - * legitimately check if a array field is set with - * this function: if the preconditions are satisfied, - * a NULL return value means this. - */ - BT_LOGV("Not creating a field because array field is frozen: " - "array-field-addr=%p, index=%" PRIu64, field, index); - goto end; - } - - new_field = bt_ctf_field_create(field_type); - array->elements->pdata[(size_t)index] = new_field; -end: - if (field_type) { - bt_put(field_type); - } - if (new_field) { - bt_get(new_field); - } - return new_field; -} - -struct bt_ctf_field *bt_ctf_field_sequence_get_field(struct bt_ctf_field *field, - uint64_t index) -{ - struct bt_ctf_field *new_field = NULL; - struct bt_ctf_field_type *field_type = NULL; - struct bt_ctf_field_sequence *sequence; - - if (!field) { - BT_LOGW_STR("Invalid parameter: field is NULL."); - goto end; - } - - if (bt_ctf_field_type_get_type_id(field->type) != - BT_CTF_FIELD_TYPE_ID_SEQUENCE) { - BT_LOGW("Invalid parameter: field's type is not a sequence field type: " - "field-addr=%p, ft-addr=%p, ft-id=%s", field, - field->type, - bt_ctf_field_type_id_string(field->type->id)); - goto end; - } - - sequence = container_of(field, struct bt_ctf_field_sequence, parent); - if (!sequence->elements) { - BT_LOGV("Sequence field's elements do not exist: addr=%p", - field); - goto end; - } - - if (index >= sequence->elements->len) { - BT_LOGW("Invalid parameter: index is out of bounds: " - "addr=%p, index=%" PRIu64 ", count=%u", - field, index, sequence->elements->len); - goto end; - } - - 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]; - goto end; - } - - /* We don't want to modify this field if it's frozen */ - if (field->frozen) { - /* - * Not logging a warning here because the user could - * legitimately check if a sequence field is set with - * this function: if the preconditions are satisfied, - * a NULL return value means this. - */ - BT_LOGV("Not creating a field because sequence field is frozen: " - "sequence-field-addr=%p, index=%" PRIu64, field, index); - goto end; - } - - new_field = bt_ctf_field_create(field_type); - sequence->elements->pdata[(size_t) index] = new_field; -end: - if (field_type) { - bt_put(field_type); - } - if (new_field) { - bt_get(new_field); - } - return new_field; -} - -struct bt_ctf_field *bt_ctf_field_variant_get_field(struct bt_ctf_field *field, - struct bt_ctf_field *tag_field) -{ - struct bt_ctf_field *new_field = NULL; - struct bt_ctf_field_variant *variant; - struct bt_ctf_field_type_variant *variant_type; - struct bt_ctf_field_type *field_type; - struct bt_ctf_field *tag_enum = NULL; - struct bt_ctf_field_integer *tag_enum_integer; - int64_t tag_enum_value; - - if (!field) { - BT_LOGW_STR("Invalid parameter: field is NULL."); - goto end; - } - - if (!tag_field) { - BT_LOGW_STR("Invalid parameter: tag field is NULL."); - goto end; - } - - if (bt_ctf_field_type_get_type_id(field->type) != - BT_CTF_FIELD_TYPE_ID_VARIANT) { - BT_LOGW("Invalid parameter: field's type is not a variant field type: " - "field-addr=%p, ft-addr=%p, ft-id=%s", field, - field->type, - bt_ctf_field_type_id_string(field->type->id)); - goto end; - } - - if (bt_ctf_field_type_get_type_id(tag_field->type) != - BT_CTF_FIELD_TYPE_ID_ENUM) { - BT_LOGW("Invalid parameter: tag field's type is not an enumeration field type: " - "field-addr=%p, ft-addr=%p, ft-id=%s", tag_field, - tag_field->type, - bt_ctf_field_type_id_string(tag_field->type->id)); - goto end; - } - - variant = container_of(field, struct bt_ctf_field_variant, parent); - variant_type = container_of(field->type, - struct bt_ctf_field_type_variant, parent); - tag_enum = bt_ctf_field_enumeration_get_container(tag_field); - if (!tag_enum) { - goto end; - } - - tag_enum_integer = container_of(tag_enum, struct bt_ctf_field_integer, - parent); - - if (bt_ctf_field_validate(tag_field) < 0) { - BT_LOGW("Invalid parameter: tag field is invalid: " - "variant-field-addr=%p, tag-field-addr=%p", - field, tag_field); - goto end; - } - - tag_enum_value = tag_enum_integer->payload.signd; - - /* - * 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); - assert(cur_tag_container); - 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->payload.signd; - - if (cur_tag_value == tag_enum_value) { - new_field = variant->payload; - bt_get(new_field); - goto end; - } - } - - /* We don't want to modify this field if it's frozen */ - if (field->frozen) { - /* - * Not logging a warning here because the user could - * legitimately check if a variant field is set with - * this function: if the preconditions are satisfied, - * a NULL return value means this. - */ - BT_LOGV("Not creating a field because variant field is frozen: " - "variant-field-addr=%p, tag-field-addr=%p", - field, tag_field); - goto end; - } - - field_type = bt_ctf_field_type_variant_get_field_type_signed( - variant_type, tag_enum_value); - if (!field_type) { - BT_LOGW("Cannot get variant field type's field: " - "variant-field-addr=%p, variant-ft-addr=%p, " - "tag-value-signed=%" PRId64, - field, variant_type, tag_enum_value); - goto end; - } - - new_field = bt_ctf_field_create(field_type); - if (!new_field) { - BT_LOGW("Cannot create field: " - "variant-field-addr=%p, variant-ft-addr=%p, " - "field-ft-addr=%p", field, field->type, field_type); - goto end; - } - - 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_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_LOGW_STR("Invalid parameter: field is NULL."); - goto end; - } - - if (bt_ctf_field_type_get_type_id(variant_field->type) != - BT_CTF_FIELD_TYPE_ID_VARIANT) { - BT_LOGW("Invalid parameter: field's type is not a variant field type: " - "field-addr=%p, ft-addr=%p, ft-id=%s", variant_field, - variant_field->type, - bt_ctf_field_type_id_string(variant_field->type->id)); - 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_variant_get_tag( - struct bt_ctf_field *variant_field) -{ - struct bt_ctf_field *tag = NULL; - struct bt_ctf_field_variant *variant; - - if (!variant_field) { - BT_LOGW_STR("Invalid parameter: field is NULL."); - goto end; - } - - if (bt_ctf_field_type_get_type_id(variant_field->type) != - BT_CTF_FIELD_TYPE_ID_VARIANT) { - BT_LOGW("Invalid parameter: field's type is not a variant field type: " - "field-addr=%p, ft-addr=%p, ft-id=%s", variant_field, - variant_field->type, - bt_ctf_field_type_id_string(variant_field->type->id)); - goto end; - } - - variant = container_of(variant_field, struct bt_ctf_field_variant, - parent); - if (variant->tag) { - tag = bt_get(variant->tag); - } -end: - return tag; -} - -struct bt_ctf_field *bt_ctf_field_enumeration_get_container( - struct bt_ctf_field *field) -{ - struct bt_ctf_field *container = NULL; - struct bt_ctf_field_enumeration *enumeration; - - if (!field) { - BT_LOGW_STR("Invalid parameter: field is NULL."); - goto end; - } - - if (bt_ctf_field_type_get_type_id(field->type) != - BT_CTF_FIELD_TYPE_ID_ENUM) { - BT_LOGW("Invalid parameter: field's type is not an enumeration field type: " - "field-addr=%p, ft-addr=%p, ft-id=%s", field, - field->type, - bt_ctf_field_type_id_string(field->type->id)); - goto end; - } - - enumeration = container_of(field, struct bt_ctf_field_enumeration, - parent); - if (!enumeration->payload) { - /* We don't want to modify this field if it's frozen */ - if (field->frozen) { - /* - * Not logging a warning here because the user - * could legitimately check if an enumeration's - * container field is set with this function: if - * the preconditions are satisfied, a NULL - * return value means this. - */ - BT_LOGV("Not creating a field because enumeration field is frozen: " - "enum-field-addr=%p", field); - goto end; - } - - struct bt_ctf_field_type_enumeration *enumeration_type = - container_of(field->type, - struct bt_ctf_field_type_enumeration, parent); - enumeration->payload = - bt_ctf_field_create(enumeration_type->container); - } - - container = enumeration->payload; - bt_get(container); -end: - return container; -} - -struct bt_ctf_field_type_enumeration_mapping_iterator * -bt_ctf_field_enumeration_get_mappings(struct bt_ctf_field *field) -{ - int ret; - struct bt_ctf_field *container = NULL; - struct bt_ctf_field_type *container_type = NULL; - struct bt_ctf_field_type_integer *integer_type = NULL; - struct bt_ctf_field_type_enumeration_mapping_iterator *iter = NULL; - - container = bt_ctf_field_enumeration_get_container(field); - if (!container) { - BT_LOGW("Invalid parameter: enumeration field has no container field: " - "addr=%p", field); - goto end; - } - - container_type = bt_ctf_field_get_type(container); - assert(container_type); - integer_type = container_of(container_type, - struct bt_ctf_field_type_integer, parent); - - if (!integer_type->is_signed) { - uint64_t value; - - ret = bt_ctf_field_unsigned_integer_get_value(container, - &value); - if (ret) { - BT_LOGW("Cannot get value from signed enumeration field's payload field: " - "enum-field-addr=%p, payload-field-addr=%p", - field, container); - goto error_put_container_type; - } - iter = bt_ctf_field_type_enumeration_find_mappings_by_unsigned_value( - field->type, value); - } else { - int64_t value; - - ret = bt_ctf_field_signed_integer_get_value(container, - &value); - if (ret) { - BT_LOGW("Cannot get value from unsigned enumeration field's payload field: " - "enum-field-addr=%p, payload-field-addr=%p", - field, container); - goto error_put_container_type; - } - iter = bt_ctf_field_type_enumeration_find_mappings_by_signed_value( - field->type, value); - } - -error_put_container_type: - bt_put(container_type); - bt_put(container); -end: - return iter; -} - -int bt_ctf_field_signed_integer_get_value(struct bt_ctf_field *field, - int64_t *value) -{ - int ret = 0; - struct bt_ctf_field_integer *integer; - struct bt_ctf_field_type_integer *integer_type; - - if (!field) { - BT_LOGW_STR("Invalid parameter: field is NULL."); - ret = -1; - goto end; - } - - if (!value) { - BT_LOGW_STR("Invalid parameter: value is NULL."); - ret = -1; - goto end; - } - - if (!field->payload_set) { - BT_LOGV("Field's payload is not set: addr=%p", field); - ret = -1; - goto end; - } - - if (bt_ctf_field_type_get_type_id(field->type) != - BT_CTF_FIELD_TYPE_ID_INTEGER) { - BT_LOGW("Invalid parameter: field's type is not an integer field type: " - "field-addr=%p, ft-addr=%p, ft-id=%s", field, - field->type, - bt_ctf_field_type_id_string(field->type->id)); - ret = -1; - goto end; - } - - integer_type = container_of(field->type, - struct bt_ctf_field_type_integer, parent); - if (!integer_type->is_signed) { - BT_LOGW("Invalid parameter: integer field's type is not signed: " - "field-addr=%p, ft-addr=%p", field, field->type); - ret = -1; - goto end; - } - - integer = container_of(field, - struct bt_ctf_field_integer, parent); - *value = integer->payload.signd; -end: - return ret; -} - -int bt_ctf_field_signed_integer_set_value(struct bt_ctf_field *field, - int64_t value) -{ - int ret = 0; - struct bt_ctf_field_integer *integer; - struct bt_ctf_field_type_integer *integer_type; - unsigned int size; - int64_t min_value, max_value; - - if (!field) { - BT_LOGW_STR("Invalid parameter: field is NULL."); - ret = -1; - goto end; - } - - if (field->frozen) { - BT_LOGW("Invalid parameter: field is frozen: addr=%p", - field); - ret = -1; - goto end; - } - - if (bt_ctf_field_type_get_type_id(field->type) != - BT_CTF_FIELD_TYPE_ID_INTEGER) { - BT_LOGW("Invalid parameter: field's type is not an integer field type: " - "field-addr=%p, ft-addr=%p, ft-id=%s", field, - field->type, - bt_ctf_field_type_id_string(field->type->id)); - ret = -1; - goto end; - } - - integer = container_of(field, struct bt_ctf_field_integer, parent); - integer_type = container_of(field->type, - struct bt_ctf_field_type_integer, parent); - if (!integer_type->is_signed) { - BT_LOGW("Invalid parameter: integer field's type is not signed: " - "field-addr=%p, ft-addr=%p", field, field->type); - ret = -1; - goto end; - } - - size = integer_type->size; - min_value = -(1ULL << (size - 1)); - max_value = (1ULL << (size - 1)) - 1; - if (value < min_value || value > max_value) { - BT_LOGW("Invalid parameter: value is out of bounds: " - "addr=%p, value=%" PRId64 ", " - "min-value=%" PRId64 ", max-value=%" PRId64, - field, value, min_value, max_value); - ret = -1; - goto end; - } - - integer->payload.signd = value; - integer->parent.payload_set = true; -end: - return ret; -} - -int bt_ctf_field_unsigned_integer_get_value(struct bt_ctf_field *field, - uint64_t *value) -{ - int ret = 0; - struct bt_ctf_field_integer *integer; - struct bt_ctf_field_type_integer *integer_type; - - if (!field) { - BT_LOGW_STR("Invalid parameter: field is NULL."); - ret = -1; - goto end; - } - - if (!value) { - BT_LOGW_STR("Invalid parameter: value is NULL."); - ret = -1; - goto end; - } - - if (!field->payload_set) { - BT_LOGV("Field's payload is not set: addr=%p", field); - ret = -1; - goto end; - } - - if (bt_ctf_field_type_get_type_id(field->type) != - BT_CTF_FIELD_TYPE_ID_INTEGER) { - BT_LOGW("Invalid parameter: field's type is not an integer field type: " - "field-addr=%p, ft-addr=%p, ft-id=%s", field, - field->type, - bt_ctf_field_type_id_string(field->type->id)); - ret = -1; - goto end; - } - - integer_type = container_of(field->type, - struct bt_ctf_field_type_integer, parent); - if (integer_type->is_signed) { - BT_LOGW("Invalid parameter: integer field's type is signed: " - "field-addr=%p, ft-addr=%p", field, field->type); - ret = -1; - goto end; - } - - integer = container_of(field, - struct bt_ctf_field_integer, parent); - *value = integer->payload.unsignd; -end: - return ret; -} - -int bt_ctf_field_unsigned_integer_set_value(struct bt_ctf_field *field, - uint64_t value) -{ - int ret = 0; - struct bt_ctf_field_integer *integer; - struct bt_ctf_field_type_integer *integer_type; - unsigned int size; - uint64_t max_value; - - if (!field) { - BT_LOGW_STR("Invalid parameter: field is NULL."); - ret = -1; - goto end; - } - - if (field->frozen) { - BT_LOGW("Invalid parameter: field is frozen: addr=%p", - field); - ret = -1; - goto end; - } - - if (bt_ctf_field_type_get_type_id(field->type) != - BT_CTF_FIELD_TYPE_ID_INTEGER) { - BT_LOGW("Invalid parameter: field's type is not an integer field type: " - "field-addr=%p, ft-addr=%p, ft-id=%s", field, - field->type, - bt_ctf_field_type_id_string(field->type->id)); - ret = -1; - goto end; - } - - integer = container_of(field, struct bt_ctf_field_integer, parent); - integer_type = container_of(field->type, - struct bt_ctf_field_type_integer, parent); - if (integer_type->is_signed) { - BT_LOGW("Invalid parameter: integer field's type is signed: " - "field-addr=%p, ft-addr=%p", field, field->type); - ret = -1; - goto end; - } - - size = integer_type->size; - max_value = (size == 64) ? UINT64_MAX : ((uint64_t) 1 << size) - 1; - if (value > max_value) { - BT_LOGW("Invalid parameter: value is out of bounds: " - "addr=%p, value=%" PRIu64 ", " - "min-value=%" PRIu64 ", max-value=%" PRIu64, - field, value, (uint64_t) 0, max_value); - ret = -1; - goto end; - } - - integer->payload.unsignd = value; - integer->parent.payload_set = true; -end: - return ret; -} - -int bt_ctf_field_floating_point_get_value(struct bt_ctf_field *field, - double *value) -{ - int ret = 0; - struct bt_ctf_field_floating_point *floating_point; - - if (!field) { - BT_LOGW_STR("Invalid parameter: field is NULL."); - ret = -1; - goto end; - } - - if (!value) { - BT_LOGW_STR("Invalid parameter: value is NULL."); - ret = -1; - goto end; - } - - if (!field->payload_set) { - BT_LOGV("Field's payload is not set: addr=%p", field); - ret = -1; - goto end; - } - - if (bt_ctf_field_type_get_type_id(field->type) != - BT_CTF_FIELD_TYPE_ID_FLOAT) { - BT_LOGW("Invalid parameter: field's type is not a floating point number field type: " - "field-addr=%p, ft-addr=%p, ft-id=%s", field, - field->type, - bt_ctf_field_type_id_string(field->type->id)); - ret = -1; - goto end; - } - - floating_point = container_of(field, - struct bt_ctf_field_floating_point, parent); - *value = floating_point->payload; -end: - return ret; -} - -int bt_ctf_field_floating_point_set_value(struct bt_ctf_field *field, - double value) -{ - int ret = 0; - struct bt_ctf_field_floating_point *floating_point; - - if (!field) { - BT_LOGW_STR("Invalid parameter: field is NULL."); - ret = -1; - goto end; - } - - if (field->frozen) { - BT_LOGW("Invalid parameter: field is frozen: addr=%p", - field); - ret = -1; - goto end; - } - - if (bt_ctf_field_type_get_type_id(field->type) != - BT_CTF_FIELD_TYPE_ID_FLOAT) { - BT_LOGW("Invalid parameter: field's type is not a floating point number field type: " - "field-addr=%p, ft-addr=%p, ft-id=%s", field, - field->type, - bt_ctf_field_type_id_string(field->type->id)); - ret = -1; - goto end; - } - - floating_point = container_of(field, struct bt_ctf_field_floating_point, - parent); - floating_point->payload = value; - floating_point->parent.payload_set = true; -end: - return ret; -} - -const char *bt_ctf_field_string_get_value(struct bt_ctf_field *field) -{ - const char *ret = NULL; - struct bt_ctf_field_string *string; - - if (!field) { - BT_LOGW_STR("Invalid parameter: field is NULL."); - goto end; - } - - if (!field->payload_set) { - BT_LOGV("Field's payload is not set: addr=%p", field); - goto end; - } - - if (bt_ctf_field_type_get_type_id(field->type) != - BT_CTF_FIELD_TYPE_ID_STRING) { - BT_LOGW("Invalid parameter: field's type is not a string field type: " - "field-addr=%p, ft-addr=%p, ft-id=%s", field, - field->type, - bt_ctf_field_type_id_string(field->type->id)); - goto end; - } - - string = container_of(field, - struct bt_ctf_field_string, parent); - ret = string->payload->str; -end: - return ret; -} - -int bt_ctf_field_string_set_value(struct bt_ctf_field *field, - const char *value) -{ - int ret = 0; - struct bt_ctf_field_string *string; - - if (!field) { - BT_LOGW_STR("Invalid parameter: field is NULL."); - ret = -1; - goto end; - } - - if (!value) { - BT_LOGW_STR("Invalid parameter: value is NULL."); - ret = -1; - goto end; - } - - if (field->frozen) { - BT_LOGW("Invalid parameter: field is frozen: addr=%p", - field); - ret = -1; - goto end; - } - - if (bt_ctf_field_type_get_type_id(field->type) != - BT_CTF_FIELD_TYPE_ID_STRING) { - BT_LOGW("Invalid parameter: field's type is not a string field type: " - "field-addr=%p, ft-addr=%p, ft-id=%s", field, - field->type, - bt_ctf_field_type_id_string(field->type->id)); - ret = -1; - goto end; - } - - string = container_of(field, struct bt_ctf_field_string, parent); - if (string->payload) { - g_string_assign(string->payload, value); - } else { - string->payload = g_string_new(value); - } - - string->parent.payload_set = true; -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) { - BT_LOGW_STR("Invalid parameter: field is NULL."); - ret = -1; - goto end; - } - - if (!value) { - BT_LOGW_STR("Invalid parameter: value is NULL."); - ret = -1; - goto end; - } - - if (field->frozen) { - BT_LOGW("Invalid parameter: field is frozen: addr=%p", - field); - ret = -1; - goto end; - } - - if (bt_ctf_field_type_get_type_id(field->type) != - BT_CTF_FIELD_TYPE_ID_STRING) { - BT_LOGW("Invalid parameter: field's type is not a string field type: " - "field-addr=%p, ft-addr=%p, ft-id=%s", field, - field->type, - bt_ctf_field_type_id_string(field->type->id)); - 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 = true; - -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) { - BT_LOGW_STR("Invalid parameter: field is NULL."); - ret = -1; - goto end; - } - - if (!value) { - BT_LOGW_STR("Invalid parameter: value is NULL."); - ret = -1; - goto end; - } - - if (field->frozen) { - BT_LOGW("Invalid parameter: field is frozen: addr=%p", - field); - ret = -1; - goto end; - } - - if (bt_ctf_field_type_get_type_id(field->type) != - BT_CTF_FIELD_TYPE_ID_STRING) { - BT_LOGW("Invalid parameter: field's type is not a string field type: " - "field-addr=%p, ft-addr=%p, ft-id=%s", field, - field->type, - bt_ctf_field_type_id_string(field->type->id)); - 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 = true; - -end: - return ret; -} - -BT_HIDDEN -int bt_ctf_field_validate(struct bt_ctf_field *field) -{ - int ret = 0; - enum bt_ctf_field_type_id type_id; - - if (!field) { - BT_LOGD_STR("Invalid parameter: field is NULL."); - ret = -1; - goto end; - } - - type_id = bt_ctf_field_type_get_type_id(field->type); - if (type_id <= BT_CTF_FIELD_TYPE_ID_UNKNOWN || type_id >= BT_CTF_NR_TYPE_IDS) { - BT_LOGW("Invalid parameter: unknown field type ID: " - "addr=%p, ft-addr=%p, ft-id=%d", - field, field->type, type_id); - ret = -1; - goto end; - } - - ret = field_validate_funcs[type_id](field); -end: - return ret; -} - -BT_HIDDEN -int bt_ctf_field_reset(struct bt_ctf_field *field) -{ - int ret = 0; - enum bt_ctf_field_type_id type_id; - - if (!field) { - BT_LOGD_STR("Invalid parameter: field is NULL."); - ret = -1; - goto end; - } - - type_id = bt_ctf_field_type_get_type_id(field->type); - if (type_id <= BT_CTF_FIELD_TYPE_ID_UNKNOWN || type_id >= BT_CTF_NR_TYPE_IDS) { - BT_LOGW("Invalid parameter: unknown field type ID: " - "addr=%p, ft-addr=%p, ft-id=%d", - field, field->type, type_id); - 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 bt_ctf_stream_pos *pos, - enum bt_ctf_byte_order native_byte_order) -{ - int ret = 0; - enum bt_ctf_field_type_id type_id; - - assert(pos); - - if (!field) { - BT_LOGD_STR("Invalid parameter: field is NULL."); - ret = -1; - goto end; - } - - type_id = bt_ctf_field_type_get_type_id(field->type); - if (type_id <= BT_CTF_FIELD_TYPE_ID_UNKNOWN || type_id >= BT_CTF_NR_TYPE_IDS) { - BT_LOGW("Invalid parameter: unknown field type ID: " - "addr=%p, ft-addr=%p, ft-id=%d", - field, field->type, type_id); - ret = -1; - goto end; - } - - ret = field_serialize_funcs[type_id](field, pos, native_byte_order); -end: - return ret; -} - - -BT_HIDDEN -bt_bool bt_ctf_field_is_set(struct bt_ctf_field *field) -{ - bt_bool is_set = BT_FALSE; - enum bt_ctf_field_type_id type_id; - - if (!field) { - goto end; - } - - type_id = bt_ctf_field_type_get_type_id(field->type); - if (type_id <= BT_CTF_FIELD_TYPE_ID_UNKNOWN || type_id >= BT_CTF_NR_TYPE_IDS) { - BT_LOGW("Invalid parameter: unknown field type ID: " - "field-addr=%p, ft-addr=%p, ft-id=%d", - field, field->type, type_id); - goto end; - } - - is_set = field_is_set_funcs[type_id](field); -end: - return is_set; -} - -struct bt_ctf_field *bt_ctf_field_copy(struct bt_ctf_field *field) -{ - int ret; - struct bt_ctf_field *copy = NULL; - enum bt_ctf_field_type_id type_id; - - if (!field) { - BT_LOGW_STR("Invalid parameter: field is NULL."); - goto end; - } - - type_id = bt_ctf_field_type_get_type_id(field->type); - if (type_id <= BT_CTF_FIELD_TYPE_ID_UNKNOWN || type_id >= BT_CTF_NR_TYPE_IDS) { - BT_LOGW("Invalid parameter: unknown field type ID: " - "field-addr=%p, ft-addr=%p, ft-id=%d", - field, field->type, type_id); - goto end; - } - - copy = bt_ctf_field_create(field->type); - if (!copy) { - BT_LOGW("Cannot create field: ft-addr=%p", field->type); - 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) -{ - struct bt_ctf_field_integer *integer = g_new0( - struct bt_ctf_field_integer, 1); - - BT_LOGD("Creating integer field object: ft-addr=%p", type); - - if (integer) { - BT_LOGD("Created integer field object: addr=%p, ft-addr=%p", - &integer->parent, type); - } else { - BT_LOGE_STR("Failed to allocate one integer field."); - } - - return integer ? &integer->parent : NULL; -} - -static -struct bt_ctf_field *bt_ctf_field_enumeration_create( - struct bt_ctf_field_type *type) -{ - struct bt_ctf_field_enumeration *enumeration = g_new0( - struct bt_ctf_field_enumeration, 1); - - BT_LOGD("Creating enumeration field object: ft-addr=%p", type); - - if (enumeration) { - BT_LOGD("Created enumeration field object: addr=%p, ft-addr=%p", - &enumeration->parent, type); - } else { - BT_LOGE_STR("Failed to allocate one enumeration field."); - } - - return enumeration ? &enumeration->parent : NULL; -} - -static -struct bt_ctf_field *bt_ctf_field_floating_point_create( - struct bt_ctf_field_type *type) -{ - struct bt_ctf_field_floating_point *floating_point; - - BT_LOGD("Creating floating point number field object: ft-addr=%p", type); - floating_point = g_new0(struct bt_ctf_field_floating_point, 1); - - if (floating_point) { - BT_LOGD("Created floating point number field object: addr=%p, ft-addr=%p", - &floating_point->parent, type); - } else { - BT_LOGE_STR("Failed to allocate one floating point number field."); - } - - return floating_point ? &floating_point->parent : NULL; -} - -static -struct bt_ctf_field *bt_ctf_field_structure_create( - struct bt_ctf_field_type *type) -{ - struct bt_ctf_field_type_structure *structure_type = container_of(type, - struct bt_ctf_field_type_structure, parent); - struct bt_ctf_field_structure *structure = g_new0( - struct bt_ctf_field_structure, 1); - struct bt_ctf_field *field = NULL; - - BT_LOGD("Creating structure field object: ft-addr=%p", type); - - if (!structure) { - BT_LOGE_STR("Failed to allocate one structure field."); - goto end; - } - - structure->field_name_to_index = structure_type->field_name_to_index; - structure->fields = g_ptr_array_new_with_free_func( - (GDestroyNotify)bt_ctf_field_put); - g_ptr_array_set_size(structure->fields, - g_hash_table_size(structure->field_name_to_index)); - field = &structure->parent; - BT_LOGD("Created structure field object: addr=%p, ft-addr=%p", - field, type); -end: - return field; -} - -static -struct bt_ctf_field *bt_ctf_field_variant_create(struct bt_ctf_field_type *type) -{ - struct bt_ctf_field_variant *variant = g_new0( - struct bt_ctf_field_variant, 1); - - BT_LOGD("Creating variant field object: ft-addr=%p", type); - - if (variant) { - BT_LOGD("Created variant field object: addr=%p, ft-addr=%p", - &variant->parent, type); - } else { - BT_LOGE_STR("Failed to allocate one variant field."); - } - - return variant ? &variant->parent : NULL; -} - -static -struct bt_ctf_field *bt_ctf_field_array_create(struct bt_ctf_field_type *type) -{ - struct bt_ctf_field_array *array = g_new0(struct bt_ctf_field_array, 1); - struct bt_ctf_field_type_array *array_type; - unsigned int array_length; - - BT_LOGD("Creating array field object: ft-addr=%p", type); - assert(type); - - if (!array) { - BT_LOGE_STR("Failed to allocate one array field."); - goto error; - } - - array_type = container_of(type, struct bt_ctf_field_type_array, parent); - array_length = array_type->length; - array->elements = g_ptr_array_sized_new(array_length); - if (!array->elements) { - goto error; - } - - g_ptr_array_set_free_func(array->elements, - (GDestroyNotify)bt_ctf_field_put); - g_ptr_array_set_size(array->elements, array_length); - BT_LOGD("Created array field object: addr=%p, ft-addr=%p", - &array->parent, type); - return &array->parent; -error: - g_free(array); - return NULL; -} - -static -struct bt_ctf_field *bt_ctf_field_sequence_create( - struct bt_ctf_field_type *type) -{ - struct bt_ctf_field_sequence *sequence = g_new0( - struct bt_ctf_field_sequence, 1); - - BT_LOGD("Creating sequence field object: ft-addr=%p", type); - - if (sequence) { - BT_LOGD("Created sequence field object: addr=%p, ft-addr=%p", - &sequence->parent, type); - } else { - BT_LOGE_STR("Failed to allocate one sequence field."); - } - - return sequence ? &sequence->parent : NULL; -} - -static -struct bt_ctf_field *bt_ctf_field_string_create(struct bt_ctf_field_type *type) -{ - struct bt_ctf_field_string *string = g_new0( - struct bt_ctf_field_string, 1); - - BT_LOGD("Creating string field object: ft-addr=%p", type); - - if (string) { - BT_LOGD("Created string field object: addr=%p, ft-addr=%p", - &string->parent, type); - } else { - BT_LOGE_STR("Failed to allocate one string field."); - } - - return string ? &string->parent : NULL; -} + } -static -void bt_ctf_field_destroy(struct bt_object *obj) -{ - struct bt_ctf_field *field; - struct bt_ctf_field_type *type; - enum bt_ctf_field_type_id type_id; + bt_field_common_set(copy, field->payload_set); - field = container_of(obj, struct bt_ctf_field, base); - type = field->type; - type_id = bt_ctf_field_type_get_type_id(type); - assert(type_id > BT_CTF_FIELD_TYPE_ID_UNKNOWN && - type_id < BT_CTF_NR_TYPE_IDS); - field_destroy_funcs[type_id](field); - BT_LOGD_STR("Putting field's type."); - bt_put(type); +end: + return copy; } static -void bt_ctf_field_integer_destroy(struct bt_ctf_field *field) +void bt_field_integer_destroy(struct bt_field *field) { - struct bt_ctf_field_integer *integer; - - if (!field) { - return; - } - BT_LOGD("Destroying integer field object: addr=%p", field); - integer = container_of(field, struct bt_ctf_field_integer, parent); - g_free(integer); + bt_field_common_integer_finalize((void *) field); + g_free(field); } static -void bt_ctf_field_enumeration_destroy(struct bt_ctf_field *field) +void bt_field_floating_point_destroy(struct bt_field *field) { - struct bt_ctf_field_enumeration *enumeration; - - if (!field) { - return; - } - - BT_LOGD("Destroying enumeration field object: addr=%p", field); - enumeration = container_of(field, struct bt_ctf_field_enumeration, - parent); - BT_LOGD_STR("Putting payload field."); - bt_put(enumeration->payload); - g_free(enumeration); + BT_LOGD("Destroying floating point field object: addr=%p", field); + bt_field_common_floating_point_finalize((void *) field); + g_free(field); } static -void bt_ctf_field_floating_point_destroy(struct bt_ctf_field *field) +void bt_field_enumeration_destroy(struct bt_field *field) { - struct bt_ctf_field_floating_point *floating_point; - - if (!field) { - return; - } - - BT_LOGD("Destroying floating point number field object: addr=%p", field); - floating_point = container_of(field, struct bt_ctf_field_floating_point, - parent); - g_free(floating_point); + BT_LOGD("Destroying enumeration field object: addr=%p", field); + bt_field_common_finalize((void *) field); + g_free(field); } static -void bt_ctf_field_structure_destroy(struct bt_ctf_field *field) +void bt_field_structure_destroy_recursive(struct bt_field *field) { - struct bt_ctf_field_structure *structure; - - if (!field) { - return; - } - BT_LOGD("Destroying structure field object: addr=%p", field); - structure = container_of(field, struct bt_ctf_field_structure, parent); - g_ptr_array_free(structure->fields, TRUE); - g_free(structure); + bt_field_common_structure_finalize_recursive((void *) field); + g_free(field); } static -void bt_ctf_field_variant_destroy(struct bt_ctf_field *field) +void bt_field_variant_destroy_recursive(struct bt_field *field) { - struct bt_ctf_field_variant *variant; - - if (!field) { - return; - } - BT_LOGD("Destroying variant field object: addr=%p", field); - variant = container_of(field, struct bt_ctf_field_variant, parent); - BT_LOGD_STR("Putting tag field."); - bt_put(variant->tag); - BT_LOGD_STR("Putting payload field."); - bt_put(variant->payload); - g_free(variant); + bt_field_common_variant_finalize_recursive((void *) field); + g_free(field); } static -void bt_ctf_field_array_destroy(struct bt_ctf_field *field) +void bt_field_array_destroy_recursive(struct bt_field *field) { - struct bt_ctf_field_array *array; - - if (!field) { - return; - } - BT_LOGD("Destroying array field object: addr=%p", field); - array = container_of(field, struct bt_ctf_field_array, parent); - g_ptr_array_free(array->elements, TRUE); - g_free(array); + bt_field_common_array_finalize_recursive((void *) field); + g_free(field); } static -void bt_ctf_field_sequence_destroy(struct bt_ctf_field *field) +void bt_field_sequence_destroy_recursive(struct bt_field *field) { - struct bt_ctf_field_sequence *sequence; - - if (!field) { - return; - } - BT_LOGD("Destroying sequence field object: addr=%p", field); - sequence = container_of(field, struct bt_ctf_field_sequence, parent); - if (sequence->elements) { - g_ptr_array_free(sequence->elements, TRUE); - } - BT_LOGD_STR("Putting length field."); - bt_put(sequence->length); - g_free(sequence); + bt_field_common_sequence_finalize_recursive((void *) field); + g_free(field); } static -void bt_ctf_field_string_destroy(struct bt_ctf_field *field) +void bt_field_string_destroy(struct bt_field *field) { - struct bt_ctf_field_string *string; - - if (!field) { - return; - } - BT_LOGD("Destroying string field object: addr=%p", field); - string = container_of(field, struct bt_ctf_field_string, parent); - if (string->payload) { - g_string_free(string->payload, TRUE); - } - g_free(string); -} - -static -int bt_ctf_field_generic_validate(struct bt_ctf_field *field) -{ - return (field && field->payload_set) ? 0 : -1; + bt_field_common_string_finalize((void *) field); + g_free(field); } -static -int bt_ctf_field_enumeration_validate(struct bt_ctf_field *field) +BT_HIDDEN +void bt_field_destroy_recursive(struct bt_field *field) { - int ret; - struct bt_ctf_field_enumeration *enumeration; + struct bt_field_common *field_common = (void *) field; if (!field) { - BT_LOGD_STR("Invalid parameter: field is NULL."); - ret = -1; - goto end; - } - - enumeration = container_of(field, struct bt_ctf_field_enumeration, - parent); - if (!enumeration->payload) { - BT_LOGW("Invalid enumeration field: payload is not set: " - "addr=%p", field); - ret = -1; - goto end; + return; } - ret = bt_ctf_field_validate(enumeration->payload); -end: - return ret; + BT_ASSERT(field_type_common_has_known_id((void *) field_common->type)); + field_destroy_funcs[field_common->type->id](field); } static -int bt_ctf_field_structure_validate(struct bt_ctf_field *field) +struct bt_field *bt_field_integer_create(struct bt_field_type *type) { - int64_t i; - int ret = 0; - struct bt_ctf_field_structure *structure; - - if (!field) { - BT_LOGD_STR("Invalid parameter: field is NULL."); - ret = -1; - goto end; - } + struct bt_field_common_integer *integer = + g_new0(struct bt_field_common_integer, 1); - structure = container_of(field, struct bt_ctf_field_structure, parent); - for (i = 0; i < structure->fields->len; i++) { - struct bt_ctf_field *entry_field = structure->fields->pdata[i]; - ret = bt_ctf_field_validate(entry_field); + BT_LOGD("Creating integer field object: ft-addr=%p", type); - if (ret) { - int this_ret; - const char *name; - struct bt_ctf_field_type *field_type = - bt_ctf_field_get_type(field); - - this_ret = bt_ctf_field_type_structure_get_field( - field_type, &name, NULL, i); - assert(this_ret == 0); - BT_LOGW("Invalid structure field's field: " - "struct-field-addr=%p, field-addr=%p, " - "field-name=\"%s\", index=%" PRId64, - field, entry_field, name, i); - bt_put(field_type); - goto end; - } + if (integer) { + bt_field_common_initialize(BT_TO_COMMON(integer), (void *) type, + NULL, &bt_field_integer_methods); + BT_LOGD("Created integer field object: addr=%p, ft-addr=%p", + integer, type); + } else { + BT_LOGE_STR("Failed to allocate one integer field."); } -end: - return ret; + + return (void *) integer; } static -int bt_ctf_field_variant_validate(struct bt_ctf_field *field) +struct bt_field *bt_field_enumeration_create(struct bt_field_type *type) { - int ret = 0; - struct bt_ctf_field_variant *variant; + struct bt_field_enumeration *enumeration = g_new0( + struct bt_field_enumeration, 1); - if (!field) { - BT_LOGD_STR("Invalid parameter: field is NULL."); - ret = -1; - goto end; - } + BT_LOGD("Creating enumeration field object: ft-addr=%p", type); - variant = container_of(field, struct bt_ctf_field_variant, parent); - ret = bt_ctf_field_validate(variant->payload); - if (ret) { - BT_LOGW("Invalid variant field's payload field: " - "variant-field-addr=%p, variant-payload-field-addr=%p", - field, variant->payload); + if (enumeration) { + bt_field_common_initialize( + BT_TO_COMMON(BT_TO_COMMON(enumeration)), + (void *) type, NULL, &bt_field_enumeration_methods); + BT_LOGD("Created enumeration field object: addr=%p, ft-addr=%p", + enumeration, type); + } else { + BT_LOGE_STR("Failed to allocate one enumeration field."); } -end: - return ret; + + return (void *) enumeration; } static -int bt_ctf_field_array_validate(struct bt_ctf_field *field) +struct bt_field *bt_field_floating_point_create(struct bt_field_type *type) { - int64_t i; - int ret = 0; - struct bt_ctf_field_array *array; + struct bt_field_common_floating_point *floating_point; - if (!field) { - BT_LOGD_STR("Invalid parameter: field is NULL."); - 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 *elem_field = array->elements->pdata[i]; + BT_LOGD("Creating floating point number field object: ft-addr=%p", type); + floating_point = g_new0(struct bt_field_common_floating_point, 1); - ret = bt_ctf_field_validate(elem_field); - if (ret) { - BT_LOGW("Invalid array field's element field: " - "array-field-addr=%p, field-addr=%p, " - "index=%" PRId64, field, elem_field, i); - goto end; - } + if (floating_point) { + bt_field_common_initialize(BT_TO_COMMON(floating_point), + (void *) type, NULL, &bt_field_floating_point_methods); + BT_LOGD("Created floating point number field object: addr=%p, ft-addr=%p", + floating_point, type); + } else { + BT_LOGE_STR("Failed to allocate one floating point number field."); } -end: - return ret; + + return (void *) floating_point; } -static -int bt_ctf_field_sequence_validate(struct bt_ctf_field *field) +BT_HIDDEN +int bt_field_common_structure_initialize(struct bt_field_common *field, + struct bt_field_type_common *type, + bt_object_release_func release_func, + struct bt_field_common_methods *methods, + bt_field_common_create_func field_create_func, + GDestroyNotify field_release_func) { - size_t i; int ret = 0; - struct bt_ctf_field_sequence *sequence; - - if (!field) { - BT_LOGD_STR("Invalid parameter: field is NULL."); - 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 *elem_field = sequence->elements->pdata[i]; + struct bt_field_type_common_structure *structure_type = + BT_FROM_COMMON(type); + struct bt_field_common_structure *structure = BT_FROM_COMMON(field); + size_t i; - ret = bt_ctf_field_validate(elem_field); - if (ret) { - BT_LOGW("Invalid sequence field's element field: " - "sequence-field-addr=%p, field-addr=%p, " - "index=%zu", field, elem_field, i); + BT_LOGD("Initializing common structure field object: ft-addr=%p", type); + bt_field_common_initialize(field, type, release_func, methods); + structure->fields = g_ptr_array_new_with_free_func(field_release_func); + g_ptr_array_set_size(structure->fields, structure_type->fields->len); + + /* Create all fields contained in the structure field. */ + for (i = 0; i < structure_type->fields->len; i++) { + struct bt_field_common *field; + struct bt_field_type_common_structure_field *struct_field = + BT_FIELD_TYPE_COMMON_STRUCTURE_FIELD_AT_INDEX( + structure_type, i); + field = field_create_func(struct_field->type); + if (!field) { + BT_LOGE("Failed to create structure field's member: name=\"%s\", index=%zu", + g_quark_to_string(struct_field->name), i); + ret = -1; goto end; } - } -end: - return ret; -} - -static -int bt_ctf_field_generic_reset(struct bt_ctf_field *field) -{ - int ret = 0; - if (!field) { - BT_LOGD_STR("Invalid parameter: field is NULL."); - ret = -1; - goto end; + g_ptr_array_index(structure->fields, i) = field; } - field->payload_set = false; + BT_LOGD("Initialized common structure field object: addr=%p, ft-addr=%p", + field, type); + end: return ret; } static -int bt_ctf_field_enumeration_reset(struct bt_ctf_field *field) +struct bt_field *bt_field_structure_create(struct bt_field_type *type) { - int ret = 0; - struct bt_ctf_field_enumeration *enumeration; + struct bt_field_common_structure *structure = g_new0( + struct bt_field_common_structure, 1); + int iret; - if (!field) { - BT_LOGD_STR("Invalid parameter: field is NULL."); - ret = -1; + BT_LOGD("Creating structure field object: ft-addr=%p", type); + + if (!structure) { + BT_LOGE_STR("Failed to allocate one structure field."); goto end; } - enumeration = container_of(field, struct bt_ctf_field_enumeration, - parent); - if (!enumeration->payload) { + iret = bt_field_common_structure_initialize(BT_TO_COMMON(structure), + (void *) type, NULL, &bt_field_structure_methods, + (bt_field_common_create_func) bt_field_create_recursive, + (GDestroyNotify) bt_field_destroy_recursive); + if (iret) { + BT_PUT(structure); goto end; } - ret = bt_ctf_field_reset(enumeration->payload); + BT_LOGD("Created structure field object: addr=%p, ft-addr=%p", + structure, type); + end: - return ret; + return (void *) structure; } -static -int bt_ctf_field_structure_reset(struct bt_ctf_field *field) +BT_HIDDEN +int bt_field_common_variant_initialize(struct bt_field_common *field, + struct bt_field_type_common *type, + bt_object_release_func release_func, + struct bt_field_common_methods *methods, + bt_field_common_create_func field_create_func, + GDestroyNotify field_release_func) { - int64_t i; int ret = 0; - struct bt_ctf_field_structure *structure; + struct bt_field_type_common_variant *variant_type = + BT_FROM_COMMON(type); + struct bt_field_common_variant *variant = BT_FROM_COMMON(field); + size_t i; - if (!field) { - BT_LOGD_STR("Invalid parameter: field is NULL."); - ret = -1; + BT_LOGD("Initializing common variant field object: ft-addr=%p", type); + bt_field_common_initialize(field, type, release_func, methods); + ret = bt_field_type_common_variant_update_choices(type); + if (ret) { + BT_LOGE("Cannot update common variant field type choices: " + "ret=%d", ret); 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]; + variant->fields = g_ptr_array_new_with_free_func(field_release_func); + g_ptr_array_set_size(variant->fields, variant_type->choices->len); - if (!member) { - /* - * Structure members are lazily initialized; skip if - * this member has not been allocated yet. - */ - continue; - } + /* Create all fields contained in the variant field. */ + for (i = 0; i < variant_type->choices->len; i++) { + struct bt_field_common *field; + struct bt_field_type_common_variant_choice *var_choice = + BT_FIELD_TYPE_COMMON_VARIANT_CHOICE_AT_INDEX( + variant_type, i); - ret = bt_ctf_field_reset(member); - if (ret) { - BT_LOGE("Failed to reset structure field's field: " - "struct-field-addr=%p, field-addr=%p, " - "index=%" PRId64, field, member, i); + field = field_create_func(var_choice->type); + if (!field) { + BT_LOGE("Failed to create variant field's member: name=\"%s\", index=%zu", + g_quark_to_string(var_choice->name), i); + ret = -1; 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) { - BT_LOGD_STR("Invalid parameter: field is NULL."); - ret = -1; - goto end; + g_ptr_array_index(variant->fields, i) = field; } - variant = container_of(field, struct bt_ctf_field_variant, parent); - if (variant->payload) { - ret = bt_ctf_field_reset(variant->payload); - if (ret) { - BT_LOGW("Failed to reset variant field's payload field: " - "variant-field-addr=%p, payload-field-addr=%p", - field, variant->payload); - } - } + BT_LOGD("Initialized common variant field object: addr=%p, ft-addr=%p", + field, type); + end: return ret; } static -int bt_ctf_field_array_reset(struct bt_ctf_field *field) +struct bt_field *bt_field_variant_create(struct bt_field_type *type) { - size_t i; - int ret = 0; - struct bt_ctf_field_array *array; + struct bt_field_common_variant *variant = g_new0( + struct bt_field_common_variant, 1); + int iret; - if (!field) { - BT_LOGD_STR("Invalid parameter: field is NULL."); - ret = -1; + BT_LOGD("Creating variant field object: ft-addr=%p", type); + + if (!variant) { + BT_LOGE_STR("Failed to allocate one variant field."); 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]; + iret = bt_field_common_variant_initialize(BT_TO_COMMON(variant), + (void *) type, NULL, &bt_field_variant_methods, + (bt_field_common_create_func) bt_field_create_recursive, + (GDestroyNotify) bt_field_destroy_recursive); + if (iret) { + BT_PUT(variant); + goto end; + } - if (!member) { - /* - * Array elements are lazily initialized; skip if - * this member has not been allocated yet. - */ - continue; - } + BT_LOGD("Created variant field object: addr=%p, ft-addr=%p", + variant, type); - ret = bt_ctf_field_reset(member); - if (ret) { - BT_LOGE("Failed to reset array field's field: " - "array-field-addr=%p, field-addr=%p, " - "index=%zu", field, member, i); - goto end; - } - } end: - return ret; + return (void *) variant; } -static -int bt_ctf_field_sequence_reset(struct bt_ctf_field *field) -{ - size_t i; +BT_HIDDEN +int bt_field_common_array_initialize(struct bt_field_common *field, + struct bt_field_type_common *type, + bt_object_release_func release_func, + struct bt_field_common_methods *methods, + bt_field_common_create_func field_create_func, + GDestroyNotify field_destroy_func) +{ + struct bt_field_type_common_array *array_type = BT_FROM_COMMON(type); + struct bt_field_common_array *array = BT_FROM_COMMON(field); + unsigned int array_length; int ret = 0; - struct bt_ctf_field_sequence *sequence; + uint64_t i; - if (!field) { - BT_LOGD_STR("Invalid parameter: field is NULL."); + BT_LOGD("Initializing common array field object: ft-addr=%p", type); + BT_ASSERT(type); + bt_field_common_initialize(field, type, release_func, methods); + array_length = array_type->length; + array->elements = g_ptr_array_sized_new(array_length); + if (!array->elements) { 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; - } + g_ptr_array_set_free_func(array->elements, field_destroy_func); + g_ptr_array_set_size(array->elements, array_length); - ret = bt_ctf_field_reset(member); - if (ret) { - BT_LOGE("Failed to reset sequence field's field: " - "sequence-field-addr=%p, field-addr=%p, " - "index=%zu", field, member, i); + for (i = 0; i < array_length; i++) { + array->elements->pdata[i] = field_create_func( + array_type->element_ft); + if (!array->elements->pdata[i]) { + ret = -1; 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) { - BT_LOGD_STR("Invalid parameter: field is NULL."); - ret = -1; - goto end; - } - ret = bt_ctf_field_generic_reset(field); - if (ret) { - goto end; - } + BT_LOGD("Initialized common array field object: addr=%p, ft-addr=%p", + field, type); - 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 bt_ctf_stream_pos *pos, - enum bt_ctf_byte_order native_byte_order) +struct bt_field *bt_field_array_create(struct bt_field_type *type) { - int ret = 0; - struct bt_ctf_field_integer *integer = container_of(field, - struct bt_ctf_field_integer, parent); + struct bt_field_common_array *array = + g_new0(struct bt_field_common_array, 1); + int ret; - BT_LOGV("Serializing integer field: addr=%p, pos-offset=%" PRId64 ", " - "native-bo=%s", field, pos->offset, - bt_ctf_byte_order_string(native_byte_order)); + BT_LOGD("Creating array field object: ft-addr=%p", type); + BT_ASSERT(type); - if (!bt_ctf_field_generic_is_set(field)) { - BT_LOGW_STR("Field's payload is not set."); - ret = -1; + if (!array) { + BT_LOGE_STR("Failed to allocate one array field."); goto end; } -retry: - ret = bt_ctf_field_integer_write(integer, pos, native_byte_order); - if (ret == -EFAULT) { - /* - * The field is too large to fit in the current packet's - * remaining space. Bump the packet size and retry. - */ - ret = increase_packet_size(pos); - if (ret) { - BT_LOGE("Cannot increase packet size: ret=%d", ret); - goto end; - } - goto retry; + + ret = bt_field_common_array_initialize(BT_TO_COMMON(array), + (void *) type, NULL, &bt_field_array_methods, + (bt_field_common_create_func) bt_field_create_recursive, + (GDestroyNotify) bt_field_destroy_recursive); + if (ret) { + BT_PUT(array); + goto end; } -end: - return ret; -} -static -int bt_ctf_field_enumeration_serialize(struct bt_ctf_field *field, - struct bt_ctf_stream_pos *pos, - enum bt_ctf_byte_order native_byte_order) -{ - struct bt_ctf_field_enumeration *enumeration = container_of( - field, struct bt_ctf_field_enumeration, parent); + BT_LOGD("Created array field object: addr=%p, ft-addr=%p", + array, type); - BT_LOGV("Serializing enumeration field: addr=%p, pos-offset=%" PRId64 ", " - "native-bo=%s", field, pos->offset, - bt_ctf_byte_order_string(native_byte_order)); - BT_LOGV_STR("Serializing enumeration field's payload field."); - return bt_ctf_field_serialize(enumeration->payload, pos, - native_byte_order); +end: + return (void *) array; } -static -int bt_ctf_field_floating_point_serialize(struct bt_ctf_field *field, - struct bt_ctf_stream_pos *pos, - enum bt_ctf_byte_order native_byte_order) +BT_HIDDEN +int bt_field_common_sequence_initialize(struct bt_field_common *field, + struct bt_field_type_common *type, + bt_object_release_func release_func, + struct bt_field_common_methods *methods, + GDestroyNotify field_destroy_func) { + struct bt_field_common_sequence *sequence = BT_FROM_COMMON(field); int ret = 0; - struct bt_ctf_field_floating_point *floating_point = container_of(field, - struct bt_ctf_field_floating_point, parent); - BT_LOGV("Serializing floating point number field: addr=%p, pos-offset=%" PRId64 ", " - "native-bo=%s", field, pos->offset, - bt_ctf_byte_order_string(native_byte_order)); - - if (!bt_ctf_field_generic_is_set(field)) { - BT_LOGW_STR("Field's payload is not set."); + BT_LOGD("Initializing common sequence field object: ft-addr=%p", type); + BT_ASSERT(type); + bt_field_common_initialize(field, type, release_func, methods); + sequence->elements = g_ptr_array_new(); + if (!sequence->elements) { ret = -1; goto end; } -retry: - ret = bt_ctf_field_floating_point_write(floating_point, pos, - native_byte_order); - if (ret == -EFAULT) { - /* - * The field is too large to fit in the current packet's - * remaining space. Bump the packet size and retry. - */ - ret = increase_packet_size(pos); - if (ret) { - BT_LOGE("Cannot increase packet size: ret=%d", ret); - goto end; - } - goto retry; - } + + g_ptr_array_set_free_func(sequence->elements, field_destroy_func); + BT_LOGD("Initialized common sequence field object: addr=%p, ft-addr=%p", + field, type); + end: return ret; } static -int bt_ctf_field_structure_serialize(struct bt_ctf_field *field, - struct bt_ctf_stream_pos *pos, - enum bt_ctf_byte_order native_byte_order) +struct bt_field *bt_field_sequence_create(struct bt_field_type *type) { - int64_t i; - int ret = 0; - struct bt_ctf_field_structure *structure = container_of( - field, struct bt_ctf_field_structure, parent); + struct bt_field_common_sequence *sequence = + g_new0(struct bt_field_common_sequence, 1); + int ret; - BT_LOGV("Serializing structure field: addr=%p, pos-offset=%" PRId64 ", " - "native-bo=%s", field, pos->offset, - bt_ctf_byte_order_string(native_byte_order)); + BT_LOGD("Creating sequence field object: ft-addr=%p", type); + BT_ASSERT(type); - while (!bt_ctf_stream_pos_access_ok(pos, - offset_align(pos->offset, field->type->alignment))) { - ret = increase_packet_size(pos); - if (ret) { - BT_LOGE("Cannot increase packet size: ret=%d", ret); - goto end; - } + if (!sequence) { + BT_LOGE_STR("Failed to allocate one sequence field."); + goto end; } - if (!bt_ctf_stream_pos_align(pos, field->type->alignment)) { - BT_LOGE("Cannot align packet's position: pos-offset=%" PRId64 ", " - "align=%u", pos->offset, field->type->alignment); - ret = -1; + ret = bt_field_common_sequence_initialize(BT_TO_COMMON(sequence), + (void *) type, NULL, &bt_field_sequence_methods, + (GDestroyNotify) bt_field_destroy_recursive); + if (ret) { + BT_PUT(sequence); goto end; } - for (i = 0; i < structure->fields->len; i++) { - struct bt_ctf_field *member = g_ptr_array_index( - structure->fields, i); - const char *field_name = NULL; - - if (BT_LOG_ON_WARN) { - ret = bt_ctf_field_type_structure_get_field( - field->type, &field_name, NULL, i); - assert(ret == 0); - } - - BT_LOGV("Serializing structure field's field: pos-offset=%" PRId64 ", " - "field-addr=%p, index=%" PRId64, - pos->offset, member, i); - - if (!member) { - BT_LOGW("Cannot serialize structure field's field: field is not set: " - "struct-field-addr=%p, " - "field-name=\"%s\", index=%" PRId64, - field, field_name, i); - ret = -1; - goto end; - } + BT_LOGD("Created sequence field object: addr=%p, ft-addr=%p", + sequence, type); - ret = bt_ctf_field_serialize(member, pos, native_byte_order); - if (ret) { - BT_LOGW("Cannot serialize structure field's field: " - "struct-field-addr=%p, field-addr=%p, " - "field-name=\"%s\", index=%" PRId64, - field->type, member, field_name, i); - break; - } - } end: - return ret; + return (void *) sequence; } static -int bt_ctf_field_variant_serialize(struct bt_ctf_field *field, - struct bt_ctf_stream_pos *pos, - enum bt_ctf_byte_order native_byte_order) +struct bt_field *bt_field_string_create(struct bt_field_type *type) { - struct bt_ctf_field_variant *variant = container_of( - field, struct bt_ctf_field_variant, parent); + struct bt_field_common_string *string = g_new0( + struct bt_field_common_string, 1); + + BT_LOGD("Creating string field object: ft-addr=%p", type); + + if (string) { + bt_field_common_initialize(BT_TO_COMMON(string), + (void *) type, NULL, &bt_field_string_methods); + BT_LOGD("Created string field object: addr=%p, ft-addr=%p", + string, type); + } else { + BT_LOGE_STR("Failed to allocate one string field."); + } - BT_LOGV("Serializing variant field: addr=%p, pos-offset=%" PRId64 ", " - "native-bo=%s", field, pos->offset, - bt_ctf_byte_order_string(native_byte_order)); - BT_LOGV_STR("Serializing variant field's payload field."); - return bt_ctf_field_serialize(variant->payload, pos, - native_byte_order); + return (void *) string; } -static -int bt_ctf_field_array_serialize(struct bt_ctf_field *field, - struct bt_ctf_stream_pos *pos, - enum bt_ctf_byte_order native_byte_order) +BT_HIDDEN +int bt_field_common_generic_validate(struct bt_field_common *field) +{ + return (field && field->payload_set) ? 0 : -1; +} + +BT_HIDDEN +int bt_field_common_structure_validate_recursive(struct bt_field_common *field) { int64_t i; int ret = 0; - struct bt_ctf_field_array *array = container_of( - field, struct bt_ctf_field_array, parent); + struct bt_field_common_structure *structure = BT_FROM_COMMON(field); - BT_LOGV("Serializing array field: addr=%p, pos-offset=%" PRId64 ", " - "native-bo=%s", field, pos->offset, - bt_ctf_byte_order_string(native_byte_order)); + BT_ASSERT(field); + + for (i = 0; i < structure->fields->len; i++) { + ret = bt_field_common_validate_recursive( + (void *) structure->fields->pdata[i]); - for (i = 0; i < array->elements->len; i++) { - struct bt_ctf_field *elem_field = - g_ptr_array_index(array->elements, i); - - BT_LOGV("Serializing array field's element field: " - "pos-offset=%" PRId64 ", field-addr=%p, index=%" PRId64, - pos->offset, elem_field, i); - ret = bt_ctf_field_serialize(elem_field, pos, - native_byte_order); if (ret) { - BT_LOGW("Cannot serialize array field's element field: " - "array-field-addr=%p, field-addr=%p, " - "index=%" PRId64, field, elem_field, i); + int this_ret; + const char *name; + + this_ret = bt_field_type_common_structure_borrow_field_by_index( + field->type, &name, NULL, i); + BT_ASSERT(this_ret == 0); + BT_ASSERT_PRE_MSG("Invalid structure field's field: " + "%![struct-field-]+_f, field-name=\"%s\", " + "index=%" PRId64 ", %![field-]+_f", + field, name, i, structure->fields->pdata[i]); goto end; } } + end: return ret; } -static -int bt_ctf_field_sequence_serialize(struct bt_ctf_field *field, - struct bt_ctf_stream_pos *pos, - enum bt_ctf_byte_order native_byte_order) +BT_HIDDEN +int bt_field_common_variant_validate_recursive(struct bt_field_common *field) { - int64_t i; int ret = 0; - struct bt_ctf_field_sequence *sequence = container_of( - field, struct bt_ctf_field_sequence, parent); + struct bt_field_common_variant *variant = BT_FROM_COMMON(field); - BT_LOGV("Serializing sequence field: addr=%p, pos-offset=%" PRId64 ", " - "native-bo=%s", field, pos->offset, - bt_ctf_byte_order_string(native_byte_order)); + BT_ASSERT(field); - for (i = 0; i < sequence->elements->len; i++) { - struct bt_ctf_field *elem_field = - g_ptr_array_index(sequence->elements, i); - - BT_LOGV("Serializing sequence field's element field: " - "pos-offset=%" PRId64 ", field-addr=%p, index=%" PRId64, - pos->offset, elem_field, i); - ret = bt_ctf_field_serialize(elem_field, pos, - native_byte_order); - if (ret) { - BT_LOGW("Cannot serialize sequence field's element field: " - "sequence-field-addr=%p, field-addr=%p, " - "index=%" PRId64, field, elem_field, i); - goto end; - } + if (!variant->current_field) { + ret = -1; + goto end; } + + ret = bt_field_common_validate_recursive(variant->current_field); + end: return ret; } -static -int bt_ctf_field_string_serialize(struct bt_ctf_field *field, - struct bt_ctf_stream_pos *pos, - enum bt_ctf_byte_order native_byte_order) +BT_HIDDEN +int bt_field_common_array_validate_recursive(struct bt_field_common *field) { int64_t i; int ret = 0; - struct bt_ctf_field_string *string = container_of(field, - struct bt_ctf_field_string, parent); - struct bt_ctf_field_type *character_type = - get_field_type(FIELD_TYPE_ALIAS_UINT8_T); - struct bt_ctf_field *character; - - BT_LOGV("Serializing string field: addr=%p, pos-offset=%" PRId64 ", " - "native-bo=%s", field, pos->offset, - bt_ctf_byte_order_string(native_byte_order)); + struct bt_field_common_array *array = BT_FROM_COMMON(field); - BT_LOGV_STR("Creating character field from string field's character field type."); - character = bt_ctf_field_create(character_type); + BT_ASSERT(field); - for (i = 0; i < string->payload->len + 1; i++) { - const uint64_t chr = (uint64_t) string->payload->str[i]; - - ret = bt_ctf_field_unsigned_integer_set_value(character, chr); - if (ret) { - BT_LOGW("Cannot set character field's value: " - "pos-offset=%" PRId64 ", field-addr=%p, " - "index=%" PRId64 ", char-int=%" PRIu64, - pos->offset, character, i, chr); - goto end; - } - - BT_LOGV("Serializing string field's character field: " - "pos-offset=%" PRId64 ", field-addr=%p, " - "index=%" PRId64 ", char-int=%" PRIu64, - pos->offset, character, i, chr); - ret = bt_ctf_field_integer_serialize(character, pos, - native_byte_order); + for (i = 0; i < array->elements->len; i++) { + ret = bt_field_common_validate_recursive((void *) array->elements->pdata[i]); if (ret) { - BT_LOGW_STR("Cannot serialize character field."); + BT_ASSERT_PRE_MSG("Invalid array field's element field: " + "%![array-field-]+_f, " PRId64 ", " + "%![elem-field-]+_f", + field, i, array->elements->pdata[i]); goto end; } } + end: - 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) +BT_HIDDEN +int bt_field_common_sequence_validate_recursive(struct bt_field_common *field) { - struct bt_ctf_field_integer *integer_src, *integer_dst; + size_t i; + int ret = 0; + struct bt_field_common_sequence *sequence = BT_FROM_COMMON(field); - BT_LOGD("Copying integer field: src-field-addr=%p, dst-field-addr=%p", - src, dst); - integer_src = container_of(src, struct bt_ctf_field_integer, parent); - integer_dst = container_of(dst, struct bt_ctf_field_integer, parent); - integer_dst->payload = integer_src->payload; - BT_LOGD_STR("Copied integer field."); - return 0; -} + BT_ASSERT(field); -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; - - BT_LOGD("Copying enumeration field: src-field-addr=%p, dst-field-addr=%p", - src, 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) { - BT_LOGD_STR("Copying enumeration field's payload field."); - enum_dst->payload = bt_ctf_field_copy(enum_src->payload); - if (!enum_dst->payload) { - BT_LOGE_STR("Cannot copy enumeration field's payload field."); - ret = -1; + for (i = 0; i < sequence->elements->len; i++) { + ret = bt_field_common_validate_recursive( + (void *) sequence->elements->pdata[i]); + if (ret) { + BT_ASSERT_PRE_MSG("Invalid sequence field's element field: " + "%![seq-field-]+_f, " PRId64 ", " + "%![elem-field-]+_f", + field, i, sequence->elements->pdata[i]); goto end; } } - - BT_LOGD_STR("Copied enumeration field."); 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; - - BT_LOGD("Copying floating point number field: src-field-addr=%p, dst-field-addr=%p", - src, 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); - float_dst->payload = float_src->payload; - BT_LOGD_STR("Copied floating point number field."); - return 0; +BT_HIDDEN +void bt_field_common_generic_reset(struct bt_field_common *field) +{ + BT_ASSERT(field); + field->payload_set = false; } -static -int bt_ctf_field_structure_copy(struct bt_ctf_field *src, - struct bt_ctf_field *dst) +BT_HIDDEN +void bt_field_common_structure_reset_recursive(struct bt_field_common *field) { - int ret = 0; int64_t i; - struct bt_ctf_field_structure *struct_src, *struct_dst; - - BT_LOGD("Copying structure field: src-field-addr=%p, dst-field-addr=%p", - src, 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) { - BT_LOGD("Copying structure field's field: src-field-addr=%p" - "index=%" PRId64, field, i); - field_copy = bt_ctf_field_copy(field); - if (!field_copy) { - BT_LOGE("Cannot copy structure field's field: " - "src-field-addr=%p, index=%" PRId64, - field, i); - ret = -1; - goto end; - } - } - - g_ptr_array_index(struct_dst->fields, i) = field_copy; - } + struct bt_field_common_structure *structure = BT_FROM_COMMON(field); - BT_LOGD_STR("Copied structure field."); + BT_ASSERT(field); -end: - return ret; -} + for (i = 0; i < structure->fields->len; i++) { + struct bt_field_common *member = structure->fields->pdata[i]; -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; - - BT_LOGD("Copying variant field: src-field-addr=%p, dst-field-addr=%p", - src, 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) { - BT_LOGD_STR("Copying variant field's tag field."); - variant_dst->tag = bt_ctf_field_copy(variant_src->tag); - if (!variant_dst->tag) { - BT_LOGE_STR("Cannot copy variant field's tag field."); - ret = -1; - goto end; - } - } - if (variant_src->payload) { - BT_LOGD_STR("Copying variant field's payload field."); - variant_dst->payload = bt_ctf_field_copy(variant_src->payload); - if (!variant_dst->payload) { - BT_LOGE_STR("Cannot copy variant field's payload field."); - ret = -1; - goto end; + if (!member) { + /* + * Structure members are lazily initialized; + * skip if this member has not been allocated + * yet. + */ + continue; } - } - - BT_LOGD_STR("Copied variant field."); -end: - return ret; + bt_field_common_reset_recursive(member); + } } -static -int bt_ctf_field_array_copy(struct bt_ctf_field *src, - struct bt_ctf_field *dst) +BT_HIDDEN +void bt_field_common_variant_reset_recursive(struct bt_field_common *field) { - int ret = 0; - int64_t i; - struct bt_ctf_field_array *array_src, *array_dst; - - BT_LOGD("Copying array field: src-field-addr=%p, dst-field-addr=%p", - src, 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) { - BT_LOGD("Copying array field's element field: field-addr=%p, " - "index=%" PRId64, field, i); - field_copy = bt_ctf_field_copy(field); - if (!field_copy) { - BT_LOGE("Cannot copy array field's element field: " - "src-field-addr=%p, index=%" PRId64, - field, i); - ret = -1; - goto end; - } - } - - g_ptr_array_index(array_dst->elements, i) = field_copy; - } + struct bt_field_common_variant *variant = BT_FROM_COMMON(field); - BT_LOGD_STR("Copied array field."); - -end: - return ret; + BT_ASSERT(field); + variant->current_field = NULL; } -static -int bt_ctf_field_sequence_copy(struct bt_ctf_field *src, - struct bt_ctf_field *dst) +BT_HIDDEN +void bt_field_common_array_reset_recursive(struct bt_field_common *field) { - int ret = 0; - int64_t i; - struct bt_ctf_field_sequence *sequence_src, *sequence_dst; - struct bt_ctf_field *src_length; - struct bt_ctf_field *dst_length; - - BT_LOGD("Copying sequence field: src-field-addr=%p, dst-field-addr=%p", - src, dst); - 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; - } + size_t i; + struct bt_field_common_array *array = BT_FROM_COMMON(field); - /* copy source length */ - BT_LOGD_STR("Copying sequence field's length field."); - dst_length = bt_ctf_field_copy(src_length); - BT_PUT(src_length); - if (!dst_length) { - BT_LOGE_STR("Cannot copy sequence field's length field."); - ret = -1; - goto end; - } + BT_ASSERT(field); - /* 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) { - BT_LOGE("Cannot set sequence field copy's length field: " - "dst-length-field-addr=%p", dst_length); - ret = -1; - goto end; - } + for (i = 0; i < array->elements->len; i++) { + struct bt_field_common *member = array->elements->pdata[i]; - 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) { - BT_LOGD("Copying sequence field's element field: field-addr=%p, " - "index=%" PRId64, field, i); - field_copy = bt_ctf_field_copy(field); - if (!field_copy) { - BT_LOGE("Cannot copy sequence field's element field: " - "src-field-addr=%p, index=%" PRId64, - field, i); - ret = -1; - goto end; - } + if (!member) { + /* + * Array elements are lazily initialized; skip + * if this member has not been allocated yet. + */ + continue; } - g_ptr_array_index(sequence_dst->elements, i) = field_copy; + bt_field_common_reset_recursive(member); } - - BT_LOGD_STR("Copied sequence field."); - -end: - return ret; } -static -int bt_ctf_field_string_copy(struct bt_ctf_field *src, - struct bt_ctf_field *dst) +BT_HIDDEN +void bt_field_common_sequence_reset_recursive(struct bt_field_common *field) { - int ret = 0; - struct bt_ctf_field_string *string_src, *string_dst; + struct bt_field_common_sequence *sequence = BT_FROM_COMMON(field); + uint64_t i; - BT_LOGD("Copying string field: src-field-addr=%p, dst-field-addr=%p", - src, dst); - string_src = container_of(src, struct bt_ctf_field_string, parent); - string_dst = container_of(dst, struct bt_ctf_field_string, parent); + BT_ASSERT(field); - if (string_src->payload) { - string_dst->payload = g_string_new(string_src->payload->str); - if (!string_dst->payload) { - BT_LOGE_STR("Failed to allocate a GString."); - ret = -1; - goto end; + for (i = 0; i < sequence->elements->len; i++) { + if (sequence->elements->pdata[i]) { + bt_field_common_reset_recursive( + sequence->elements->pdata[i]); } } - BT_LOGD_STR("Copied string field."); - -end: - return ret; + sequence->length = 0; } -static -int increase_packet_size(struct bt_ctf_stream_pos *pos) +BT_HIDDEN +void bt_field_common_string_reset(struct bt_field_common *field) { - int ret; - - assert(pos); - BT_LOGV("Increasing packet size: pos-offset=%" PRId64 ", " - "cur-packet-size=%" PRIu64, - pos->offset, pos->packet_size); - ret = munmap_align(pos->base_mma); - if (ret) { - BT_LOGE_ERRNO("Failed to perform an aligned memory unmapping", - ": ret=%d", ret); - goto end; - } + struct bt_field_common_string *string = BT_FROM_COMMON(field); - pos->packet_size += PACKET_LEN_INCREMENT; - do { - ret = bt_posix_fallocate(pos->fd, pos->mmap_offset, - pos->packet_size / CHAR_BIT); - } while (ret == EINTR); - if (ret) { - BT_LOGE_ERRNO("Failed to preallocate memory space", - ": ret=%d", ret); - errno = EINTR; - ret = -1; - goto end; - } + BT_ASSERT(field); + bt_field_common_generic_reset(field); - pos->base_mma = mmap_align(pos->packet_size / CHAR_BIT, pos->prot, - pos->flags, pos->fd, pos->mmap_offset); - if (pos->base_mma == MAP_FAILED) { - BT_LOGE_ERRNO("Failed to perform an aligned memory mapping", - ": ret=%d", ret); - ret = -1; + if (string->payload) { + g_string_truncate(string->payload, 0); } - - BT_LOGV("Increased packet size: pos-offset=%" PRId64 ", " - "new-packet-size=%" PRIu64, - pos->offset, pos->packet_size); - assert(pos->packet_size % 8 == 0); - -end: - return ret; -} - -static -void generic_field_freeze(struct bt_ctf_field *field) -{ - field->frozen = true; } -static -void bt_ctf_field_enumeration_freeze(struct bt_ctf_field *field) +BT_HIDDEN +void bt_field_common_generic_set_is_frozen(struct bt_field_common *field, + bool is_frozen) { - struct bt_ctf_field_enumeration *enum_field = - container_of(field, struct bt_ctf_field_enumeration, parent); - - BT_LOGD("Freezing enumeration field object: addr=%p", field); - BT_LOGD("Freezing enumeration field object's contained payload field: payload-field-addr=%p", enum_field->payload); - bt_ctf_field_freeze(enum_field->payload); - generic_field_freeze(field); + field->frozen = is_frozen; } -static -void bt_ctf_field_structure_freeze(struct bt_ctf_field *field) +BT_HIDDEN +void bt_field_common_structure_set_is_frozen_recursive( + struct bt_field_common *field, bool is_frozen) { - int64_t i; - struct bt_ctf_field_structure *structure_field = - container_of(field, struct bt_ctf_field_structure, parent); + uint64_t i; + struct bt_field_common_structure *structure_field = + BT_FROM_COMMON(field); BT_LOGD("Freezing structure field object: addr=%p", field); for (i = 0; i < structure_field->fields->len; i++) { - struct bt_ctf_field *field = + struct bt_field_common *struct_field = g_ptr_array_index(structure_field->fields, i); BT_LOGD("Freezing structure field's field: field-addr=%p, index=%" PRId64, - field, i); - bt_ctf_field_freeze(field); + struct_field, i); + bt_field_common_set_is_frozen_recursive(struct_field, + is_frozen); } - generic_field_freeze(field); + bt_field_common_generic_set_is_frozen(field, is_frozen); } -static -void bt_ctf_field_variant_freeze(struct bt_ctf_field *field) +BT_HIDDEN +void bt_field_common_variant_set_is_frozen_recursive( + struct bt_field_common *field, bool is_frozen) { - struct bt_ctf_field_variant *variant_field = - container_of(field, struct bt_ctf_field_variant, parent); + uint64_t i; + struct bt_field_common_variant *variant_field = BT_FROM_COMMON(field); BT_LOGD("Freezing variant field object: addr=%p", field); - BT_LOGD("Freezing variant field object's tag field: tag-field-addr=%p", variant_field->tag); - bt_ctf_field_freeze(variant_field->tag); - BT_LOGD("Freezing variant field object's payload field: payload-field-addr=%p", variant_field->payload); - bt_ctf_field_freeze(variant_field->payload); - generic_field_freeze(field); + + for (i = 0; i < variant_field->fields->len; i++) { + struct bt_field_common *var_field = + g_ptr_array_index(variant_field->fields, i); + + BT_LOGD("Freezing variant field's field: field-addr=%p, index=%" PRId64, + var_field, i); + bt_field_common_set_is_frozen_recursive(var_field, is_frozen); + } + + bt_field_common_generic_set_is_frozen(field, is_frozen); } -static -void bt_ctf_field_array_freeze(struct bt_ctf_field *field) +BT_HIDDEN +void bt_field_common_array_set_is_frozen_recursive( + struct bt_field_common *field, bool is_frozen) { int64_t i; - struct bt_ctf_field_array *array_field = - container_of(field, struct bt_ctf_field_array, parent); + struct bt_field_common_array *array_field = BT_FROM_COMMON(field); BT_LOGD("Freezing array field object: addr=%p", field); for (i = 0; i < array_field->elements->len; i++) { - struct bt_ctf_field *elem_field = + struct bt_field_common *elem_field = g_ptr_array_index(array_field->elements, i); BT_LOGD("Freezing array field object's element field: " "element-field-addr=%p, index=%" PRId64, elem_field, i); - bt_ctf_field_freeze(elem_field); + bt_field_common_set_is_frozen_recursive(elem_field, is_frozen); } - generic_field_freeze(field); + bt_field_common_generic_set_is_frozen(field, is_frozen); } -static -void bt_ctf_field_sequence_freeze(struct bt_ctf_field *field) +BT_HIDDEN +void bt_field_common_sequence_set_is_frozen_recursive( + struct bt_field_common *field, bool is_frozen) { int64_t i; - struct bt_ctf_field_sequence *sequence_field = - container_of(field, struct bt_ctf_field_sequence, parent); + struct bt_field_common_sequence *sequence_field = + BT_FROM_COMMON(field); BT_LOGD("Freezing sequence field object: addr=%p", field); - BT_LOGD("Freezing sequence field object's length field: length-field-addr=%p", - sequence_field->length); - bt_ctf_field_freeze(sequence_field->length); - for (i = 0; i < sequence_field->elements->len; i++) { - struct bt_ctf_field *elem_field = + for (i = 0; i < sequence_field->length; i++) { + struct bt_field_common *elem_field = g_ptr_array_index(sequence_field->elements, i); BT_LOGD("Freezing sequence field object's element field: " "element-field-addr=%p, index=%" PRId64, elem_field, i); - bt_ctf_field_freeze(elem_field); + bt_field_common_set_is_frozen_recursive(elem_field, is_frozen); } - generic_field_freeze(field); + bt_field_common_generic_set_is_frozen(field, is_frozen); } BT_HIDDEN -void bt_ctf_field_freeze(struct bt_ctf_field *field) +void _bt_field_common_set_is_frozen_recursive(struct bt_field_common *field, + bool is_frozen) { - enum bt_ctf_field_type_id type_id; - if (!field) { goto end; } @@ -3184,120 +1244,101 @@ void bt_ctf_field_freeze(struct bt_ctf_field *field) goto end; } - BT_LOGD("Freezing field object: addr=%p", field); - type_id = bt_ctf_field_get_type_id(field); - assert(type_id > BT_CTF_FIELD_TYPE_ID_UNKNOWN && - type_id < BT_CTF_NR_TYPE_IDS); - field_freeze_funcs[type_id](field); + BT_LOGD("Setting field object's frozen state: addr=%p, is-frozen=%d", + field, is_frozen); + BT_ASSERT(field_type_common_has_known_id(field->type)); + BT_ASSERT(field->methods->set_is_frozen); + field->methods->set_is_frozen(field, is_frozen); + end: return; } -static -bt_bool bt_ctf_field_generic_is_set(struct bt_ctf_field *field) +BT_HIDDEN +bt_bool bt_field_common_generic_is_set(struct bt_field_common *field) { return field && field->payload_set; } -static -bt_bool bt_ctf_field_enumeration_is_set(struct bt_ctf_field *field) -{ - bt_bool is_set = BT_FALSE; - struct bt_ctf_field_enumeration *enumeration; - - if (!field) { - goto end; - } - - enumeration = container_of(field, struct bt_ctf_field_enumeration, - parent); - if (!enumeration->payload) { - goto end; - } - - is_set = bt_ctf_field_is_set(enumeration->payload); -end: - return is_set; -} - -static -bt_bool bt_ctf_field_structure_is_set(struct bt_ctf_field *field) +BT_HIDDEN +bt_bool bt_field_common_structure_is_set_recursive( + struct bt_field_common *field) { bt_bool is_set = BT_FALSE; size_t i; - struct bt_ctf_field_structure *structure; + struct bt_field_common_structure *structure = BT_FROM_COMMON(field); - if (!field) { - goto end; - } + BT_ASSERT(field); - structure = container_of(field, struct bt_ctf_field_structure, parent); for (i = 0; i < structure->fields->len; i++) { - is_set = bt_ctf_field_is_set(structure->fields->pdata[i]); + is_set = bt_field_common_is_set_recursive( + structure->fields->pdata[i]); if (!is_set) { goto end; } } + end: return is_set; } -static -bt_bool bt_ctf_field_variant_is_set(struct bt_ctf_field *field) +BT_HIDDEN +bt_bool bt_field_common_variant_is_set_recursive(struct bt_field_common *field) { + struct bt_field_common_variant *variant = BT_FROM_COMMON(field); bt_bool is_set = BT_FALSE; - struct bt_ctf_field_variant *variant; - if (!field) { - goto end; + BT_ASSERT(field); + + if (variant->current_field) { + is_set = bt_field_common_is_set_recursive( + variant->current_field); } - variant = container_of(field, struct bt_ctf_field_variant, parent); - is_set = bt_ctf_field_is_set(variant->payload); -end: return is_set; } -static -bt_bool bt_ctf_field_array_is_set(struct bt_ctf_field *field) +BT_HIDDEN +bt_bool bt_field_common_array_is_set_recursive(struct bt_field_common *field) { size_t i; bt_bool is_set = BT_FALSE; - struct bt_ctf_field_array *array; + struct bt_field_common_array *array = BT_FROM_COMMON(field); - if (!field) { - goto end; - } + BT_ASSERT(field); - array = container_of(field, struct bt_ctf_field_array, parent); for (i = 0; i < array->elements->len; i++) { - is_set = bt_ctf_field_is_set(array->elements->pdata[i]); + is_set = bt_field_common_is_set_recursive(array->elements->pdata[i]); if (!is_set) { goto end; } } + end: return is_set; } -static -bt_bool bt_ctf_field_sequence_is_set(struct bt_ctf_field *field) +BT_HIDDEN +bt_bool bt_field_common_sequence_is_set_recursive(struct bt_field_common *field) { size_t i; bt_bool is_set = BT_FALSE; - struct bt_ctf_field_sequence *sequence; + struct bt_field_common_sequence *sequence = BT_FROM_COMMON(field); - if (!field) { + BT_ASSERT(field); + + if (!sequence->elements) { goto end; } - sequence = container_of(field, struct bt_ctf_field_sequence, parent); for (i = 0; i < sequence->elements->len; i++) { - is_set = bt_ctf_field_validate(sequence->elements->pdata[i]); + is_set = bt_field_common_is_set_recursive( + sequence->elements->pdata[i]); if (!is_set) { goto end; } } + end: return is_set; }