2 * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
4 * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 #define BT_LOG_TAG "CTF-WRITER-FIELDS"
26 #include <babeltrace/lib-logging-internal.h>
28 #include <babeltrace/compat/fcntl-internal.h>
29 #include <babeltrace/ctf-writer/fields-internal.h>
30 #include <babeltrace/ctf-writer/field-types-internal.h>
31 #include <babeltrace/ctf-writer/serialize-internal.h>
32 #include <babeltrace/ctf-ir/fields-internal.h>
33 #include <babeltrace/ctf-ir/field-types-internal.h>
34 #include <babeltrace/assert-pre-internal.h>
35 #include <babeltrace/object-internal.h>
36 #include <babeltrace/ref.h>
37 #include <babeltrace/compiler-internal.h>
38 #include <babeltrace/endian-internal.h>
39 #include <babeltrace/assert-internal.h>
44 static struct bt_field_common_methods bt_ctf_field_integer_methods
= {
45 .set_is_frozen
= bt_field_common_generic_set_is_frozen
,
46 .validate
= bt_field_common_generic_validate
,
48 .is_set
= bt_field_common_generic_is_set
,
49 .reset
= bt_field_common_generic_reset
,
52 static struct bt_field_common_methods bt_ctf_field_floating_point_methods
= {
53 .set_is_frozen
= bt_field_common_generic_set_is_frozen
,
54 .validate
= bt_field_common_generic_validate
,
56 .is_set
= bt_field_common_generic_is_set
,
57 .reset
= bt_field_common_generic_reset
,
61 void bt_ctf_field_enumeration_set_is_frozen_recursive(
62 struct bt_field_common
*field
, bool is_frozen
);
65 int bt_ctf_field_enumeration_validate_recursive(struct bt_field_common
*field
);
68 bt_bool
bt_ctf_field_enumeration_is_set_recursive(
69 struct bt_field_common
*field
);
72 void bt_ctf_field_enumeration_reset_recursive(struct bt_field_common
*field
);
74 static struct bt_field_common_methods bt_ctf_field_enumeration_methods
= {
75 .set_is_frozen
= bt_ctf_field_enumeration_set_is_frozen_recursive
,
76 .validate
= bt_ctf_field_enumeration_validate_recursive
,
78 .is_set
= bt_ctf_field_enumeration_is_set_recursive
,
79 .reset
= bt_ctf_field_enumeration_reset_recursive
,
82 static struct bt_field_common_methods bt_ctf_field_string_methods
= {
83 .set_is_frozen
= bt_field_common_generic_set_is_frozen
,
84 .validate
= bt_field_common_generic_validate
,
86 .is_set
= bt_field_common_generic_is_set
,
87 .reset
= bt_field_common_generic_reset
,
90 static struct bt_field_common_methods bt_ctf_field_structure_methods
= {
91 .set_is_frozen
= bt_field_common_structure_set_is_frozen_recursive
,
92 .validate
= bt_field_common_structure_validate_recursive
,
94 .is_set
= bt_field_common_structure_is_set_recursive
,
95 .reset
= bt_field_common_structure_reset_recursive
,
98 static struct bt_field_common_methods bt_ctf_field_sequence_methods
= {
99 .set_is_frozen
= bt_field_common_sequence_set_is_frozen_recursive
,
100 .validate
= bt_field_common_sequence_validate_recursive
,
102 .is_set
= bt_field_common_sequence_is_set_recursive
,
103 .reset
= bt_field_common_sequence_reset_recursive
,
106 static struct bt_field_common_methods bt_ctf_field_array_methods
= {
107 .set_is_frozen
= bt_field_common_array_set_is_frozen_recursive
,
108 .validate
= bt_field_common_array_validate_recursive
,
110 .is_set
= bt_field_common_array_is_set_recursive
,
111 .reset
= bt_field_common_array_reset_recursive
,
115 void bt_ctf_field_variant_set_is_frozen_recursive(struct bt_field_common
*field
,
119 int bt_ctf_field_variant_validate_recursive(struct bt_field_common
*field
);
122 bt_bool
bt_ctf_field_variant_is_set_recursive(struct bt_field_common
*field
);
125 void bt_ctf_field_variant_reset_recursive(struct bt_field_common
*field
);
127 static struct bt_field_common_methods bt_ctf_field_variant_methods
= {
128 .set_is_frozen
= bt_ctf_field_variant_set_is_frozen_recursive
,
129 .validate
= bt_ctf_field_variant_validate_recursive
,
131 .is_set
= bt_ctf_field_variant_is_set_recursive
,
132 .reset
= bt_ctf_field_variant_reset_recursive
,
136 struct bt_ctf_field
*bt_ctf_field_integer_create(struct bt_ctf_field_type
*);
139 struct bt_ctf_field
*bt_ctf_field_enumeration_create(struct bt_ctf_field_type
*);
142 struct bt_ctf_field
*bt_ctf_field_floating_point_create(struct bt_ctf_field_type
*);
145 struct bt_ctf_field
*bt_ctf_field_structure_create(struct bt_ctf_field_type
*);
148 struct bt_ctf_field
*bt_ctf_field_variant_create(struct bt_ctf_field_type
*);
151 struct bt_ctf_field
*bt_ctf_field_array_create(struct bt_ctf_field_type
*);
154 struct bt_ctf_field
*bt_ctf_field_sequence_create(struct bt_ctf_field_type
*);
157 struct bt_ctf_field
*bt_ctf_field_string_create(struct bt_ctf_field_type
*);
160 struct bt_ctf_field
*(* const field_create_funcs
[])(struct bt_ctf_field_type
*) = {
161 [BT_FIELD_TYPE_ID_INTEGER
] = bt_ctf_field_integer_create
,
162 [BT_FIELD_TYPE_ID_ENUM
] = bt_ctf_field_enumeration_create
,
163 [BT_FIELD_TYPE_ID_FLOAT
] = bt_ctf_field_floating_point_create
,
164 [BT_FIELD_TYPE_ID_STRUCT
] = bt_ctf_field_structure_create
,
165 [BT_FIELD_TYPE_ID_VARIANT
] = bt_ctf_field_variant_create
,
166 [BT_FIELD_TYPE_ID_ARRAY
] = bt_ctf_field_array_create
,
167 [BT_FIELD_TYPE_ID_SEQUENCE
] = bt_ctf_field_sequence_create
,
168 [BT_FIELD_TYPE_ID_STRING
] = bt_ctf_field_string_create
,
171 typedef int (*bt_ctf_field_serialize_recursive_func
)(
172 struct bt_field_common
*, struct bt_ctf_stream_pos
*,
173 enum bt_ctf_byte_order
);
176 void bt_ctf_field_integer_destroy(struct bt_ctf_field
*field
)
178 BT_LOGD("Destroying CTF writer integer field object: addr=%p", field
);
179 bt_field_common_integer_finalize((void *) field
);
184 void bt_ctf_field_floating_point_destroy(struct bt_ctf_field
*field
)
186 BT_LOGD("Destroying CTF writer floating point field object: addr=%p",
188 bt_field_common_floating_point_finalize((void *) field
);
193 void bt_ctf_field_enumeration_destroy_recursive(struct bt_ctf_field
*field
)
195 struct bt_ctf_field_enumeration
*enumeration
= BT_FROM_COMMON(field
);
197 BT_LOGD("Destroying CTF writer enumeration field object: addr=%p",
199 BT_LOGD_STR("Putting container field.");
200 bt_put(enumeration
->container
);
201 bt_field_common_finalize((void *) field
);
206 void bt_ctf_field_structure_destroy_recursive(struct bt_ctf_field
*field
)
208 BT_LOGD("Destroying CTF writer structure field object: addr=%p", field
);
209 bt_field_common_structure_finalize_recursive((void *) field
);
214 void bt_ctf_field_variant_destroy_recursive(struct bt_ctf_field
*field
)
216 struct bt_ctf_field_variant
*variant
= BT_FROM_COMMON(field
);
218 BT_LOGD("Destroying CTF writer variant field object: addr=%p", field
);
219 BT_LOGD_STR("Putting tag field.");
220 bt_put(variant
->tag
);
221 bt_field_common_variant_finalize_recursive((void *) field
);
226 void bt_ctf_field_array_destroy_recursive(struct bt_ctf_field
*field
)
228 BT_LOGD("Destroying CTF writer array field object: addr=%p", field
);
229 bt_field_common_array_finalize_recursive((void *) field
);
234 void bt_ctf_field_sequence_destroy_recursive(struct bt_ctf_field
*field
)
236 BT_LOGD("Destroying CTF writer sequence field object: addr=%p", field
);
237 bt_field_common_sequence_finalize_recursive((void *) field
);
242 void bt_ctf_field_string_destroy(struct bt_ctf_field
*field
)
244 BT_LOGD("Destroying CTF writer string field object: addr=%p", field
);
245 bt_field_common_string_finalize((void *) field
);
250 int bt_ctf_field_serialize_recursive(struct bt_ctf_field
*field
,
251 struct bt_ctf_stream_pos
*pos
,
252 enum bt_ctf_byte_order native_byte_order
)
254 struct bt_field_common
*field_common
= (void *) field
;
255 bt_ctf_field_serialize_recursive_func serialize_func
;
258 BT_ASSERT_PRE_NON_NULL(field
, "Field");
259 BT_ASSERT(field_common
->spec
.writer
.serialize_func
);
260 serialize_func
= field_common
->spec
.writer
.serialize_func
;
261 return serialize_func(field_common
, pos
,
266 int increase_packet_size(struct bt_ctf_stream_pos
*pos
)
271 BT_LOGV("Increasing packet size: pos-offset=%" PRId64
", "
272 "cur-packet-size=%" PRIu64
,
273 pos
->offset
, pos
->packet_size
);
274 ret
= munmap_align(pos
->base_mma
);
276 BT_LOGE_ERRNO("Failed to perform an aligned memory unmapping",
281 pos
->packet_size
+= PACKET_LEN_INCREMENT
;
283 ret
= bt_posix_fallocate(pos
->fd
, pos
->mmap_offset
,
284 pos
->packet_size
/ CHAR_BIT
);
285 } while (ret
== EINTR
);
287 BT_LOGE_ERRNO("Failed to preallocate memory space",
294 pos
->base_mma
= mmap_align(pos
->packet_size
/ CHAR_BIT
, pos
->prot
,
295 pos
->flags
, pos
->fd
, pos
->mmap_offset
);
296 if (pos
->base_mma
== MAP_FAILED
) {
297 BT_LOGE_ERRNO("Failed to perform an aligned memory mapping",
302 BT_LOGV("Increased packet size: pos-offset=%" PRId64
", "
303 "new-packet-size=%" PRIu64
,
304 pos
->offset
, pos
->packet_size
);
305 BT_ASSERT(pos
->packet_size
% 8 == 0);
312 int bt_ctf_field_integer_serialize(struct bt_field_common
*field
,
313 struct bt_ctf_stream_pos
*pos
,
314 enum bt_ctf_byte_order native_byte_order
)
318 BT_ASSERT_PRE_FIELD_COMMON_IS_SET(field
, "Integer field");
319 BT_LOGV("Serializing CTF writer integer field: addr=%p, pos-offset=%" PRId64
", "
320 "native-bo=%s", field
, pos
->offset
,
321 bt_common_byte_order_string((int) native_byte_order
));
324 ret
= bt_ctf_field_integer_write(field
, pos
, native_byte_order
);
325 if (ret
== -EFAULT
) {
327 * The field is too large to fit in the current packet's
328 * remaining space. Bump the packet size and retry.
330 ret
= increase_packet_size(pos
);
332 BT_LOGE("Cannot increase packet size: ret=%d", ret
);
343 int bt_ctf_field_enumeration_serialize_recursive(struct bt_field_common
*field
,
344 struct bt_ctf_stream_pos
*pos
,
345 enum bt_ctf_byte_order native_byte_order
)
347 struct bt_ctf_field_enumeration
*enumeration
= (void *) field
;
349 BT_LOGV("Serializing enumeration field: addr=%p, pos-offset=%" PRId64
", "
350 "native-bo=%s", field
, pos
->offset
,
351 bt_common_byte_order_string((int) native_byte_order
));
352 BT_LOGV_STR("Serializing enumeration field's payload field.");
353 return bt_ctf_field_serialize_recursive(
354 (void *) enumeration
->container
, pos
, native_byte_order
);
358 int bt_ctf_field_floating_point_serialize(struct bt_field_common
*field
,
359 struct bt_ctf_stream_pos
*pos
,
360 enum bt_ctf_byte_order native_byte_order
)
364 BT_ASSERT_PRE_FIELD_COMMON_IS_SET(field
, "Floating point number field");
365 BT_LOGV("Serializing floating point number field: addr=%p, pos-offset=%" PRId64
", "
366 "native-bo=%s", field
, pos
->offset
,
367 bt_common_byte_order_string((int) native_byte_order
));
370 ret
= bt_ctf_field_floating_point_write(field
, pos
,
372 if (ret
== -EFAULT
) {
374 * The field is too large to fit in the current packet's
375 * remaining space. Bump the packet size and retry.
377 ret
= increase_packet_size(pos
);
379 BT_LOGE("Cannot increase packet size: ret=%d", ret
);
390 int bt_ctf_field_structure_serialize_recursive(struct bt_field_common
*field
,
391 struct bt_ctf_stream_pos
*pos
,
392 enum bt_ctf_byte_order native_byte_order
)
396 struct bt_field_common_structure
*structure
= BT_FROM_COMMON(field
);
398 BT_LOGV("Serializing structure field: addr=%p, pos-offset=%" PRId64
", "
399 "native-bo=%s", field
, pos
->offset
,
400 bt_common_byte_order_string((int) native_byte_order
));
402 while (!bt_ctf_stream_pos_access_ok(pos
,
403 offset_align(pos
->offset
, field
->type
->alignment
))) {
404 ret
= increase_packet_size(pos
);
406 BT_LOGE("Cannot increase packet size: ret=%d", ret
);
411 if (!bt_ctf_stream_pos_align(pos
, field
->type
->alignment
)) {
412 BT_LOGE("Cannot align packet's position: pos-offset=%" PRId64
", "
413 "align=%u", pos
->offset
, field
->type
->alignment
);
418 for (i
= 0; i
< structure
->fields
->len
; i
++) {
419 struct bt_field_common
*member
= g_ptr_array_index(
420 structure
->fields
, i
);
421 const char *field_name
= NULL
;
423 BT_LOGV("Serializing structure field's field: pos-offset=%" PRId64
", "
424 "field-addr=%p, index=%" PRId64
,
425 pos
->offset
, member
, i
);
428 ret
= bt_field_type_common_structure_borrow_field_by_index(
429 field
->type
, &field_name
, NULL
, i
);
431 BT_LOGW("Cannot serialize structure field's field: field is not set: "
432 "struct-field-addr=%p, "
433 "field-name=\"%s\", index=%" PRId64
,
434 field
, field_name
, i
);
439 ret
= bt_ctf_field_serialize_recursive((void *) member
, pos
,
442 ret
= bt_field_type_common_structure_borrow_field_by_index(
443 field
->type
, &field_name
, NULL
, i
);
445 BT_LOGW("Cannot serialize structure field's field: "
446 "struct-field-addr=%p, field-addr=%p, "
447 "field-name=\"%s\", index=%" PRId64
,
448 field
->type
, member
, field_name
, i
);
458 int bt_ctf_field_variant_serialize_recursive(struct bt_field_common
*field
,
459 struct bt_ctf_stream_pos
*pos
,
460 enum bt_ctf_byte_order native_byte_order
)
462 struct bt_field_common_variant
*variant
= BT_FROM_COMMON(field
);
464 BT_LOGV("Serializing variant field: addr=%p, pos-offset=%" PRId64
", "
465 "native-bo=%s", field
, pos
->offset
,
466 bt_common_byte_order_string((int) native_byte_order
));
467 BT_LOGV_STR("Serializing variant field's payload field.");
468 return bt_ctf_field_serialize_recursive(
469 (void *) variant
->current_field
, pos
, native_byte_order
);
473 int bt_ctf_field_array_serialize_recursive(struct bt_field_common
*field
,
474 struct bt_ctf_stream_pos
*pos
,
475 enum bt_ctf_byte_order native_byte_order
)
479 struct bt_field_common_array
*array
= BT_FROM_COMMON(field
);
481 BT_LOGV("Serializing array field: addr=%p, pos-offset=%" PRId64
", "
482 "native-bo=%s", field
, pos
->offset
,
483 bt_common_byte_order_string((int) native_byte_order
));
485 for (i
= 0; i
< array
->elements
->len
; i
++) {
486 struct bt_field_common
*elem_field
=
487 g_ptr_array_index(array
->elements
, i
);
489 BT_LOGV("Serializing array field's element field: "
490 "pos-offset=%" PRId64
", field-addr=%p, index=%" PRId64
,
491 pos
->offset
, elem_field
, i
);
492 ret
= bt_ctf_field_serialize_recursive(
493 (void *) elem_field
, pos
, native_byte_order
);
495 BT_LOGW("Cannot serialize array field's element field: "
496 "array-field-addr=%p, field-addr=%p, "
497 "index=%" PRId64
, field
, elem_field
, i
);
507 int bt_ctf_field_sequence_serialize_recursive(struct bt_field_common
*field
,
508 struct bt_ctf_stream_pos
*pos
,
509 enum bt_ctf_byte_order native_byte_order
)
513 struct bt_field_common_sequence
*sequence
= BT_FROM_COMMON(field
);
515 BT_LOGV("Serializing sequence field: addr=%p, pos-offset=%" PRId64
", "
516 "native-bo=%s", field
, pos
->offset
,
517 bt_common_byte_order_string((int) native_byte_order
));
519 for (i
= 0; i
< sequence
->elements
->len
; i
++) {
520 struct bt_field_common
*elem_field
=
521 g_ptr_array_index(sequence
->elements
, i
);
523 BT_LOGV("Serializing sequence field's element field: "
524 "pos-offset=%" PRId64
", field-addr=%p, index=%" PRId64
,
525 pos
->offset
, elem_field
, i
);
526 ret
= bt_ctf_field_serialize_recursive(
527 (void *) elem_field
, pos
, native_byte_order
);
529 BT_LOGW("Cannot serialize sequence field's element field: "
530 "sequence-field-addr=%p, field-addr=%p, "
531 "index=%" PRId64
, field
, elem_field
, i
);
541 int bt_ctf_field_string_serialize(struct bt_field_common
*field
,
542 struct bt_ctf_stream_pos
*pos
,
543 enum bt_ctf_byte_order native_byte_order
)
547 struct bt_field_common_string
*string
= BT_FROM_COMMON(field
);
548 struct bt_ctf_field_type
*character_type
=
549 get_field_type(FIELD_TYPE_ALIAS_UINT8_T
);
550 struct bt_ctf_field
*character
;
552 BT_ASSERT_PRE_FIELD_COMMON_IS_SET(field
, "String field");
553 BT_LOGV("Serializing string field: addr=%p, pos-offset=%" PRId64
", "
554 "native-bo=%s", field
, pos
->offset
,
555 bt_common_byte_order_string((int) native_byte_order
));
557 BT_LOGV_STR("Creating character field from string field's character field type.");
558 character
= bt_ctf_field_create(character_type
);
560 for (i
= 0; i
< string
->payload
->len
+ 1; i
++) {
561 const uint64_t chr
= (uint64_t) string
->payload
->str
[i
];
563 ret
= bt_ctf_field_integer_unsigned_set_value(character
, chr
);
565 BT_LOGV("Serializing string field's character field: "
566 "pos-offset=%" PRId64
", field-addr=%p, "
567 "index=%" PRId64
", char-int=%" PRIu64
,
568 pos
->offset
, character
, i
, chr
);
569 ret
= bt_ctf_field_integer_serialize(
570 (void *) character
, pos
, native_byte_order
);
572 BT_LOGW_STR("Cannot serialize character field.");
579 bt_put(character_type
);
583 struct bt_ctf_field
*bt_ctf_field_create(struct bt_ctf_field_type
*type
)
585 struct bt_ctf_field
*field
= NULL
;
586 enum bt_ctf_field_type_id type_id
;
588 BT_ASSERT_PRE_NON_NULL(type
, "Field type");
589 BT_ASSERT(field_type_common_has_known_id((void *) type
));
590 BT_ASSERT_PRE(bt_field_type_common_validate((void *) type
) == 0,
591 "Field type is invalid: %!+wF", type
);
592 type_id
= bt_ctf_field_type_get_type_id(type
);
593 field
= field_create_funcs
[type_id
](type
);
598 bt_field_type_common_freeze((void *) type
);
604 struct bt_ctf_field_type
*bt_ctf_field_get_type(struct bt_ctf_field
*field
)
606 return bt_get(bt_field_common_borrow_type((void *) field
));
609 enum bt_ctf_field_type_id
bt_ctf_field_get_type_id(struct bt_ctf_field
*field
)
611 struct bt_field_common
*field_common
= (void *) field
;
613 BT_ASSERT_PRE_NON_NULL(field
, "Field");
614 return (int) field_common
->type
->id
;
617 int bt_ctf_field_sequence_set_length(struct bt_ctf_field
*field
,
618 struct bt_ctf_field
*length_field
)
621 struct bt_field_common
*common_length_field
= (void *) length_field
;
624 BT_ASSERT_PRE_NON_NULL(length_field
, "Length field");
625 BT_ASSERT_PRE_FIELD_COMMON_IS_SET((void *) length_field
, "Length field");
626 BT_ASSERT_PRE(common_length_field
->type
->id
== BT_FIELD_TYPE_ID_INTEGER
||
627 common_length_field
->type
->id
== BT_FIELD_TYPE_ID_ENUM
,
628 "Length field must be an integer or enumeration field: %!+wf",
631 if (common_length_field
->type
->id
== BT_FIELD_TYPE_ID_ENUM
) {
632 struct bt_ctf_field_enumeration
*enumeration
= (void *)
635 length_field
= (void *) enumeration
->container
;
638 ret
= bt_ctf_field_integer_unsigned_get_value(length_field
, &length
);
640 return bt_field_common_sequence_set_length((void *) field
,
641 length
, (bt_field_common_create_func
) bt_ctf_field_create
);
644 struct bt_ctf_field
*bt_ctf_field_structure_get_field_by_index(
645 struct bt_ctf_field
*field
, uint64_t index
)
647 return bt_get(bt_field_common_structure_borrow_field_by_index(
648 (void *) field
, index
));
651 struct bt_ctf_field
*bt_ctf_field_structure_get_field_by_name(
652 struct bt_ctf_field
*field
, const char *name
)
654 return bt_get(bt_field_common_structure_borrow_field_by_name(
655 (void *) field
, name
));
658 struct bt_ctf_field
*bt_ctf_field_array_get_field(
659 struct bt_ctf_field
*field
, uint64_t index
)
662 bt_field_common_array_borrow_field((void *) field
, index
));
665 struct bt_ctf_field
*bt_ctf_field_sequence_get_field(
666 struct bt_ctf_field
*field
, uint64_t index
)
669 bt_field_common_sequence_borrow_field((void *) field
, index
));
672 struct bt_ctf_field
*bt_ctf_field_variant_get_field(struct bt_ctf_field
*field
,
673 struct bt_ctf_field
*tag_field
)
675 struct bt_ctf_field_variant
*variant_field
= (void *) field
;
676 struct bt_ctf_field_enumeration
*enum_field
= (void *) tag_field
;
677 struct bt_field_type_common_variant
*variant_ft
;
678 struct bt_field_type_common_enumeration
*tag_ft
;
679 struct bt_ctf_field
*current_field
= NULL
;
684 BT_ASSERT_PRE_NON_NULL(field
, "Variant field");
685 BT_ASSERT_PRE_NON_NULL(tag_field
, "Tag field");
686 BT_ASSERT_PRE_FIELD_COMMON_IS_SET((void *) tag_field
, "Tag field");
687 BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(
688 (struct bt_field_common
*) tag_field
,
689 BT_FIELD_TYPE_ID_ENUM
, "Tag field");
690 BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(
691 (struct bt_field_common
*) field
,
692 BT_FIELD_TYPE_ID_VARIANT
, "Field");
694 bt_field_common_validate_recursive((void *) tag_field
) == 0,
695 "Tag field is invalid: %!+wf", tag_field
);
696 variant_ft
= BT_FROM_COMMON(variant_field
->common
.common
.type
);
697 BT_ASSERT_PRE(bt_field_type_common_compare(
698 BT_TO_COMMON(variant_ft
->tag_ft
), enum_field
->common
.type
) == 0,
699 "Unexpected tag field's type: %![expected-ft-]+wF, "
700 "%![tag-ft-]+wF", variant_ft
->tag_ft
,
701 enum_field
->common
.type
);
702 tag_ft
= BT_FROM_COMMON(enum_field
->common
.type
);
703 is_signed
= tag_ft
->container_ft
->is_signed
;
708 ret
= bt_ctf_field_integer_signed_get_value(
709 (void *) enum_field
->container
, &tag_ival
);
710 tag_uval
= (uint64_t) tag_ival
;
712 ret
= bt_ctf_field_integer_unsigned_get_value(
713 (void *) enum_field
->container
, &tag_uval
);
717 ret
= bt_field_variant_common_set_tag((void *) field
, tag_uval
,
723 bt_put(variant_field
->tag
);
724 variant_field
->tag
= bt_get(tag_field
);
725 current_field
= bt_ctf_field_variant_get_current_field(field
);
726 BT_ASSERT(current_field
);
729 return current_field
;
732 struct bt_ctf_field
*bt_ctf_field_variant_get_current_field(
733 struct bt_ctf_field
*variant_field
)
735 return bt_get(bt_field_common_variant_borrow_current_field(
736 (void *) variant_field
));
740 struct bt_ctf_field
*bt_ctf_field_enumeration_borrow_container(
741 struct bt_ctf_field
*field
)
743 struct bt_ctf_field_enumeration
*enumeration
= (void *) field
;
745 BT_ASSERT_PRE_NON_NULL(field
, "Enumeration field");
746 BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID((struct bt_field_common
*) field
,
747 BT_CTF_FIELD_TYPE_ID_ENUM
, "Field");
748 BT_ASSERT(enumeration
->container
);
749 return (void *) enumeration
->container
;
752 struct bt_ctf_field
*bt_ctf_field_enumeration_get_container(
753 struct bt_ctf_field
*field
)
755 return bt_get(bt_ctf_field_enumeration_borrow_container(field
));
758 int bt_ctf_field_integer_signed_get_value(struct bt_ctf_field
*field
,
761 struct bt_field_common_integer
*integer
= (void *) field
;
763 BT_ASSERT_PRE_NON_NULL(field
, "Integer field");
764 BT_ASSERT_PRE_NON_NULL(value
, "Value");
765 BT_ASSERT_PRE_FIELD_COMMON_IS_SET(BT_TO_COMMON(integer
), "Integer field");
766 BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(BT_TO_COMMON(integer
),
767 BT_FIELD_TYPE_ID_INTEGER
, "Field");
768 BT_ASSERT_PRE(bt_field_type_common_integer_is_signed(
769 integer
->common
.type
),
770 "Field's type is unsigned: %!+_f", field
);
771 *value
= integer
->payload
.signd
;
775 int bt_ctf_field_integer_signed_set_value(struct bt_ctf_field
*field
,
779 struct bt_field_common_integer
*integer
= (void *) field
;
780 struct bt_field_type_common_integer
*integer_type
;
782 BT_ASSERT_PRE_NON_NULL(field
, "Integer field");
783 BT_ASSERT_PRE_FIELD_COMMON_HOT(BT_TO_COMMON(integer
), "Integer field");
784 BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(BT_TO_COMMON(integer
),
785 BT_FIELD_TYPE_ID_INTEGER
, "Field");
786 integer_type
= BT_FROM_COMMON(integer
->common
.type
);
788 bt_field_type_common_integer_is_signed(integer
->common
.type
),
789 "Field's type is unsigned: %!+wf", field
);
790 BT_ASSERT_PRE(value_is_in_range_signed(integer_type
->size
, value
),
791 "Value is out of bounds: value=%" PRId64
", %![field-]+wf",
793 integer
->payload
.signd
= value
;
794 bt_field_common_set(BT_TO_COMMON(integer
), true);
798 int bt_ctf_field_integer_unsigned_get_value(struct bt_ctf_field
*field
,
801 struct bt_field_common_integer
*integer
= (void *) field
;
803 BT_ASSERT_PRE_NON_NULL(field
, "Integer field");
804 BT_ASSERT_PRE_NON_NULL(value
, "Value");
805 BT_ASSERT_PRE_FIELD_COMMON_IS_SET(BT_TO_COMMON(integer
), "Integer field");
806 BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(BT_TO_COMMON(integer
),
807 BT_FIELD_TYPE_ID_INTEGER
, "Field");
809 !bt_field_type_common_integer_is_signed(integer
->common
.type
),
810 "Field's type is signed: %!+wf", field
);
811 *value
= integer
->payload
.unsignd
;
815 int bt_ctf_field_integer_unsigned_set_value(struct bt_ctf_field
*field
,
818 struct bt_field_common_integer
*integer
= (void *) field
;
819 struct bt_field_type_common_integer
*integer_type
;
821 BT_ASSERT_PRE_NON_NULL(field
, "Integer field");
822 BT_ASSERT_PRE_FIELD_COMMON_HOT(BT_TO_COMMON(integer
), "Integer field");
823 BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(BT_TO_COMMON(integer
),
824 BT_FIELD_TYPE_ID_INTEGER
, "Field");
825 integer_type
= BT_FROM_COMMON(integer
->common
.type
);
827 !bt_field_type_common_integer_is_signed(integer
->common
.type
),
828 "Field's type is signed: %!+wf", field
);
829 BT_ASSERT_PRE(value_is_in_range_unsigned(integer_type
->size
, value
),
830 "Value is out of bounds: value=%" PRIu64
", %![field-]+wf",
832 integer
->payload
.unsignd
= value
;
833 bt_field_common_set(BT_TO_COMMON(integer
), true);
837 int bt_ctf_field_floating_point_get_value(struct bt_ctf_field
*field
,
840 return bt_field_common_floating_point_get_value((void *) field
, value
);
843 int bt_ctf_field_floating_point_set_value(struct bt_ctf_field
*field
,
846 return bt_field_common_floating_point_set_value((void *) field
, value
);
849 const char *bt_ctf_field_string_get_value(struct bt_ctf_field
*field
)
851 return bt_field_common_string_get_value((void *) field
);
854 int bt_ctf_field_string_set_value(struct bt_ctf_field
*field
, const char *value
)
856 return bt_field_common_string_set_value((void *) field
, value
);
859 int bt_ctf_field_string_append(struct bt_ctf_field
*field
, const char *value
)
861 return bt_field_common_string_append((void *) field
, value
);
864 int bt_ctf_field_string_append_len(struct bt_ctf_field
*field
,
865 const char *value
, unsigned int length
)
867 return bt_field_common_string_append_len((void *) field
, value
, length
);
870 struct bt_ctf_field
*bt_ctf_field_copy(struct bt_ctf_field
*field
)
872 return (void *) bt_field_common_copy((void *) field
);
876 struct bt_ctf_field
*bt_ctf_field_integer_create(struct bt_ctf_field_type
*type
)
878 struct bt_field_common_integer
*integer
=
879 g_new0(struct bt_field_common_integer
, 1);
881 BT_LOGD("Creating CTF writer integer field object: ft-addr=%p", type
);
884 bt_field_common_initialize(BT_TO_COMMON(integer
), (void *) type
,
885 (bt_object_release_func
) bt_ctf_field_integer_destroy
,
886 &bt_ctf_field_integer_methods
);
887 integer
->common
.spec
.writer
.serialize_func
=
888 (bt_ctf_field_serialize_recursive_func
) bt_ctf_field_integer_serialize
;
889 BT_LOGD("Created CTF writer integer field object: addr=%p, ft-addr=%p",
892 BT_LOGE_STR("Failed to allocate one integer field.");
895 return (void *) integer
;
899 struct bt_ctf_field
*bt_ctf_field_enumeration_create(
900 struct bt_ctf_field_type
*type
)
902 struct bt_field_type_common_enumeration
*enum_ft
= (void *) type
;
903 struct bt_ctf_field_enumeration
*enumeration
= g_new0(
904 struct bt_ctf_field_enumeration
, 1);
906 BT_LOGD("Creating CTF writer enumeration field object: ft-addr=%p", type
);
909 BT_LOGE_STR("Failed to allocate one enumeration field.");
913 bt_field_common_initialize(BT_TO_COMMON(enumeration
),
915 (bt_object_release_func
)
916 bt_ctf_field_enumeration_destroy_recursive
,
917 &bt_ctf_field_enumeration_methods
);
918 enumeration
->container
= (void *) bt_ctf_field_create(
919 BT_FROM_COMMON(enum_ft
->container_ft
));
920 if (!enumeration
->container
) {
925 enumeration
->common
.spec
.writer
.serialize_func
=
926 (bt_ctf_field_serialize_recursive_func
)
927 bt_ctf_field_enumeration_serialize_recursive
;
928 BT_LOGD("Created CTF writer enumeration field object: addr=%p, ft-addr=%p",
932 return (void *) enumeration
;
936 struct bt_ctf_field
*bt_ctf_field_floating_point_create(
937 struct bt_ctf_field_type
*type
)
939 struct bt_field_common_floating_point
*floating_point
;
941 BT_LOGD("Creating CTF writer floating point number field object: ft-addr=%p", type
);
942 floating_point
= g_new0(struct bt_field_common_floating_point
, 1);
944 if (floating_point
) {
945 bt_field_common_initialize(BT_TO_COMMON(floating_point
),
947 (bt_object_release_func
)
948 bt_ctf_field_floating_point_destroy
,
949 &bt_ctf_field_floating_point_methods
);
950 floating_point
->common
.spec
.writer
.serialize_func
=
951 (bt_ctf_field_serialize_recursive_func
) bt_ctf_field_floating_point_serialize
;
952 BT_LOGD("Created CTF writer floating point number field object: addr=%p, ft-addr=%p",
953 floating_point
, type
);
955 BT_LOGE_STR("Failed to allocate one floating point number field.");
958 return (void *) floating_point
;
962 struct bt_ctf_field
*bt_ctf_field_structure_create(
963 struct bt_ctf_field_type
*type
)
965 struct bt_field_common_structure
*structure
= g_new0(
966 struct bt_field_common_structure
, 1);
969 BT_LOGD("Creating CTF writer structure field object: ft-addr=%p", type
);
972 BT_LOGE_STR("Failed to allocate one structure field.");
976 iret
= bt_field_common_structure_initialize(BT_TO_COMMON(structure
),
978 (bt_object_release_func
)
979 bt_ctf_field_structure_destroy_recursive
,
980 &bt_ctf_field_structure_methods
,
981 (bt_field_common_create_func
) bt_ctf_field_create
,
982 (GDestroyNotify
) bt_put
);
983 structure
->common
.spec
.writer
.serialize_func
=
984 (bt_ctf_field_serialize_recursive_func
) bt_ctf_field_structure_serialize_recursive
;
990 BT_LOGD("Created CTF writer structure field object: addr=%p, ft-addr=%p",
994 return (void *) structure
;
998 struct bt_ctf_field
*bt_ctf_field_variant_create(struct bt_ctf_field_type
*type
)
1000 struct bt_field_type_common_variant
*var_ft
= (void *) type
;
1001 struct bt_ctf_field_variant
*variant
= g_new0(
1002 struct bt_ctf_field_variant
, 1);
1004 BT_LOGD("Creating CTF writer variant field object: ft-addr=%p", type
);
1007 BT_LOGE_STR("Failed to allocate one variant field.");
1011 bt_field_common_variant_initialize(BT_TO_COMMON(BT_TO_COMMON(variant
)),
1013 (bt_object_release_func
)
1014 bt_ctf_field_variant_destroy_recursive
,
1015 &bt_ctf_field_variant_methods
,
1016 (bt_field_common_create_func
) bt_ctf_field_create
,
1017 (GDestroyNotify
) bt_put
);
1018 variant
->tag
= (void *) bt_ctf_field_create(
1019 BT_FROM_COMMON(var_ft
->tag_ft
));
1020 variant
->common
.common
.spec
.writer
.serialize_func
=
1021 (bt_ctf_field_serialize_recursive_func
) bt_ctf_field_variant_serialize_recursive
;
1022 BT_LOGD("Created CTF writer variant field object: addr=%p, ft-addr=%p",
1026 return (void *) variant
;
1030 struct bt_ctf_field
*bt_ctf_field_array_create(struct bt_ctf_field_type
*type
)
1032 struct bt_field_common_array
*array
=
1033 g_new0(struct bt_field_common_array
, 1);
1036 BT_LOGD("Creating CTF writer array field object: ft-addr=%p", type
);
1040 BT_LOGE_STR("Failed to allocate one array field.");
1044 ret
= bt_field_common_array_initialize(BT_TO_COMMON(array
),
1046 (bt_object_release_func
)
1047 bt_ctf_field_array_destroy_recursive
,
1048 &bt_ctf_field_array_methods
,
1049 (bt_field_common_create_func
) bt_ctf_field_create
,
1050 (GDestroyNotify
) bt_put
);
1051 array
->common
.spec
.writer
.serialize_func
=
1052 (bt_ctf_field_serialize_recursive_func
) bt_ctf_field_array_serialize_recursive
;
1058 BT_LOGD("Created CTF writer array field object: addr=%p, ft-addr=%p",
1062 return (void *) array
;
1066 struct bt_ctf_field
*bt_ctf_field_sequence_create(struct bt_ctf_field_type
*type
)
1068 struct bt_field_common_sequence
*sequence
= g_new0(
1069 struct bt_field_common_sequence
, 1);
1071 BT_LOGD("Creating CTF writer sequence field object: ft-addr=%p", type
);
1074 bt_field_common_sequence_initialize(BT_TO_COMMON(sequence
),
1076 (bt_object_release_func
)
1077 bt_ctf_field_sequence_destroy_recursive
,
1078 &bt_ctf_field_sequence_methods
,
1079 (GDestroyNotify
) bt_put
);
1080 sequence
->common
.spec
.writer
.serialize_func
=
1081 (bt_ctf_field_serialize_recursive_func
) bt_ctf_field_sequence_serialize_recursive
;
1082 BT_LOGD("Created CTF writer sequence field object: addr=%p, ft-addr=%p",
1085 BT_LOGE_STR("Failed to allocate one sequence field.");
1088 return (void *) sequence
;
1092 struct bt_ctf_field
*bt_ctf_field_string_create(struct bt_ctf_field_type
*type
)
1094 struct bt_field_common_string
*string
= g_new0(
1095 struct bt_field_common_string
, 1);
1097 BT_LOGD("Creating CTF writer string field object: ft-addr=%p", type
);
1100 bt_field_common_initialize(BT_TO_COMMON(string
),
1102 (bt_object_release_func
)
1103 bt_ctf_field_string_destroy
,
1104 &bt_ctf_field_string_methods
);
1105 string
->common
.spec
.writer
.serialize_func
=
1106 (bt_ctf_field_serialize_recursive_func
) bt_ctf_field_string_serialize
;
1107 BT_LOGD("Created CTF writer string field object: addr=%p, ft-addr=%p",
1110 BT_LOGE_STR("Failed to allocate one string field.");
1113 return (void *) string
;
1117 void bt_ctf_field_enumeration_set_is_frozen_recursive(
1118 struct bt_field_common
*field
, bool is_frozen
)
1120 struct bt_ctf_field_enumeration
*enumeration
= (void *) field
;
1122 if (enumeration
->container
) {
1123 bt_field_common_set_is_frozen_recursive(
1124 (void *) enumeration
->container
, is_frozen
);
1127 bt_field_common_generic_set_is_frozen((void *) field
, is_frozen
);
1131 int bt_ctf_field_enumeration_validate_recursive(struct bt_field_common
*field
)
1134 struct bt_ctf_field_enumeration
*enumeration
= (void *) field
;
1136 if (enumeration
->container
) {
1137 ret
= bt_field_common_validate_recursive(
1138 (void *) enumeration
->container
);
1145 bt_bool
bt_ctf_field_enumeration_is_set_recursive(struct bt_field_common
*field
)
1147 bt_bool is_set
= BT_FALSE
;
1148 struct bt_ctf_field_enumeration
*enumeration
= (void *) field
;
1150 if (enumeration
->container
) {
1151 is_set
= bt_field_common_is_set_recursive(
1152 (void *) enumeration
->container
);
1159 void bt_ctf_field_enumeration_reset_recursive(struct bt_field_common
*field
)
1161 struct bt_ctf_field_enumeration
*enumeration
= (void *) field
;
1163 if (enumeration
->container
) {
1164 bt_field_common_reset_recursive(
1165 (void *) enumeration
->container
);
1168 bt_field_common_generic_reset((void *) field
);
1172 void bt_ctf_field_variant_set_is_frozen_recursive(
1173 struct bt_field_common
*field
, bool is_frozen
)
1175 struct bt_ctf_field_variant
*variant
= (void *) field
;
1178 bt_field_common_set_is_frozen_recursive(
1179 (void *) variant
->tag
, is_frozen
);
1182 bt_field_common_variant_set_is_frozen_recursive((void *) field
,
1187 int bt_ctf_field_variant_validate_recursive(struct bt_field_common
*field
)
1190 struct bt_ctf_field_variant
*variant
= (void *) field
;
1193 ret
= bt_field_common_validate_recursive(
1194 (void *) variant
->tag
);
1200 ret
= bt_field_common_variant_validate_recursive((void *) field
);
1207 bt_bool
bt_ctf_field_variant_is_set_recursive(struct bt_field_common
*field
)
1210 struct bt_ctf_field_variant
*variant
= (void *) field
;
1213 is_set
= bt_field_common_is_set_recursive(
1214 (void *) variant
->tag
);
1220 is_set
= bt_field_common_variant_is_set_recursive((void *) field
);
1227 void bt_ctf_field_variant_reset_recursive(struct bt_field_common
*field
)
1229 struct bt_ctf_field_variant
*variant
= (void *) field
;
1232 bt_field_common_reset_recursive(
1233 (void *) variant
->tag
);
1236 bt_field_common_variant_reset_recursive((void *) field
);
1240 static inline bool field_to_set_has_expected_type(
1241 struct bt_field_common
*struct_field
,
1242 const char *name
, struct bt_field_common
*value
)
1245 struct bt_field_type_common
*expected_field_type
= NULL
;
1247 expected_field_type
=
1248 bt_field_type_common_structure_borrow_field_type_by_name(
1249 struct_field
->type
, name
);
1251 if (bt_field_type_common_compare(expected_field_type
, value
->type
)) {
1252 BT_ASSERT_PRE_MSG("Value field's type is different from the expected field type: "
1253 "%![value-ft-]+_F, %![expected-ft-]+_F", value
->type
,
1254 expected_field_type
);
1264 int bt_ctf_field_structure_set_field_by_name(struct bt_ctf_field
*field
,
1265 const char *name
, struct bt_ctf_field
*value
)
1269 struct bt_field_common
*common_field
= (void *) field
;
1270 struct bt_field_common_structure
*structure
=
1271 BT_FROM_COMMON(common_field
);
1272 struct bt_field_common
*common_value
= (void *) value
;
1274 GHashTable
*field_name_to_index
;
1275 struct bt_field_type_common_structure
*structure_ft
;
1277 BT_ASSERT_PRE_NON_NULL(field
, "Parent field");
1278 BT_ASSERT_PRE_NON_NULL(name
, "Field name");
1279 BT_ASSERT_PRE_NON_NULL(value
, "Value field");
1280 BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(common_field
,
1281 BT_FIELD_TYPE_ID_STRUCT
, "Parent field");
1282 BT_ASSERT_PRE(field_to_set_has_expected_type(common_field
,
1283 name
, common_value
),
1284 "Value field's type is different from the expected field type.");
1285 field_quark
= g_quark_from_string(name
);
1286 structure_ft
= BT_FROM_COMMON(common_field
->type
);
1287 field_name_to_index
= structure_ft
->field_name_to_index
;
1288 if (!g_hash_table_lookup_extended(field_name_to_index
,
1289 GUINT_TO_POINTER(field_quark
), NULL
,
1290 (gpointer
*) &index
)) {
1291 BT_LOGV("Invalid parameter: no such field in structure field's type: "
1292 "struct-field-addr=%p, struct-ft-addr=%p, "
1293 "field-ft-addr=%p, name=\"%s\"",
1294 field
, common_field
->type
, common_value
->type
, name
);
1299 BT_MOVE(structure
->fields
->pdata
[index
], value
);