Fix: ir: disallow setting the alignment of certain types
[babeltrace.git] / formats / ctf / ir / event-types.c
index 9b78c0dbfd5b43f02b0ad9184c5b7337ba26897e..40c26da01d47cbed5966f1318712dc2529007d8e 100644 (file)
@@ -1172,11 +1172,6 @@ int bt_ctf_field_type_structure_add_field(struct bt_ctf_field_type *type,
                ret = -1;
                goto end;
        }
-
-       if (type->declaration->alignment < field_type->declaration->alignment) {
-               type->declaration->alignment =
-                       field_type->declaration->alignment;
-       }
 end:
        return ret;
 }
@@ -1207,8 +1202,7 @@ int bt_ctf_field_type_structure_get_field(struct bt_ctf_field_type *type,
        struct structure_field *field;
        int ret = 0;
 
-       if (!type || index < 0 || !field_name || !field_type ||
-               (type->declaration->id != CTF_TYPE_STRUCT)) {
+       if (!type || index < 0 || (type->declaration->id != CTF_TYPE_STRUCT)) {
                ret = -1;
                goto end;
        }
@@ -1221,9 +1215,13 @@ int bt_ctf_field_type_structure_get_field(struct bt_ctf_field_type *type,
        }
 
        field = g_ptr_array_index(structure->fields, index);
-       *field_type = field->type;
-       bt_ctf_field_type_get(field->type);
-       *field_name = g_quark_to_string(field->name);
+       if (field_type) {
+               *field_type = field->type;
+               bt_ctf_field_type_get(field->type);
+       }
+       if (field_name) {
+               *field_name = g_quark_to_string(field->name);
+       }
 end:
        return ret;
 }
@@ -1484,8 +1482,7 @@ int bt_ctf_field_type_variant_get_field(struct bt_ctf_field_type *type,
        struct structure_field *field;
        int ret = 0;
 
-       if (!type || index < 0 || !field_name || !field_type ||
-               (type->declaration->id != CTF_TYPE_VARIANT)) {
+       if (!type || index < 0 || (type->declaration->id != CTF_TYPE_VARIANT)) {
                ret = -1;
                goto end;
        }
@@ -1498,9 +1495,13 @@ int bt_ctf_field_type_variant_get_field(struct bt_ctf_field_type *type,
        }
 
        field = g_ptr_array_index(variant->fields, index);
-       *field_type = field->type;
-       bt_ctf_field_type_get(field->type);
-       *field_name = g_quark_to_string(field->name);
+       if (field_type) {
+               *field_type = field->type;
+               bt_ctf_field_type_get(field->type);
+       }
+       if (field_name) {
+               *field_name = g_quark_to_string(field->name);
+       }
 end:
        return ret;
 }
@@ -1528,8 +1529,6 @@ struct bt_ctf_field_type *bt_ctf_field_type_array_create(
        array->element_type = element_type;
        array->length = length;
        bt_ctf_field_type_init(&array->parent);
-       array->parent.declaration->alignment =
-               element_type->declaration->alignment;
        return &array->parent;
 error:
        return NULL;
@@ -1590,8 +1589,6 @@ struct bt_ctf_field_type *bt_ctf_field_type_sequence_create(
        sequence->element_type = element_type;
        sequence->length_field_name = g_string_new(length_field_name);
        bt_ctf_field_type_init(&sequence->parent);
-       sequence->parent.declaration->alignment =
-               element_type->declaration->alignment;
        return &sequence->parent;
 error:
        return NULL;
@@ -1688,13 +1685,91 @@ end:
 int bt_ctf_field_type_get_alignment(struct bt_ctf_field_type *type)
 {
        int ret;
+       enum ctf_type_id type_id;
 
        if (!type) {
                ret = -1;
                goto end;
        }
 
-       ret = (int) type->declaration->alignment;
+       if (type->frozen) {
+               ret = (int) type->declaration->alignment;
+               goto end;
+       }
+
+       type_id = bt_ctf_field_type_get_type_id(type);
+       switch (type_id) {
+       case CTF_TYPE_SEQUENCE:
+       {
+               struct bt_ctf_field_type *element =
+                       bt_ctf_field_type_sequence_get_element_type(type);
+
+               if (!element) {
+                       ret = -1;
+                       goto end;
+               }
+
+               ret = bt_ctf_field_type_get_alignment(element);
+               bt_ctf_field_type_put(element);
+               break;
+       }
+       case CTF_TYPE_ARRAY:
+       {
+               struct bt_ctf_field_type *element =
+                       bt_ctf_field_type_array_get_element_type(type);
+
+               if (!element) {
+                       ret = -1;
+                       goto end;
+               }
+
+               ret = bt_ctf_field_type_get_alignment(element);
+               bt_ctf_field_type_put(element);
+               break;
+       }
+       case CTF_TYPE_STRUCT:
+       {
+               int i, element_count;
+
+               element_count = bt_ctf_field_type_structure_get_field_count(
+                       type);
+               if (element_count < 0) {
+                       ret = element_count;
+                       goto end;
+               }
+
+               for (i = 0; i < element_count; i++) {
+                       struct bt_ctf_field_type *field;
+                       int field_alignment;
+
+                       ret = bt_ctf_field_type_structure_get_field(type, NULL,
+                               &field, i);
+                       if (ret) {
+                               goto end;
+                       }
+
+                       assert(field);
+                       field_alignment = bt_ctf_field_type_get_alignment(
+                               field);
+                       bt_ctf_field_type_put(field);
+                       if (field_alignment < 0) {
+                               ret = field_alignment;
+                               goto end;
+                       }
+
+                       type->declaration->alignment = MAX(field_alignment,
+                               type->declaration->alignment);
+               }
+               ret = (int) type->declaration->alignment;
+               break;
+       }
+       case CTF_TYPE_UNKNOWN:
+               ret = -1;
+               break;
+       default:
+               ret = (int) type->declaration->alignment;
+               break;
+       }
 end:
        return ret;
 }
@@ -1703,6 +1778,7 @@ int bt_ctf_field_type_set_alignment(struct bt_ctf_field_type *type,
                unsigned int alignment)
 {
        int ret = 0;
+       enum ctf_type_id type_id;
 
        /* Alignment must be bit-aligned (1) or byte aligned */
        if (!type || type->frozen || (alignment != 1 && (alignment & 0x7))) {
@@ -1710,12 +1786,25 @@ int bt_ctf_field_type_set_alignment(struct bt_ctf_field_type *type,
                goto end;
        }
 
+       type_id = bt_ctf_field_type_get_type_id(type);
+       if (type_id == CTF_TYPE_UNKNOWN) {
+               ret = -1;
+               goto end;
+       }
+
        if (type->declaration->id == CTF_TYPE_STRING &&
                alignment != CHAR_BIT) {
                ret = -1;
                goto end;
        }
 
+       if (type_id == CTF_TYPE_STRUCT || type_id == CTF_TYPE_VARIANT ||
+               type_id == CTF_TYPE_SEQUENCE || type_id == CTF_TYPE_ARRAY) {
+               /* Setting an alignment on these types makes no sense */
+               ret = -1;
+               goto end;
+       }
+
        type->declaration->alignment = alignment;
        ret = 0;
 end:
@@ -1955,6 +2044,56 @@ end:
        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(
@@ -2021,6 +2160,77 @@ int bt_ctf_field_type_variant_get_field_name_index(
 end:
        return ret;
 }
+
+BT_HIDDEN
+int bt_ctf_field_type_sequence_set_length_field_path(
+               struct bt_ctf_field_type *type,
+               struct bt_ctf_field_path *path)
+{
+       int ret = 0;
+       struct bt_ctf_field_type_sequence *sequence;
+
+       if (!type || bt_ctf_field_type_get_type_id(type) != CTF_TYPE_SEQUENCE) {
+               ret = -1;
+               goto end;
+       }
+
+       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;
+end:
+       return ret;
+}
+
+BT_HIDDEN
+int bt_ctf_field_type_variant_set_tag_field_path(struct bt_ctf_field_type *type,
+               struct bt_ctf_field_path *path)
+{
+       int ret = 0;
+       struct bt_ctf_field_type_variant *variant;
+
+       if (!type || bt_ctf_field_type_get_type_id(type) != CTF_TYPE_VARIANT) {
+               ret = -1;
+               goto end;
+       }
+
+       variant = container_of(type, struct bt_ctf_field_type_variant,
+               parent);
+       if (variant->tag_path) {
+               bt_ctf_field_path_destroy(variant->tag_path);
+       }
+       variant->tag_path = path;
+end:
+       return ret;
+}
+
+BT_HIDDEN
+int bt_ctf_field_type_variant_set_tag(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) {
+               ret = -1;
+               goto end;
+       }
+
+       variant = container_of(type, struct bt_ctf_field_type_variant,
+               parent);
+       bt_ctf_field_type_get(tag);
+       if (variant->tag) {
+               bt_ctf_field_type_put(&variant->tag->parent);
+       }
+       variant->tag = container_of(tag, struct bt_ctf_field_type_enumeration,
+               parent);
+end:
+       return ret;
+}
+
 static
 void bt_ctf_field_type_integer_destroy(struct bt_ctf_ref *ref)
 {
@@ -2104,6 +2314,7 @@ void bt_ctf_field_type_variant_destroy(struct bt_ctf_ref *ref)
        g_hash_table_destroy(variant->field_name_to_index);
        g_string_free(variant->tag_name, TRUE);
        bt_ctf_field_type_put(&variant->tag->parent);
+       bt_ctf_field_path_destroy(variant->tag_path);
        g_free(variant);
 }
 
@@ -2137,6 +2348,7 @@ void bt_ctf_field_type_sequence_destroy(struct bt_ctf_ref *ref)
                struct bt_ctf_field_type_sequence, parent);
        bt_ctf_field_type_put(sequence->element_type);
        g_string_free(sequence->length_field_name, TRUE);
+       bt_ctf_field_path_destroy(sequence->length_field_path);
        g_free(sequence);
 }
 
@@ -2183,9 +2395,11 @@ void bt_ctf_field_type_structure_freeze(struct bt_ctf_field_type *type)
        struct bt_ctf_field_type_structure *structure_type = container_of(
                type, struct bt_ctf_field_type_structure, parent);
 
+       /* Cache the alignment */
+       type->declaration->alignment = bt_ctf_field_type_get_alignment(type);
        generic_field_type_freeze(type);
-       g_ptr_array_foreach(structure_type->fields, (GFunc)freeze_structure_field,
-               NULL);
+       g_ptr_array_foreach(structure_type->fields,
+               (GFunc) freeze_structure_field, NULL);
 }
 
 static
@@ -2194,9 +2408,11 @@ void bt_ctf_field_type_variant_freeze(struct bt_ctf_field_type *type)
        struct bt_ctf_field_type_variant *variant_type = container_of(
                type, struct bt_ctf_field_type_variant, parent);
 
+       /* Cache the alignment */
+       type->declaration->alignment = bt_ctf_field_type_get_alignment(type);
        generic_field_type_freeze(type);
-       g_ptr_array_foreach(variant_type->fields, (GFunc)freeze_structure_field,
-               NULL);
+       g_ptr_array_foreach(variant_type->fields,
+               (GFunc) freeze_structure_field, NULL);
 }
 
 static
@@ -2205,6 +2421,8 @@ void bt_ctf_field_type_array_freeze(struct bt_ctf_field_type *type)
        struct bt_ctf_field_type_array *array_type = container_of(
                type, struct bt_ctf_field_type_array, parent);
 
+       /* Cache the alignment */
+       type->declaration->alignment = bt_ctf_field_type_get_alignment(type);
        generic_field_type_freeze(type);
        bt_ctf_field_type_freeze(array_type->element_type);
 }
@@ -2215,6 +2433,8 @@ void bt_ctf_field_type_sequence_freeze(struct bt_ctf_field_type *type)
        struct bt_ctf_field_type_sequence *sequence_type = container_of(
                type, struct bt_ctf_field_type_sequence, parent);
 
+       /* Cache the alignment */
+       type->declaration->alignment = bt_ctf_field_type_get_alignment(type);
        generic_field_type_freeze(type);
        bt_ctf_field_type_freeze(sequence_type->element_type);
 }
@@ -2920,6 +3140,13 @@ struct bt_ctf_field_type *bt_ctf_field_type_variant_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) {
+                       goto error;
+               }
+       }
 end:
        if (copy_tag) {
                bt_ctf_field_type_put(copy_tag);
@@ -2989,12 +3216,25 @@ struct bt_ctf_field_type *bt_ctf_field_type_sequence_copy(
        copy_sequence = container_of(copy, struct bt_ctf_field_type_sequence,
                parent);
        copy_sequence->declaration = sequence->declaration;
+       if (sequence->length_field_path) {
+               copy_sequence->length_field_path = bt_ctf_field_path_copy(
+                       sequence->length_field_path);
+               if (!copy_sequence->length_field_path) {
+                       goto error;
+               }
+       }
 end:
        if (copy_element) {
                bt_ctf_field_type_put(copy_element);
        }
 
        return copy;
+error:
+       if (copy) {
+               bt_ctf_field_type_put(copy);
+               copy = NULL;
+       }
+       goto end;
 }
 
 static
This page took 0.027449 seconds and 4 git commands to generate.