Fix: memory leak when using mapping iterator
[babeltrace.git] / formats / ctf / ir / fields.c
index 93e9486c504b158a31e363b59c9f1b6bc4f4b80f..412b7fdef065cc3adf0cf80bd3d35f32a5d811bb 100644 (file)
@@ -148,6 +148,32 @@ 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
+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 *);
+static
+void bt_ctf_field_array_freeze(struct bt_ctf_field *);
+static
+void bt_ctf_field_sequence_freeze(struct bt_ctf_field *);
+
+static
+bool bt_ctf_field_generic_is_set(struct bt_ctf_field *);
+static
+bool bt_ctf_field_structure_is_set(struct bt_ctf_field *);
+static
+bool bt_ctf_field_variant_is_set(struct bt_ctf_field *);
+static
+bool bt_ctf_field_enumeration_is_set(struct bt_ctf_field *);
+static
+bool bt_ctf_field_array_is_set(struct bt_ctf_field *);
+static
+bool bt_ctf_field_sequence_is_set(struct bt_ctf_field *);
+
 static
 int increase_packet_size(struct ctf_stream_pos *pos);
 
@@ -229,6 +255,30 @@ int (* const field_copy_funcs[])(struct bt_ctf_field *,
        [BT_CTF_TYPE_ID_STRING] = bt_ctf_field_string_copy,
 };
 
