Fix: ir: return current variant's field if possible
[babeltrace.git] / formats / ctf / ir / event-fields.c
index a93cf695c6c5a86c50c41889cd254177b4563640..6220144a2b57bc94d216a73bf1de34f2adbb8388 100644 (file)
@@ -601,6 +601,31 @@ struct bt_ctf_field *bt_ctf_field_variant_get_field(struct bt_ctf_field *field,
        }
 
        tag_enum_value = tag_enum_integer->definition.value._signed;
+
+       /*
+        * If the variant currently has a tag and a payload, and if the
+        * requested tag value is the same as the current one, return
+        * the current payload instead of creating a fresh one.
+        */
+       if (variant->tag && variant->payload) {
+               struct bt_ctf_field *cur_tag_container = NULL;
+               struct bt_ctf_field_integer *cur_tag_enum_integer;
+               int64_t cur_tag_value;
+
+               cur_tag_container =
+                       bt_ctf_field_enumeration_get_container(variant->tag);
+               cur_tag_enum_integer = container_of(cur_tag_container,
+                       struct bt_ctf_field_integer, parent);
+               bt_ctf_field_put(cur_tag_container);
+               cur_tag_value = cur_tag_enum_integer->definition.value._signed;
+
+               if (cur_tag_value == tag_enum_value) {
+                       new_field = variant->payload;
+                       bt_ctf_field_get(new_field);
+                       goto end;
+               }
+       }
+
        field_type = bt_ctf_field_type_variant_get_field_type_signed(
                variant_type, tag_enum_value);
        if (!field_type) {
@@ -919,6 +944,72 @@ end:
        return ret;
 }
 
+int bt_ctf_field_string_append(struct bt_ctf_field *field,
+               const char *value)
+{
+       int ret = 0;
+       struct bt_ctf_field_string *string_field;
+
+       if (!field || !value ||
+               bt_ctf_field_type_get_type_id(field->type) !=
+                       CTF_TYPE_STRING) {
+               ret = -1;
+               goto end;
+       }
+
+       string_field = container_of(field, struct bt_ctf_field_string, parent);
+
+       if (string_field->payload) {
+               g_string_append(string_field->payload, value);
+       } else {
+               string_field->payload = g_string_new(value);
+       }
+
+       string_field->parent.payload_set = 1;
+
+end:
+       return ret;
+}
+
+int bt_ctf_field_string_append_len(struct bt_ctf_field *field,
+               const char *value, unsigned int length)
+{
+       int i;
+       int ret = 0;
+       unsigned int effective_length = length;
+       struct bt_ctf_field_string *string_field;
+
+       if (!field || !value ||
+               bt_ctf_field_type_get_type_id(field->type) !=
+                       CTF_TYPE_STRING) {
+               ret = -1;
+               goto end;
+       }
+
+       string_field = container_of(field, struct bt_ctf_field_string, parent);
+
+       /* make sure no null bytes are appended */
+       for (i = 0; i < length; ++i) {
+               if (value[i] == '\0') {
+                       effective_length = i;
+                       break;
+               }
+       }
+
+       if (string_field->payload) {
+               g_string_append_len(string_field->payload, value,
+                       effective_length);
+       } else {
+               string_field->payload = g_string_new_len(value,
+                       effective_length);
+       }
+
+       string_field->parent.payload_set = 1;
+
+end:
+       return ret;
+}
+
 BT_HIDDEN
 int bt_ctf_field_validate(struct bt_ctf_field *field)
 {
@@ -1007,6 +1098,7 @@ struct bt_ctf_field *bt_ctf_field_copy(struct bt_ctf_field *field)
                goto end;
        }
 
+       copy->payload_set = field->payload_set;
        ret = field_copy_funcs[type_id](field, copy);
        if (ret) {
                bt_ctf_field_put(copy);
@@ -1908,12 +2000,38 @@ int bt_ctf_field_sequence_copy(struct bt_ctf_field *src,
 {
        int ret = 0, i;
        struct bt_ctf_field_sequence *sequence_src, *sequence_dst;
+       struct bt_ctf_field *src_length;
+       struct bt_ctf_field *dst_length;
 
        sequence_src = container_of(src, struct bt_ctf_field_sequence, parent);
        sequence_dst = container_of(dst, struct bt_ctf_field_sequence, parent);
 
-       g_ptr_array_set_size(sequence_dst->elements,
-               sequence_src->elements->len);
+       src_length = bt_ctf_field_sequence_get_length(src);
+
+       if (!src_length) {
+               /* no length set yet: keep destination sequence empty */
+               goto end;
+       }
+
+       /* copy source length */
+       dst_length = bt_ctf_field_copy(src_length);
+       bt_ctf_field_put(src_length);
+
+       if (!dst_length) {
+               ret = -1;
+               goto end;
+       }
+
+       /* this will initialize the destination sequence's internal array */
+       ret = bt_ctf_field_sequence_set_length(dst, dst_length);
+       bt_ctf_field_put(dst_length);
+
+       if (ret) {
+               goto end;
+       }
+
+       assert(sequence_dst->elements->len == sequence_src->elements->len);
+
        for (i = 0; i < sequence_src->elements->len; i++) {
                struct bt_ctf_field *field_copy = bt_ctf_field_copy(
                        g_ptr_array_index(sequence_src->elements, i));
@@ -1922,6 +2040,7 @@ int bt_ctf_field_sequence_copy(struct bt_ctf_field *src,
                        ret = -1;
                        goto end;
                }
+
                g_ptr_array_index(sequence_dst->elements, i) = field_copy;
        }
 end:
This page took 0.025712 seconds and 4 git commands to generate.