4 * Babeltrace CTF Writer
6 * Copyright 2013 EfficiOS Inc.
8 * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
10 * Permission is hereby granted, free of charge, to any person obtaining a copy
11 * of this software and associated documentation files (the "Software"), to deal
12 * in the Software without restriction, including without limitation the rights
13 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 * copies of the Software, and to permit persons to whom the Software is
15 * furnished to do so, subject to the following conditions:
17 * The above copyright notice and this permission notice shall be included in
18 * all copies or substantial portions of the Software.
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29 #include <babeltrace/ctf-writer/event-types.h>
30 #include <babeltrace/ctf-ir/event-types-internal.h>
31 #include <babeltrace/ctf-writer/writer-internal.h>
32 #include <babeltrace/compiler.h>
33 #include <babeltrace/endian.h>
38 struct range_overlap_query
{
39 int64_t range_start
, range_end
;
45 void bt_ctf_field_type_integer_destroy(struct bt_ctf_ref
*);
47 void bt_ctf_field_type_enumeration_destroy(struct bt_ctf_ref
*);
49 void bt_ctf_field_type_floating_point_destroy(struct bt_ctf_ref
*);
51 void bt_ctf_field_type_structure_destroy(struct bt_ctf_ref
*);
53 void bt_ctf_field_type_variant_destroy(struct bt_ctf_ref
*);
55 void bt_ctf_field_type_array_destroy(struct bt_ctf_ref
*);
57 void bt_ctf_field_type_sequence_destroy(struct bt_ctf_ref
*);
59 void bt_ctf_field_type_string_destroy(struct bt_ctf_ref
*);
62 void (* const type_destroy_funcs
[])(struct bt_ctf_ref
*) = {
63 [CTF_TYPE_INTEGER
] = bt_ctf_field_type_integer_destroy
,
65 bt_ctf_field_type_enumeration_destroy
,
67 bt_ctf_field_type_floating_point_destroy
,
68 [CTF_TYPE_STRUCT
] = bt_ctf_field_type_structure_destroy
,
69 [CTF_TYPE_VARIANT
] = bt_ctf_field_type_variant_destroy
,
70 [CTF_TYPE_ARRAY
] = bt_ctf_field_type_array_destroy
,
71 [CTF_TYPE_SEQUENCE
] = bt_ctf_field_type_sequence_destroy
,
72 [CTF_TYPE_STRING
] = bt_ctf_field_type_string_destroy
,
76 void generic_field_type_freeze(struct bt_ctf_field_type
*);
78 void bt_ctf_field_type_enumeration_freeze(struct bt_ctf_field_type
*);
80 void bt_ctf_field_type_structure_freeze(struct bt_ctf_field_type
*);
82 void bt_ctf_field_type_variant_freeze(struct bt_ctf_field_type
*);
84 void bt_ctf_field_type_array_freeze(struct bt_ctf_field_type
*);
86 void bt_ctf_field_type_sequence_freeze(struct bt_ctf_field_type
*);
89 type_freeze_func
const type_freeze_funcs
[] = {
90 [CTF_TYPE_INTEGER
] = generic_field_type_freeze
,
91 [CTF_TYPE_ENUM
] = bt_ctf_field_type_enumeration_freeze
,
92 [CTF_TYPE_FLOAT
] = generic_field_type_freeze
,
93 [CTF_TYPE_STRUCT
] = bt_ctf_field_type_structure_freeze
,
94 [CTF_TYPE_VARIANT
] = bt_ctf_field_type_variant_freeze
,
95 [CTF_TYPE_ARRAY
] = bt_ctf_field_type_array_freeze
,
96 [CTF_TYPE_SEQUENCE
] = bt_ctf_field_type_sequence_freeze
,
97 [CTF_TYPE_STRING
] = generic_field_type_freeze
,
101 int bt_ctf_field_type_integer_serialize(struct bt_ctf_field_type
*,
102 struct metadata_context
*);
104 int bt_ctf_field_type_enumeration_serialize(struct bt_ctf_field_type
*,
105 struct metadata_context
*);
107 int bt_ctf_field_type_floating_point_serialize(
108 struct bt_ctf_field_type
*, struct metadata_context
*);
110 int bt_ctf_field_type_structure_serialize(struct bt_ctf_field_type
*,
111 struct metadata_context
*);
113 int bt_ctf_field_type_variant_serialize(struct bt_ctf_field_type
*,
114 struct metadata_context
*);
116 int bt_ctf_field_type_array_serialize(struct bt_ctf_field_type
*,
117 struct metadata_context
*);
119 int bt_ctf_field_type_sequence_serialize(struct bt_ctf_field_type
*,
120 struct metadata_context
*);
122 int bt_ctf_field_type_string_serialize(struct bt_ctf_field_type
*,
123 struct metadata_context
*);
126 type_serialize_func
const type_serialize_funcs
[] = {
127 [CTF_TYPE_INTEGER
] = bt_ctf_field_type_integer_serialize
,
129 bt_ctf_field_type_enumeration_serialize
,
131 bt_ctf_field_type_floating_point_serialize
,
133 bt_ctf_field_type_structure_serialize
,
134 [CTF_TYPE_VARIANT
] = bt_ctf_field_type_variant_serialize
,
135 [CTF_TYPE_ARRAY
] = bt_ctf_field_type_array_serialize
,
136 [CTF_TYPE_SEQUENCE
] = bt_ctf_field_type_sequence_serialize
,
137 [CTF_TYPE_STRING
] = bt_ctf_field_type_string_serialize
,
141 void bt_ctf_field_type_integer_set_byte_order(struct bt_ctf_field_type
*,
144 void bt_ctf_field_type_floating_point_set_byte_order(
145 struct bt_ctf_field_type
*, int byte_order
);
148 void (* const set_byte_order_funcs
[])(struct bt_ctf_field_type
*,
151 bt_ctf_field_type_integer_set_byte_order
,
153 bt_ctf_field_type_floating_point_set_byte_order
,
154 [CTF_TYPE_ENUM
... CTF_TYPE_SEQUENCE
] = NULL
,
159 void destroy_enumeration_mapping(struct enumeration_mapping
*mapping
)
165 void destroy_structure_field(struct structure_field
*field
)
168 bt_ctf_field_type_put(field
->type
);
175 void check_ranges_overlap(gpointer element
, gpointer query
)
177 struct enumeration_mapping
*mapping
= element
;
178 struct range_overlap_query
*overlap_query
= query
;
180 if (mapping
->range_start
<= overlap_query
->range_end
181 && overlap_query
->range_start
<= mapping
->range_end
) {
182 overlap_query
->overlaps
= 1;
183 overlap_query
->mapping_name
= mapping
->string
;
186 overlap_query
->overlaps
|=
187 mapping
->string
== overlap_query
->mapping_name
;
191 void bt_ctf_field_type_init(struct bt_ctf_field_type
*type
)
193 enum ctf_type_id type_id
= type
->declaration
->id
;
196 assert(type
&& (type_id
> CTF_TYPE_UNKNOWN
) &&
197 (type_id
< NR_CTF_TYPES
));
199 bt_ctf_ref_init(&type
->ref_count
);
200 type
->freeze
= type_freeze_funcs
[type_id
];
201 type
->serialize
= type_serialize_funcs
[type_id
];
202 ret
= bt_ctf_field_type_set_byte_order(type
, BT_CTF_BYTE_ORDER_NATIVE
);
204 type
->declaration
->alignment
= 1;
208 int add_structure_field(GPtrArray
*fields
,
209 GHashTable
*field_name_to_index
,
210 struct bt_ctf_field_type
*field_type
,
211 const char *field_name
)
214 GQuark name_quark
= g_quark_from_string(field_name
);
215 struct structure_field
*field
;
217 /* Make sure structure does not contain a field of the same name */
218 if (g_hash_table_lookup_extended(field_name_to_index
,
219 GUINT_TO_POINTER(name_quark
), NULL
, NULL
)) {
224 field
= g_new0(struct structure_field
, 1);
230 bt_ctf_field_type_get(field_type
);
231 field
->name
= name_quark
;
232 field
->type
= field_type
;
233 g_hash_table_insert(field_name_to_index
,
234 (gpointer
) (unsigned long) name_quark
,
235 (gpointer
) (unsigned long) fields
->len
);
236 g_ptr_array_add(fields
, field
);
237 bt_ctf_field_type_freeze(field_type
);
243 int bt_ctf_field_type_validate(struct bt_ctf_field_type
*type
)
252 if (type
->declaration
->id
== CTF_TYPE_ENUM
) {
253 struct bt_ctf_field_type_enumeration
*enumeration
=
254 container_of(type
, struct bt_ctf_field_type_enumeration
,
257 ret
= enumeration
->entries
->len
? 0 : -1;
263 struct bt_ctf_field_type
*bt_ctf_field_type_integer_create(unsigned int size
)
265 struct bt_ctf_field_type_integer
*integer
=
266 g_new0(struct bt_ctf_field_type_integer
, 1);
268 if (!integer
|| size
> 64) {
272 integer
->parent
.declaration
= &integer
->declaration
.p
;
273 integer
->parent
.declaration
->id
= CTF_TYPE_INTEGER
;
274 integer
->declaration
.len
= size
;
275 integer
->declaration
.base
= BT_CTF_INTEGER_BASE_DECIMAL
;
276 integer
->declaration
.encoding
= CTF_STRING_NONE
;
277 bt_ctf_field_type_init(&integer
->parent
);
278 return &integer
->parent
;
281 int bt_ctf_field_type_integer_set_signed(struct bt_ctf_field_type
*type
,
285 struct bt_ctf_field_type_integer
*integer
;
287 if (!type
|| type
->frozen
||
288 type
->declaration
->id
!= CTF_TYPE_INTEGER
) {
293 integer
= container_of(type
, struct bt_ctf_field_type_integer
, parent
);
294 if (is_signed
&& integer
->declaration
.len
<= 1) {
299 integer
->declaration
.signedness
= !!is_signed
;
304 int bt_ctf_field_type_integer_set_base(struct bt_ctf_field_type
*type
,
305 enum bt_ctf_integer_base base
)
309 if (!type
|| type
->frozen
||
310 type
->declaration
->id
!= CTF_TYPE_INTEGER
) {
316 case BT_CTF_INTEGER_BASE_BINARY
:
317 case BT_CTF_INTEGER_BASE_OCTAL
:
318 case BT_CTF_INTEGER_BASE_DECIMAL
:
319 case BT_CTF_INTEGER_BASE_HEXADECIMAL
:
321 struct bt_ctf_field_type_integer
*integer
= container_of(type
,
322 struct bt_ctf_field_type_integer
, parent
);
323 integer
->declaration
.base
= base
;
333 int bt_ctf_field_type_integer_set_encoding(struct bt_ctf_field_type
*type
,
334 enum ctf_string_encoding encoding
)
337 struct bt_ctf_field_type_integer
*integer
;
339 if (!type
|| type
->frozen
||
340 (type
->declaration
->id
!= CTF_TYPE_INTEGER
) ||
341 (encoding
< CTF_STRING_NONE
) ||
342 (encoding
>= CTF_STRING_UNKNOWN
)) {
347 integer
= container_of(type
, struct bt_ctf_field_type_integer
, parent
);
348 integer
->declaration
.encoding
= encoding
;
353 struct bt_ctf_field_type
*bt_ctf_field_type_enumeration_create(
354 struct bt_ctf_field_type
*integer_container_type
)
356 struct bt_ctf_field_type_enumeration
*enumeration
= NULL
;
358 if (!integer_container_type
) {
362 if (integer_container_type
->declaration
->id
!= CTF_TYPE_INTEGER
) {
366 enumeration
= g_new0(struct bt_ctf_field_type_enumeration
, 1);
371 enumeration
->parent
.declaration
= &enumeration
->declaration
.p
;
372 enumeration
->parent
.declaration
->id
= CTF_TYPE_ENUM
;
373 bt_ctf_field_type_get(integer_container_type
);
374 enumeration
->container
= integer_container_type
;
375 enumeration
->entries
= g_ptr_array_new_with_free_func(
376 (GDestroyNotify
)destroy_enumeration_mapping
);
377 bt_ctf_field_type_init(&enumeration
->parent
);
378 return &enumeration
->parent
;
384 int bt_ctf_field_type_enumeration_add_mapping(
385 struct bt_ctf_field_type
*type
, const char *string
,
386 int64_t range_start
, int64_t range_end
)
390 struct enumeration_mapping
*mapping
;
391 struct bt_ctf_field_type_enumeration
*enumeration
;
392 struct range_overlap_query query
;
393 char *escaped_string
;
395 if (!type
|| (type
->declaration
->id
!= CTF_TYPE_ENUM
) ||
397 (range_end
< range_start
)) {
402 if (!string
|| strlen(string
) == 0) {
407 escaped_string
= g_strescape(string
, NULL
);
408 if (!escaped_string
) {
413 mapping_name
= g_quark_from_string(escaped_string
);
414 query
= (struct range_overlap_query
) { .range_start
= range_start
,
415 .range_end
= range_end
,
416 .mapping_name
= mapping_name
,
418 enumeration
= container_of(type
, struct bt_ctf_field_type_enumeration
,
421 /* Check that the range does not overlap with one already present */
422 g_ptr_array_foreach(enumeration
->entries
, check_ranges_overlap
, &query
);
423 if (query
.overlaps
) {
428 mapping
= g_new(struct enumeration_mapping
, 1);
434 *mapping
= (struct enumeration_mapping
) {.range_start
= range_start
,
435 .range_end
= range_end
, .string
= mapping_name
};
436 g_ptr_array_add(enumeration
->entries
, mapping
);
438 free(escaped_string
);
443 const char *bt_ctf_field_type_enumeration_get_mapping_name_unsigned(
444 struct bt_ctf_field_type_enumeration
*enumeration_type
,
447 const char *name
= NULL
;
448 struct range_overlap_query query
=
449 (struct range_overlap_query
) {
450 /* FIXME: should not need a cast */
451 .range_start
= (int64_t) value
,
452 .range_end
= (int64_t) value
,
455 g_ptr_array_foreach(enumeration_type
->entries
, check_ranges_overlap
,
457 if (!query
.overlaps
) {
461 name
= g_quark_to_string(query
.mapping_name
);
466 const char *bt_ctf_field_type_enumeration_get_mapping_name_signed(
467 struct bt_ctf_field_type_enumeration
*enumeration_type
,
470 const char *name
= NULL
;
471 struct range_overlap_query query
=
472 (struct range_overlap_query
) {
473 .range_start
= value
,
477 g_ptr_array_foreach(enumeration_type
->entries
, check_ranges_overlap
,
479 if (!query
.overlaps
) {
483 name
= g_quark_to_string(query
.mapping_name
);
488 struct bt_ctf_field_type
*bt_ctf_field_type_floating_point_create(void)
490 struct bt_ctf_field_type_floating_point
*floating_point
=
491 g_new0(struct bt_ctf_field_type_floating_point
, 1);
493 if (!floating_point
) {
497 floating_point
->declaration
.sign
= &floating_point
->sign
;
498 floating_point
->declaration
.mantissa
= &floating_point
->mantissa
;
499 floating_point
->declaration
.exp
= &floating_point
->exp
;
500 floating_point
->sign
.len
= 1;
501 floating_point
->parent
.declaration
= &floating_point
->declaration
.p
;
502 floating_point
->parent
.declaration
->id
= CTF_TYPE_FLOAT
;
503 floating_point
->declaration
.exp
->len
=
504 sizeof(float) * CHAR_BIT
- FLT_MANT_DIG
;
505 floating_point
->declaration
.mantissa
->len
= FLT_MANT_DIG
- 1;
506 floating_point
->sign
.p
.alignment
= 1;
507 floating_point
->mantissa
.p
.alignment
= 1;
508 floating_point
->exp
.p
.alignment
= 1;
510 bt_ctf_field_type_init(&floating_point
->parent
);
512 return floating_point
? &floating_point
->parent
: NULL
;
515 int bt_ctf_field_type_floating_point_set_exponent_digits(
516 struct bt_ctf_field_type
*type
,
517 unsigned int exponent_digits
)
520 struct bt_ctf_field_type_floating_point
*floating_point
;
522 if (!type
|| type
->frozen
||
523 (type
->declaration
->id
!= CTF_TYPE_FLOAT
)) {
528 floating_point
= container_of(type
,
529 struct bt_ctf_field_type_floating_point
, parent
);
530 if ((exponent_digits
!= sizeof(float) * CHAR_BIT
- FLT_MANT_DIG
) &&
531 (exponent_digits
!= sizeof(double) * CHAR_BIT
- DBL_MANT_DIG
) &&
533 sizeof(long double) * CHAR_BIT
- LDBL_MANT_DIG
)) {
538 floating_point
->declaration
.exp
->len
= exponent_digits
;
543 int bt_ctf_field_type_floating_point_set_mantissa_digits(
544 struct bt_ctf_field_type
*type
,
545 unsigned int mantissa_digits
)
548 struct bt_ctf_field_type_floating_point
*floating_point
;
550 if (!type
|| type
->frozen
||
551 (type
->declaration
->id
!= CTF_TYPE_FLOAT
)) {
556 floating_point
= container_of(type
,
557 struct bt_ctf_field_type_floating_point
, parent
);
559 if ((mantissa_digits
!= FLT_MANT_DIG
) &&
560 (mantissa_digits
!= DBL_MANT_DIG
) &&
561 (mantissa_digits
!= LDBL_MANT_DIG
)) {
566 floating_point
->declaration
.mantissa
->len
= mantissa_digits
- 1;
571 struct bt_ctf_field_type
*bt_ctf_field_type_structure_create(void)
573 struct bt_ctf_field_type_structure
*structure
=
574 g_new0(struct bt_ctf_field_type_structure
, 1);
580 structure
->parent
.declaration
= &structure
->declaration
.p
;
581 structure
->parent
.declaration
->id
= CTF_TYPE_STRUCT
;
582 bt_ctf_field_type_init(&structure
->parent
);
583 structure
->fields
= g_ptr_array_new_with_free_func(
584 (GDestroyNotify
)destroy_structure_field
);
585 structure
->field_name_to_index
= g_hash_table_new(NULL
, NULL
);
586 return &structure
->parent
;
591 int bt_ctf_field_type_structure_add_field(struct bt_ctf_field_type
*type
,
592 struct bt_ctf_field_type
*field_type
,
593 const char *field_name
)
596 struct bt_ctf_field_type_structure
*structure
;
598 if (!type
|| !field_type
|| type
->frozen
||
599 validate_identifier(field_name
) ||
600 (type
->declaration
->id
!= CTF_TYPE_STRUCT
) ||
601 bt_ctf_field_type_validate(field_type
)) {
605 structure
= container_of(type
,
606 struct bt_ctf_field_type_structure
, parent
);
607 if (add_structure_field(structure
->fields
,
608 structure
->field_name_to_index
, field_type
, field_name
)) {
613 if (type
->declaration
->alignment
< field_type
->declaration
->alignment
) {
614 type
->declaration
->alignment
=
615 field_type
->declaration
->alignment
;
621 struct bt_ctf_field_type
*bt_ctf_field_type_variant_create(
622 struct bt_ctf_field_type
*enum_tag
, const char *tag_name
)
624 struct bt_ctf_field_type_variant
*variant
= NULL
;
626 if (!enum_tag
|| validate_identifier(tag_name
) ||
627 (enum_tag
->declaration
->id
!= CTF_TYPE_ENUM
)) {
631 variant
= g_new0(struct bt_ctf_field_type_variant
, 1);
636 variant
->parent
.declaration
= &variant
->declaration
.p
;
637 variant
->parent
.declaration
->id
= CTF_TYPE_VARIANT
;
638 variant
->tag_name
= g_string_new(tag_name
);
639 bt_ctf_field_type_init(&variant
->parent
);
640 variant
->field_name_to_index
= g_hash_table_new(NULL
, NULL
);
641 variant
->fields
= g_ptr_array_new_with_free_func(
642 (GDestroyNotify
)destroy_structure_field
);
643 bt_ctf_field_type_get(enum_tag
);
644 variant
->tag
= container_of(enum_tag
,
645 struct bt_ctf_field_type_enumeration
, parent
);
646 return &variant
->parent
;
651 int bt_ctf_field_type_variant_add_field(struct bt_ctf_field_type
*type
,
652 struct bt_ctf_field_type
*field_type
,
653 const char *field_name
)
658 struct bt_ctf_field_type_variant
*variant
;
659 GQuark field_name_quark
= g_quark_from_string(field_name
);
661 if (!type
|| !field_type
|| type
->frozen
||
662 validate_identifier(field_name
) ||
663 (type
->declaration
->id
!= CTF_TYPE_VARIANT
) ||
664 bt_ctf_field_type_validate(field_type
)) {
669 variant
= container_of(type
, struct bt_ctf_field_type_variant
, parent
);
670 /* Make sure this name is present in the enum tag */
671 for (i
= 0; i
< variant
->tag
->entries
->len
; i
++) {
672 struct enumeration_mapping
*mapping
=
673 g_ptr_array_index(variant
->tag
->entries
, i
);
675 if (mapping
->string
== field_name_quark
) {
681 if (!name_found
|| add_structure_field(variant
->fields
,
682 variant
->field_name_to_index
, field_type
, field_name
)) {
690 struct bt_ctf_field_type
*bt_ctf_field_type_array_create(
691 struct bt_ctf_field_type
*element_type
,
694 struct bt_ctf_field_type_array
*array
= NULL
;
696 if (!element_type
|| length
== 0 ||
697 bt_ctf_field_type_validate(element_type
)) {
701 array
= g_new0(struct bt_ctf_field_type_array
, 1);
706 array
->parent
.declaration
= &array
->declaration
.p
;
707 array
->parent
.declaration
->id
= CTF_TYPE_ARRAY
;
708 bt_ctf_field_type_init(&array
->parent
);
709 bt_ctf_field_type_get(element_type
);
710 array
->element_type
= element_type
;
711 array
->length
= length
;
712 array
->parent
.declaration
->alignment
=
713 element_type
->declaration
->alignment
;
714 return &array
->parent
;
719 struct bt_ctf_field_type
*bt_ctf_field_type_sequence_create(
720 struct bt_ctf_field_type
*element_type
,
721 const char *length_field_name
)
723 struct bt_ctf_field_type_sequence
*sequence
= NULL
;
725 if (!element_type
|| validate_identifier(length_field_name
) ||
726 bt_ctf_field_type_validate(element_type
)) {
730 sequence
= g_new0(struct bt_ctf_field_type_sequence
, 1);
735 sequence
->parent
.declaration
= &sequence
->declaration
.p
;
736 sequence
->parent
.declaration
->id
= CTF_TYPE_SEQUENCE
;
737 bt_ctf_field_type_init(&sequence
->parent
);
738 bt_ctf_field_type_get(element_type
);
739 sequence
->element_type
= element_type
;
740 sequence
->length_field_name
= g_string_new(length_field_name
);
741 sequence
->parent
.declaration
->alignment
=
742 element_type
->declaration
->alignment
;
743 return &sequence
->parent
;
748 struct bt_ctf_field_type
*bt_ctf_field_type_string_create(void)
750 struct bt_ctf_field_type_string
*string
=
751 g_new0(struct bt_ctf_field_type_string
, 1);
757 string
->parent
.declaration
= &string
->declaration
.p
;
758 string
->parent
.declaration
->id
= CTF_TYPE_STRING
;
759 bt_ctf_field_type_init(&string
->parent
);
760 string
->declaration
.encoding
= CTF_STRING_UTF8
;
761 string
->parent
.declaration
->alignment
= CHAR_BIT
;
762 return &string
->parent
;
765 int bt_ctf_field_type_string_set_encoding(
766 struct bt_ctf_field_type
*type
,
767 enum ctf_string_encoding encoding
)
770 struct bt_ctf_field_type_string
*string
;
772 if (!type
|| type
->declaration
->id
!= CTF_TYPE_STRING
||
773 (encoding
!= CTF_STRING_UTF8
&&
774 encoding
!= CTF_STRING_ASCII
)) {
779 string
= container_of(type
, struct bt_ctf_field_type_string
, parent
);
780 string
->declaration
.encoding
= encoding
;
785 int bt_ctf_field_type_set_alignment(struct bt_ctf_field_type
*type
,
786 unsigned int alignment
)
790 /* Alignment must be bit-aligned (1) or byte aligned */
791 if (!type
|| type
->frozen
|| (alignment
!= 1 && (alignment
& 0x7))) {
796 if (type
->declaration
->id
== CTF_TYPE_STRING
&&
797 alignment
!= CHAR_BIT
) {
802 type
->declaration
->alignment
= alignment
;
808 int bt_ctf_field_type_set_byte_order(struct bt_ctf_field_type
*type
,
809 enum bt_ctf_byte_order byte_order
)
812 int internal_byte_order
;
813 enum ctf_type_id type_id
;
815 if (!type
|| type
->frozen
) {
820 type_id
= type
->declaration
->id
;
821 switch (byte_order
) {
822 case BT_CTF_BYTE_ORDER_NATIVE
:
823 internal_byte_order
= (G_BYTE_ORDER
== G_LITTLE_ENDIAN
?
824 LITTLE_ENDIAN
: BIG_ENDIAN
);
826 case BT_CTF_BYTE_ORDER_LITTLE_ENDIAN
:
827 internal_byte_order
= LITTLE_ENDIAN
;
829 case BT_CTF_BYTE_ORDER_BIG_ENDIAN
:
830 case BT_CTF_BYTE_ORDER_NETWORK
:
831 internal_byte_order
= BIG_ENDIAN
;
838 if (set_byte_order_funcs
[type_id
]) {
839 set_byte_order_funcs
[type_id
](type
, internal_byte_order
);
845 void bt_ctf_field_type_get(struct bt_ctf_field_type
*type
)
851 bt_ctf_ref_get(&type
->ref_count
);
854 void bt_ctf_field_type_put(struct bt_ctf_field_type
*type
)
856 enum ctf_type_id type_id
;
862 type_id
= type
->declaration
->id
;
863 assert(type_id
> CTF_TYPE_UNKNOWN
&& type_id
< NR_CTF_TYPES
);
864 bt_ctf_ref_put(&type
->ref_count
, type_destroy_funcs
[type_id
]);
868 void bt_ctf_field_type_freeze(struct bt_ctf_field_type
*type
)
878 enum ctf_type_id
bt_ctf_field_type_get_type_id(
879 struct bt_ctf_field_type
*type
)
882 return CTF_TYPE_UNKNOWN
;
885 return type
->declaration
->id
;
889 struct bt_ctf_field_type
*bt_ctf_field_type_structure_get_type(
890 struct bt_ctf_field_type_structure
*structure
,
893 struct bt_ctf_field_type
*type
= NULL
;
894 struct structure_field
*field
;
895 GQuark name_quark
= g_quark_try_string(name
);
902 if (!g_hash_table_lookup_extended(structure
->field_name_to_index
,
903 GUINT_TO_POINTER(name_quark
), NULL
, (gpointer
*)&index
)) {
907 field
= structure
->fields
->pdata
[index
];
914 struct bt_ctf_field_type
*bt_ctf_field_type_array_get_element_type(
915 struct bt_ctf_field_type_array
*array
)
918 return array
->element_type
;
922 struct bt_ctf_field_type
*bt_ctf_field_type_sequence_get_element_type(
923 struct bt_ctf_field_type_sequence
*sequence
)
926 return sequence
->element_type
;
930 struct bt_ctf_field_type
*bt_ctf_field_type_variant_get_field_type(
931 struct bt_ctf_field_type_variant
*variant
,
934 struct bt_ctf_field_type
*type
= NULL
;
935 GQuark field_name_quark
;
937 struct structure_field
*field_entry
;
938 struct range_overlap_query query
= {.range_start
= tag_value
,
939 .range_end
= tag_value
, .mapping_name
= 0, .overlaps
= 0};
941 g_ptr_array_foreach(variant
->tag
->entries
, check_ranges_overlap
,
943 if (!query
.overlaps
) {
947 field_name_quark
= query
.mapping_name
;
948 if (!g_hash_table_lookup_extended(variant
->field_name_to_index
,
949 GUINT_TO_POINTER(field_name_quark
), NULL
, &index
)) {
953 field_entry
= g_ptr_array_index(variant
->fields
, (size_t)index
);
954 type
= field_entry
->type
;
960 int bt_ctf_field_type_serialize(struct bt_ctf_field_type
*type
,
961 struct metadata_context
*context
)
965 if (!type
|| !context
) {
970 ret
= type
->serialize(type
, context
);
976 void bt_ctf_field_type_integer_destroy(struct bt_ctf_ref
*ref
)
978 struct bt_ctf_field_type_integer
*integer
;
984 integer
= container_of(
985 container_of(ref
, struct bt_ctf_field_type
, ref_count
),
986 struct bt_ctf_field_type_integer
, parent
);
991 void bt_ctf_field_type_enumeration_destroy(struct bt_ctf_ref
*ref
)
993 struct bt_ctf_field_type_enumeration
*enumeration
;
999 enumeration
= container_of(
1000 container_of(ref
, struct bt_ctf_field_type
, ref_count
),
1001 struct bt_ctf_field_type_enumeration
, parent
);
1002 g_ptr_array_free(enumeration
->entries
, TRUE
);
1003 bt_ctf_field_type_put(enumeration
->container
);
1004 g_free(enumeration
);
1008 void bt_ctf_field_type_floating_point_destroy(struct bt_ctf_ref
*ref
)
1010 struct bt_ctf_field_type_floating_point
*floating_point
;
1016 floating_point
= container_of(
1017 container_of(ref
, struct bt_ctf_field_type
, ref_count
),
1018 struct bt_ctf_field_type_floating_point
, parent
);
1019 g_free(floating_point
);
1023 void bt_ctf_field_type_structure_destroy(struct bt_ctf_ref
*ref
)
1025 struct bt_ctf_field_type_structure
*structure
;
1031 structure
= container_of(
1032 container_of(ref
, struct bt_ctf_field_type
, ref_count
),
1033 struct bt_ctf_field_type_structure
, parent
);
1034 g_ptr_array_free(structure
->fields
, TRUE
);
1035 g_hash_table_destroy(structure
->field_name_to_index
);
1040 void bt_ctf_field_type_variant_destroy(struct bt_ctf_ref
*ref
)
1042 struct bt_ctf_field_type_variant
*variant
;
1048 variant
= container_of(
1049 container_of(ref
, struct bt_ctf_field_type
, ref_count
),
1050 struct bt_ctf_field_type_variant
, parent
);
1051 g_ptr_array_free(variant
->fields
, TRUE
);
1052 g_hash_table_destroy(variant
->field_name_to_index
);
1053 g_string_free(variant
->tag_name
, TRUE
);
1054 bt_ctf_field_type_put(&variant
->tag
->parent
);
1059 void bt_ctf_field_type_array_destroy(struct bt_ctf_ref
*ref
)
1061 struct bt_ctf_field_type_array
*array
;
1067 array
= container_of(
1068 container_of(ref
, struct bt_ctf_field_type
, ref_count
),
1069 struct bt_ctf_field_type_array
, parent
);
1070 bt_ctf_field_type_put(array
->element_type
);
1075 void bt_ctf_field_type_sequence_destroy(struct bt_ctf_ref
*ref
)
1077 struct bt_ctf_field_type_sequence
*sequence
;
1083 sequence
= container_of(
1084 container_of(ref
, struct bt_ctf_field_type
, ref_count
),
1085 struct bt_ctf_field_type_sequence
, parent
);
1086 bt_ctf_field_type_put(sequence
->element_type
);
1087 g_string_free(sequence
->length_field_name
, TRUE
);
1092 void bt_ctf_field_type_string_destroy(struct bt_ctf_ref
*ref
)
1094 struct bt_ctf_field_type_string
*string
;
1100 string
= container_of(
1101 container_of(ref
, struct bt_ctf_field_type
, ref_count
),
1102 struct bt_ctf_field_type_string
, parent
);
1107 void generic_field_type_freeze(struct bt_ctf_field_type
*type
)
1113 void bt_ctf_field_type_enumeration_freeze(struct bt_ctf_field_type
*type
)
1115 struct bt_ctf_field_type_enumeration
*enumeration_type
= container_of(
1116 type
, struct bt_ctf_field_type_enumeration
, parent
);
1118 generic_field_type_freeze(type
);
1119 bt_ctf_field_type_freeze(enumeration_type
->container
);
1123 void freeze_structure_field(struct structure_field
*field
)
1125 bt_ctf_field_type_freeze(field
->type
);
1129 void bt_ctf_field_type_structure_freeze(struct bt_ctf_field_type
*type
)
1131 struct bt_ctf_field_type_structure
*structure_type
= container_of(
1132 type
, struct bt_ctf_field_type_structure
, parent
);
1134 generic_field_type_freeze(type
);
1135 g_ptr_array_foreach(structure_type
->fields
, (GFunc
)freeze_structure_field
,
1140 void bt_ctf_field_type_variant_freeze(struct bt_ctf_field_type
*type
)
1142 struct bt_ctf_field_type_variant
*variant_type
= container_of(
1143 type
, struct bt_ctf_field_type_variant
, parent
);
1145 generic_field_type_freeze(type
);
1146 g_ptr_array_foreach(variant_type
->fields
, (GFunc
)freeze_structure_field
,
1151 void bt_ctf_field_type_array_freeze(struct bt_ctf_field_type
*type
)
1153 struct bt_ctf_field_type_array
*array_type
= container_of(
1154 type
, struct bt_ctf_field_type_array
, parent
);
1156 generic_field_type_freeze(type
);
1157 bt_ctf_field_type_freeze(array_type
->element_type
);
1161 void bt_ctf_field_type_sequence_freeze(struct bt_ctf_field_type
*type
)
1163 struct bt_ctf_field_type_sequence
*sequence_type
= container_of(
1164 type
, struct bt_ctf_field_type_sequence
, parent
);
1166 generic_field_type_freeze(type
);
1167 bt_ctf_field_type_freeze(sequence_type
->element_type
);
1171 const char *get_encoding_string(enum ctf_string_encoding encoding
)
1173 const char *encoding_string
;
1176 case CTF_STRING_NONE
:
1177 encoding_string
= "none";
1179 case CTF_STRING_ASCII
:
1180 encoding_string
= "ASCII";
1182 case CTF_STRING_UTF8
:
1183 encoding_string
= "UTF8";
1186 encoding_string
= "unknown";
1190 return encoding_string
;
1194 const char *get_integer_base_string(enum bt_ctf_integer_base base
)
1196 const char *base_string
;
1199 case BT_CTF_INTEGER_BASE_DECIMAL
:
1200 base_string
= "decimal";
1202 case BT_CTF_INTEGER_BASE_HEXADECIMAL
:
1203 base_string
= "hexadecimal";
1205 case BT_CTF_INTEGER_BASE_OCTAL
:
1206 base_string
= "octal";
1208 case BT_CTF_INTEGER_BASE_BINARY
:
1209 base_string
= "binary";
1212 base_string
= "unknown";
1220 int bt_ctf_field_type_integer_serialize(struct bt_ctf_field_type
*type
,
1221 struct metadata_context
*context
)
1223 struct bt_ctf_field_type_integer
*integer
= container_of(type
,
1224 struct bt_ctf_field_type_integer
, parent
);
1226 g_string_append_printf(context
->string
,
1227 "integer { size = %zu; align = %zu; signed = %s; encoding = %s; base = %s; byte_order = %s; }",
1228 integer
->declaration
.len
, type
->declaration
->alignment
,
1229 (integer
->declaration
.signedness
? "true" : "false"),
1230 get_encoding_string(integer
->declaration
.encoding
),
1231 get_integer_base_string(integer
->declaration
.base
),
1232 get_byte_order_string(integer
->declaration
.byte_order
));
1237 int bt_ctf_field_type_enumeration_serialize(struct bt_ctf_field_type
*type
,
1238 struct metadata_context
*context
)
1242 struct bt_ctf_field_type_enumeration
*enumeration
= container_of(type
,
1243 struct bt_ctf_field_type_enumeration
, parent
);
1245 ret
= bt_ctf_field_type_validate(type
);
1250 g_string_append(context
->string
, "enum : ");
1251 ret
= bt_ctf_field_type_serialize(enumeration
->container
, context
);
1256 g_string_append(context
->string
, " { ");
1257 for (entry
= 0; entry
< enumeration
->entries
->len
; entry
++) {
1258 struct enumeration_mapping
*mapping
=
1259 enumeration
->entries
->pdata
[entry
];
1261 if (mapping
->range_start
== mapping
->range_end
) {
1262 g_string_append_printf(context
->string
,
1263 "\"%s\" = %" PRId64
,
1264 g_quark_to_string(mapping
->string
),
1265 mapping
->range_start
);
1267 g_string_append_printf(context
->string
,
1268 "\"%s\" = %" PRId64
" ... %" PRId64
,
1269 g_quark_to_string(mapping
->string
),
1270 mapping
->range_start
, mapping
->range_end
);
1273 g_string_append(context
->string
,
1274 ((entry
!= (enumeration
->entries
->len
- 1)) ?
1278 if (context
->field_name
->len
) {
1279 g_string_append_printf(context
->string
, " %s",
1280 context
->field_name
->str
);
1281 g_string_assign(context
->field_name
, "");
1288 int bt_ctf_field_type_floating_point_serialize(struct bt_ctf_field_type
*type
,
1289 struct metadata_context
*context
)
1291 struct bt_ctf_field_type_floating_point
*floating_point
= container_of(
1292 type
, struct bt_ctf_field_type_floating_point
, parent
);
1294 g_string_append_printf(context
->string
,
1295 "floating_point { exp_dig = %zu; mant_dig = %zu; byte_order = %s; align = %zu; }",
1296 floating_point
->declaration
.exp
->len
,
1297 floating_point
->declaration
.mantissa
->len
+ 1,
1298 get_byte_order_string(floating_point
->declaration
.byte_order
),
1299 type
->declaration
->alignment
);
1304 int bt_ctf_field_type_structure_serialize(struct bt_ctf_field_type
*type
,
1305 struct metadata_context
*context
)
1308 unsigned int indent
;
1310 struct bt_ctf_field_type_structure
*structure
= container_of(type
,
1311 struct bt_ctf_field_type_structure
, parent
);
1312 GString
*structure_field_name
= context
->field_name
;
1314 context
->field_name
= g_string_new("");
1316 context
->current_indentation_level
++;
1317 g_string_append(context
->string
, "struct {\n");
1319 for (i
= 0; i
< structure
->fields
->len
; i
++) {
1320 struct structure_field
*field
;
1322 for (indent
= 0; indent
< context
->current_indentation_level
;
1324 g_string_append_c(context
->string
, '\t');
1327 field
= structure
->fields
->pdata
[i
];
1328 g_string_assign(context
->field_name
,
1329 g_quark_to_string(field
->name
));
1330 ret
= bt_ctf_field_type_serialize(field
->type
, context
);
1335 if (context
->field_name
->len
) {
1336 g_string_append_printf(context
->string
, " %s",
1337 context
->field_name
->str
);
1339 g_string_append(context
->string
, ";\n");
1342 context
->current_indentation_level
--;
1343 for (indent
= 0; indent
< context
->current_indentation_level
;
1345 g_string_append_c(context
->string
, '\t');
1348 g_string_append_printf(context
->string
, "} align(%zu)",
1349 type
->declaration
->alignment
);
1351 g_string_free(context
->field_name
, TRUE
);
1352 context
->field_name
= structure_field_name
;
1357 int bt_ctf_field_type_variant_serialize(struct bt_ctf_field_type
*type
,
1358 struct metadata_context
*context
)
1361 unsigned int indent
;
1363 struct bt_ctf_field_type_variant
*variant
= container_of(
1364 type
, struct bt_ctf_field_type_variant
, parent
);
1365 GString
*variant_field_name
= context
->field_name
;
1367 context
->field_name
= g_string_new("");
1368 g_string_append_printf(context
->string
,
1369 "variant <%s> {\n", variant
->tag_name
->str
);
1370 context
->current_indentation_level
++;
1371 for (i
= 0; i
< variant
->fields
->len
; i
++) {
1372 struct structure_field
*field
= variant
->fields
->pdata
[i
];
1374 g_string_assign(context
->field_name
,
1375 g_quark_to_string(field
->name
));
1376 for (indent
= 0; indent
< context
->current_indentation_level
;
1378 g_string_append_c(context
->string
, '\t');
1381 g_string_assign(context
->field_name
,
1382 g_quark_to_string(field
->name
));
1383 ret
= bt_ctf_field_type_serialize(field
->type
, context
);
1388 if (context
->field_name
->len
) {
1389 g_string_append_printf(context
->string
, " %s;",
1390 context
->field_name
->str
);
1393 g_string_append_c(context
->string
, '\n');
1396 context
->current_indentation_level
--;
1397 for (indent
= 0; indent
< context
->current_indentation_level
;
1399 g_string_append_c(context
->string
, '\t');
1402 g_string_append(context
->string
, "}");
1404 g_string_free(context
->field_name
, TRUE
);
1405 context
->field_name
= variant_field_name
;
1410 int bt_ctf_field_type_array_serialize(struct bt_ctf_field_type
*type
,
1411 struct metadata_context
*context
)
1414 struct bt_ctf_field_type_array
*array
= container_of(type
,
1415 struct bt_ctf_field_type_array
, parent
);
1417 ret
= bt_ctf_field_type_serialize(array
->element_type
, context
);
1422 if (context
->field_name
->len
) {
1423 g_string_append_printf(context
->string
, " %s[%u]",
1424 context
->field_name
->str
, array
->length
);
1425 g_string_assign(context
->field_name
, "");
1427 g_string_append_printf(context
->string
, "[%u]", array
->length
);
1434 int bt_ctf_field_type_sequence_serialize(struct bt_ctf_field_type
*type
,
1435 struct metadata_context
*context
)
1438 struct bt_ctf_field_type_sequence
*sequence
= container_of(
1439 type
, struct bt_ctf_field_type_sequence
, parent
);
1441 ret
= bt_ctf_field_type_serialize(sequence
->element_type
, context
);
1446 if (context
->field_name
->len
) {
1447 g_string_append_printf(context
->string
, " %s[%s]",
1448 context
->field_name
->str
,
1449 sequence
->length_field_name
->str
);
1450 g_string_assign(context
->field_name
, "");
1452 g_string_append_printf(context
->string
, "[%s]",
1453 sequence
->length_field_name
->str
);
1460 int bt_ctf_field_type_string_serialize(struct bt_ctf_field_type
*type
,
1461 struct metadata_context
*context
)
1463 struct bt_ctf_field_type_string
*string
= container_of(
1464 type
, struct bt_ctf_field_type_string
, parent
);
1466 g_string_append_printf(context
->string
,
1467 "string { encoding = %s; }",
1468 get_encoding_string(string
->declaration
.encoding
));
1473 void bt_ctf_field_type_integer_set_byte_order(struct bt_ctf_field_type
*type
,
1476 struct bt_ctf_field_type_integer
*integer_type
= container_of(type
,
1477 struct bt_ctf_field_type_integer
, parent
);
1479 integer_type
->declaration
.byte_order
= byte_order
;
1483 void bt_ctf_field_type_floating_point_set_byte_order(
1484 struct bt_ctf_field_type
*type
, int byte_order
)
1486 struct bt_ctf_field_type_floating_point
*floating_point_type
=
1487 container_of(type
, struct bt_ctf_field_type_floating_point
,
1490 floating_point_type
->declaration
.byte_order
= byte_order
;
1491 floating_point_type
->sign
.byte_order
= byte_order
;
1492 floating_point_type
->mantissa
.byte_order
= byte_order
;
1493 floating_point_type
->exp
.byte_order
= byte_order
;