+static
+void (* const field_freeze_funcs[])(struct bt_ctf_field *) = {
+       [BT_CTF_TYPE_ID_INTEGER] = generic_field_freeze,
+       [BT_CTF_TYPE_ID_FLOAT] = generic_field_freeze,
+       [BT_CTF_TYPE_ID_STRING] = generic_field_freeze,
+       [BT_CTF_TYPE_ID_ENUM] = bt_ctf_field_enumeration_freeze,
+       [BT_CTF_TYPE_ID_STRUCT] = bt_ctf_field_structure_freeze,
+       [BT_CTF_TYPE_ID_VARIANT] = bt_ctf_field_variant_freeze,
+       [BT_CTF_TYPE_ID_ARRAY] = bt_ctf_field_array_freeze,
+       [BT_CTF_TYPE_ID_SEQUENCE] = bt_ctf_field_sequence_freeze,
+};
+
+static
+bool (* const field_is_set_funcs[])(struct bt_ctf_field *) = {
+       [BT_CTF_TYPE_ID_INTEGER] = bt_ctf_field_generic_is_set,
+       [BT_CTF_TYPE_ID_ENUM] = bt_ctf_field_enumeration_is_set,
+       [BT_CTF_TYPE_ID_FLOAT] = bt_ctf_field_generic_is_set,
+       [BT_CTF_TYPE_ID_STRUCT] = bt_ctf_field_structure_is_set,
+       [BT_CTF_TYPE_ID_VARIANT] = bt_ctf_field_variant_is_set,
+       [BT_CTF_TYPE_ID_ARRAY] = bt_ctf_field_array_is_set,
+       [BT_CTF_TYPE_ID_SEQUENCE] = bt_ctf_field_sequence_is_set,
+       [BT_CTF_TYPE_ID_STRING] = bt_ctf_field_generic_is_set,
+};
+
 struct bt_ctf_field *bt_ctf_field_create(struct bt_ctf_field_type *type)
 {
        struct bt_ctf_field *field = NULL;
@@ -375,7 +425,7 @@ int bt_ctf_field_sequence_set_length(struct bt_ctf_field *field,
        struct bt_ctf_field_sequence *sequence;
        uint64_t sequence_length;
 
-       if (!field || !length_field) {
+       if (!field || !length_field || field->frozen) {
                ret = -1;
                goto end;
        }
@@ -447,6 +497,11 @@ struct bt_ctf_field *bt_ctf_field_structure_get_field(
                goto end;
        }
 
+       /* We don't want to modify this field if it's frozen */
+       if (field->frozen) {
+               goto end;
+       }
+
        new_field = bt_ctf_field_create(field_type);
        if (!new_field) {
                goto error;
@@ -488,6 +543,11 @@ struct bt_ctf_field *bt_ctf_field_structure_get_field_by_index(
                goto end;
        }
 
+       /* We don't want to modify this field if it's frozen */
+       if (field->frozen) {
+               goto end;
+       }
+
        /* Field has not been instanciated yet, create it */
        structure_type = bt_ctf_field_get_type(field);
        if (!structure_type) {
@@ -524,7 +584,7 @@ int bt_ctf_field_structure_set_field(struct bt_ctf_field *field,
        struct bt_ctf_field_type *expected_field_type = NULL;
        size_t index;
 
-       if (!field || !name || !value ||
+       if (!field || !name || !value || field->frozen ||
                bt_ctf_field_type_get_type_id(field->type) !=
                        BT_CTF_TYPE_ID_STRUCT) {
                ret = -1;
@@ -583,6 +643,11 @@ struct bt_ctf_field *bt_ctf_field_array_get_field(struct bt_ctf_field *field,
                goto end;
        }
 
+       /* We don't want to modify this field if it's frozen */
+       if (field->frozen) {
+               goto end;
+       }
+
        new_field = bt_ctf_field_create(field_type);
        array->elements->pdata[(size_t)index] = new_field;
 end:
@@ -618,6 +683,11 @@ struct bt_ctf_field *bt_ctf_field_sequence_get_field(struct bt_ctf_field *field,
                goto end;
        }
 
+       /* We don't want to modify this field if it's frozen */
+       if (field->frozen) {
+               goto end;
+       }
+
        new_field = bt_ctf_field_create(field_type);
        sequence->elements->pdata[(size_t) index] = new_field;
 end:
@@ -691,6 +761,11 @@ struct bt_ctf_field *bt_ctf_field_variant_get_field(struct bt_ctf_field *field,
                }
        }
 
+       /* We don't want to modify this field if it's frozen */
+       if (field->frozen) {
+               goto end;
+       }
+
        field_type = bt_ctf_field_type_variant_get_field_type_signed(
                variant_type, tag_enum_value);
        if (!field_type) {
@@ -738,6 +813,27 @@ 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_ctf_field_type_get_type_id(variant_field->type) !=
+                       BT_CTF_TYPE_ID_VARIANT) {
+               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)
 {
@@ -752,6 +848,11 @@ struct bt_ctf_field *bt_ctf_field_enumeration_get_container(
        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) {
+                       goto end;
+               }
+
                struct bt_ctf_field_type_enumeration *enumeration_type =
                        container_of(field->type,
                        struct bt_ctf_field_type_enumeration, parent);
@@ -765,7 +866,7 @@ end:
        return container;
 }
 
-const char *bt_ctf_field_enumeration_get_mapping_name(
+const char *bt_ctf_field_enumeration_get_single_mapping_name(
        struct bt_ctf_field *field)
 {
        int ret;
@@ -773,7 +874,7 @@ const char *bt_ctf_field_enumeration_get_mapping_name(
        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 *enumeration_type = NULL;
+       struct bt_ctf_field_type_enumeration_mapping_iterator *iter = NULL;
 
        container = bt_ctf_field_enumeration_get_container(field);
        if (!container) {
@@ -787,29 +888,37 @@ const char *bt_ctf_field_enumeration_get_mapping_name(
 
        integer_type = container_of(container_type,
                struct bt_ctf_field_type_integer, parent);
-       enumeration_type = container_of(field->type,
-               struct bt_ctf_field_type_enumeration, parent);
 
        if (!integer_type->declaration.signedness) {
                uint64_t value;
+
                ret = bt_ctf_field_unsigned_integer_get_value(container,
                      &value);
                if (ret) {
                        goto error_put_container_type;
                }
-
-               name = bt_ctf_field_type_enumeration_get_mapping_name_unsigned(
-                       enumeration_type, value);
+               iter = bt_ctf_field_type_enumeration_find_mappings_by_unsigned_value(
+                               field->type, value);
+               if (!iter) {
+                       goto error_put_container_type;
+               }
+               (void) bt_ctf_field_type_enumeration_mapping_iterator_get_unsigned(
+                               iter, &name, NULL, NULL);
        } else {
                int64_t value;
+
                ret = bt_ctf_field_signed_integer_get_value(container,
                      &value);
                if (ret) {
                        goto error_put_container_type;
                }
-
-               name = bt_ctf_field_type_enumeration_get_mapping_name_signed(
-                       enumeration_type, value);
+               iter = bt_ctf_field_type_enumeration_find_mappings_by_signed_value(
+                               field->type, value);
+               if (!iter) {
+                       goto error_put_container_type;
+               }
+               (void) bt_ctf_field_type_enumeration_mapping_iterator_get_signed(
+                               iter, &name, NULL, NULL);
        }
 
 error_put_container_type:
@@ -817,6 +926,7 @@ error_put_container_type:
 error_put_container:
        bt_put(container);
 end:
+       bt_put(iter);
        return name;
 }
 
@@ -857,7 +967,7 @@ int bt_ctf_field_signed_integer_set_value(struct bt_ctf_field *field,
        unsigned int size;
        int64_t min_value, max_value;
 
-       if (!field ||
+       if (!field || field->frozen ||
                bt_ctf_field_type_get_type_id(field->type) !=
                        BT_CTF_TYPE_ID_INTEGER) {
                ret = -1;
@@ -873,8 +983,8 @@ int bt_ctf_field_signed_integer_set_value(struct bt_ctf_field *field,
        }
 
        size = integer_type->declaration.len;
-       min_value = -((int64_t)1 << (size - 1));
-       max_value = ((int64_t)1 << (size - 1)) - 1;
+       min_value = -(1ULL << (size - 1));
+       max_value = (1ULL << (size - 1)) - 1;
        if (value < min_value || value > max_value) {
                ret = -1;
                goto end;
@@ -923,7 +1033,7 @@ int bt_ctf_field_unsigned_integer_set_value(struct bt_ctf_field *field,
        unsigned int size;
        uint64_t max_value;
 
-       if (!field ||
+       if (!field || field->frozen ||
                bt_ctf_field_type_get_type_id(field->type) !=
                        BT_CTF_TYPE_ID_INTEGER) {
                ret = -1;
@@ -939,7 +1049,7 @@ int bt_ctf_field_unsigned_integer_set_value(struct bt_ctf_field *field,
        }
 
        size = integer_type->declaration.len;
-       max_value = (size == 64) ? UINT64_MAX : ((uint64_t)1 << size) - 1;
+       max_value = (size == 64) ? UINT64_MAX : ((uint64_t) 1 << size) - 1;
        if (value > max_value) {
                ret = -1;
                goto end;
@@ -977,7 +1087,7 @@ int bt_ctf_field_floating_point_set_value(struct bt_ctf_field *field,
        int ret = 0;
        struct bt_ctf_field_floating_point *floating_point;
 
-       if (!field ||
+       if (!field || field->frozen ||
                bt_ctf_field_type_get_type_id(field->type) !=
                        BT_CTF_TYPE_ID_FLOAT) {
                ret = -1;
@@ -1015,7 +1125,7 @@ int bt_ctf_field_string_set_value(struct bt_ctf_field *field,
        int ret = 0;
        struct bt_ctf_field_string *string;
 
-       if (!field || !value ||
+       if (!field || !value || field->frozen ||
                bt_ctf_field_type_get_type_id(field->type) !=
                        BT_CTF_TYPE_ID_STRING) {
                ret = -1;
@@ -1040,7 +1150,7 @@ int bt_ctf_field_string_append(struct bt_ctf_field *field,
        int ret = 0;
        struct bt_ctf_field_string *string_field;
 
-       if (!field || !value ||
+       if (!field || !value || field->frozen ||
                bt_ctf_field_type_get_type_id(field->type) !=
                        BT_CTF_TYPE_ID_STRING) {
                ret = -1;
@@ -1069,7 +1179,7 @@ int bt_ctf_field_string_append_len(struct bt_ctf_field *field,
        unsigned int effective_length = length;
        struct bt_ctf_field_string *string_field;
 
-       if (!field || !value ||
+       if (!field || !value || field->frozen ||
                bt_ctf_field_type_get_type_id(field->type) !=
                        BT_CTF_TYPE_ID_STRING) {
                ret = -1;
@@ -1167,6 +1277,27 @@ end:
        return ret;
 }
 
+
+BT_HIDDEN
+bool bt_ctf_field_is_set(struct bt_ctf_field *field)
+{
+       bool is_set = false;
+       enum bt_ctf_type_id type_id;
+
+       if (!field) {
+               goto end;
+       }
+
+       type_id = bt_ctf_field_type_get_type_id(field->type);
+       if (type_id <= BT_CTF_TYPE_ID_UNKNOWN || type_id >= BT_CTF_NR_TYPE_IDS) {
+               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;
@@ -1516,6 +1647,15 @@ int bt_ctf_field_structure_validate(struct bt_ctf_field *field)
        for (i = 0; i < structure->fields->len; i++) {
                ret = bt_ctf_field_validate(structure->fields->pdata[i]);
                if (ret) {
+                       const char *name;
+                       struct bt_ctf_field_type *field_type =
+                                       bt_ctf_field_get_type(field);
+
+                       (void) bt_ctf_field_type_structure_get_field(field_type,
+                                       &name, NULL, i);
+                       fprintf(stderr, "Field %s failed validation\n",
+                                       name ? name : "NULL");
+                       bt_put(field_type);
                        goto end;
                }
        }
@@ -1556,6 +1696,7 @@ int bt_ctf_field_array_validate(struct bt_ctf_field *field)
        for (i = 0; i < array->elements->len; i++) {
                ret = bt_ctf_field_validate(array->elements->pdata[i]);
                if (ret) {
+                       fprintf(stderr, "Failed to validate array field #%zu\n", i);
                        goto end;
                }
        }
@@ -1579,6 +1720,7 @@ int bt_ctf_field_sequence_validate(struct bt_ctf_field *field)
        for (i = 0; i < sequence->elements->len; i++) {
                ret = bt_ctf_field_validate(sequence->elements->pdata[i]);
                if (ret) {
+                       fprintf(stderr, "Failed to validate sequence field #%zu\n", i);
                        goto end;
                }
        }
@@ -1854,6 +1996,15 @@ int bt_ctf_field_structure_serialize(struct bt_ctf_field *field,
 
                ret = bt_ctf_field_serialize(field, pos);
                if (ret) {
+                       const char *name;
+                       struct bt_ctf_field_type *field_type =
+                                       bt_ctf_field_get_type(field);
+
+                       (void) bt_ctf_field_type_structure_get_field(field_type,
+                                       &name, NULL, i);
+                       fprintf(stderr, "Field %s failed to serialize\n",
+                                       name ? name : "NULL");
+                       bt_put(field_type);
                        break;
                }
        }
@@ -1884,6 +2035,7 @@ int bt_ctf_field_array_serialize(struct bt_ctf_field *field,
                ret = bt_ctf_field_serialize(
                        g_ptr_array_index(array->elements, i), pos);
                if (ret) {
+                       fprintf(stderr, "Failed to serialize array element #%zu\n", i);
                        goto end;
                }
        }
@@ -1904,6 +2056,7 @@ int bt_ctf_field_sequence_serialize(struct bt_ctf_field *field,
                ret = bt_ctf_field_serialize(
                        g_ptr_array_index(sequence->elements, i), pos);
                if (ret) {
+                       fprintf(stderr, "Failed to serialize sequence element #%zu\n", i);
                        goto end;
                }
        }
@@ -2200,3 +2353,212 @@ int increase_packet_size(struct ctf_stream_pos *pos)
 end:
        return ret;
 }
+
+static
+void generic_field_freeze(struct bt_ctf_field *field)
+{
+       field->frozen = 1;
+}
+
+static
+void bt_ctf_field_enumeration_freeze(struct bt_ctf_field *field)
+{
+       struct bt_ctf_field_enumeration *enum_field =
+               container_of(field, struct bt_ctf_field_enumeration, parent);
+
+       bt_ctf_field_freeze(enum_field->payload);
+       generic_field_freeze(field);
+}
+
+static
+void bt_ctf_field_structure_freeze(struct bt_ctf_field *field)
+{
+       int i;
+       struct bt_ctf_field_structure *structure_field =
+               container_of(field, struct bt_ctf_field_structure, parent);
+
+       for (i = 0; i < structure_field->fields->len; i++) {
+               struct bt_ctf_field *field =
+                       g_ptr_array_index(structure_field->fields, i);
+
+               bt_ctf_field_freeze(field);
+       }
+
+       generic_field_freeze(field);
+}
+
+static
+void bt_ctf_field_variant_freeze(struct bt_ctf_field *field)
+{
+       struct bt_ctf_field_variant *variant_field =
+               container_of(field, struct bt_ctf_field_variant, parent);
+
+       bt_ctf_field_freeze(variant_field->tag);
+       bt_ctf_field_freeze(variant_field->payload);
+       generic_field_freeze(field);
+}
+
+static
+void bt_ctf_field_array_freeze(struct bt_ctf_field *field)
+{
+       int i;
+       struct bt_ctf_field_array *array_field =
+               container_of(field, struct bt_ctf_field_array, parent);
+
+       for (i = 0; i < array_field->elements->len; i++) {
+               struct bt_ctf_field *field =
+                       g_ptr_array_index(array_field->elements, i);
+
+               bt_ctf_field_freeze(field);
+       }
+
+       generic_field_freeze(field);
+}
+
+static
+void bt_ctf_field_sequence_freeze(struct bt_ctf_field *field)
+{
+       int i;
+       struct bt_ctf_field_sequence *sequence_field =
+               container_of(field, struct bt_ctf_field_sequence, parent);
+
+       bt_ctf_field_freeze(sequence_field->length);
+
+       for (i = 0; i < sequence_field->elements->len; i++) {
+               struct bt_ctf_field *field =
+                       g_ptr_array_index(sequence_field->elements, i);
+
+               bt_ctf_field_freeze(field);
+       }
+
+       generic_field_freeze(field);
+}
+
+BT_HIDDEN
+void bt_ctf_field_freeze(struct bt_ctf_field *field)
+{
+       enum bt_ctf_type_id type_id;
+
+       if (!field) {
+               goto end;
+       }
+
+       type_id = bt_ctf_field_get_type_id(field);
+       if (type_id <= BT_CTF_TYPE_ID_UNKNOWN ||
+                       type_id >= BT_CTF_NR_TYPE_IDS) {
+               goto end;
+       }
+
+       field_freeze_funcs[type_id](field);
+end:
+       return;
+}
+
+static
+bool bt_ctf_field_generic_is_set(struct bt_ctf_field *field)
+{
+       return field && field->payload_set;
+}
+
+static
+bool bt_ctf_field_enumeration_is_set(struct bt_ctf_field *field)
+{
+       bool is_set = 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
+bool bt_ctf_field_structure_is_set(struct bt_ctf_field *field)
+{
+       bool is_set = false;
+       size_t i;
+       struct bt_ctf_field_structure *structure;
+
+       if (!field) {
+               goto end;
+       }
+
+       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]);
+               if (!is_set) {
+                       goto end;
+               }
+       }
+end:
+       return is_set;
+}
+
+static
+bool bt_ctf_field_variant_is_set(struct bt_ctf_field *field)
+{
+       bool is_set = false;
+       struct bt_ctf_field_variant *variant;
+
+       if (!field) {
+               goto end;
+       }
+
+       variant = container_of(field, struct bt_ctf_field_variant, parent);
+       is_set = bt_ctf_field_is_set(variant->payload);
+end:
+       return is_set;
+}
+
+static
+bool bt_ctf_field_array_is_set(struct bt_ctf_field *field)
+{
+       size_t i;
+       bool is_set = false;
+       struct bt_ctf_field_array *array;
+
+       if (!field) {
+               goto end;
+       }
+
+       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]);
+               if (!is_set) {
+                       goto end;
+               }
+       }
+end:
+       return is_set;
+}
+
+static
+bool bt_ctf_field_sequence_is_set(struct bt_ctf_field *field)
+{
+       size_t i;
+       bool is_set = false;
+       struct bt_ctf_field_sequence *sequence;
+
+       if (!field) {
+               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]);
+               if (!is_set) {
+                       goto end;
+               }
+       }
+end:
+       return is_set;
+}
This page took 0.031541 seconds and 4 git commands to generate.