#include <babeltrace/ctf-writer/event-types.h>
#include <babeltrace/ctf-ir/event-types-internal.h>
+#include <babeltrace/ctf-ir/field-path-internal.h>
#include <babeltrace/ctf-ir/utils.h>
#include <babeltrace/ref.h>
#include <babeltrace/ctf-ir/clock.h>
[CTF_TYPE_STRING] = bt_ctf_field_type_string_compare,
};
+static
+int bt_ctf_field_type_enumeration_validate(struct bt_ctf_field_type *);
+static
+int bt_ctf_field_type_structure_validate(struct bt_ctf_field_type *);
+static
+int bt_ctf_field_type_variant_validate(struct bt_ctf_field_type *);
+static
+int bt_ctf_field_type_array_validate(struct bt_ctf_field_type *);
+static
+int bt_ctf_field_type_sequence_validate(struct bt_ctf_field_type *);
+
+static
+int (* const type_validate_funcs[])(struct bt_ctf_field_type *) = {
+ [CTF_TYPE_INTEGER] = NULL,
+ [CTF_TYPE_FLOAT] = NULL,
+ [CTF_TYPE_STRING] = NULL,
+ [CTF_TYPE_ENUM] = bt_ctf_field_type_enumeration_validate,
+ [CTF_TYPE_STRUCT] = bt_ctf_field_type_structure_validate,
+ [CTF_TYPE_VARIANT] = bt_ctf_field_type_variant_validate,
+ [CTF_TYPE_ARRAY] = bt_ctf_field_type_array_validate,
+ [CTF_TYPE_SEQUENCE] = bt_ctf_field_type_sequence_validate,
+};
+
static
void destroy_enumeration_mapping(struct enumeration_mapping *mapping)
{
type_destroy_funcs[type_id](type);
}
-BT_HIDDEN
-int bt_ctf_field_type_validate(struct bt_ctf_field_type *type)
+static
+int bt_ctf_field_type_enumeration_validate(struct bt_ctf_field_type *type)
{
int ret = 0;
- if (!type) {
+ struct bt_ctf_field_type_enumeration *enumeration =
+ container_of(type, struct bt_ctf_field_type_enumeration,
+ parent);
+ struct bt_ctf_field_type *container_type =
+ bt_ctf_field_type_enumeration_get_container_type(type);
+
+ if (!container_type) {
ret = -1;
goto end;
}
- switch (type->declaration->id) {
- case CTF_TYPE_ENUM:
- {
- struct bt_ctf_field_type_enumeration *enumeration =
- container_of(type, struct bt_ctf_field_type_enumeration,
- parent);
+ ret = bt_ctf_field_type_validate(container_type);
+ if (ret) {
+ goto end;
+ }
- /* Ensure enum has entries */
- ret = enumeration->entries->len ? 0 : -1;
- break;
+ /* Ensure enum has entries */
+ ret = enumeration->entries->len ? 0 : -1;
+
+end:
+ BT_PUT(container_type);
+ return ret;
+}
+
+static
+int bt_ctf_field_type_sequence_validate(struct bt_ctf_field_type *type)
+{
+ int ret = 0;
+ struct bt_ctf_field_type *element_type = NULL;
+ struct bt_ctf_field_type_sequence *sequence =
+ container_of(type, struct bt_ctf_field_type_sequence,
+ parent);
+
+ /* Length field name should be set at this point */
+ if (sequence->length_field_name->len == 0) {
+ ret = -1;
+ goto end;
}
- case CTF_TYPE_SEQUENCE:
- {
- struct bt_ctf_field_type_sequence *sequence =
- container_of(type, struct bt_ctf_field_type_sequence,
+
+ element_type = bt_ctf_field_type_sequence_get_element_type(type);
+ if (!element_type) {
+ ret = -1;
+ goto end;
+ }
+
+ ret = bt_ctf_field_type_validate(element_type);
+
+end:
+ BT_PUT(element_type);
+
+ return ret;
+}
+
+static
+int bt_ctf_field_type_array_validate(struct bt_ctf_field_type *type)
+{
+ int ret = 0;
+ struct bt_ctf_field_type *element_type = NULL;
+
+ element_type = bt_ctf_field_type_array_get_element_type(type);
+ if (!element_type) {
+ ret = -1;
+ goto end;
+ }
+
+ ret = bt_ctf_field_type_validate(element_type);
+
+end:
+ BT_PUT(element_type);
+
+ return ret;
+}
+
+static
+int bt_ctf_field_type_structure_validate(struct bt_ctf_field_type *type)
+{
+ int ret = 0;
+ struct bt_ctf_field_type *child_type = NULL;
+ int field_count = bt_ctf_field_type_structure_get_field_count(type);
+ int i;
+
+ if (field_count < 0) {
+ ret = -1;
+ goto end;
+ }
+
+ for (i = 0; i < field_count; ++i) {
+ ret = bt_ctf_field_type_structure_get_field(type,
+ NULL, &child_type, i);
+ if (ret) {
+ goto end;
+ }
+
+ ret = bt_ctf_field_type_validate(child_type);
+ if (ret) {
+ goto end;
+ }
+
+ BT_PUT(child_type);
+ }
+
+end:
+ BT_PUT(child_type);
+
+ return ret;
+}
+
+static
+int bt_ctf_field_type_variant_validate(struct bt_ctf_field_type *type)
+{
+ int ret = 0;
+ int field_count;
+ struct bt_ctf_field_type *child_type = NULL;
+ struct bt_ctf_field_type_variant *variant =
+ container_of(type, struct bt_ctf_field_type_variant,
parent);
+ int i;
+ int tag_mappings_count;
- /* length field name should be set at this point */
- ret = sequence->length_field_name->len ? 0 : -1;
- break;
+ if (variant->tag_name->len == 0 || !variant->tag) {
+ ret = -1;
+ goto end;
+ }
+
+ tag_mappings_count =
+ bt_ctf_field_type_enumeration_get_mapping_count(
+ (struct bt_ctf_field_type *) variant->tag);
+
+ if (tag_mappings_count != variant->fields->len) {
+ ret = -1;
+ goto end;
}
- case CTF_TYPE_VARIANT:
- {
- struct bt_ctf_field_type_variant *variant =
- container_of(type, struct bt_ctf_field_type_variant,
- parent);
- if (variant->tag_name->len == 0 || !variant->tag) {
+ for (i = 0; i < tag_mappings_count; ++i) {
+ const char *label;
+ int64_t range_start, range_end;
+ struct bt_ctf_field_type *ft;
+
+ ret = bt_ctf_field_type_enumeration_get_mapping(
+ (struct bt_ctf_field_type *) variant->tag,
+ i, &label, &range_start, &range_end);
+ if (ret) {
+ goto end;
+ }
+ if (!label) {
ret = -1;
+ goto end;
}
- break;
+
+ ft = bt_ctf_field_type_variant_get_field_type_by_name(
+ type, label);
+ if (!ft) {
+ ret = -1;
+ goto end;
+ }
+
+ BT_PUT(ft);
}
- default:
- break;
+
+ field_count = bt_ctf_field_type_variant_get_field_count(type);
+ if (field_count < 0) {
+ ret = -1;
+ goto end;
+ }
+
+ for (i = 0; i < field_count; ++i) {
+ ret = bt_ctf_field_type_variant_get_field(type,
+ NULL, &child_type, i);
+ if (ret) {
+ goto end;
+ }
+
+ ret = bt_ctf_field_type_validate(child_type);
+ if (ret) {
+ goto end;
+ }
+
+ BT_PUT(child_type);
+ }
+
+end:
+ BT_PUT(child_type);
+
+ return ret;
+}
+
+/*
+ * This function validates a given field type without considering
+ * where this field type is located. It only validates the properties
+ * of the given field type and the properties of its children if
+ * applicable.
+ */
+BT_HIDDEN
+int bt_ctf_field_type_validate(struct bt_ctf_field_type *type)
+{
+ int ret = 0;
+ enum ctf_type_id id = bt_ctf_field_type_get_type_id(type);
+
+ if (!type) {
+ ret = -1;
+ goto end;
+ }
+
+ if (type->valid) {
+ /* Already marked as valid */
+ goto end;
+ }
+
+ if (type_validate_funcs[id]) {
+ ret = type_validate_funcs[id](type);
+ }
+
+ if (!ret && type->frozen) {
+ /* Field type is valid */
+ type->valid = 1;
}
+
end:
return ret;
}
if (!type || !field_type || type->frozen ||
bt_ctf_validate_identifier(field_name) ||
- (type->declaration->id != CTF_TYPE_STRUCT) ||
- bt_ctf_field_type_validate(field_type)) {
+ (type->declaration->id != CTF_TYPE_STRUCT)) {
ret = -1;
goto end;
}
if (!type || !field_type || type->frozen ||
bt_ctf_validate_identifier(field_name) ||
- (type->declaration->id != CTF_TYPE_VARIANT) ||
- bt_ctf_field_type_validate(field_type)) {
+ (type->declaration->id != CTF_TYPE_VARIANT)) {
ret = -1;
goto end;
}
{
struct bt_ctf_field_type_array *array = NULL;
- if (!element_type || length == 0 ||
- bt_ctf_field_type_validate(element_type)) {
+ if (!element_type || length == 0) {
goto error;
}
{
struct bt_ctf_field_type_sequence *sequence = NULL;
- if (!element_type || bt_ctf_validate_identifier(length_field_name) ||
- bt_ctf_field_type_validate(element_type)) {
+ if (!element_type || bt_ctf_validate_identifier(length_field_name)) {
goto error;
}
goto end;
}
+ /* Make sure field type is valid before serializing it */
+ ret = bt_ctf_field_type_validate(type);
+
+ if (ret) {
+ goto end;
+ }
+
ret = type->serialize(type, context);
end:
return ret;
return copy;
}
-BT_HIDDEN
-struct bt_ctf_field_path *bt_ctf_field_path_create(void)
-{
- struct bt_ctf_field_path *field_path = NULL;
-
- field_path = g_new0(struct bt_ctf_field_path, 1);
- if (!field_path) {
- goto end;
- }
-
- field_path->root = CTF_NODE_UNKNOWN;
- field_path->path_indexes = g_array_new(TRUE, FALSE, sizeof(int));
- if (!field_path->path_indexes) {
- bt_ctf_field_path_destroy(field_path);
- field_path = NULL;
- }
-end:
- return field_path;
-}
-
-
-BT_HIDDEN
-struct bt_ctf_field_path *bt_ctf_field_path_copy(
- struct bt_ctf_field_path *path)
-{
- struct bt_ctf_field_path *new_path = bt_ctf_field_path_create();
-
- if (!new_path) {
- goto end;
- }
-
- new_path->root = path->root;
- g_array_insert_vals(new_path->path_indexes, 0,
- path->path_indexes->data, path->path_indexes->len);
-end:
- return new_path;
-}
-
-BT_HIDDEN
-void bt_ctf_field_path_destroy(struct bt_ctf_field_path *path)
-{
- if (!path) {
- return;
- }
-
- if (path->path_indexes) {
- g_array_free(path->path_indexes, TRUE);
- }
- g_free(path);
-}
-
BT_HIDDEN
int bt_ctf_field_type_structure_get_field_name_index(
struct bt_ctf_field_type *type, const char *name)
sequence = container_of(type, struct bt_ctf_field_type_sequence,
parent);
- if (sequence->length_field_path) {
- bt_ctf_field_path_destroy(sequence->length_field_path);
- }
- sequence->length_field_path = path;
+ bt_get(path);
+ BT_MOVE(sequence->length_field_path, path);
end:
return ret;
}
-BT_HIDDEN
-struct bt_ctf_field_path *bt_ctf_field_type_sequence_get_length_field_path(
- struct bt_ctf_field_type *type)
-{
- struct bt_ctf_field_type_sequence *sequence;
-
- sequence = container_of(type, struct bt_ctf_field_type_sequence,
- parent);
-
- return sequence->length_field_path;
-}
-
BT_HIDDEN
int bt_ctf_field_type_variant_set_tag_field_path(struct bt_ctf_field_type *type,
struct bt_ctf_field_path *path)
variant = container_of(type, struct bt_ctf_field_type_variant,
parent);
- if (variant->tag_path) {
- bt_ctf_field_path_destroy(variant->tag_path);
- }
- variant->tag_path = path;
+ bt_get(path);
+ BT_MOVE(variant->tag_field_path, path);
end:
return ret;
}
BT_HIDDEN
-struct bt_ctf_field_path *bt_ctf_field_type_variant_get_tag_field_path(
- struct bt_ctf_field_type *type)
-{
- struct bt_ctf_field_type_variant *variant;
-
- variant = container_of(type, struct bt_ctf_field_type_variant,
- parent);
-
- return variant->tag_path;
-}
-
-BT_HIDDEN
-int bt_ctf_field_type_variant_set_tag(struct bt_ctf_field_type *type,
+int bt_ctf_field_type_variant_set_tag_field_type(struct bt_ctf_field_type *type,
struct bt_ctf_field_type *tag)
{
int ret = 0;
struct bt_ctf_field_type_variant *variant;
- if (!type || !tag || type->frozen ||
- bt_ctf_field_type_get_type_id(tag) != CTF_TYPE_ENUM) {
+ if (!type || !tag ||
+ bt_ctf_field_type_get_type_id(tag) != CTF_TYPE_ENUM) {
ret = -1;
goto end;
}
g_hash_table_destroy(variant->field_name_to_index);
g_string_free(variant->tag_name, TRUE);
bt_put(&variant->tag->parent);
- bt_ctf_field_path_destroy(variant->tag_path);
+ BT_PUT(variant->tag_field_path);
g_free(variant);
}
bt_put(sequence->element_type);
g_string_free(sequence->length_field_name, TRUE);
- bt_ctf_field_path_destroy(sequence->length_field_path);
+ BT_PUT(sequence->length_field_path);
g_free(sequence);
}
struct bt_ctf_field_type *container_type;
int container_signed;
- ret = bt_ctf_field_type_validate(type);
- if (ret) {
- goto end;
- }
-
container_type = bt_ctf_field_type_enumeration_get_container_type(type);
if (!container_type) {
ret = -1;
copy_float->mantissa = floating_point->mantissa;
copy_float->exp = floating_point->exp;
copy_float->user_byte_order = floating_point->user_byte_order;
+ copy_float->declaration.sign = ©_float->sign;
+ copy_float->declaration.mantissa = ©_float->mantissa;
+ copy_float->declaration.exp = ©_float->exp;
end:
return copy;
}
}
copy_variant->declaration = variant->declaration;
- if (variant->tag_path) {
- copy_variant->tag_path = bt_ctf_field_path_copy(
- variant->tag_path);
- if (!copy_variant->tag_path) {
+ if (variant->tag_field_path) {
+ copy_variant->tag_field_path = bt_ctf_field_path_copy(
+ variant->tag_field_path);
+ if (!copy_variant->tag_field_path) {
goto error;
}
}
if (ret) {
goto end;
}
-
- ret = 1;
}
/* Equal */
if (ret) {
goto end;
}
-
- ret = 1;
}
/* Equal */
end:
return ret;
}
+
+BT_HIDDEN
+int bt_ctf_field_type_get_field_count(struct bt_ctf_field_type *field_type)
+{
+ int field_count = -1;
+ enum ctf_type_id type_id = bt_ctf_field_type_get_type_id(field_type);
+
+ switch (type_id) {
+ case CTF_TYPE_STRUCT:
+ field_count =
+ bt_ctf_field_type_structure_get_field_count(field_type);
+ break;
+ case CTF_TYPE_VARIANT:
+ field_count =
+ bt_ctf_field_type_variant_get_field_count(field_type);
+ break;
+ case CTF_TYPE_ARRAY:
+ case CTF_TYPE_SEQUENCE:
+ /*
+ * Array and sequence types always contain a single member
+ * (the element type).
+ */
+ field_count = 1;
+ break;
+ default:
+ break;
+ }
+
+ return field_count;
+}
+
+BT_HIDDEN
+struct bt_ctf_field_type *bt_ctf_field_type_get_field_at_index(
+ struct bt_ctf_field_type *field_type, int index)
+{
+ struct bt_ctf_field_type *field = NULL;
+ enum ctf_type_id type_id = bt_ctf_field_type_get_type_id(field_type);
+
+ switch (type_id) {
+ case CTF_TYPE_STRUCT:
+ bt_ctf_field_type_structure_get_field(field_type, NULL, &field,
+ index);
+ break;
+ case CTF_TYPE_VARIANT:
+ bt_ctf_field_type_variant_get_field(field_type, NULL,
+ &field, index);
+ break;
+ case CTF_TYPE_ARRAY:
+ field = bt_ctf_field_type_array_get_element_type(field_type);
+ break;
+ case CTF_TYPE_SEQUENCE:
+ field = bt_ctf_field_type_sequence_get_element_type(field_type);
+ break;
+ default:
+ break;
+ }
+
+ return field;
+}
+
+BT_HIDDEN
+int bt_ctf_field_type_get_field_index(struct bt_ctf_field_type *field_type,
+ const char *name)
+{
+ int field_index = -1;
+ enum ctf_type_id type_id = bt_ctf_field_type_get_type_id(field_type);
+
+ switch (type_id) {
+ case CTF_TYPE_STRUCT:
+ field_index = bt_ctf_field_type_structure_get_field_name_index(
+ field_type, name);
+ break;
+ case CTF_TYPE_VARIANT:
+ field_index = bt_ctf_field_type_variant_get_field_name_index(
+ field_type, name);
+ break;
+ default:
+ break;
+ }
+
+ return field_index;
+}
+
+struct bt_ctf_field_path *bt_ctf_field_type_variant_get_tag_field_path(
+ struct bt_ctf_field_type *type)
+{
+ struct bt_ctf_field_path *field_path = NULL;
+ struct bt_ctf_field_type_variant *variant;
+
+ if (!type || !bt_ctf_field_type_is_variant(type)) {
+ goto end;
+ }
+
+ variant = container_of(type, struct bt_ctf_field_type_variant,
+ parent);
+ field_path = bt_get(variant->tag_field_path);
+end:
+ return field_path;
+}
+
+struct bt_ctf_field_path *bt_ctf_field_type_sequence_get_length_field_path(
+ struct bt_ctf_field_type *type)
+{
+ struct bt_ctf_field_path *field_path = NULL;
+ struct bt_ctf_field_type_sequence *sequence;
+
+ if (!type || !bt_ctf_field_type_is_sequence(type)) {
+ goto end;
+ }
+
+ sequence = container_of(type, struct bt_ctf_field_type_sequence,
+ parent);
+ field_path = bt_get(sequence->length_field_path);
+end:
+ return field_path;
+}