cpp-common/bt2c/fmt.hpp: use `wise_enum::string_type` in `EnableIfIsWiseEnum` definition
[babeltrace.git] / src / ctf-writer / field-types.c
1 /*
2 * SPDX-License-Identifier: MIT
3 *
4 * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
5 */
6
7 #define BT_LOG_TAG "CTF-WRITER/FIELD-TYPES"
8 #include "logging.h"
9
10 #include <float.h>
11 #include <inttypes.h>
12 #include <stdbool.h>
13 #include <stdlib.h>
14
15 #include <babeltrace2-ctf-writer/fields.h>
16 #include <babeltrace2-ctf-writer/field-types.h>
17 #include <babeltrace2-ctf-writer/object.h>
18 #include <babeltrace2-ctf-writer/utils.h>
19
20 #include "common/assert.h"
21 #include "compat/compiler.h"
22 #include "compat/endian.h"
23
24 #include "assert-pre.h"
25 #include "clock-class.h"
26 #include "clock.h"
27 #include "field-path.h"
28 #include "fields.h"
29 #include "field-types.h"
30 #include "object.h"
31 #include "utils.h"
32
33 static
34 void destroy_enumeration_mapping(struct bt_ctf_enumeration_mapping *mapping)
35 {
36 g_free(mapping);
37 }
38
39 void bt_ctf_field_type_common_initialize(struct bt_ctf_field_type_common *ft,
40 bool init_bo, bt_ctf_object_release_func release_func,
41 struct bt_ctf_field_type_common_methods *methods)
42 {
43 BT_ASSERT_DBG(ft && (ft->id > BT_CTF_FIELD_TYPE_ID_UNKNOWN) &&
44 (ft->id < BT_CTF_FIELD_TYPE_ID_NR));
45
46 bt_ctf_object_init_shared(&ft->base, release_func);
47 ft->methods = methods;
48
49 if (init_bo) {
50 int ret;
51 const enum bt_ctf_byte_order bo = BT_CTF_BYTE_ORDER_NATIVE;
52
53 BT_LOGD("Setting initial field type's byte order: bo=%s",
54 bt_ctf_byte_order_string(bo));
55 ret = bt_ctf_field_type_common_set_byte_order(ft, bo);
56 BT_ASSERT_DBG(ret == 0);
57 }
58
59 ft->alignment = 1;
60 }
61
62 void bt_ctf_field_type_common_integer_initialize(
63 struct bt_ctf_field_type_common *ft,
64 unsigned int size, bt_ctf_object_release_func release_func,
65 struct bt_ctf_field_type_common_methods *methods)
66 {
67 struct bt_ctf_field_type_common_integer *int_ft = BT_CTF_FROM_COMMON(ft);
68
69 BT_ASSERT_DBG(size > 0);
70 BT_LOGD("Initializing common integer field type object: size=%u",
71 size);
72 ft->id = BT_CTF_FIELD_TYPE_ID_INTEGER;
73 int_ft->size = size;
74 int_ft->base = BT_CTF_INTEGER_BASE_DECIMAL;
75 int_ft->encoding = BT_CTF_STRING_ENCODING_NONE;
76 bt_ctf_field_type_common_initialize(ft, true, release_func, methods);
77 BT_LOGD("Initialized common integer field type object: addr=%p, size=%u",
78 ft, size);
79 }
80
81 void bt_ctf_field_type_common_floating_point_initialize(
82 struct bt_ctf_field_type_common *ft,
83 bt_ctf_object_release_func release_func,
84 struct bt_ctf_field_type_common_methods *methods)
85 {
86 struct bt_ctf_field_type_common_floating_point *flt_ft = BT_CTF_FROM_COMMON(ft);
87
88 BT_LOGD_STR("Initializing common floating point number field type object.");
89 ft->id = BT_CTF_FIELD_TYPE_ID_FLOAT;
90 flt_ft->exp_dig = sizeof(float) * CHAR_BIT - FLT_MANT_DIG;
91 flt_ft->mant_dig = FLT_MANT_DIG;
92 bt_ctf_field_type_common_initialize(ft, true, release_func, methods);
93 BT_LOGD("Initialized common floating point number field type object: addr=%p, "
94 "exp-size=%u, mant-size=%u", ft, flt_ft->exp_dig,
95 flt_ft->mant_dig);
96 }
97
98 void bt_ctf_field_type_common_enumeration_initialize(
99 struct bt_ctf_field_type_common *ft,
100 struct bt_ctf_field_type_common *container_ft,
101 bt_ctf_object_release_func release_func,
102 struct bt_ctf_field_type_common_methods *methods)
103 {
104 struct bt_ctf_field_type_common_enumeration *enum_ft = BT_CTF_FROM_COMMON(ft);
105
106 BT_ASSERT_DBG(container_ft);
107 BT_LOGD("Initializing common enumeration field type object: int-ft-addr=%p",
108 container_ft);
109 ft->id = BT_CTF_FIELD_TYPE_ID_ENUM;
110 enum_ft->container_ft = bt_ctf_object_get_ref(container_ft);
111 enum_ft->entries = g_ptr_array_new_with_free_func(
112 (GDestroyNotify) destroy_enumeration_mapping);
113 bt_ctf_field_type_common_initialize(ft, false, release_func, methods);
114 BT_LOGD("Initialized common enumeration field type object: addr=%p, "
115 "int-ft-addr=%p, int-ft-size=%u", ft, container_ft,
116 bt_ctf_field_type_common_integer_get_size(container_ft));
117 }
118
119 void bt_ctf_field_type_common_string_initialize(
120 struct bt_ctf_field_type_common *ft,
121 bt_ctf_object_release_func release_func,
122 struct bt_ctf_field_type_common_methods *methods)
123 {
124 struct bt_ctf_field_type_common_string *string_ft = BT_CTF_FROM_COMMON(ft);
125
126 BT_LOGD_STR("Initializing common string field type object.");
127 ft->id = BT_CTF_FIELD_TYPE_ID_STRING;
128 bt_ctf_field_type_common_initialize(ft, true, release_func, methods);
129 string_ft->encoding = BT_CTF_STRING_ENCODING_UTF8;
130 ft->alignment = CHAR_BIT;
131 BT_LOGD("Initialized common string field type object: addr=%p", ft);
132 }
133
134 void bt_ctf_field_type_common_structure_initialize(
135 struct bt_ctf_field_type_common *ft,
136 bt_ctf_object_release_func release_func,
137 struct bt_ctf_field_type_common_methods *methods)
138 {
139 struct bt_ctf_field_type_common_structure *struct_ft = BT_CTF_FROM_COMMON(ft);
140
141 BT_LOGD_STR("Initializing common structure field type object.");
142 ft->id = BT_CTF_FIELD_TYPE_ID_STRUCT;
143 struct_ft->fields = g_array_new(FALSE, TRUE,
144 sizeof(struct bt_ctf_field_type_common_structure_field));
145 struct_ft->field_name_to_index = g_hash_table_new(NULL, NULL);
146 bt_ctf_field_type_common_initialize(ft, true, release_func, methods);
147 BT_LOGD("Initialized common structure field type object: addr=%p", ft);
148 }
149
150 void bt_ctf_field_type_common_array_initialize(
151 struct bt_ctf_field_type_common *ft,
152 struct bt_ctf_field_type_common *element_ft,
153 unsigned int length, bt_ctf_object_release_func release_func,
154 struct bt_ctf_field_type_common_methods *methods)
155 {
156 struct bt_ctf_field_type_common_array *array_ft = BT_CTF_FROM_COMMON(ft);
157
158 BT_ASSERT_DBG(element_ft);
159 BT_LOGD("Initializing common array field type object: element-ft-addr=%p, "
160 "length=%u", element_ft, length);
161 ft->id = BT_CTF_FIELD_TYPE_ID_ARRAY;
162 array_ft->element_ft = bt_ctf_object_get_ref(element_ft);
163 array_ft->length = length;
164 bt_ctf_field_type_common_initialize(ft, false, release_func, methods);
165 BT_LOGD("Initialized common array field type object: addr=%p, "
166 "element-ft-addr=%p, length=%u", ft, element_ft, length);
167 }
168
169 void bt_ctf_field_type_common_sequence_initialize(
170 struct bt_ctf_field_type_common *ft,
171 struct bt_ctf_field_type_common *element_ft,
172 const char *length_field_name,
173 bt_ctf_object_release_func release_func,
174 struct bt_ctf_field_type_common_methods *methods)
175 {
176 struct bt_ctf_field_type_common_sequence *seq_ft = BT_CTF_FROM_COMMON(ft);
177
178 BT_ASSERT_DBG(element_ft);
179 BT_ASSERT_DBG(length_field_name);
180 BT_ASSERT_DBG(bt_ctf_identifier_is_valid(length_field_name));
181 BT_LOGD("Initializing common sequence field type object: element-ft-addr=%p, "
182 "length-field-name=\"%s\"", element_ft, length_field_name);
183 ft->id = BT_CTF_FIELD_TYPE_ID_SEQUENCE;
184 seq_ft->element_ft = bt_ctf_object_get_ref(element_ft);
185 seq_ft->length_field_name = g_string_new(length_field_name);
186 bt_ctf_field_type_common_initialize(ft, false, release_func, methods);
187 BT_LOGD("Initialized common sequence field type object: addr=%p, "
188 "element-ft-addr=%p, length-field-name=\"%s\"",
189 ft, element_ft, length_field_name);
190 }
191
192 void bt_ctf_field_type_common_variant_initialize(
193 struct bt_ctf_field_type_common *ft,
194 struct bt_ctf_field_type_common *tag_ft,
195 const char *tag_name,
196 bt_ctf_object_release_func release_func,
197 struct bt_ctf_field_type_common_methods *methods)
198 {
199 struct bt_ctf_field_type_common_variant *var_ft = BT_CTF_FROM_COMMON(ft);
200
201 BT_ASSERT_DBG(!tag_name || bt_ctf_identifier_is_valid(tag_name));
202 BT_LOGD("Initializing common variant field type object: "
203 "tag-ft-addr=%p, tag-field-name=\"%s\"",
204 tag_ft, tag_name);
205 ft->id = BT_CTF_FIELD_TYPE_ID_VARIANT;
206 var_ft->tag_name = g_string_new(tag_name);
207 var_ft->choice_name_to_index = g_hash_table_new(NULL, NULL);
208 var_ft->choices = g_array_new(FALSE, TRUE,
209 sizeof(struct bt_ctf_field_type_common_variant_choice));
210
211 if (tag_ft) {
212 var_ft->tag_ft = bt_ctf_object_get_ref(tag_ft);
213 }
214
215 bt_ctf_field_type_common_initialize(ft, true, release_func, methods);
216 /* A variant's alignment is undefined */
217 ft->alignment = 0;
218 BT_LOGD("Initialized common variant field type object: addr=%p, "
219 "tag-ft-addr=%p, tag-field-name=\"%s\"",
220 ft, tag_ft, tag_name);
221 }
222
223 void bt_ctf_field_type_common_integer_destroy(struct bt_ctf_object *obj)
224 {
225 struct bt_ctf_field_type_common_integer *ft = (void *) obj;
226
227 if (!ft) {
228 return;
229 }
230
231 BT_LOGD("Destroying integer field type object: addr=%p", ft);
232 BT_LOGD_STR("Putting mapped clock class.");
233 bt_ctf_object_put_ref(ft->mapped_clock_class);
234 g_free(ft);
235 }
236
237 void bt_ctf_field_type_common_floating_point_destroy(struct bt_ctf_object *obj)
238 {
239 struct bt_ctf_field_type_common_floating_point *ft = (void *) obj;
240
241 if (!ft) {
242 return;
243 }
244
245 BT_LOGD("Destroying floating point number field type object: addr=%p", ft);
246 g_free(ft);
247 }
248
249 void bt_ctf_field_type_common_enumeration_destroy_recursive(struct bt_ctf_object *obj)
250 {
251 struct bt_ctf_field_type_common_enumeration *ft = (void *) obj;
252
253 if (!ft) {
254 return;
255 }
256
257 BT_LOGD("Destroying enumeration field type object: addr=%p", ft);
258 g_ptr_array_free(ft->entries, TRUE);
259 BT_LOGD_STR("Putting container field type.");
260 bt_ctf_object_put_ref(ft->container_ft);
261 g_free(ft);
262 }
263
264 void bt_ctf_field_type_common_string_destroy(struct bt_ctf_object *obj)
265 {
266 struct bt_ctf_field_type_common_string *ft = (void *) obj;
267
268 if (!ft) {
269 return;
270 }
271
272 BT_LOGD("Destroying string field type object: addr=%p", ft);
273 g_free(ft);
274 }
275
276 static
277 void bt_ctf_field_type_common_structure_field_finalize(
278 struct bt_ctf_field_type_common_structure_field *field)
279 {
280 if (!field) {
281 return;
282 }
283
284 BT_LOGD("Finalizing structure field type's field: "
285 "addr=%p, field-ft-addr=%p, field-name=\"%s\"",
286 field, field->type, g_quark_to_string(field->name));
287 BT_LOGD_STR("Putting field type.");
288 bt_ctf_object_put_ref(field->type);
289 }
290
291 void bt_ctf_field_type_common_structure_destroy_recursive(struct bt_ctf_object *obj)
292 {
293 struct bt_ctf_field_type_common_structure *ft = (void *) obj;
294 uint64_t i;
295
296 if (!ft) {
297 return;
298 }
299
300 BT_LOGD("Destroying structure field type object: addr=%p", ft);
301
302 if (ft->fields) {
303 for (i = 0; i < ft->fields->len; i++) {
304 bt_ctf_field_type_common_structure_field_finalize(
305 BT_CTF_FIELD_TYPE_COMMON_STRUCTURE_FIELD_AT_INDEX(
306 ft, i));
307 }
308
309 g_array_free(ft->fields, TRUE);
310 }
311
312 if (ft->field_name_to_index) {
313 g_hash_table_destroy(ft->field_name_to_index);
314 }
315
316 g_free(ft);
317 }
318
319 void bt_ctf_field_type_common_array_destroy_recursive(struct bt_ctf_object *obj)
320 {
321 struct bt_ctf_field_type_common_array *ft = (void *) obj;
322
323 if (!ft) {
324 return;
325 }
326
327 BT_LOGD("Destroying array field type object: addr=%p", ft);
328 BT_LOGD_STR("Putting element field type.");
329 bt_ctf_object_put_ref(ft->element_ft);
330 g_free(ft);
331 }
332
333 void bt_ctf_field_type_common_sequence_destroy_recursive(struct bt_ctf_object *obj)
334 {
335 struct bt_ctf_field_type_common_sequence *ft = (void *) obj;
336
337 if (!ft) {
338 return;
339 }
340
341 BT_LOGD("Destroying sequence field type object: addr=%p", ft);
342 BT_LOGD_STR("Putting element field type.");
343 bt_ctf_object_put_ref(ft->element_ft);
344 g_string_free(ft->length_field_name, TRUE);
345 BT_LOGD_STR("Putting length field path.");
346 bt_ctf_object_put_ref(ft->length_field_path);
347 g_free(ft);
348 }
349
350 static
351 void bt_ctf_field_type_common_variant_choice_finalize(
352 struct bt_ctf_field_type_common_variant_choice *choice)
353 {
354 if (!choice) {
355 return;
356 }
357
358 BT_LOGD("Finalizing variant field type's choice: "
359 "addr=%p, field-ft-addr=%p, field-name=\"%s\"",
360 choice, choice->type, g_quark_to_string(choice->name));
361 BT_LOGD_STR("Putting field type.");
362 bt_ctf_object_put_ref(choice->type);
363
364 if (choice->ranges) {
365 g_array_free(choice->ranges, TRUE);
366 }
367 }
368
369 void bt_ctf_field_type_common_variant_destroy_recursive(struct bt_ctf_object *obj)
370 {
371 struct bt_ctf_field_type_common_variant *ft = (void *) obj;
372 uint64_t i;
373
374 if (!ft) {
375 return;
376 }
377
378 BT_LOGD("Destroying variant field type object: addr=%p", ft);
379
380 if (ft->choices) {
381 for (i = 0; i < ft->choices->len; i++) {
382 bt_ctf_field_type_common_variant_choice_finalize(
383 BT_CTF_FIELD_TYPE_COMMON_VARIANT_CHOICE_AT_INDEX(
384 ft, i));
385 }
386
387 g_array_free(ft->choices, TRUE);
388 }
389
390 if (ft->choice_name_to_index) {
391 g_hash_table_destroy(ft->choice_name_to_index);
392 }
393
394 if (ft->tag_name) {
395 g_string_free(ft->tag_name, TRUE);
396 }
397
398 BT_LOGD_STR("Putting tag field type.");
399 bt_ctf_object_put_ref(ft->tag_ft);
400 BT_LOGD_STR("Putting tag field path.");
401 bt_ctf_object_put_ref(ft->tag_field_path);
402 g_free(ft);
403 }
404
405 struct range_overlap_query {
406 union {
407 uint64_t _unsigned;
408 int64_t _signed;
409 } range_start;
410
411 union {
412 uint64_t _unsigned;
413 int64_t _signed;
414 } range_end;
415 int overlaps;
416 GQuark mapping_name;
417 };
418
419 static
420 void check_ranges_overlap(gpointer element, gpointer query)
421 {
422 struct bt_ctf_enumeration_mapping *mapping = element;
423 struct range_overlap_query *overlap_query = query;
424
425 if (mapping->range_start._signed <= overlap_query->range_end._signed
426 && overlap_query->range_start._signed <=
427 mapping->range_end._signed) {
428 overlap_query->overlaps = 1;
429 overlap_query->mapping_name = mapping->string;
430 }
431
432 overlap_query->overlaps |=
433 mapping->string == overlap_query->mapping_name;
434
435 if (overlap_query->overlaps) {
436 BT_LOGT("Overlapping enumeration field type mappings: "
437 "mapping-name=\"%s\", "
438 "mapping-a-range-start=%" PRId64 ", "
439 "mapping-a-range-end=%" PRId64 ", "
440 "mapping-b-range-start=%" PRId64 ", "
441 "mapping-b-range-end=%" PRId64,
442 g_quark_to_string(mapping->string),
443 mapping->range_start._signed,
444 mapping->range_end._signed,
445 overlap_query->range_start._signed,
446 overlap_query->range_end._signed);
447 }
448 }
449
450 static
451 void check_ranges_overlap_unsigned(gpointer element, gpointer query)
452 {
453 struct bt_ctf_enumeration_mapping *mapping = element;
454 struct range_overlap_query *overlap_query = query;
455
456 if (mapping->range_start._unsigned <= overlap_query->range_end._unsigned
457 && overlap_query->range_start._unsigned <=
458 mapping->range_end._unsigned) {
459 overlap_query->overlaps = 1;
460 overlap_query->mapping_name = mapping->string;
461 }
462
463 overlap_query->overlaps |=
464 mapping->string == overlap_query->mapping_name;
465
466 if (overlap_query->overlaps) {
467 BT_LOGW("Overlapping enumeration field type mappings: "
468 "mapping-name=\"%s\", "
469 "mapping-a-range-start=%" PRIu64 ", "
470 "mapping-a-range-end=%" PRIu64 ", "
471 "mapping-b-range-start=%" PRIu64 ", "
472 "mapping-b-range-end=%" PRIu64,
473 g_quark_to_string(mapping->string),
474 mapping->range_start._unsigned,
475 mapping->range_end._unsigned,
476 overlap_query->range_start._unsigned,
477 overlap_query->range_end._unsigned);
478 }
479 }
480
481 static
482 gint compare_enumeration_mappings_signed(struct bt_ctf_enumeration_mapping **a,
483 struct bt_ctf_enumeration_mapping **b)
484 {
485 return ((*a)->range_start._signed < (*b)->range_start._signed) ? -1 : 1;
486 }
487
488 static
489 gint compare_enumeration_mappings_unsigned(struct bt_ctf_enumeration_mapping **a,
490 struct bt_ctf_enumeration_mapping **b)
491 {
492 return ((*a)->range_start._unsigned < (*b)->range_start._unsigned) ? -1 : 1;
493 }
494
495 static
496 int add_structure_variant_member(GArray *members,
497 GHashTable *field_name_to_index,
498 struct bt_ctf_field_type_common *field_type, const char *field_name,
499 bool is_variant)
500 {
501 int ret = 0;
502 GQuark name_quark = g_quark_from_string(field_name);
503 struct bt_ctf_field_type_common **member_ft;
504 GQuark *member_name;
505
506 /* Make sure structure does not contain a field of the same name */
507 if (g_hash_table_lookup_extended(field_name_to_index,
508 GUINT_TO_POINTER(name_quark), NULL, NULL)) {
509 BT_LOGW("Structure or variant field type already contains a field type with this name: "
510 "field-name=\"%s\"", field_name);
511 ret = -1;
512 goto end;
513 }
514
515 g_array_set_size(members, members->len + 1);
516
517 if (is_variant) {
518 struct bt_ctf_field_type_common_variant_choice *choice =
519 &bt_g_array_index(members,
520 struct bt_ctf_field_type_common_variant_choice,
521 members->len - 1);
522
523 member_ft = &choice->type;
524 member_name = &choice->name;
525 BT_ASSERT_DBG(!choice->ranges);
526 choice->ranges = g_array_new(FALSE, TRUE,
527 sizeof(struct bt_ctf_field_type_common_variant_choice_range));
528 BT_ASSERT_DBG(choice->ranges);
529 } else {
530 struct bt_ctf_field_type_common_structure_field *field =
531 &bt_g_array_index(members,
532 struct bt_ctf_field_type_common_structure_field,
533 members->len - 1);
534
535 member_ft = &field->type;
536 member_name = &field->name;
537 }
538
539 *member_name = name_quark;
540 *member_ft = bt_ctf_object_get_ref(field_type);
541 g_hash_table_insert(field_name_to_index,
542 GUINT_TO_POINTER(name_quark),
543 GUINT_TO_POINTER(members->len - 1));
544 BT_LOGT("Added structure/variant field type member: member-ft-addr=%p, "
545 "member-name=\"%s\"", field_type, field_name);
546
547 end:
548 return ret;
549 }
550
551 int bt_ctf_field_type_common_integer_validate(struct bt_ctf_field_type_common *ft)
552 {
553 int ret = 0;
554 struct bt_ctf_field_type_common_integer *int_ft = BT_CTF_FROM_COMMON(ft);
555
556 if (int_ft->mapped_clock_class && int_ft->is_signed) {
557 BT_LOGW("Invalid integer field type: cannot be signed and have a mapped clock class: "
558 "ft-addr=%p, clock-class-addr=%p, clock-class-name=\"%s\"",
559 ft, int_ft->mapped_clock_class,
560 bt_ctf_clock_class_get_name(int_ft->mapped_clock_class));
561 ret = -1;
562 goto end;
563 }
564
565 end:
566 return ret;
567 }
568
569 static
570 void bt_ctf_field_type_enum_iter_destroy(struct bt_ctf_object *obj)
571 {
572 struct bt_ctf_field_type_enumeration_mapping_iterator *iter =
573 container_of(obj,
574 struct bt_ctf_field_type_enumeration_mapping_iterator,
575 base);
576
577 BT_LOGD("Destroying enumeration field type mapping iterator: addr=%p",
578 obj);
579 BT_LOGD_STR("Putting parent enumeration field type.");
580 bt_ctf_object_put_ref(iter->enumeration_ft);
581 g_free(iter);
582 }
583
584 static
585 struct bt_ctf_field_type_enumeration_mapping_iterator *
586 bt_ctf_field_type_common_enumeration_find_mappings_type(
587 struct bt_ctf_field_type_common *ft,
588 enum bt_ctf_field_type_enumeration_mapping_iterator_type iterator_type)
589 {
590 struct bt_ctf_field_type_enumeration_mapping_iterator *iter = NULL;
591
592 BT_CTF_ASSERT_PRE_NON_NULL(ft, "Field type");
593 BT_CTF_ASSERT_PRE_CTF_FT_COMMON_HAS_ID(ft, BT_CTF_FIELD_TYPE_ID_ENUM,
594 "Field type");
595 iter = g_new0(struct bt_ctf_field_type_enumeration_mapping_iterator, 1);
596 if (!iter) {
597 BT_LOGE_STR("Failed to allocate one enumeration field type mapping.");
598 goto end;
599 }
600
601 bt_ctf_object_init_shared(&iter->base, bt_ctf_field_type_enum_iter_destroy);
602 iter->enumeration_ft = bt_ctf_object_get_ref(ft);
603 iter->index = -1;
604 iter->type = iterator_type;
605
606 end:
607 return iter;
608 }
609
610 struct bt_ctf_field_type_enumeration_mapping_iterator *
611 bt_ctf_field_type_common_enumeration_find_mappings_by_name(
612 struct bt_ctf_field_type_common *ft, const char *name)
613 {
614 struct bt_ctf_field_type_enumeration_mapping_iterator *iter;
615
616 iter = bt_ctf_field_type_common_enumeration_find_mappings_type(
617 ft, CTF_ITERATOR_BY_NAME);
618 if (!iter) {
619 BT_LOGW("Cannot create enumeration field type mapping iterator: "
620 "ft-addr=%p, mapping-name=\"%s\"", ft, name);
621 goto error;
622 }
623
624 iter->u.name_quark = g_quark_try_string(name);
625 if (!iter->u.name_quark) {
626 /*
627 * No results are possible, set the iterator's position at the
628 * end.
629 */
630 iter->index = iter->enumeration_ft->entries->len;
631 }
632
633 return iter;
634
635 error:
636 bt_ctf_object_put_ref(iter);
637 return NULL;
638 }
639
640 static
641 struct bt_ctf_enumeration_mapping *bt_ctf_field_type_common_enumeration_get_mapping_by_index(
642 struct bt_ctf_field_type_common *ft, uint64_t index)
643 {
644 struct bt_ctf_field_type_common_enumeration *enum_ft = BT_CTF_FROM_COMMON(ft);
645 struct bt_ctf_enumeration_mapping *mapping = NULL;
646
647 if (index >= enum_ft->entries->len) {
648 BT_LOGW("Invalid parameter: index is out of bounds: "
649 "addr=%p, index=%" PRIu64 ", count=%u",
650 ft, index, enum_ft->entries->len);
651 goto end;
652 }
653
654 mapping = g_ptr_array_index(enum_ft->entries, index);
655
656 end:
657 return mapping;
658 }
659
660 int bt_ctf_field_type_enumeration_mapping_iterator_next(
661 struct bt_ctf_field_type_enumeration_mapping_iterator *iter)
662 {
663 struct bt_ctf_field_type_common_enumeration *enum_ft = iter->enumeration_ft;
664 int i, ret = 0, len;
665
666 BT_CTF_ASSERT_PRE_NON_NULL(iter, "Enumeration field type mapping iterator");
667 len = enum_ft->entries->len;
668 for (i = iter->index + 1; i < len; i++) {
669 struct bt_ctf_enumeration_mapping *mapping =
670 bt_ctf_field_type_common_enumeration_get_mapping_by_index(
671 BT_CTF_TO_COMMON(enum_ft), i);
672
673 switch (iter->type) {
674 case CTF_ITERATOR_BY_NAME:
675 if (mapping->string == iter->u.name_quark) {
676 iter->index = i;
677 goto end;
678 }
679 break;
680 case CTF_ITERATOR_BY_SIGNED_VALUE:
681 {
682 int64_t value = iter->u.signed_value;
683
684 if (value >= mapping->range_start._signed &&
685 value <= mapping->range_end._signed) {
686 iter->index = i;
687 goto end;
688 }
689 break;
690 }
691 case CTF_ITERATOR_BY_UNSIGNED_VALUE:
692 {
693 uint64_t value = iter->u.unsigned_value;
694
695 if (value >= mapping->range_start._unsigned &&
696 value <= mapping->range_end._unsigned) {
697 iter->index = i;
698 goto end;
699 }
700 break;
701 }
702 default:
703 BT_LOGF("Invalid enumeration field type mapping iterator type: "
704 "type=%d", iter->type);
705 bt_common_abort();
706 }
707 }
708
709 ret = -1;
710
711 end:
712 return ret;
713 }
714
715 struct bt_ctf_field_type_enumeration_mapping_iterator *
716 bt_ctf_field_type_common_enumeration_signed_find_mappings_by_value(
717 struct bt_ctf_field_type_common *ft, int64_t value)
718 {
719 struct bt_ctf_field_type_enumeration_mapping_iterator *iter;
720
721 iter = bt_ctf_field_type_common_enumeration_find_mappings_type(
722 ft, CTF_ITERATOR_BY_SIGNED_VALUE);
723 if (!iter) {
724 BT_LOGW("Cannot create enumeration field type mapping iterator: "
725 "ft-addr=%p, value=%" PRId64, ft, value);
726 goto error;
727 }
728
729 if (bt_ctf_field_type_common_integer_is_signed(
730 BT_CTF_TO_COMMON(iter->enumeration_ft->container_ft)) != 1) {
731 BT_LOGW("Invalid parameter: enumeration field type is unsigned: "
732 "enum-ft-addr=%p, int-ft-addr=%p",
733 ft, iter->enumeration_ft->container_ft);
734 goto error;
735 }
736
737 iter->u.signed_value = value;
738 return iter;
739
740 error:
741 bt_ctf_object_put_ref(iter);
742 return NULL;
743 }
744
745 struct bt_ctf_field_type_enumeration_mapping_iterator *
746 bt_ctf_field_type_common_enumeration_unsigned_find_mappings_by_value(
747 struct bt_ctf_field_type_common *ft, uint64_t value)
748 {
749 struct bt_ctf_field_type_enumeration_mapping_iterator *iter;
750
751 iter = bt_ctf_field_type_common_enumeration_find_mappings_type(
752 ft, CTF_ITERATOR_BY_UNSIGNED_VALUE);
753 if (!iter) {
754 BT_LOGW("Cannot create enumeration field type mapping iterator: "
755 "ft-addr=%p, value=%" PRIu64, ft, value);
756 goto error;
757 }
758
759 if (bt_ctf_field_type_common_integer_is_signed(
760 BT_CTF_TO_COMMON(iter->enumeration_ft->container_ft)) != 0) {
761 BT_LOGW("Invalid parameter: enumeration field type is signed: "
762 "enum-ft-addr=%p, int-ft-addr=%p",
763 ft, iter->enumeration_ft->container_ft);
764 goto error;
765 }
766
767 iter->u.unsigned_value = value;
768 return iter;
769
770 error:
771 bt_ctf_object_put_ref(iter);
772 return NULL;
773 }
774
775 int bt_ctf_field_type_enumeration_mapping_iterator_signed_get(
776 struct bt_ctf_field_type_enumeration_mapping_iterator *iter,
777 const char **mapping_name, int64_t *range_begin,
778 int64_t *range_end)
779 {
780 BT_CTF_ASSERT_PRE_NON_NULL(iter, "Enumeration field type mapping iterator");
781 BT_CTF_ASSERT_PRE(iter->index != -1,
782 "Invalid enumeration field type mapping iterator access: "
783 "addr=%p, position=-1", iter);
784 return bt_ctf_field_type_common_enumeration_signed_get_mapping_by_index(
785 (void *) iter->enumeration_ft, iter->index,
786 mapping_name, range_begin, range_end);
787 }
788
789 int bt_ctf_field_type_enumeration_mapping_iterator_unsigned_get(
790 struct bt_ctf_field_type_enumeration_mapping_iterator *iter,
791 const char **mapping_name, uint64_t *range_begin,
792 uint64_t *range_end)
793 {
794 BT_CTF_ASSERT_PRE_NON_NULL(iter, "Enumeration field type mapping iterator");
795 BT_CTF_ASSERT_PRE(iter->index != -1,
796 "Invalid enumeration field type mapping iterator access: "
797 "addr=%p, position=-1", iter);
798 return bt_ctf_field_type_common_enumeration_unsigned_get_mapping_by_index(
799 (void *) iter->enumeration_ft, iter->index,
800 mapping_name, range_begin, range_end);
801 }
802
803 /*
804 * Note: This algorithm is O(n^2) vs number of enumeration mappings.
805 * Only used when freezing an enumeration.
806 */
807 static
808 void bt_ctf_field_type_common_enumeration_set_range_overlap(
809 struct bt_ctf_field_type_common_enumeration *ft)
810 {
811 int64_t i, j, len;
812 int is_signed;
813
814 BT_LOGT("Setting enumeration field type's overlap flag: addr=%p",
815 ft);
816 len = ft->entries->len;
817 is_signed = bt_ctf_field_type_common_integer_is_signed(
818 BT_CTF_TO_COMMON(ft->container_ft));
819
820 for (i = 0; i < len; i++) {
821 for (j = i + 1; j < len; j++) {
822 struct bt_ctf_enumeration_mapping *mapping[2];
823
824 mapping[0] = bt_ctf_field_type_common_enumeration_get_mapping_by_index(
825 BT_CTF_TO_COMMON(ft), i);
826 mapping[1] = bt_ctf_field_type_common_enumeration_get_mapping_by_index(
827 BT_CTF_TO_COMMON(ft), j);
828 if (is_signed) {
829 if (mapping[0]->range_start._signed
830 <= mapping[1]->range_end._signed
831 && mapping[0]->range_end._signed
832 >= mapping[1]->range_start._signed) {
833 ft->has_overlapping_ranges = BT_CTF_TRUE;
834 goto end;
835 }
836 } else {
837 if (mapping[0]->range_start._unsigned
838 <= mapping[1]->range_end._unsigned
839 && mapping[0]->range_end._unsigned
840 >= mapping[1]->range_start._unsigned) {
841 ft->has_overlapping_ranges = BT_CTF_TRUE;
842 goto end;
843 }
844 }
845 }
846 }
847
848 end:
849 if (ft->has_overlapping_ranges) {
850 BT_LOGT_STR("Enumeration field type has overlapping ranges.");
851 } else {
852 BT_LOGT_STR("Enumeration field type has no overlapping ranges.");
853 }
854 }
855
856 int bt_ctf_field_type_common_enumeration_validate_recursive(
857 struct bt_ctf_field_type_common *ft)
858 {
859 int ret = 0;
860 struct bt_ctf_field_type_common_enumeration *enum_ft = BT_CTF_FROM_COMMON(ft);
861
862 ret = bt_ctf_field_type_common_integer_validate(
863 BT_CTF_TO_COMMON(enum_ft->container_ft));
864 if (ret) {
865 BT_LOGW("Invalid enumeration field type: container type is invalid: "
866 "enum-ft-addr=%p, int-ft-addr=%p",
867 ft, enum_ft->container_ft);
868 goto end;
869 }
870
871 /* Ensure enum has entries */
872 if (enum_ft->entries->len == 0) {
873 BT_LOGW("Invalid enumeration field type: no entries: "
874 "addr=%p", ft);
875 ret = -1;
876 goto end;
877 }
878
879 end:
880 return ret;
881 }
882
883 int bt_ctf_field_type_common_sequence_validate_recursive(
884 struct bt_ctf_field_type_common *ft)
885 {
886 int ret = 0;
887 struct bt_ctf_field_type_common_sequence *seq_ft = BT_CTF_FROM_COMMON(ft);
888
889 /* Length field name should be set at this point */
890 if (seq_ft->length_field_name->len == 0) {
891 BT_LOGW("Invalid sequence field type: no length field name: "
892 "addr=%p", ft);
893 ret = -1;
894 goto end;
895 }
896
897 ret = bt_ctf_field_type_common_validate(seq_ft->element_ft);
898 if (ret) {
899 BT_LOGW("Invalid sequence field type: invalid element field type: "
900 "seq-ft-addr=%p, element-ft-add=%p",
901 ft, seq_ft->element_ft);
902 }
903
904 end:
905 return ret;
906 }
907
908 int bt_ctf_field_type_common_array_validate_recursive(
909 struct bt_ctf_field_type_common *ft)
910 {
911 int ret = 0;
912 struct bt_ctf_field_type_common_array *array_ft = BT_CTF_FROM_COMMON(ft);
913
914 ret = bt_ctf_field_type_common_validate(array_ft->element_ft);
915 if (ret) {
916 BT_LOGW("Invalid array field type: invalid element field type: "
917 "array-ft-addr=%p, element-ft-add=%p",
918 ft, array_ft->element_ft);
919 }
920
921 return ret;
922 }
923
924 int bt_ctf_field_type_common_structure_validate_recursive(
925 struct bt_ctf_field_type_common *ft)
926 {
927 int ret = 0;
928 struct bt_ctf_field_type_common *child_ft = NULL;
929 int64_t field_count =
930 bt_ctf_field_type_common_structure_get_field_count(ft);
931 int64_t i;
932
933 BT_ASSERT_DBG(field_count >= 0);
934
935 for (i = 0; i < field_count; ++i) {
936 const char *field_name;
937
938 ret = bt_ctf_field_type_common_structure_borrow_field_by_index(ft,
939 &field_name, &child_ft, i);
940 BT_ASSERT_DBG(ret == 0);
941 ret = bt_ctf_field_type_common_validate(child_ft);
942 if (ret) {
943 BT_LOGW("Invalid structure field type: "
944 "a contained field type is invalid: "
945 "struct-ft-addr=%p, field-ft-addr=%p, "
946 "field-name=\"%s\", field-index=%" PRId64,
947 ft, child_ft, field_name, i);
948 goto end;
949 }
950 }
951
952 end:
953 return ret;
954 }
955
956 static
957 bt_ctf_bool bt_ctf_field_type_common_enumeration_has_overlapping_ranges(
958 struct bt_ctf_field_type_common_enumeration *enum_ft)
959 {
960 if (!enum_ft->common.frozen) {
961 bt_ctf_field_type_common_enumeration_set_range_overlap(enum_ft);
962 }
963
964 return enum_ft->has_overlapping_ranges;
965 }
966
967 int bt_ctf_field_type_common_variant_validate_recursive(
968 struct bt_ctf_field_type_common *ft)
969 {
970 int ret = 0;
971 int64_t field_count;
972 struct bt_ctf_field_type_common *child_ft = NULL;
973 struct bt_ctf_field_type_common_variant *var_ft = BT_CTF_FROM_COMMON(ft);
974 int64_t i;
975
976 if (var_ft->tag_name->len == 0) {
977 BT_LOGW("Invalid variant field type: no tag field name: "
978 "addr=%p", ft);
979 ret = -1;
980 goto end;
981 }
982
983 if (!var_ft->tag_ft) {
984 BT_LOGW("Invalid variant field type: no tag field type: "
985 "addr=%p, tag-field-name=\"%s\"", var_ft,
986 var_ft->tag_name->str);
987 ret = -1;
988 goto end;
989 }
990
991 if (bt_ctf_field_type_common_enumeration_has_overlapping_ranges(var_ft->tag_ft)) {
992 BT_LOGW("Invalid variant field type: enumeration tag field type has overlapping ranges: "
993 "variant-ft-addr=%p, tag-field-name=\"%s\", "
994 "enum-ft-addr=%p", ft, var_ft->tag_name->str,
995 var_ft->tag_ft);
996 ret = -1;
997 goto end;
998 }
999
1000 /*
1001 * It is valid to have a variant field type which does not have
1002 * the fields corresponding to each label in the associated
1003 * enumeration.
1004 *
1005 * It is also valid to have variant field type fields which
1006 * cannot be selected because the variant field type tag has no
1007 * mapping named as such. This scenario, while not ideal, cannot
1008 * cause any error.
1009 *
1010 * If a non-existing field happens to be selected by an
1011 * enumeration while reading a variant field, an error will be
1012 * generated at that point (while reading the stream).
1013 */
1014 field_count = bt_ctf_field_type_common_variant_get_field_count(ft);
1015 if (field_count < 0) {
1016 BT_LOGW("Invalid variant field type: no fields: "
1017 "addr=%p, tag-field-name=\"%s\"",
1018 ft, var_ft->tag_name->str);
1019 ret = -1;
1020 goto end;
1021 }
1022
1023 for (i = 0; i < field_count; ++i) {
1024 const char *field_name;
1025
1026 ret = bt_ctf_field_type_common_variant_borrow_field_by_index(ft,
1027 &field_name, &child_ft, i);
1028 BT_ASSERT_DBG(ret == 0);
1029 ret = bt_ctf_field_type_common_validate(child_ft);
1030 if (ret) {
1031 BT_LOGW("Invalid variant field type: "
1032 "a contained field type is invalid: "
1033 "variant-ft-addr=%p, tag-field-name=\"%s\", "
1034 "field-ft-addr=%p, field-name=\"%s\", "
1035 "field-index=%" PRId64,
1036 ft, var_ft->tag_name->str, child_ft,
1037 field_name, i);
1038 goto end;
1039 }
1040 }
1041
1042 end:
1043 return ret;
1044 }
1045
1046 /*
1047 * This function validates a given field type without considering
1048 * where this field type is located. It only validates the properties
1049 * of the given field type and the properties of its children if
1050 * applicable.
1051 */
1052 int bt_ctf_field_type_common_validate(struct bt_ctf_field_type_common *ft)
1053 {
1054 int ret = 0;
1055
1056 BT_ASSERT_DBG(ft);
1057
1058 if (ft->valid) {
1059 /* Already marked as valid */
1060 goto end;
1061 }
1062
1063 if (ft->methods->validate) {
1064 ret = ft->methods->validate(ft);
1065 }
1066
1067 if (ret == 0 && ft->frozen) {
1068 /* Field type is valid */
1069 BT_LOGT("Marking field type as valid: addr=%p", ft);
1070 ft->valid = 1;
1071 }
1072
1073 end:
1074 return ret;
1075 }
1076
1077 int bt_ctf_field_type_common_integer_get_size(struct bt_ctf_field_type_common *ft)
1078 {
1079 struct bt_ctf_field_type_common_integer *int_ft = BT_CTF_FROM_COMMON(ft);
1080
1081 BT_CTF_ASSERT_PRE_NON_NULL(ft, "Field type");
1082 BT_CTF_ASSERT_PRE_CTF_FT_COMMON_HAS_ID(ft, BT_CTF_FIELD_TYPE_ID_INTEGER,
1083 "Field type");
1084 return (int) int_ft->size;
1085 }
1086
1087 bt_ctf_bool bt_ctf_field_type_common_integer_is_signed(struct bt_ctf_field_type_common *ft)
1088 {
1089 struct bt_ctf_field_type_common_integer *int_ft = BT_CTF_FROM_COMMON(ft);
1090
1091 BT_CTF_ASSERT_PRE_NON_NULL(ft, "Field type");
1092 BT_CTF_ASSERT_PRE_CTF_FT_COMMON_HAS_ID(ft, BT_CTF_FIELD_TYPE_ID_INTEGER,
1093 "Field type");
1094 return int_ft->is_signed;
1095 }
1096
1097 int bt_ctf_field_type_common_integer_set_is_signed(struct bt_ctf_field_type_common *ft,
1098 bt_ctf_bool is_signed)
1099 {
1100 int ret = 0;
1101 struct bt_ctf_field_type_common_integer *int_ft = BT_CTF_FROM_COMMON(ft);
1102
1103 if (!ft) {
1104 BT_LOGW_STR("Invalid parameter: field type is NULL.");
1105 ret = -1;
1106 goto end;
1107 }
1108
1109 if (ft->frozen) {
1110 BT_LOGW("Invalid parameter: field type is frozen: addr=%p",
1111 ft);
1112 ret = -1;
1113 goto end;
1114 }
1115
1116 if (ft->id != BT_CTF_FIELD_TYPE_ID_INTEGER) {
1117 BT_LOGW("Invalid parameter: field type is not an integer field type: "
1118 "addr=%p, ft-id=%s", ft,
1119 bt_ctf_field_type_id_string(ft->id));
1120 ret = -1;
1121 goto end;
1122 }
1123
1124 int_ft->is_signed = !!is_signed;
1125 BT_LOGT("Set integer field type's signedness: addr=%p, is-signed=%d",
1126 ft, is_signed);
1127
1128 end:
1129 return ret;
1130 }
1131
1132 int bt_ctf_field_type_common_integer_set_size(struct bt_ctf_field_type_common *ft,
1133 unsigned int size)
1134 {
1135 int ret = 0;
1136 struct bt_ctf_field_type_common_integer *int_ft = BT_CTF_FROM_COMMON(ft);
1137
1138 if (!ft) {
1139 BT_LOGW_STR("Invalid parameter: field type is NULL.");
1140 ret = -1;
1141 goto end;
1142 }
1143
1144 if (ft->frozen) {
1145 BT_LOGW("Invalid parameter: field type is frozen: addr=%p",
1146 ft);
1147 ret = -1;
1148 goto end;
1149 }
1150
1151 if (ft->id != BT_CTF_FIELD_TYPE_ID_INTEGER) {
1152 BT_LOGW("Invalid parameter: field type is not an integer field type: "
1153 "addr=%p, ft-id=%s", ft,
1154 bt_ctf_field_type_id_string(ft->id));
1155 ret = -1;
1156 goto end;
1157 }
1158
1159 if (size == 0 || size > 64) {
1160 BT_LOGW("Invalid parameter: size must be between 1 and 64: "
1161 "addr=%p, size=%u", ft, size);
1162 ret = -1;
1163 goto end;
1164 }
1165
1166 int_ft->size = size;
1167 BT_LOGT("Set integer field type's size: addr=%p, size=%u",
1168 ft, size);
1169
1170 end:
1171 return ret;
1172 }
1173
1174 enum bt_ctf_integer_base bt_ctf_field_type_common_integer_get_base(
1175 struct bt_ctf_field_type_common *ft)
1176 {
1177 struct bt_ctf_field_type_common_integer *int_ft = BT_CTF_FROM_COMMON(ft);
1178
1179 BT_CTF_ASSERT_PRE_NON_NULL(ft, "Field type");
1180 BT_CTF_ASSERT_PRE_CTF_FT_COMMON_HAS_ID(ft, BT_CTF_FIELD_TYPE_ID_INTEGER,
1181 "Field type");
1182 return int_ft->base;
1183 }
1184
1185 int bt_ctf_field_type_common_integer_set_base(struct bt_ctf_field_type_common *ft,
1186 enum bt_ctf_integer_base base)
1187 {
1188 int ret = 0;
1189 struct bt_ctf_field_type_common_integer *int_ft = BT_CTF_FROM_COMMON(ft);
1190
1191 if (!ft) {
1192 BT_LOGW_STR("Invalid parameter: field type is NULL.");
1193 ret = -1;
1194 goto end;
1195 }
1196
1197 if (ft->frozen) {
1198 BT_LOGW("Invalid parameter: field type is frozen: addr=%p",
1199 ft);
1200 ret = -1;
1201 goto end;
1202 }
1203
1204 if (ft->id != BT_CTF_FIELD_TYPE_ID_INTEGER) {
1205 BT_LOGW("Invalid parameter: field type is not an integer field type: "
1206 "addr=%p, ft-id=%s", ft,
1207 bt_ctf_field_type_id_string(ft->id));
1208 ret = -1;
1209 goto end;
1210 }
1211
1212 switch (base) {
1213 case BT_CTF_INTEGER_BASE_UNSPECIFIED:
1214 case BT_CTF_INTEGER_BASE_BINARY:
1215 case BT_CTF_INTEGER_BASE_OCTAL:
1216 case BT_CTF_INTEGER_BASE_DECIMAL:
1217 case BT_CTF_INTEGER_BASE_HEXADECIMAL:
1218 {
1219 int_ft->base = base;
1220 break;
1221 }
1222 default:
1223 BT_LOGW("Invalid parameter: unknown integer field type base: "
1224 "addr=%p, base=%d", ft, base);
1225 ret = -1;
1226 }
1227
1228 BT_LOGT("Set integer field type's base: addr=%p, base=%s",
1229 ft, bt_ctf_integer_base_string(base));
1230
1231 end:
1232 return ret;
1233 }
1234
1235 enum bt_ctf_string_encoding bt_ctf_field_type_common_integer_get_encoding(
1236 struct bt_ctf_field_type_common *ft)
1237 {
1238 struct bt_ctf_field_type_common_integer *int_ft = BT_CTF_FROM_COMMON(ft);
1239
1240 BT_CTF_ASSERT_PRE_NON_NULL(ft, "Field type");
1241 BT_CTF_ASSERT_PRE_CTF_FT_COMMON_HAS_ID(ft, BT_CTF_FIELD_TYPE_ID_INTEGER,
1242 "Field type");
1243 return int_ft->encoding;
1244 }
1245
1246 int bt_ctf_field_type_common_integer_set_encoding(struct bt_ctf_field_type_common *ft,
1247 enum bt_ctf_string_encoding encoding)
1248 {
1249 int ret = 0;
1250 struct bt_ctf_field_type_common_integer *int_ft = BT_CTF_FROM_COMMON(ft);
1251
1252 if (!ft) {
1253 BT_LOGW_STR("Invalid parameter: field type is NULL.");
1254 ret = -1;
1255 goto end;
1256 }
1257
1258 if (ft->frozen) {
1259 BT_LOGW("Invalid parameter: field type is frozen: addr=%p",
1260 ft);
1261 ret = -1;
1262 goto end;
1263 }
1264
1265 if (ft->id != BT_CTF_FIELD_TYPE_ID_INTEGER) {
1266 BT_LOGW("Invalid parameter: field type is not an integer field type: "
1267 "addr=%p, ft-id=%s", ft,
1268 bt_ctf_field_type_id_string(ft->id));
1269 ret = -1;
1270 goto end;
1271 }
1272
1273 if (encoding != BT_CTF_STRING_ENCODING_UTF8 &&
1274 encoding != BT_CTF_STRING_ENCODING_ASCII &&
1275 encoding != BT_CTF_STRING_ENCODING_NONE) {
1276 BT_LOGW("Invalid parameter: unknown string encoding: "
1277 "addr=%p, encoding=%d", ft, encoding);
1278 ret = -1;
1279 goto end;
1280 }
1281
1282 int_ft->encoding = encoding;
1283 BT_LOGT("Set integer field type's encoding: addr=%p, encoding=%s",
1284 ft, bt_ctf_string_encoding_string(encoding));
1285
1286 end:
1287 return ret;
1288 }
1289
1290 struct bt_ctf_clock_class *bt_ctf_field_type_common_integer_borrow_mapped_clock_class(
1291 struct bt_ctf_field_type_common *ft)
1292 {
1293 struct bt_ctf_field_type_common_integer *int_ft = BT_CTF_FROM_COMMON(ft);
1294
1295 BT_CTF_ASSERT_PRE_NON_NULL(ft, "Field type");
1296 BT_CTF_ASSERT_PRE_CTF_FT_COMMON_HAS_ID(ft, BT_CTF_FIELD_TYPE_ID_INTEGER,
1297 "Field type");
1298 return int_ft->mapped_clock_class;
1299 }
1300
1301 int bt_ctf_field_type_common_integer_set_mapped_clock_class_no_check_frozen(
1302 struct bt_ctf_field_type_common *ft,
1303 struct bt_ctf_clock_class *clock_class)
1304 {
1305 struct bt_ctf_field_type_common_integer *int_ft = BT_CTF_FROM_COMMON(ft);
1306 int ret = 0;
1307
1308 if (!clock_class) {
1309 BT_LOGW_STR("Invalid parameter: clock class is NULL.");
1310 ret = -1;
1311 goto end;
1312 }
1313
1314 if (ft->id != BT_CTF_FIELD_TYPE_ID_INTEGER) {
1315 BT_LOGW("Invalid parameter: field type is not an integer field type: "
1316 "addr=%p, ft-id=%s", ft,
1317 bt_ctf_field_type_id_string(ft->id));
1318 goto end;
1319 }
1320
1321 if (!bt_ctf_clock_class_is_valid(clock_class)) {
1322 BT_LOGW("Invalid parameter: clock class is invalid: ft-addr=%p"
1323 "clock-class-addr=%p, clock-class-name=\"%s\"",
1324 ft, clock_class,
1325 bt_ctf_clock_class_get_name(clock_class));
1326 ret = -1;
1327 goto end;
1328 }
1329
1330 bt_ctf_object_put_ref(int_ft->mapped_clock_class);
1331 int_ft->mapped_clock_class = bt_ctf_object_get_ref(clock_class);
1332 BT_LOGT("Set integer field type's mapped clock class: ft-addr=%p, "
1333 "clock-class-addr=%p, clock-class-name=\"%s\"",
1334 ft, clock_class, bt_ctf_clock_class_get_name(clock_class));
1335
1336 end:
1337 return ret;
1338 }
1339
1340 int bt_ctf_field_type_common_integer_set_mapped_clock_class(
1341 struct bt_ctf_field_type_common *ft,
1342 struct bt_ctf_clock_class *clock_class)
1343 {
1344 int ret = 0;
1345
1346 if (!ft) {
1347 BT_LOGW_STR("Invalid parameter: field type is NULL.");
1348 ret = -1;
1349 goto end;
1350 }
1351
1352 if (ft->frozen) {
1353 BT_LOGW("Invalid parameter: field type is frozen: addr=%p",
1354 ft);
1355 ret = -1;
1356 goto end;
1357 }
1358
1359 ret = bt_ctf_field_type_common_integer_set_mapped_clock_class_no_check_frozen(
1360 ft, clock_class);
1361
1362 end:
1363 return ret;
1364 }
1365
1366 int bt_ctf_field_type_common_enumeration_signed_get_mapping_by_index(
1367 struct bt_ctf_field_type_common *ft, uint64_t index,
1368 const char **mapping_name, int64_t *range_begin,
1369 int64_t *range_end)
1370 {
1371 int ret = 0;
1372 struct bt_ctf_enumeration_mapping *mapping;
1373
1374 BT_CTF_ASSERT_PRE_NON_NULL(ft, "Field type");
1375 BT_CTF_ASSERT_PRE_CTF_FT_COMMON_HAS_ID(ft,
1376 BT_CTF_FIELD_TYPE_ID_ENUM, "Field type");
1377 mapping = bt_ctf_field_type_common_enumeration_get_mapping_by_index(ft,
1378 index);
1379 if (!mapping) {
1380 /* bt_ctf_field_type_common_enumeration_get_mapping_by_index() logs errors */
1381 ret = -1;
1382 goto end;
1383 }
1384
1385 if (mapping_name) {
1386 *mapping_name = g_quark_to_string(mapping->string);
1387 BT_ASSERT_DBG(*mapping_name);
1388 }
1389
1390 if (range_begin) {
1391 *range_begin = mapping->range_start._signed;
1392 }
1393
1394 if (range_end) {
1395 *range_end = mapping->range_end._signed;
1396 }
1397
1398 end:
1399 return ret;
1400 }
1401
1402 int bt_ctf_field_type_common_enumeration_unsigned_get_mapping_by_index(
1403 struct bt_ctf_field_type_common *ft, uint64_t index,
1404 const char **mapping_name, uint64_t *range_begin,
1405 uint64_t *range_end)
1406 {
1407 int ret = 0;
1408 struct bt_ctf_enumeration_mapping *mapping;
1409
1410 BT_CTF_ASSERT_PRE_NON_NULL(ft, "Field type");
1411 BT_CTF_ASSERT_PRE_CTF_FT_COMMON_HAS_ID(ft, BT_CTF_FIELD_TYPE_ID_ENUM, "Field type");
1412 mapping = bt_ctf_field_type_common_enumeration_get_mapping_by_index(
1413 ft, index);
1414 if (!mapping) {
1415 /* bt_ctf_field_type_common_enumeration_get_mapping_by_index() reports any error */
1416 ret = -1;
1417 goto end;
1418 }
1419
1420 if (mapping_name) {
1421 *mapping_name = g_quark_to_string(mapping->string);
1422 BT_ASSERT_DBG(*mapping_name);
1423 }
1424
1425 if (range_begin) {
1426 *range_begin = mapping->range_start._unsigned;
1427 }
1428
1429 if (range_end) {
1430 *range_end = mapping->range_end._unsigned;
1431 }
1432
1433 end:
1434 return ret;
1435 }
1436
1437 struct bt_ctf_field_type_common *
1438 bt_ctf_field_type_common_enumeration_borrow_container_field_type(
1439 struct bt_ctf_field_type_common *ft)
1440 {
1441 struct bt_ctf_field_type_common_enumeration *enum_ft = BT_CTF_FROM_COMMON(ft);
1442
1443 BT_CTF_ASSERT_PRE_NON_NULL(ft, "Field type");
1444 BT_CTF_ASSERT_PRE_CTF_FT_COMMON_HAS_ID(ft, BT_CTF_FIELD_TYPE_ID_ENUM, "Field type");
1445 return BT_CTF_TO_COMMON(enum_ft->container_ft);
1446 }
1447
1448 int bt_ctf_field_type_common_enumeration_signed_add_mapping(
1449 struct bt_ctf_field_type_common *ft, const char *string,
1450 int64_t range_start, int64_t range_end)
1451 {
1452 int ret = 0;
1453 GQuark mapping_name;
1454 struct bt_ctf_enumeration_mapping *mapping;
1455 struct bt_ctf_field_type_common_enumeration *enum_ft = BT_CTF_FROM_COMMON(ft);
1456 char *escaped_string;
1457
1458 if (!ft) {
1459 BT_LOGW_STR("Invalid parameter: field type is NULL.");
1460 ret = -1;
1461 goto end;
1462 }
1463
1464 if (!string) {
1465 BT_LOGW_STR("Invalid parameter: string is NULL.");
1466 ret = -1;
1467 goto end;
1468 }
1469
1470 if (ft->frozen) {
1471 BT_LOGW("Invalid parameter: field type is frozen: addr=%p",
1472 ft);
1473 ret = -1;
1474 goto end;
1475 }
1476
1477 if (ft->id != BT_CTF_FIELD_TYPE_ID_ENUM) {
1478 BT_LOGW("Invalid parameter: field type is not an enumeration field type: "
1479 "addr=%p, ft-id=%s", ft,
1480 bt_ctf_field_type_id_string(ft->id));
1481 ret = -1;
1482 goto end;
1483 }
1484
1485 if (range_end < range_start) {
1486 BT_LOGW("Invalid parameter: range's end is lesser than range's start: "
1487 "addr=%p, range-start=%" PRId64 ", range-end=%" PRId64,
1488 ft, range_start, range_end);
1489 ret = -1;
1490 goto end;
1491 }
1492
1493 if (strlen(string) == 0) {
1494 BT_LOGW("Invalid parameter: mapping name is an empty string: "
1495 "enum-ft-addr=%p, mapping-name-addr=%p", ft,
1496 string);
1497 ret = -1;
1498 goto end;
1499 }
1500
1501 escaped_string = g_strescape(string, NULL);
1502 if (!escaped_string) {
1503 BT_LOGE("Cannot escape mapping name: enum-ft-addr=%p, "
1504 "mapping-name-addr=%p, mapping-name=\"%s\"",
1505 ft, string, string);
1506 ret = -1;
1507 goto end;
1508 }
1509
1510 mapping = g_new(struct bt_ctf_enumeration_mapping, 1);
1511 if (!mapping) {
1512 BT_LOGE_STR("Failed to allocate one enumeration mapping.");
1513 ret = -1;
1514 goto error_free;
1515 }
1516 mapping_name = g_quark_from_string(escaped_string);
1517 *mapping = (struct bt_ctf_enumeration_mapping) {
1518 .range_start._signed = range_start,
1519 .range_end._signed = range_end,
1520 .string = mapping_name,
1521 };
1522 g_ptr_array_add(enum_ft->entries, mapping);
1523 g_ptr_array_sort(enum_ft->entries,
1524 (GCompareFunc) compare_enumeration_mappings_signed);
1525 BT_LOGT("Added mapping to signed enumeration field type: addr=%p, "
1526 "name=\"%s\", range-start=%" PRId64 ", "
1527 "range-end=%" PRId64,
1528 ft, string, range_start, range_end);
1529
1530 error_free:
1531 free(escaped_string);
1532
1533 end:
1534 return ret;
1535 }
1536
1537 int bt_ctf_field_type_common_enumeration_unsigned_add_mapping(
1538 struct bt_ctf_field_type_common *ft, const char *string,
1539 uint64_t range_start, uint64_t range_end)
1540 {
1541 int ret = 0;
1542 GQuark mapping_name;
1543 struct bt_ctf_enumeration_mapping *mapping;
1544 struct bt_ctf_field_type_common_enumeration *enum_ft = BT_CTF_FROM_COMMON(ft);
1545 char *escaped_string;
1546
1547 if (!ft) {
1548 BT_LOGW_STR("Invalid parameter: field type is NULL.");
1549 ret = -1;
1550 goto end;
1551 }
1552
1553 if (!string) {
1554 BT_LOGW_STR("Invalid parameter: string is NULL.");
1555 ret = -1;
1556 goto end;
1557 }
1558
1559 if (ft->frozen) {
1560 BT_LOGW("Invalid parameter: field type is frozen: addr=%p",
1561 ft);
1562 ret = -1;
1563 goto end;
1564 }
1565
1566 if (ft->id != BT_CTF_FIELD_TYPE_ID_ENUM) {
1567 BT_LOGW("Invalid parameter: field type is not an enumeration field type: "
1568 "addr=%p, ft-id=%s", ft,
1569 bt_ctf_field_type_id_string(ft->id));
1570 ret = -1;
1571 goto end;
1572 }
1573
1574 if (range_end < range_start) {
1575 BT_LOGW("Invalid parameter: range's end is lesser than range's start: "
1576 "addr=%p, range-start=%" PRIu64 ", range-end=%" PRIu64,
1577 ft, range_start, range_end);
1578 ret = -1;
1579 goto end;
1580 }
1581
1582 if (strlen(string) == 0) {
1583 BT_LOGW("Invalid parameter: mapping name is an empty string: "
1584 "enum-ft-addr=%p, mapping-name-addr=%p", ft,
1585 string);
1586 ret = -1;
1587 goto end;
1588 }
1589
1590 escaped_string = g_strescape(string, NULL);
1591 if (!escaped_string) {
1592 BT_LOGE("Cannot escape mapping name: enum-ft-addr=%p, "
1593 "mapping-name-addr=%p, mapping-name=\"%s\"",
1594 ft, string, string);
1595 ret = -1;
1596 goto end;
1597 }
1598
1599 mapping = g_new(struct bt_ctf_enumeration_mapping, 1);
1600 if (!mapping) {
1601 BT_LOGE_STR("Failed to allocate one enumeration mapping.");
1602 ret = -1;
1603 goto error_free;
1604 }
1605 mapping_name = g_quark_from_string(escaped_string);
1606 *mapping = (struct bt_ctf_enumeration_mapping) {
1607 .range_start._unsigned = range_start,
1608 .range_end._unsigned = range_end,
1609 .string = mapping_name,
1610 };
1611 g_ptr_array_add(enum_ft->entries, mapping);
1612 g_ptr_array_sort(enum_ft->entries,
1613 (GCompareFunc) compare_enumeration_mappings_unsigned);
1614 BT_LOGT("Added mapping to unsigned enumeration field type: addr=%p, "
1615 "name=\"%s\", range-start=%" PRIu64 ", "
1616 "range-end=%" PRIu64,
1617 ft, string, range_start, range_end);
1618
1619 error_free:
1620 free(escaped_string);
1621
1622 end:
1623 return ret;
1624 }
1625
1626 int64_t bt_ctf_field_type_common_enumeration_get_mapping_count(
1627 struct bt_ctf_field_type_common *ft)
1628 {
1629 struct bt_ctf_field_type_common_enumeration *enum_ft = BT_CTF_FROM_COMMON(ft);
1630
1631 BT_CTF_ASSERT_PRE_NON_NULL(ft, "Field type");
1632 BT_CTF_ASSERT_PRE_CTF_FT_COMMON_HAS_ID(ft, BT_CTF_FIELD_TYPE_ID_ENUM, "Field type");
1633 return (int64_t) enum_ft->entries->len;
1634 }
1635
1636 int bt_ctf_field_type_common_floating_point_get_exponent_digits(
1637 struct bt_ctf_field_type_common *ft)
1638 {
1639 struct bt_ctf_field_type_common_floating_point *flt_ft = BT_CTF_FROM_COMMON(ft);
1640
1641 BT_CTF_ASSERT_PRE_NON_NULL(ft, "Field type");
1642 BT_CTF_ASSERT_PRE_CTF_FT_COMMON_HAS_ID(ft, BT_CTF_FIELD_TYPE_ID_FLOAT,
1643 "Field type");
1644 return (int) flt_ft->exp_dig;
1645 }
1646
1647 int bt_ctf_field_type_common_floating_point_set_exponent_digits(
1648 struct bt_ctf_field_type_common *ft,
1649 unsigned int exponent_digits)
1650 {
1651 int ret = 0;
1652 struct bt_ctf_field_type_common_floating_point *flt_ft = BT_CTF_FROM_COMMON(ft);
1653
1654 if (!ft) {
1655 BT_LOGW_STR("Invalid parameter: field type is NULL.");
1656 ret = -1;
1657 goto end;
1658 }
1659
1660 if (ft->frozen) {
1661 BT_LOGW("Invalid parameter: field type is frozen: addr=%p",
1662 ft);
1663 ret = -1;
1664 goto end;
1665 }
1666
1667 if (ft->id != BT_CTF_FIELD_TYPE_ID_FLOAT) {
1668 BT_LOGW("Invalid parameter: field type is not a floating point number field type: "
1669 "addr=%p, ft-id=%s", ft,
1670 bt_ctf_field_type_id_string(ft->id));
1671 ret = -1;
1672 goto end;
1673 }
1674
1675 if ((exponent_digits != sizeof(float) * CHAR_BIT - FLT_MANT_DIG) &&
1676 (exponent_digits != sizeof(double) * CHAR_BIT - DBL_MANT_DIG) &&
1677 (exponent_digits !=
1678 sizeof(long double) * CHAR_BIT - LDBL_MANT_DIG)) {
1679 BT_LOGW("Invalid parameter: invalid exponent size: "
1680 "addr=%p, exp-size=%u", ft, exponent_digits);
1681 ret = -1;
1682 goto end;
1683 }
1684
1685 flt_ft->exp_dig = exponent_digits;
1686 BT_LOGT("Set floating point number field type's exponent size: addr=%p, "
1687 "exp-size=%u", ft, exponent_digits);
1688
1689 end:
1690 return ret;
1691 }
1692
1693 int bt_ctf_field_type_common_floating_point_get_mantissa_digits(
1694 struct bt_ctf_field_type_common *ft)
1695 {
1696 struct bt_ctf_field_type_common_floating_point *flt_ft = BT_CTF_FROM_COMMON(ft);
1697
1698 BT_CTF_ASSERT_PRE_NON_NULL(ft, "Field type");
1699 BT_CTF_ASSERT_PRE_CTF_FT_COMMON_HAS_ID(ft, BT_CTF_FIELD_TYPE_ID_FLOAT,
1700 "Field type");
1701 return (int) flt_ft->mant_dig;
1702 }
1703
1704 int bt_ctf_field_type_common_floating_point_set_mantissa_digits(
1705 struct bt_ctf_field_type_common *ft, unsigned int mantissa_digits)
1706 {
1707 int ret = 0;
1708 struct bt_ctf_field_type_common_floating_point *flt_ft = BT_CTF_FROM_COMMON(ft);
1709
1710 if (!ft) {
1711 BT_LOGW_STR("Invalid parameter: field type is NULL.");
1712 ret = -1;
1713 goto end;
1714 }
1715
1716 if (ft->frozen) {
1717 BT_LOGW("Invalid parameter: field type is frozen: addr=%p",
1718 ft);
1719 ret = -1;
1720 goto end;
1721 }
1722
1723 if (ft->id != BT_CTF_FIELD_TYPE_ID_FLOAT) {
1724 BT_LOGW("Invalid parameter: field type is not a floating point number field type: "
1725 "addr=%p, ft-id=%s", ft,
1726 bt_ctf_field_type_id_string(ft->id));
1727 ret = -1;
1728 goto end;
1729 }
1730
1731 if ((mantissa_digits != FLT_MANT_DIG) &&
1732 (mantissa_digits != DBL_MANT_DIG) &&
1733 (mantissa_digits != LDBL_MANT_DIG)) {
1734 BT_LOGW("Invalid parameter: invalid mantissa size: "
1735 "addr=%p, mant-size=%u", ft, mantissa_digits);
1736 ret = -1;
1737 goto end;
1738 }
1739
1740 flt_ft->mant_dig = mantissa_digits;
1741 BT_LOGT("Set floating point number field type's mantissa size: addr=%p, "
1742 "mant-size=%u", ft, mantissa_digits);
1743
1744 end:
1745 return ret;
1746 }
1747
1748 int bt_ctf_field_type_common_structure_replace_field(
1749 struct bt_ctf_field_type_common *ft,
1750 const char *field_name,
1751 struct bt_ctf_field_type_common *field_type)
1752 {
1753 int ret = 0;
1754 struct bt_ctf_field_type_common_structure *struct_ft = BT_CTF_FROM_COMMON(ft);
1755 GQuark name_quark;
1756 uint64_t i;
1757
1758 BT_ASSERT_DBG(ft);
1759 BT_ASSERT_DBG(field_name);
1760 BT_ASSERT_DBG(field_type);
1761 BT_ASSERT_DBG(ft->id == BT_CTF_FIELD_TYPE_ID_STRUCT);
1762 name_quark = g_quark_from_string(field_name);
1763
1764 for (i = 0; i < struct_ft->fields->len; i++) {
1765 struct bt_ctf_field_type_common_structure_field *field =
1766 BT_CTF_FIELD_TYPE_COMMON_STRUCTURE_FIELD_AT_INDEX(ft, i);
1767
1768 if (field->name == name_quark) {
1769 bt_ctf_object_put_ref(field->type);
1770 field->type = bt_ctf_object_get_ref(field_type);
1771 }
1772 }
1773
1774 return ret;
1775 }
1776
1777 int bt_ctf_field_type_common_structure_add_field(struct bt_ctf_field_type_common *ft,
1778 struct bt_ctf_field_type_common *field_type,
1779 const char *field_name)
1780 {
1781 int ret = 0;
1782 struct bt_ctf_field_type_common_structure *struct_ft = BT_CTF_FROM_COMMON(ft);
1783
1784 /*
1785 * TODO: check that `field_type` does not contain `type`,
1786 * recursively.
1787 */
1788 if (!ft) {
1789 BT_LOGW_STR("Invalid parameter: field type is NULL.");
1790 ret = -1;
1791 goto end;
1792 }
1793
1794 if (!field_name) {
1795 BT_LOGW_STR("Invalid parameter: field name is NULL.");
1796 ret = -1;
1797 goto end;
1798 }
1799
1800 if (ft->frozen) {
1801 BT_LOGW("Invalid parameter: field type is frozen: addr=%p",
1802 ft);
1803 ret = -1;
1804 goto end;
1805 }
1806
1807 if (ft->id != BT_CTF_FIELD_TYPE_ID_STRUCT) {
1808 BT_LOGW("Invalid parameter: field type is not a structure field type: "
1809 "addr=%p, ft-id=%s", ft,
1810 bt_ctf_field_type_id_string(ft->id));
1811 ret = -1;
1812 goto end;
1813 }
1814
1815 if (ft == field_type) {
1816 BT_LOGW("Invalid parameter: structure field type and field type to add are the same: "
1817 "addr=%p", ft);
1818 ret = -1;
1819 goto end;
1820 }
1821
1822 if (add_structure_variant_member(struct_ft->fields,
1823 struct_ft->field_name_to_index, field_type, field_name,
1824 false)) {
1825 BT_LOGW("Cannot add field to structure field type: "
1826 "struct-ft-addr=%p, field-ft-addr=%p, field-name=\"%s\"",
1827 ft, field_type, field_name);
1828 ret = -1;
1829 goto end;
1830 }
1831
1832 BT_LOGT("Added structure field type field: struct-ft-addr=%p, "
1833 "field-ft-addr=%p, field-name=\"%s\"", ft,
1834 field_type, field_name);
1835
1836 end:
1837 return ret;
1838 }
1839
1840 int64_t bt_ctf_field_type_common_structure_get_field_count(
1841 struct bt_ctf_field_type_common *ft)
1842 {
1843 struct bt_ctf_field_type_common_structure *struct_ft = BT_CTF_FROM_COMMON(ft);
1844
1845 BT_CTF_ASSERT_PRE_NON_NULL(ft, "Field type");
1846 BT_CTF_ASSERT_PRE_CTF_FT_COMMON_HAS_ID(ft, BT_CTF_FIELD_TYPE_ID_STRUCT,
1847 "Field type");
1848 return (int64_t) struct_ft->fields->len;
1849 }
1850
1851 int bt_ctf_field_type_common_structure_borrow_field_by_index(
1852 struct bt_ctf_field_type_common *ft,
1853 const char **field_name,
1854 struct bt_ctf_field_type_common **field_type, uint64_t index)
1855 {
1856 struct bt_ctf_field_type_common_structure *struct_ft = BT_CTF_FROM_COMMON(ft);
1857 struct bt_ctf_field_type_common_structure_field *field;
1858
1859 BT_CTF_ASSERT_PRE_NON_NULL(ft, "Field type");
1860 BT_CTF_ASSERT_PRE_CTF_FT_COMMON_HAS_ID(ft, BT_CTF_FIELD_TYPE_ID_STRUCT,
1861 "Field type");
1862 BT_CTF_ASSERT_PRE(index < struct_ft->fields->len,
1863 "Index is out of bounds: index=%" PRIu64 ", "
1864 "count=%u, ft-addr=%p",
1865 index, struct_ft->fields->len, ft);
1866 field = BT_CTF_FIELD_TYPE_COMMON_STRUCTURE_FIELD_AT_INDEX(struct_ft, index);
1867
1868 if (field_type) {
1869 *field_type = field->type;
1870 }
1871
1872 if (field_name) {
1873 *field_name = g_quark_to_string(field->name);
1874 BT_ASSERT_DBG(*field_name);
1875 }
1876
1877 return 0;
1878 }
1879
1880 struct bt_ctf_field_type_common *
1881 bt_ctf_field_type_common_structure_borrow_field_type_by_name(
1882 struct bt_ctf_field_type_common *ft, const char *name)
1883 {
1884 size_t index;
1885 GQuark name_quark;
1886 struct bt_ctf_field_type_common_structure_field *field;
1887 struct bt_ctf_field_type_common_structure *struct_ft = BT_CTF_FROM_COMMON(ft);
1888 struct bt_ctf_field_type_common *field_type = NULL;
1889
1890 BT_CTF_ASSERT_PRE_NON_NULL(ft, "Field type");
1891 BT_CTF_ASSERT_PRE_NON_NULL(name, "Name");
1892 BT_CTF_ASSERT_PRE_CTF_FT_COMMON_HAS_ID(ft, BT_CTF_FIELD_TYPE_ID_STRUCT,
1893 "Field type");
1894 name_quark = g_quark_try_string(name);
1895 if (!name_quark) {
1896 BT_LOGT("No such structure field type field name: "
1897 "ft-addr=%p, field-name=\"%s\"",
1898 ft, name);
1899 goto end;
1900 }
1901
1902 if (!g_hash_table_lookup_extended(struct_ft->field_name_to_index,
1903 GUINT_TO_POINTER(name_quark), NULL, (gpointer *) &index)) {
1904 BT_LOGT("No such structure field type field name: "
1905 "ft-addr=%p, field-name=\"%s\"",
1906 ft, name);
1907 goto end;
1908 }
1909
1910 field = BT_CTF_FIELD_TYPE_COMMON_STRUCTURE_FIELD_AT_INDEX(ft, index);
1911 field_type = field->type;
1912
1913 end:
1914 return field_type;
1915 }
1916
1917 struct bt_ctf_field_type_common *
1918 bt_ctf_field_type_common_variant_borrow_tag_field_type(
1919 struct bt_ctf_field_type_common *ft)
1920 {
1921 struct bt_ctf_field_type_common_variant *var_ft = BT_CTF_FROM_COMMON(ft);
1922 struct bt_ctf_field_type_common *tag_ft = NULL;
1923
1924 BT_CTF_ASSERT_PRE_NON_NULL(ft, "Field type");
1925 BT_CTF_ASSERT_PRE_CTF_FT_COMMON_HAS_ID(ft, BT_CTF_FIELD_TYPE_ID_VARIANT,
1926 "Field type");
1927
1928 if (!var_ft->tag_ft) {
1929 BT_LOGT("Variant field type has no tag field type: "
1930 "addr=%p", ft);
1931 goto end;
1932 }
1933
1934 tag_ft = BT_CTF_TO_COMMON(var_ft->tag_ft);
1935
1936 end:
1937 return tag_ft;
1938 }
1939
1940 const char *bt_ctf_field_type_common_variant_get_tag_name(
1941 struct bt_ctf_field_type_common *ft)
1942 {
1943 struct bt_ctf_field_type_common_variant *var_ft = BT_CTF_FROM_COMMON(ft);
1944 const char *tag_name = NULL;
1945
1946 BT_CTF_ASSERT_PRE_NON_NULL(ft, "Field type");
1947 BT_CTF_ASSERT_PRE_CTF_FT_COMMON_HAS_ID(ft, BT_CTF_FIELD_TYPE_ID_VARIANT,
1948 "Field type");
1949
1950 if (var_ft->tag_name->len == 0) {
1951 BT_LOGT("Variant field type has no tag field name: "
1952 "addr=%p", ft);
1953 goto end;
1954 }
1955
1956 tag_name = var_ft->tag_name->str;
1957
1958 end:
1959 return tag_name;
1960 }
1961
1962 int bt_ctf_field_type_common_variant_set_tag_name(
1963 struct bt_ctf_field_type_common *ft, const char *name)
1964 {
1965 int ret = 0;
1966 struct bt_ctf_field_type_common_variant *var_ft = BT_CTF_FROM_COMMON(ft);
1967
1968 if (!ft) {
1969 BT_LOGW_STR("Invalid parameter: field type is NULL.");
1970 ret = -1;
1971 goto end;
1972 }
1973
1974 if (ft->frozen) {
1975 BT_LOGW("Invalid parameter: field type is frozen: addr=%p",
1976 ft);
1977 ret = -1;
1978 goto end;
1979 }
1980
1981 if (ft->id != BT_CTF_FIELD_TYPE_ID_VARIANT) {
1982 BT_LOGW("Invalid parameter: field type is not a variant field type: "
1983 "addr=%p, ft-id=%s", ft, bt_ctf_field_type_id_string(ft->id));
1984 ret = -1;
1985 goto end;
1986 }
1987
1988 if (!bt_ctf_identifier_is_valid(name)) {
1989 BT_LOGW("Invalid parameter: tag field name is not a valid CTF identifier: "
1990 "variant-ft-addr=%p, tag-field-name=\"%s\"",
1991 ft, name);
1992 ret = -1;
1993 goto end;
1994 }
1995
1996 g_string_assign(var_ft->tag_name, name);
1997 BT_LOGT("Set variant field type's tag field name: addr=%p, "
1998 "tag-field-name=\"%s\"", ft, name);
1999
2000 end:
2001 return ret;
2002 }
2003
2004 int bt_ctf_field_type_common_variant_add_field(struct bt_ctf_field_type_common *ft,
2005 struct bt_ctf_field_type_common *field_type,
2006 const char *field_name)
2007 {
2008 size_t i;
2009 int ret = 0;
2010 struct bt_ctf_field_type_common_variant *var_ft = BT_CTF_FROM_COMMON(ft);
2011 GQuark field_name_quark = g_quark_from_string(field_name);
2012
2013 /*
2014 * TODO: check that `field_type` does not contain `type`,
2015 * recursively.
2016 */
2017 if (!ft) {
2018 BT_LOGW_STR("Invalid parameter: field type is NULL.");
2019 ret = -1;
2020 goto end;
2021 }
2022
2023 if (ft->frozen) {
2024 BT_LOGW("Invalid parameter: field type is frozen: addr=%p",
2025 ft);
2026 ret = -1;
2027 goto end;
2028 }
2029
2030 if (ft->id != BT_CTF_FIELD_TYPE_ID_VARIANT) {
2031 BT_LOGW("Invalid parameter: field type is not a variant field type: "
2032 "addr=%p, ft-id=%s", ft,
2033 bt_ctf_field_type_id_string(ft->id));
2034 ret = -1;
2035 goto end;
2036 }
2037
2038 if (ft == field_type) {
2039 BT_LOGW("Invalid parameter: variant field type and field type to add are the same: "
2040 "addr=%p", ft);
2041 ret = -1;
2042 goto end;
2043 }
2044
2045 /* The user has explicitly provided a tag; validate against it. */
2046 if (var_ft->tag_ft) {
2047 int name_found = 0;
2048
2049 /* Make sure this name is present in the enum tag */
2050 for (i = 0; i < var_ft->tag_ft->entries->len; i++) {
2051 struct bt_ctf_enumeration_mapping *mapping =
2052 g_ptr_array_index(var_ft->tag_ft->entries, i);
2053
2054 if (mapping->string == field_name_quark) {
2055 name_found = 1;
2056 break;
2057 }
2058 }
2059
2060 if (!name_found) {
2061 /* Validation failed */
2062 BT_LOGW("Invalid parameter: field name does not name a tag field type's mapping: "
2063 "variant-ft-addr=%p, tag-ft-addr=%p, "
2064 "tag-field-name=\"%s\""
2065 "field-ft-addr=%p, field-name=\"%s\"",
2066 ft, var_ft->tag_ft, var_ft->tag_name->str,
2067 field_type, field_name);
2068 ret = -1;
2069 goto end;
2070 }
2071 }
2072
2073 if (add_structure_variant_member(var_ft->choices,
2074 var_ft->choice_name_to_index, field_type,
2075 field_name, true)) {
2076 BT_LOGW("Cannot add field to variant field type: "
2077 "variant-ft-addr=%p, field-ft-addr=%p, field-name=\"%s\"",
2078 ft, field_type, field_name);
2079 ret = -1;
2080 goto end;
2081 }
2082
2083 BT_LOGT("Added variant field type field: variant-ft-addr=%p, "
2084 "field-ft-addr=%p, field-name=\"%s\"", ft,
2085 field_type, field_name);
2086
2087 end:
2088 return ret;
2089 }
2090
2091 struct bt_ctf_field_type_common *
2092 bt_ctf_field_type_common_variant_borrow_field_type_by_name(
2093 struct bt_ctf_field_type_common *ft,
2094 const char *field_name)
2095 {
2096 size_t index;
2097 GQuark name_quark;
2098 struct bt_ctf_field_type_common_variant_choice *choice;
2099 struct bt_ctf_field_type_common_variant *var_ft = BT_CTF_FROM_COMMON(ft);
2100 struct bt_ctf_field_type_common *field_type = NULL;
2101
2102 BT_CTF_ASSERT_PRE_NON_NULL(ft, "Field type");
2103 BT_CTF_ASSERT_PRE_NON_NULL(field_name, "Name");
2104 BT_CTF_ASSERT_PRE_CTF_FT_COMMON_HAS_ID(ft, BT_CTF_FIELD_TYPE_ID_VARIANT,
2105 "Field type");
2106 name_quark = g_quark_try_string(field_name);
2107 if (!name_quark) {
2108 BT_LOGT("No such variant field type field name: "
2109 "ft-addr=%p, field-name=\"%s\"",
2110 ft, field_name);
2111 goto end;
2112 }
2113
2114 if (!g_hash_table_lookup_extended(var_ft->choice_name_to_index,
2115 GUINT_TO_POINTER(name_quark), NULL, (gpointer *) &index)) {
2116 BT_LOGT("No such variant field type field name: "
2117 "ft-addr=%p, field-name=\"%s\"",
2118 ft, field_name);
2119 goto end;
2120 }
2121
2122 choice = BT_CTF_FIELD_TYPE_COMMON_VARIANT_CHOICE_AT_INDEX(ft, index);
2123 field_type = choice->type;
2124
2125 end:
2126 return field_type;
2127 }
2128
2129 int64_t bt_ctf_field_type_common_variant_get_field_count(
2130 struct bt_ctf_field_type_common *ft)
2131 {
2132 struct bt_ctf_field_type_common_variant *var_ft = BT_CTF_FROM_COMMON(ft);
2133
2134 BT_CTF_ASSERT_PRE_NON_NULL(ft, "Variant field type");
2135 BT_CTF_ASSERT_PRE_CTF_FT_COMMON_HAS_ID(ft, BT_CTF_FIELD_TYPE_ID_VARIANT,
2136 "Field type");
2137 return (int64_t) var_ft->choices->len;
2138 }
2139
2140 int bt_ctf_field_type_common_variant_borrow_field_by_index(
2141 struct bt_ctf_field_type_common *ft,
2142 const char **field_name,
2143 struct bt_ctf_field_type_common **field_type, uint64_t index)
2144 {
2145 struct bt_ctf_field_type_common_variant *var_ft = BT_CTF_FROM_COMMON(ft);
2146 struct bt_ctf_field_type_common_variant_choice *choice;
2147
2148 BT_CTF_ASSERT_PRE_NON_NULL(ft, "Field type");
2149 BT_CTF_ASSERT_PRE_CTF_FT_COMMON_HAS_ID(ft, BT_CTF_FIELD_TYPE_ID_VARIANT,
2150 "Field type");
2151 BT_CTF_ASSERT_PRE(index < var_ft->choices->len,
2152 "Index is out of bounds: index=%" PRIu64 ", "
2153 "count=%u, ft-addr=%p",
2154 index, var_ft->choices->len, ft);
2155 choice = BT_CTF_FIELD_TYPE_COMMON_VARIANT_CHOICE_AT_INDEX(ft, index);
2156
2157 if (field_type) {
2158 *field_type = choice->type;
2159 }
2160
2161 if (field_name) {
2162 *field_name = g_quark_to_string(choice->name);
2163 BT_ASSERT_DBG(*field_name);
2164 }
2165
2166 return 0;
2167 }
2168
2169 int64_t bt_ctf_field_type_common_variant_find_choice_index(
2170 struct bt_ctf_field_type_common *ft, uint64_t uval,
2171 bool is_signed)
2172 {
2173 int64_t ret;
2174 uint64_t i;
2175 struct bt_ctf_field_type_common_variant *var_ft = BT_CTF_FROM_COMMON(ft);
2176
2177 BT_ASSERT_DBG(ft);
2178 BT_ASSERT_DBG(ft->id == BT_CTF_FIELD_TYPE_ID_VARIANT);
2179
2180 if (bt_ctf_field_type_common_variant_update_choices(ft)) {
2181 ret = INT64_C(-1);
2182 goto end;
2183 }
2184
2185 for (i = 0; i < var_ft->choices->len; i++) {
2186 uint64_t range_i;
2187 struct bt_ctf_field_type_common_variant_choice *choice =
2188 BT_CTF_FIELD_TYPE_COMMON_VARIANT_CHOICE_AT_INDEX(
2189 var_ft, i);
2190
2191 for (range_i = 0; range_i < choice->ranges->len; range_i++) {
2192 struct bt_ctf_field_type_common_variant_choice_range *range =
2193 &bt_g_array_index(
2194 choice->ranges,
2195 struct bt_ctf_field_type_common_variant_choice_range,
2196 range_i);
2197
2198 if (is_signed) {
2199 int64_t tag_ival = (int64_t) uval;
2200
2201 if (tag_ival >= range->lower.i &&
2202 tag_ival <= range->upper.i) {
2203 goto found;
2204 }
2205 } else {
2206 if (uval >= range->lower.u &&
2207 uval <= range->upper.u) {
2208 goto found;
2209 }
2210 }
2211 }
2212 }
2213
2214 /* Range not found */
2215 ret = INT64_C(-1);
2216 goto end;
2217
2218 found:
2219 ret = (int64_t) i;
2220
2221 end:
2222 return ret;
2223 }
2224
2225 struct bt_ctf_field_type_common *
2226 bt_ctf_field_type_common_array_borrow_element_field_type(
2227 struct bt_ctf_field_type_common *ft)
2228 {
2229 struct bt_ctf_field_type_common_array *array_ft = BT_CTF_FROM_COMMON(ft);
2230
2231 BT_CTF_ASSERT_PRE_NON_NULL(ft, "Field type");
2232 BT_CTF_ASSERT_PRE_CTF_FT_COMMON_HAS_ID(ft, BT_CTF_FIELD_TYPE_ID_ARRAY,
2233 "Field type");
2234 BT_ASSERT_DBG(array_ft && array_ft->element_ft);
2235 return array_ft->element_ft;
2236 }
2237
2238 int bt_ctf_field_type_common_array_set_element_field_type(
2239 struct bt_ctf_field_type_common *ft,
2240 struct bt_ctf_field_type_common *element_ft)
2241 {
2242 int ret = 0;
2243 struct bt_ctf_field_type_common_array *array_ft = BT_CTF_FROM_COMMON(ft);
2244
2245 if (!ft) {
2246 BT_LOGW_STR("Invalid parameter: array field type is NULL.");
2247 ret = -1;
2248 goto end;
2249 }
2250
2251 if (!element_ft) {
2252 BT_LOGW_STR("Invalid parameter: element field type is NULL.");
2253 ret = -1;
2254 goto end;
2255 }
2256
2257 if (ft->id != BT_CTF_FIELD_TYPE_ID_ARRAY) {
2258 BT_LOGW("Invalid parameter: field type is not an array field type: "
2259 "addr=%p, ft-id=%s", ft,
2260 bt_ctf_field_type_id_string(ft->id));
2261 ret = -1;
2262 goto end;
2263 }
2264
2265 if (array_ft->element_ft) {
2266 BT_CTF_OBJECT_PUT_REF_AND_RESET(array_ft->element_ft);
2267 }
2268
2269 array_ft->element_ft = bt_ctf_object_get_ref(element_ft);
2270 BT_LOGT("Set array field type's element field type: array-ft-addr=%p, "
2271 "element-ft-addr=%p", ft, element_ft);
2272
2273 end:
2274 return ret;
2275 }
2276
2277 int64_t bt_ctf_field_type_common_array_get_length(struct bt_ctf_field_type_common *ft)
2278 {
2279 struct bt_ctf_field_type_common_array *array_ft = BT_CTF_FROM_COMMON(ft);
2280
2281 BT_CTF_ASSERT_PRE_NON_NULL(ft, "Field type");
2282 BT_CTF_ASSERT_PRE_CTF_FT_COMMON_HAS_ID(ft, BT_CTF_FIELD_TYPE_ID_ARRAY,
2283 "Field type");
2284 return (int64_t) array_ft->length;
2285 }
2286
2287 struct bt_ctf_field_type_common *bt_ctf_field_type_common_sequence_borrow_element_field_type(
2288 struct bt_ctf_field_type_common *ft)
2289 {
2290 struct bt_ctf_field_type_common_sequence *seq_ft = BT_CTF_FROM_COMMON(ft);
2291
2292 BT_CTF_ASSERT_PRE_NON_NULL(ft, "Field type");
2293 BT_CTF_ASSERT_PRE_CTF_FT_COMMON_HAS_ID(ft, BT_CTF_FIELD_TYPE_ID_SEQUENCE,
2294 "Field type");
2295 return seq_ft->element_ft;
2296 }
2297
2298 int bt_ctf_field_type_common_sequence_set_element_field_type(
2299 struct bt_ctf_field_type_common *ft,
2300 struct bt_ctf_field_type_common *element_ft)
2301 {
2302 int ret = 0;
2303 struct bt_ctf_field_type_common_sequence *seq_ft = BT_CTF_FROM_COMMON(ft);
2304
2305 if (!ft) {
2306 BT_LOGW_STR("Invalid parameter: sequence field type is NULL.");
2307 ret = -1;
2308 goto end;
2309 }
2310
2311 if (!element_ft) {
2312 BT_LOGW_STR("Invalid parameter: element field type is NULL.");
2313 ret = -1;
2314 goto end;
2315 }
2316
2317 if (ft->id != BT_CTF_FIELD_TYPE_ID_SEQUENCE) {
2318 BT_LOGW("Invalid parameter: field type is not a sequence field type: "
2319 "addr=%p, ft-id=%s", ft,
2320 bt_ctf_field_type_id_string(ft->id));
2321 ret = -1;
2322 goto end;
2323 }
2324
2325 if (seq_ft->element_ft) {
2326 BT_CTF_OBJECT_PUT_REF_AND_RESET(seq_ft->element_ft);
2327 }
2328
2329 seq_ft->element_ft = element_ft;
2330 bt_ctf_object_get_ref(seq_ft->element_ft);
2331 BT_LOGT("Set sequence field type's element field type: sequence-ft-addr=%p, "
2332 "element-ft-addr=%p", ft, element_ft);
2333
2334 end:
2335 return ret;
2336 }
2337
2338 const char *bt_ctf_field_type_common_sequence_get_length_field_name(
2339 struct bt_ctf_field_type_common *ft)
2340 {
2341 struct bt_ctf_field_type_common_sequence *seq_ft = BT_CTF_FROM_COMMON(ft);
2342
2343 BT_CTF_ASSERT_PRE_NON_NULL(ft, "Field type");
2344 BT_CTF_ASSERT_PRE_CTF_FT_COMMON_HAS_ID(ft, BT_CTF_FIELD_TYPE_ID_SEQUENCE,
2345 "Field type");
2346 return seq_ft->length_field_name ?
2347 seq_ft->length_field_name->str : NULL;
2348 }
2349
2350 enum bt_ctf_string_encoding bt_ctf_field_type_common_string_get_encoding(
2351 struct bt_ctf_field_type_common *ft)
2352 {
2353 struct bt_ctf_field_type_common_string *string_ft = BT_CTF_FROM_COMMON(ft);
2354
2355 BT_CTF_ASSERT_PRE_NON_NULL(ft, "Field type");
2356 BT_CTF_ASSERT_PRE_CTF_FT_COMMON_HAS_ID(ft, BT_CTF_FIELD_TYPE_ID_STRING,
2357 "Field type");
2358 return string_ft->encoding;
2359 }
2360
2361 int bt_ctf_field_type_common_string_set_encoding(struct bt_ctf_field_type_common *ft,
2362 enum bt_ctf_string_encoding encoding)
2363 {
2364 int ret = 0;
2365 struct bt_ctf_field_type_common_string *string_ft = BT_CTF_FROM_COMMON(ft);
2366
2367 if (!ft) {
2368 BT_LOGW_STR("Invalid parameter: field type is NULL.");
2369 ret = -1;
2370 goto end;
2371 }
2372
2373 if (ft->id != BT_CTF_FIELD_TYPE_ID_STRING) {
2374 BT_LOGW("Invalid parameter: field type is not a string field type: "
2375 "addr=%p, ft-id=%s", ft,
2376 bt_ctf_field_type_id_string(ft->id));
2377 ret = -1;
2378 goto end;
2379 }
2380
2381 if (encoding != BT_CTF_STRING_ENCODING_UTF8 &&
2382 encoding != BT_CTF_STRING_ENCODING_ASCII) {
2383 BT_LOGW("Invalid parameter: unknown string encoding: "
2384 "addr=%p, encoding=%d", ft, encoding);
2385 ret = -1;
2386 goto end;
2387 }
2388
2389 string_ft->encoding = encoding;
2390 BT_LOGT("Set string field type's encoding: addr=%p, encoding=%s",
2391 ft, bt_ctf_string_encoding_string(encoding));
2392
2393 end:
2394 return ret;
2395 }
2396
2397 int bt_ctf_field_type_common_get_alignment(struct bt_ctf_field_type_common *ft)
2398 {
2399 int ret;
2400 enum bt_ctf_field_type_id type_id;
2401
2402 BT_CTF_ASSERT_PRE_NON_NULL(ft, "Field type");
2403
2404 if (ft->frozen) {
2405 ret = (int) ft->alignment;
2406 goto end;
2407 }
2408
2409 type_id = bt_ctf_field_type_common_get_type_id(ft);
2410 switch (type_id) {
2411 case BT_CTF_FIELD_TYPE_ID_SEQUENCE:
2412 {
2413 struct bt_ctf_field_type_common *element_ft =
2414 bt_ctf_field_type_common_sequence_borrow_element_field_type(ft);
2415
2416 BT_ASSERT_DBG(element_ft);
2417 ret = bt_ctf_field_type_common_get_alignment(element_ft);
2418 break;
2419 }
2420 case BT_CTF_FIELD_TYPE_ID_ARRAY:
2421 {
2422 struct bt_ctf_field_type_common *element_ft =
2423 bt_ctf_field_type_common_array_borrow_element_field_type(ft);
2424
2425 BT_ASSERT_DBG(element_ft);
2426 ret = bt_ctf_field_type_common_get_alignment(element_ft);
2427 break;
2428 }
2429 case BT_CTF_FIELD_TYPE_ID_STRUCT:
2430 {
2431 int64_t i, element_count;
2432
2433 element_count = bt_ctf_field_type_common_structure_get_field_count(
2434 ft);
2435 BT_ASSERT_DBG(element_count >= 0);
2436
2437 for (i = 0; i < element_count; i++) {
2438 struct bt_ctf_field_type_common *field = NULL;
2439 int field_alignment;
2440
2441 ret = bt_ctf_field_type_common_structure_borrow_field_by_index(
2442 ft, NULL, &field, i);
2443 BT_ASSERT_DBG(ret == 0);
2444 BT_ASSERT_DBG(field);
2445 field_alignment = bt_ctf_field_type_common_get_alignment(
2446 field);
2447 if (field_alignment < 0) {
2448 ret = field_alignment;
2449 goto end;
2450 }
2451
2452 ft->alignment = MAX(field_alignment, ft->alignment);
2453 }
2454 ret = (int) ft->alignment;
2455 break;
2456 }
2457 case BT_CTF_FIELD_TYPE_ID_UNKNOWN:
2458 BT_LOGW("Invalid parameter: unknown field type ID: "
2459 "addr=%p, ft-id=%d", ft, type_id);
2460 ret = -1;
2461 break;
2462 default:
2463 ret = (int) ft->alignment;
2464 break;
2465 }
2466
2467 end:
2468 return ret;
2469 }
2470
2471 static inline
2472 int is_power_of_two(unsigned int value)
2473 {
2474 return ((value & (value - 1)) == 0) && value > 0;
2475 }
2476
2477 int bt_ctf_field_type_common_set_alignment(struct bt_ctf_field_type_common *ft,
2478 unsigned int alignment)
2479 {
2480 int ret = 0;
2481 enum bt_ctf_field_type_id type_id;
2482
2483 /* Alignment must be a power of two */
2484 if (!ft) {
2485 BT_LOGW_STR("Invalid parameter: field type is NULL.");
2486 ret = -1;
2487 goto end;
2488 }
2489
2490 if (ft->frozen) {
2491 BT_LOGW("Invalid parameter: field type is frozen: addr=%p",
2492 ft);
2493 ret = -1;
2494 goto end;
2495 }
2496
2497 if (!is_power_of_two(alignment)) {
2498 BT_LOGW("Invalid parameter: alignment is not a power of two: "
2499 "addr=%p, align=%u", ft, alignment);
2500 ret = -1;
2501 goto end;
2502 }
2503
2504 type_id = bt_ctf_field_type_common_get_type_id(ft);
2505 if (type_id == BT_CTF_FIELD_TYPE_ID_UNKNOWN) {
2506 BT_LOGW("Invalid parameter: unknown field type ID: "
2507 "addr=%p, ft-id=%d", ft, type_id);
2508 ret = -1;
2509 goto end;
2510 }
2511
2512 if (ft->id == BT_CTF_FIELD_TYPE_ID_STRING && alignment != CHAR_BIT) {
2513 BT_LOGW("Invalid parameter: alignment must be %u for a string field type: "
2514 "addr=%p, align=%u", CHAR_BIT, ft, alignment);
2515 ret = -1;
2516 goto end;
2517 }
2518
2519 if (type_id == BT_CTF_FIELD_TYPE_ID_VARIANT ||
2520 type_id == BT_CTF_FIELD_TYPE_ID_SEQUENCE ||
2521 type_id == BT_CTF_FIELD_TYPE_ID_ARRAY) {
2522 /* Setting an alignment on these types makes no sense */
2523 BT_LOGW("Invalid parameter: cannot set the alignment of this field type: "
2524 "addr=%p, ft-id=%s", ft,
2525 bt_ctf_field_type_id_string(ft->id));
2526 ret = -1;
2527 goto end;
2528 }
2529
2530 ft->alignment = alignment;
2531 ret = 0;
2532 BT_LOGT("Set field type's alignment: addr=%p, align=%u",
2533 ft, alignment);
2534
2535 end:
2536 return ret;
2537 }
2538
2539 enum bt_ctf_byte_order bt_ctf_field_type_common_get_byte_order(
2540 struct bt_ctf_field_type_common *ft)
2541 {
2542 enum bt_ctf_byte_order ret = BT_CTF_BYTE_ORDER_UNKNOWN;
2543
2544 BT_CTF_ASSERT_PRE_NON_NULL(ft, "Field type");
2545
2546 switch (ft->id) {
2547 case BT_CTF_FIELD_TYPE_ID_INTEGER:
2548 {
2549 struct bt_ctf_field_type_common_integer *integer =
2550 BT_CTF_FROM_COMMON(ft);
2551
2552 ret = integer->user_byte_order;
2553 break;
2554 }
2555 case BT_CTF_FIELD_TYPE_ID_ENUM:
2556 {
2557 struct bt_ctf_field_type_common_enumeration *enum_ft =
2558 BT_CTF_FROM_COMMON(ft);
2559
2560 ret = bt_ctf_field_type_common_get_byte_order(
2561 BT_CTF_TO_COMMON(enum_ft->container_ft));
2562 break;
2563 }
2564 case BT_CTF_FIELD_TYPE_ID_FLOAT:
2565 {
2566 struct bt_ctf_field_type_common_floating_point *floating_point =
2567 BT_CTF_FROM_COMMON(ft);
2568 ret = floating_point->user_byte_order;
2569 break;
2570 }
2571 default:
2572 BT_LOGW("Invalid parameter: cannot get the byte order of this field type: "
2573 "addr=%p, ft-id=%s", ft,
2574 bt_ctf_field_type_id_string(ft->id));
2575 goto end;
2576 }
2577
2578 BT_ASSERT_DBG(ret == BT_CTF_BYTE_ORDER_NATIVE ||
2579 ret == BT_CTF_BYTE_ORDER_LITTLE_ENDIAN ||
2580 ret == BT_CTF_BYTE_ORDER_BIG_ENDIAN ||
2581 ret == BT_CTF_BYTE_ORDER_NETWORK);
2582
2583 end:
2584 return ret;
2585 }
2586
2587 int bt_ctf_field_type_common_set_byte_order(struct bt_ctf_field_type_common *ft,
2588 enum bt_ctf_byte_order byte_order)
2589 {
2590 int ret = 0;
2591
2592 if (!ft) {
2593 BT_LOGW_STR("Invalid parameter: field type is NULL.");
2594 ret = -1;
2595 goto end;
2596 }
2597
2598 if (ft->frozen) {
2599 BT_LOGW("Invalid parameter: field type is frozen: addr=%p",
2600 ft);
2601 ret = -1;
2602 goto end;
2603 }
2604
2605 if (byte_order != BT_CTF_BYTE_ORDER_NATIVE &&
2606 byte_order != BT_CTF_BYTE_ORDER_LITTLE_ENDIAN &&
2607 byte_order != BT_CTF_BYTE_ORDER_BIG_ENDIAN &&
2608 byte_order != BT_CTF_BYTE_ORDER_NETWORK) {
2609 BT_LOGW("Invalid parameter: invalid byte order: "
2610 "addr=%p, bo=%s", ft,
2611 bt_ctf_byte_order_string(byte_order));
2612 ret = -1;
2613 goto end;
2614 }
2615
2616 if (ft->methods->set_byte_order) {
2617 ft->methods->set_byte_order(ft, byte_order);
2618 }
2619
2620 BT_LOGT("Set field type's byte order: addr=%p, bo=%s",
2621 ft, bt_ctf_byte_order_string(byte_order));
2622
2623 end:
2624 return ret;
2625 }
2626
2627 enum bt_ctf_field_type_id bt_ctf_field_type_common_get_type_id(
2628 struct bt_ctf_field_type_common *ft)
2629 {
2630 BT_CTF_ASSERT_PRE_NON_NULL(ft, "Field type");
2631 return ft->id;
2632 }
2633
2634 void bt_ctf_field_type_common_freeze(struct bt_ctf_field_type_common *ft)
2635 {
2636 if (!ft || ft->frozen) {
2637 return;
2638 }
2639
2640 BT_ASSERT_DBG(ft->methods->freeze);
2641 ft->methods->freeze(ft);
2642 }
2643
2644 struct bt_ctf_field_type_common *
2645 bt_ctf_field_type_common_variant_borrow_field_type_signed(
2646 struct bt_ctf_field_type_common_variant *var_ft,
2647 int64_t tag_value)
2648 {
2649 struct bt_ctf_field_type_common *field_type = NULL;
2650 GQuark field_name_quark;
2651 gpointer index;
2652 struct bt_ctf_field_type_common_variant_choice *choice;
2653 struct range_overlap_query query = {
2654 .range_start._signed = tag_value,
2655 .range_end._signed = tag_value,
2656 .mapping_name = 0,
2657 .overlaps = 0,
2658 };
2659
2660 g_ptr_array_foreach(var_ft->tag_ft->entries, check_ranges_overlap,
2661 &query);
2662 if (!query.overlaps) {
2663 goto end;
2664 }
2665
2666 field_name_quark = query.mapping_name;
2667 if (!g_hash_table_lookup_extended(var_ft->choice_name_to_index,
2668 GUINT_TO_POINTER(field_name_quark), NULL, &index)) {
2669 goto end;
2670 }
2671
2672 choice = BT_CTF_FIELD_TYPE_COMMON_VARIANT_CHOICE_AT_INDEX(var_ft,
2673 (size_t) index);
2674 field_type = choice->type;
2675
2676 end:
2677 return field_type;
2678 }
2679
2680 struct bt_ctf_field_type_common *
2681 bt_ctf_field_type_common_variant_borrow_field_type_unsigned(
2682 struct bt_ctf_field_type_common_variant *var_ft,
2683 uint64_t tag_value)
2684 {
2685 struct bt_ctf_field_type_common *field_type = NULL;
2686 GQuark field_name_quark;
2687 gpointer index;
2688 struct bt_ctf_field_type_common_variant_choice *choice;
2689 struct range_overlap_query query = {
2690 .range_start._unsigned = tag_value,
2691 .range_end._unsigned = tag_value,
2692 .mapping_name = 0,
2693 .overlaps = 0,
2694 };
2695
2696 g_ptr_array_foreach(var_ft->tag_ft->entries,
2697 check_ranges_overlap_unsigned, &query);
2698 if (!query.overlaps) {
2699 goto end;
2700 }
2701
2702 field_name_quark = query.mapping_name;
2703 if (!g_hash_table_lookup_extended(var_ft->choice_name_to_index,
2704 GUINT_TO_POINTER(field_name_quark), NULL, &index)) {
2705 goto end;
2706 }
2707
2708 choice = BT_CTF_FIELD_TYPE_COMMON_VARIANT_CHOICE_AT_INDEX(var_ft,
2709 (size_t) index);
2710 field_type = choice->type;
2711
2712 end:
2713 return field_type;
2714 }
2715
2716 struct bt_ctf_field_type_common *bt_ctf_field_type_common_copy(
2717 struct bt_ctf_field_type_common *ft)
2718 {
2719 struct bt_ctf_field_type_common *ft_copy = NULL;
2720
2721 BT_CTF_ASSERT_PRE_NON_NULL(ft, "Field type");
2722 BT_ASSERT_DBG(ft->methods->copy);
2723 ft_copy = ft->methods->copy(ft);
2724 if (!ft_copy) {
2725 BT_LOGE_STR("Cannot copy field type.");
2726 goto end;
2727 }
2728
2729 ft_copy->alignment = ft->alignment;
2730
2731 end:
2732 return ft_copy;
2733 }
2734
2735 int bt_ctf_field_type_common_structure_get_field_name_index(
2736 struct bt_ctf_field_type_common *ft, const char *name)
2737 {
2738 int ret;
2739 size_t index;
2740 GQuark name_quark;
2741 struct bt_ctf_field_type_common_structure *struct_ft = BT_CTF_FROM_COMMON(ft);
2742
2743 BT_CTF_ASSERT_PRE_NON_NULL(ft, "Field type");
2744 BT_CTF_ASSERT_PRE_NON_NULL(name, "Name");
2745 BT_CTF_ASSERT_PRE_CTF_FT_COMMON_HAS_ID(ft, BT_CTF_FIELD_TYPE_ID_STRUCT,
2746 "Field type");
2747
2748 name_quark = g_quark_try_string(name);
2749 if (!name_quark) {
2750 BT_LOGT("No such structure field type field name: "
2751 "ft-addr=%p, field-name=\"%s\"",
2752 ft, name);
2753 ret = -1;
2754 goto end;
2755 }
2756
2757 if (!g_hash_table_lookup_extended(struct_ft->field_name_to_index,
2758 GUINT_TO_POINTER(name_quark),
2759 NULL, (gpointer *) &index)) {
2760 BT_LOGT("No such structure field type field name: "
2761 "ft-addr=%p, field-name=\"%s\"",
2762 ft, name);
2763 ret = -1;
2764 goto end;
2765 }
2766
2767 ret = (int) index;
2768
2769 end:
2770 return ret;
2771 }
2772
2773 int bt_ctf_field_type_common_variant_get_field_name_index(
2774 struct bt_ctf_field_type_common *ft, const char *name)
2775 {
2776 int ret;
2777 size_t index;
2778 GQuark name_quark;
2779 struct bt_ctf_field_type_common_variant *var_ft = BT_CTF_FROM_COMMON(ft);
2780
2781 BT_CTF_ASSERT_PRE_NON_NULL(ft, "Field type");
2782 BT_CTF_ASSERT_PRE_NON_NULL(name, "Name");
2783 BT_CTF_ASSERT_PRE_CTF_FT_COMMON_HAS_ID(ft, BT_CTF_FIELD_TYPE_ID_VARIANT,
2784 "Field type");
2785 name_quark = g_quark_try_string(name);
2786 if (!name_quark) {
2787 BT_LOGT("No such variant field type field name: "
2788 "ft-addr=%p, field-name=\"%s\"",
2789 ft, name);
2790 ret = -1;
2791 goto end;
2792 }
2793
2794 if (!g_hash_table_lookup_extended(var_ft->choice_name_to_index,
2795 GUINT_TO_POINTER(name_quark),
2796 NULL, (gpointer *) &index)) {
2797 BT_LOGT("No such variant field type field name: "
2798 "ft-addr=%p, field-name=\"%s\"",
2799 ft, name);
2800 ret = -1;
2801 goto end;
2802 }
2803
2804 ret = (int) index;
2805
2806 end:
2807 return ret;
2808 }
2809
2810 int bt_ctf_field_type_common_sequence_set_length_field_path(
2811 struct bt_ctf_field_type_common *ft, struct bt_ctf_field_path *path)
2812 {
2813 int ret = 0;
2814 struct bt_ctf_field_type_common_sequence *seq_ft = BT_CTF_FROM_COMMON(ft);
2815
2816 if (!ft) {
2817 BT_LOGW_STR("Invalid parameter: field type is NULL.");
2818 ret = -1;
2819 goto end;
2820 }
2821
2822 if (ft->id != BT_CTF_FIELD_TYPE_ID_SEQUENCE) {
2823 BT_LOGW("Invalid parameter: field type is not a sequence field type: "
2824 "addr=%p, ft-id=%s", ft,
2825 bt_ctf_field_type_id_string(ft->id));
2826 ret = -1;
2827 goto end;
2828 }
2829
2830 bt_ctf_object_get_ref(path);
2831 BT_CTF_OBJECT_MOVE_REF(seq_ft->length_field_path, path);
2832 BT_LOGT("Set sequence field type's length field path: ft-addr=%p, "
2833 "field-path-addr=%p", ft, path);
2834
2835 end:
2836 return ret;
2837 }
2838
2839 int bt_ctf_field_type_common_variant_set_tag_field_path(
2840 struct bt_ctf_field_type_common *ft,
2841 struct bt_ctf_field_path *path)
2842 {
2843 int ret = 0;
2844 struct bt_ctf_field_type_common_variant *var_ft = BT_CTF_FROM_COMMON(ft);
2845
2846 if (!ft) {
2847 BT_LOGW_STR("Invalid parameter: field type is NULL.");
2848 ret = -1;
2849 goto end;
2850 }
2851
2852 if (ft->id != BT_CTF_FIELD_TYPE_ID_VARIANT) {
2853 BT_LOGW("Invalid parameter: field type is not a variant field type: "
2854 "addr=%p, ft-id=%s", ft,
2855 bt_ctf_field_type_id_string(ft->id));
2856 ret = -1;
2857 goto end;
2858 }
2859
2860 bt_ctf_object_get_ref(path);
2861 BT_CTF_OBJECT_MOVE_REF(var_ft->tag_field_path, path);
2862 BT_LOGT("Set variant field type's tag field path: ft-addr=%p, "
2863 "field-path-addr=%p", ft, path);
2864
2865 end:
2866 return ret;
2867 }
2868
2869 int bt_ctf_field_type_common_variant_set_tag_field_type(
2870 struct bt_ctf_field_type_common *ft,
2871 struct bt_ctf_field_type_common *tag_ft)
2872 {
2873 int ret = 0;
2874 struct bt_ctf_field_type_common_variant *var_ft = BT_CTF_FROM_COMMON(ft);
2875
2876 if (!ft) {
2877 BT_LOGW_STR("Invalid parameter: variant field type is NULL.");
2878 ret = -1;
2879 goto end;
2880 }
2881
2882 if (!tag_ft) {
2883 BT_LOGW_STR("Invalid parameter: tag field type is NULL.");
2884 ret = -1;
2885 goto end;
2886 }
2887
2888 if (tag_ft->id != BT_CTF_FIELD_TYPE_ID_ENUM) {
2889 BT_LOGW("Invalid parameter: tag field type is not an enumeration field type: "
2890 "addr=%p, ft-id=%s", tag_ft,
2891 bt_ctf_field_type_id_string(tag_ft->id));
2892 ret = -1;
2893 goto end;
2894 }
2895
2896 bt_ctf_object_put_ref(var_ft->tag_ft);
2897 var_ft->tag_ft = bt_ctf_object_get_ref(tag_ft);
2898 BT_LOGT("Set variant field type's tag field type: variant-ft-addr=%p, "
2899 "tag-ft-addr=%p", ft, tag_ft);
2900
2901 end:
2902 return ret;
2903 }
2904
2905 void bt_ctf_field_type_common_generic_freeze(struct bt_ctf_field_type_common *ft)
2906 {
2907 ft->frozen = 1;
2908 }
2909
2910 void bt_ctf_field_type_common_enumeration_freeze_recursive(
2911 struct bt_ctf_field_type_common *ft)
2912 {
2913 struct bt_ctf_field_type_common_enumeration *enum_ft = BT_CTF_FROM_COMMON(ft);
2914
2915 BT_LOGD("Freezing enumeration field type object: addr=%p", ft);
2916 bt_ctf_field_type_common_enumeration_set_range_overlap(enum_ft);
2917 bt_ctf_field_type_common_generic_freeze(ft);
2918 BT_LOGD("Freezing enumeration field type object's container field type: int-ft-addr=%p",
2919 enum_ft->container_ft);
2920 bt_ctf_field_type_common_freeze(BT_CTF_TO_COMMON(enum_ft->container_ft));
2921 }
2922
2923 void bt_ctf_field_type_common_structure_freeze_recursive(
2924 struct bt_ctf_field_type_common *ft)
2925 {
2926 struct bt_ctf_field_type_common_structure *struct_ft = BT_CTF_FROM_COMMON(ft);
2927 uint64_t i;
2928
2929 /* Cache the alignment */
2930 BT_LOGD("Freezing structure field type object: addr=%p", ft);
2931 ft->alignment = bt_ctf_field_type_common_get_alignment(ft);
2932 bt_ctf_field_type_common_generic_freeze(ft);
2933
2934 for (i = 0; i < struct_ft->fields->len; i++) {
2935 struct bt_ctf_field_type_common_structure_field *field =
2936 BT_CTF_FIELD_TYPE_COMMON_STRUCTURE_FIELD_AT_INDEX(ft, i);
2937
2938 BT_LOGD("Freezing structure field type field: "
2939 "ft-addr=%p, name=\"%s\"",
2940 field->type, g_quark_to_string(field->name));
2941 bt_ctf_field_type_common_freeze(field->type);
2942 }
2943 }
2944
2945 int bt_ctf_field_type_common_variant_update_choices(struct bt_ctf_field_type_common *ft)
2946 {
2947 struct bt_ctf_field_type_common_variant *var_ft = BT_CTF_FROM_COMMON(ft);
2948 uint64_t i;
2949 int ret = 0;
2950 bool is_signed;
2951
2952 if (ft->frozen && var_ft->choices_up_to_date) {
2953 goto end;
2954 }
2955
2956 BT_ASSERT_DBG(var_ft->tag_ft);
2957 is_signed = !!var_ft->tag_ft->container_ft->is_signed;
2958
2959 for (i = 0; i < var_ft->choices->len; i++) {
2960 struct bt_ctf_field_type_common_variant_choice *choice =
2961 BT_CTF_FIELD_TYPE_COMMON_VARIANT_CHOICE_AT_INDEX(ft, i);
2962 const char *choice_name = g_quark_to_string(choice->name);
2963 struct bt_ctf_field_type_enumeration_mapping_iterator *iter =
2964 bt_ctf_field_type_common_enumeration_find_mappings_by_name(
2965 BT_CTF_TO_COMMON(var_ft->tag_ft), choice_name);
2966
2967 if (!iter) {
2968 ret = -1;
2969 goto end;
2970 }
2971
2972 BT_ASSERT_DBG(choice->ranges);
2973 g_array_set_size(choice->ranges, 0);
2974
2975 while (bt_ctf_field_type_enumeration_mapping_iterator_next(iter) == 0) {
2976 struct bt_ctf_field_type_common_variant_choice_range range;
2977
2978 if (is_signed) {
2979 ret = bt_ctf_field_type_enumeration_mapping_iterator_signed_get(
2980 iter, NULL,
2981 &range.lower.i, &range.upper.i);
2982 } else {
2983 ret = bt_ctf_field_type_enumeration_mapping_iterator_unsigned_get(
2984 iter, NULL,
2985 &range.lower.u, &range.upper.u);
2986 }
2987
2988 BT_ASSERT_DBG(ret == 0);
2989 g_array_append_val(choice->ranges, range);
2990 }
2991
2992 bt_ctf_object_put_ref(iter);
2993 }
2994
2995 var_ft->choices_up_to_date = true;
2996
2997 end:
2998 return ret;
2999 }
3000
3001 void bt_ctf_field_type_common_variant_freeze_recursive(
3002 struct bt_ctf_field_type_common *ft)
3003 {
3004 struct bt_ctf_field_type_common_variant *var_ft = BT_CTF_FROM_COMMON(ft);
3005 uint64_t i;
3006
3007 BT_LOGD("Freezing variant field type object: addr=%p", ft);
3008 bt_ctf_field_type_common_generic_freeze(ft);
3009
3010 for (i = 0; i < var_ft->choices->len; i++) {
3011 struct bt_ctf_field_type_common_variant_choice *choice =
3012 BT_CTF_FIELD_TYPE_COMMON_VARIANT_CHOICE_AT_INDEX(ft, i);
3013
3014 BT_LOGD("Freezing variant field type member: "
3015 "ft-addr=%p, name=\"%s\"",
3016 choice->type, g_quark_to_string(choice->name));
3017 bt_ctf_field_type_common_freeze(choice->type);
3018 }
3019 }
3020
3021 void bt_ctf_field_type_common_array_freeze_recursive(
3022 struct bt_ctf_field_type_common *ft)
3023 {
3024 struct bt_ctf_field_type_common_array *array_ft = BT_CTF_FROM_COMMON(ft);
3025
3026 /* Cache the alignment */
3027 BT_LOGD("Freezing array field type object: addr=%p", ft);
3028 ft->alignment = bt_ctf_field_type_common_get_alignment(ft);
3029 bt_ctf_field_type_common_generic_freeze(ft);
3030 BT_LOGD("Freezing array field type object's element field type: element-ft-addr=%p",
3031 array_ft->element_ft);
3032 bt_ctf_field_type_common_freeze(array_ft->element_ft);
3033 }
3034
3035 void bt_ctf_field_type_common_sequence_freeze_recursive(
3036 struct bt_ctf_field_type_common *ft)
3037 {
3038 struct bt_ctf_field_type_common_sequence *seq_ft = BT_CTF_FROM_COMMON(ft);
3039
3040 /* Cache the alignment */
3041 BT_LOGD("Freezing sequence field type object: addr=%p", ft);
3042 ft->alignment = bt_ctf_field_type_common_get_alignment(ft);
3043 bt_ctf_field_type_common_generic_freeze(ft);
3044 BT_LOGD("Freezing sequence field type object's element field type: element-ft-addr=%p",
3045 seq_ft->element_ft);
3046 bt_ctf_field_type_common_freeze(seq_ft->element_ft);
3047 }
3048
3049 void bt_ctf_field_type_common_integer_set_byte_order(
3050 struct bt_ctf_field_type_common *ft, enum bt_ctf_byte_order byte_order)
3051 {
3052 struct bt_ctf_field_type_common_integer *int_ft = BT_CTF_FROM_COMMON(ft);
3053
3054 int_ft->user_byte_order = byte_order;
3055 }
3056
3057 void bt_ctf_field_type_common_enumeration_set_byte_order_recursive(
3058 struct bt_ctf_field_type_common *ft, enum bt_ctf_byte_order byte_order)
3059 {
3060 struct bt_ctf_field_type_common_enumeration *enum_ft = BT_CTF_FROM_COMMON(ft);
3061
3062 bt_ctf_field_type_common_set_byte_order(BT_CTF_TO_COMMON(enum_ft->container_ft),
3063 byte_order);
3064 }
3065
3066 void bt_ctf_field_type_common_floating_point_set_byte_order(
3067 struct bt_ctf_field_type_common *ft, enum bt_ctf_byte_order byte_order)
3068 {
3069 struct bt_ctf_field_type_common_floating_point *flt_ft = BT_CTF_FROM_COMMON(ft);
3070
3071 flt_ft->user_byte_order = byte_order;
3072 }
3073
3074 void bt_ctf_field_type_common_structure_set_byte_order_recursive(
3075 struct bt_ctf_field_type_common *ft,
3076 enum bt_ctf_byte_order byte_order)
3077 {
3078 int i;
3079 struct bt_ctf_field_type_common_structure *struct_ft = BT_CTF_FROM_COMMON(ft);
3080
3081 for (i = 0; i < struct_ft->fields->len; i++) {
3082 struct bt_ctf_field_type_common_structure_field *field =
3083 BT_CTF_FIELD_TYPE_COMMON_STRUCTURE_FIELD_AT_INDEX(
3084 struct_ft, i);
3085 struct bt_ctf_field_type_common *field_type = field->type;
3086
3087 bt_ctf_field_type_common_set_byte_order(field_type, byte_order);
3088 }
3089 }
3090
3091 void bt_ctf_field_type_common_variant_set_byte_order_recursive(
3092 struct bt_ctf_field_type_common *ft,
3093 enum bt_ctf_byte_order byte_order)
3094 {
3095 int i;
3096 struct bt_ctf_field_type_common_variant *var_ft = BT_CTF_FROM_COMMON(ft);
3097
3098 for (i = 0; i < var_ft->choices->len; i++) {
3099 struct bt_ctf_field_type_common_variant_choice *choice =
3100 BT_CTF_FIELD_TYPE_COMMON_VARIANT_CHOICE_AT_INDEX(
3101 var_ft, i);
3102 struct bt_ctf_field_type_common *field_type = choice->type;
3103
3104 bt_ctf_field_type_common_set_byte_order(field_type, byte_order);
3105 }
3106 }
3107
3108 void bt_ctf_field_type_common_array_set_byte_order_recursive(
3109 struct bt_ctf_field_type_common *ft,
3110 enum bt_ctf_byte_order byte_order)
3111 {
3112 struct bt_ctf_field_type_common_array *array_ft = BT_CTF_FROM_COMMON(ft);
3113
3114 bt_ctf_field_type_common_set_byte_order(array_ft->element_ft, byte_order);
3115 }
3116
3117 void bt_ctf_field_type_common_sequence_set_byte_order_recursive(
3118 struct bt_ctf_field_type_common *ft,
3119 enum bt_ctf_byte_order byte_order)
3120 {
3121 struct bt_ctf_field_type_common_sequence *seq_ft = BT_CTF_FROM_COMMON(ft);
3122
3123 bt_ctf_field_type_common_set_byte_order(seq_ft->element_ft, byte_order);
3124 }
3125
3126
3127 int bt_ctf_field_type_common_integer_compare(struct bt_ctf_field_type_common *ft_a,
3128 struct bt_ctf_field_type_common *ft_b)
3129 {
3130 int ret = 1;
3131 struct bt_ctf_field_type_common_integer *int_ft_a = BT_CTF_FROM_COMMON(ft_a);
3132 struct bt_ctf_field_type_common_integer *int_ft_b = BT_CTF_FROM_COMMON(ft_b);
3133
3134 /* Length */
3135 if (int_ft_a->size != int_ft_b->size) {
3136 BT_LOGT("Integer field types differ: different sizes: "
3137 "ft-a-size=%u, ft-b-size=%u",
3138 int_ft_a->size, int_ft_b->size);
3139 goto end;
3140 }
3141
3142 /* Byte order */
3143 if (int_ft_a->user_byte_order != int_ft_b->user_byte_order) {
3144 BT_LOGT("Integer field types differ: different byte orders: "
3145 "ft-a-bo=%s, ft-b-bo=%s",
3146 bt_ctf_byte_order_string(int_ft_a->user_byte_order),
3147 bt_ctf_byte_order_string(int_ft_b->user_byte_order));
3148 goto end;
3149 }
3150
3151 /* Signedness */
3152 if (int_ft_a->is_signed != int_ft_b->is_signed) {
3153 BT_LOGT("Integer field types differ: different signedness: "
3154 "ft-a-is-signed=%d, ft-b-is-signed=%d",
3155 int_ft_a->is_signed,
3156 int_ft_b->is_signed);
3157 goto end;
3158 }
3159
3160 /* Base */
3161 if (int_ft_a->base != int_ft_b->base) {
3162 BT_LOGT("Integer field types differ: different bases: "
3163 "ft-a-base=%s, ft-b-base=%s",
3164 bt_ctf_integer_base_string(int_ft_a->base),
3165 bt_ctf_integer_base_string(int_ft_b->base));
3166 goto end;
3167 }
3168
3169 /* Encoding */
3170 if (int_ft_a->encoding != int_ft_b->encoding) {
3171 BT_LOGT("Integer field types differ: different encodings: "
3172 "ft-a-encoding=%s, ft-b-encoding=%s",
3173 bt_ctf_string_encoding_string(int_ft_a->encoding),
3174 bt_ctf_string_encoding_string(int_ft_b->encoding));
3175 goto end;
3176 }
3177
3178 /* Mapped clock class */
3179 if (int_ft_a->mapped_clock_class) {
3180 if (!int_ft_b->mapped_clock_class) {
3181 BT_LOGT_STR("Integer field types differ: field type A "
3182 "has a mapped clock class, but field type B "
3183 "does not.");
3184 goto end;
3185 }
3186
3187 if (bt_ctf_clock_class_compare(int_ft_a->mapped_clock_class,
3188 int_ft_b->mapped_clock_class) != 0) {
3189 BT_LOGT_STR("Integer field types differ: different "
3190 "mapped clock classes.");
3191 }
3192 } else {
3193 if (int_ft_b->mapped_clock_class) {
3194 BT_LOGT_STR("Integer field types differ: field type A "
3195 "has no description, but field type B has one.");
3196 goto end;
3197 }
3198 }
3199
3200 /* Equal */
3201 ret = 0;
3202
3203 end:
3204 return ret;
3205 }
3206
3207 int bt_ctf_field_type_common_floating_point_compare(
3208 struct bt_ctf_field_type_common *ft_a,
3209 struct bt_ctf_field_type_common *ft_b)
3210 {
3211 int ret = 1;
3212 struct bt_ctf_field_type_common_floating_point *flt_ft_a =
3213 BT_CTF_FROM_COMMON(ft_a);
3214 struct bt_ctf_field_type_common_floating_point *flt_ft_b =
3215 BT_CTF_FROM_COMMON(ft_b);
3216
3217 /* Byte order */
3218 if (flt_ft_a->user_byte_order != flt_ft_b->user_byte_order) {
3219 BT_LOGT("Floating point number field types differ: different byte orders: "
3220 "ft-a-bo=%s, ft-b-bo=%s",
3221 bt_ctf_byte_order_string(flt_ft_a->user_byte_order),
3222 bt_ctf_byte_order_string(flt_ft_b->user_byte_order));
3223 goto end;
3224 }
3225
3226 /* Exponent length */
3227 if (flt_ft_a->exp_dig != flt_ft_b->exp_dig) {
3228 BT_LOGT("Floating point number field types differ: different exponent sizes: "
3229 "ft-a-exp-size=%u, ft-b-exp-size=%u",
3230 flt_ft_a->exp_dig, flt_ft_b->exp_dig);
3231 goto end;
3232 }
3233
3234 /* Mantissa length */
3235 if (flt_ft_a->mant_dig != flt_ft_b->mant_dig) {
3236 BT_LOGT("Floating point number field types differ: different mantissa sizes: "
3237 "ft-a-mant-size=%u, ft-b-mant-size=%u",
3238 flt_ft_a->mant_dig, flt_ft_b->mant_dig);
3239 goto end;
3240 }
3241
3242 /* Equal */
3243 ret = 0;
3244
3245 end:
3246 return ret;
3247 }
3248
3249 static
3250 int compare_enumeration_mappings(struct bt_ctf_enumeration_mapping *mapping_a,
3251 struct bt_ctf_enumeration_mapping *mapping_b)
3252 {
3253 int ret = 1;
3254
3255 /* Label */
3256 if (mapping_a->string != mapping_b->string) {
3257 BT_LOGT("Enumeration field type mappings differ: different names: "
3258 "mapping-a-name=\"%s\", mapping-b-name=\"%s\"",
3259 g_quark_to_string(mapping_a->string),
3260 g_quark_to_string(mapping_b->string));
3261 goto end;
3262 }
3263
3264 /* Range start */
3265 if (mapping_a->range_start._unsigned !=
3266 mapping_b->range_start._unsigned) {
3267 BT_LOGT("Enumeration field type mappings differ: different starts of range: "
3268 "mapping-a-range-start-unsigned=%" PRIu64 ", "
3269 "mapping-b-range-start-unsigned=%" PRIu64,
3270 mapping_a->range_start._unsigned,
3271 mapping_b->range_start._unsigned);
3272 goto end;
3273 }
3274
3275 /* Range end */
3276 if (mapping_a->range_end._unsigned !=
3277 mapping_b->range_end._unsigned) {
3278 BT_LOGT("Enumeration field type mappings differ: different ends of range: "
3279 "mapping-a-range-end-unsigned=%" PRIu64 ", "
3280 "mapping-b-range-end-unsigned=%" PRIu64,
3281 mapping_a->range_end._unsigned,
3282 mapping_b->range_end._unsigned);
3283 goto end;
3284 }
3285
3286 /* Equal */
3287 ret = 0;
3288
3289 end:
3290 return ret;
3291 }
3292
3293 int bt_ctf_field_type_common_enumeration_compare_recursive(
3294 struct bt_ctf_field_type_common *ft_a,
3295 struct bt_ctf_field_type_common *ft_b)
3296 {
3297 int ret = 1;
3298 int i;
3299 struct bt_ctf_field_type_common_enumeration *enum_ft_a =
3300 BT_CTF_FROM_COMMON(ft_a);
3301 struct bt_ctf_field_type_common_enumeration *enum_ft_b =
3302 BT_CTF_FROM_COMMON(ft_b);
3303
3304 /* Container field type */
3305 ret = bt_ctf_field_type_common_compare(
3306 BT_CTF_TO_COMMON(enum_ft_a->container_ft),
3307 BT_CTF_TO_COMMON(enum_ft_b->container_ft));
3308 if (ret) {
3309 BT_LOGT("Enumeration field types differ: different container field types: "
3310 "ft-a-container-ft-addr=%p, ft-b-container-ft-addr=%p",
3311 enum_ft_a->container_ft, enum_ft_b->container_ft);
3312 goto end;
3313 }
3314
3315 ret = 1;
3316
3317 /* Entries */
3318 if (enum_ft_a->entries->len != enum_ft_b->entries->len) {
3319 goto end;
3320 }
3321
3322 for (i = 0; i < enum_ft_a->entries->len; ++i) {
3323 struct bt_ctf_enumeration_mapping *mapping_a =
3324 g_ptr_array_index(enum_ft_a->entries, i);
3325 struct bt_ctf_enumeration_mapping *mapping_b =
3326 g_ptr_array_index(enum_ft_b->entries, i);
3327
3328 if (compare_enumeration_mappings(mapping_a, mapping_b)) {
3329 BT_LOGT("Enumeration field types differ: different mappings: "
3330 "ft-a-mapping-addr=%p, ft-b-mapping-addr=%p, "
3331 "ft-a-mapping-name=\"%s\", ft-b-mapping-name=\"%s\"",
3332 mapping_a, mapping_b,
3333 g_quark_to_string(mapping_a->string),
3334 g_quark_to_string(mapping_b->string));
3335 goto end;
3336 }
3337 }
3338
3339 /* Equal */
3340 ret = 0;
3341
3342 end:
3343 return ret;
3344 }
3345
3346 int bt_ctf_field_type_common_string_compare(struct bt_ctf_field_type_common *ft_a,
3347 struct bt_ctf_field_type_common *ft_b)
3348 {
3349 int ret = 1;
3350 struct bt_ctf_field_type_common_string *string_ft_a = BT_CTF_FROM_COMMON(ft_a);
3351 struct bt_ctf_field_type_common_string *string_ft_b = BT_CTF_FROM_COMMON(ft_b);
3352
3353 /* Encoding */
3354 if (string_ft_a->encoding != string_ft_b->encoding) {
3355 BT_LOGT("String field types differ: different encodings: "
3356 "ft-a-encoding=%s, ft-b-encoding=%s",
3357 bt_ctf_string_encoding_string(string_ft_a->encoding),
3358 bt_ctf_string_encoding_string(string_ft_b->encoding));
3359 goto end;
3360 }
3361
3362 /* Equal */
3363 ret = 0;
3364
3365 end:
3366 return ret;
3367 }
3368
3369 static
3370 int compare_structure_variant_members(
3371 struct bt_ctf_field_type_common *member_a_ft,
3372 struct bt_ctf_field_type_common *member_b_ft,
3373 GQuark member_a_name, GQuark member_b_name)
3374 {
3375 int ret = 1;
3376
3377 /* Label */
3378 if (member_a_name != member_b_name) {
3379 BT_LOGT("Structure/variant field type fields differ: different names: "
3380 "field-a-name=%s, field-b-name=%s",
3381 g_quark_to_string(member_a_name),
3382 g_quark_to_string(member_b_name));
3383 goto end;
3384 }
3385
3386 /* Type */
3387 ret = bt_ctf_field_type_common_compare(member_a_ft, member_b_ft);
3388 if (ret == 1) {
3389 BT_LOGT("Structure/variant field type fields differ: different field types: "
3390 "field-name=\"%s\", field-a-ft-addr=%p, field-b-ft-addr=%p",
3391 g_quark_to_string(member_a_name),
3392 member_a_ft, member_b_ft);
3393 }
3394
3395 end:
3396 return ret;
3397 }
3398
3399 int bt_ctf_field_type_common_structure_compare_recursive(
3400 struct bt_ctf_field_type_common *ft_a,
3401 struct bt_ctf_field_type_common *ft_b)
3402 {
3403 int ret = 1;
3404 int i;
3405 struct bt_ctf_field_type_common_structure *struct_ft_a =
3406 BT_CTF_FROM_COMMON(ft_a);
3407 struct bt_ctf_field_type_common_structure *struct_ft_b =
3408 BT_CTF_FROM_COMMON(ft_b);
3409
3410 /* Alignment */
3411 if (bt_ctf_field_type_common_get_alignment(ft_a) !=
3412 bt_ctf_field_type_common_get_alignment(ft_b)) {
3413 BT_LOGT("Structure field types differ: different alignments: "
3414 "ft-a-align=%u, ft-b-align=%u",
3415 bt_ctf_field_type_common_get_alignment(ft_a),
3416 bt_ctf_field_type_common_get_alignment(ft_b));
3417 goto end;
3418 }
3419
3420 /* Fields */
3421 if (struct_ft_a->fields->len != struct_ft_b->fields->len) {
3422 BT_LOGT("Structure field types differ: different field counts: "
3423 "ft-a-field-count=%u, ft-b-field-count=%u",
3424 struct_ft_a->fields->len, struct_ft_b->fields->len);
3425 goto end;
3426 }
3427
3428 for (i = 0; i < struct_ft_a->fields->len; ++i) {
3429 struct bt_ctf_field_type_common_structure_field *field_a =
3430 BT_CTF_FIELD_TYPE_COMMON_STRUCTURE_FIELD_AT_INDEX(
3431 struct_ft_a, i);
3432 struct bt_ctf_field_type_common_structure_field *field_b =
3433 BT_CTF_FIELD_TYPE_COMMON_STRUCTURE_FIELD_AT_INDEX(
3434 struct_ft_b, i);
3435
3436 ret = compare_structure_variant_members(field_a->type,
3437 field_b->type, field_a->name, field_b->name);
3438 if (ret) {
3439 /* compare_structure_variant_members() logs what differs */
3440 BT_LOGT_STR("Structure field types differ: different fields.");
3441 goto end;
3442 }
3443 }
3444
3445 /* Equal */
3446 ret = 0;
3447
3448 end:
3449 return ret;
3450 }
3451
3452 int bt_ctf_field_type_common_variant_compare_recursive(
3453 struct bt_ctf_field_type_common *ft_a,
3454 struct bt_ctf_field_type_common *ft_b)
3455 {
3456 int ret = 1;
3457 int i;
3458 struct bt_ctf_field_type_common_variant *var_ft_a = BT_CTF_FROM_COMMON(ft_a);
3459 struct bt_ctf_field_type_common_variant *var_ft_b = BT_CTF_FROM_COMMON(ft_b);
3460
3461 /* Tag name */
3462 if (strcmp(var_ft_a->tag_name->str, var_ft_b->tag_name->str)) {
3463 BT_LOGT("Variant field types differ: different tag field names: "
3464 "ft-a-tag-field-name=\"%s\", ft-b-tag-field-name=\"%s\"",
3465 var_ft_a->tag_name->str, var_ft_b->tag_name->str);
3466 goto end;
3467 }
3468
3469 /* Tag type */
3470 ret = bt_ctf_field_type_common_compare(BT_CTF_TO_COMMON(var_ft_a->tag_ft),
3471 BT_CTF_TO_COMMON(var_ft_b->tag_ft));
3472 if (ret) {
3473 BT_LOGT("Variant field types differ: different tag field types: "
3474 "ft-a-tag-ft-addr=%p, ft-b-tag-ft-addr=%p",
3475 var_ft_a->tag_ft, var_ft_b->tag_ft);
3476 goto end;
3477 }
3478
3479 ret = 1;
3480
3481 /* Fields */
3482 if (var_ft_a->choices->len != var_ft_b->choices->len) {
3483 BT_LOGT("Variant field types differ: different field counts: "
3484 "ft-a-field-count=%u, ft-b-field-count=%u",
3485 var_ft_a->choices->len, var_ft_b->choices->len);
3486 goto end;
3487 }
3488
3489 for (i = 0; i < var_ft_a->choices->len; ++i) {
3490 struct bt_ctf_field_type_common_variant_choice *choice_a =
3491 BT_CTF_FIELD_TYPE_COMMON_VARIANT_CHOICE_AT_INDEX(
3492 var_ft_a, i);
3493 struct bt_ctf_field_type_common_variant_choice *choice_b =
3494 BT_CTF_FIELD_TYPE_COMMON_VARIANT_CHOICE_AT_INDEX(
3495 var_ft_b, i);
3496
3497 ret = compare_structure_variant_members(choice_a->type,
3498 choice_b->type, choice_a->name, choice_b->name);
3499 if (ret) {
3500 /* compare_structure_variant_members() logs what differs */
3501 BT_LOGT_STR("Variant field types differ: different fields.");
3502 goto end;
3503 }
3504 }
3505
3506 /* Equal */
3507 ret = 0;
3508
3509 end:
3510 return ret;
3511 }
3512
3513 int bt_ctf_field_type_common_array_compare_recursive(
3514 struct bt_ctf_field_type_common *ft_a,
3515 struct bt_ctf_field_type_common *ft_b)
3516 {
3517 int ret = 1;
3518 struct bt_ctf_field_type_common_array *array_ft_a = BT_CTF_FROM_COMMON(ft_a);
3519 struct bt_ctf_field_type_common_array *array_ft_b = BT_CTF_FROM_COMMON(ft_b);
3520
3521 /* Length */
3522 if (array_ft_a->length != array_ft_b->length) {
3523 BT_LOGT("Structure field types differ: different lengths: "
3524 "ft-a-length=%u, ft-b-length=%u",
3525 array_ft_a->length, array_ft_b->length);
3526 goto end;
3527 }
3528
3529 /* Element type */
3530 ret = bt_ctf_field_type_common_compare(array_ft_a->element_ft,
3531 array_ft_b->element_ft);
3532 if (ret == 1) {
3533 BT_LOGT("Array field types differ: different element field types: "
3534 "ft-a-element-ft-addr=%p, ft-b-element-ft-addr=%p",
3535 array_ft_a->element_ft, array_ft_b->element_ft);
3536 }
3537
3538 end:
3539 return ret;
3540 }
3541
3542 int bt_ctf_field_type_common_sequence_compare_recursive(
3543 struct bt_ctf_field_type_common *ft_a,
3544 struct bt_ctf_field_type_common *ft_b)
3545 {
3546 int ret = -1;
3547 struct bt_ctf_field_type_common_sequence *seq_ft_a = BT_CTF_FROM_COMMON(ft_a);
3548 struct bt_ctf_field_type_common_sequence *seq_ft_b = BT_CTF_FROM_COMMON(ft_b);
3549
3550 /* Length name */
3551 if (strcmp(seq_ft_a->length_field_name->str,
3552 seq_ft_b->length_field_name->str)) {
3553 BT_LOGT("Sequence field types differ: different length field names: "
3554 "ft-a-length-field-name=\"%s\", "
3555 "ft-b-length-field-name=\"%s\"",
3556 seq_ft_a->length_field_name->str,
3557 seq_ft_b->length_field_name->str);
3558 goto end;
3559 }
3560
3561 /* Element type */
3562 ret = bt_ctf_field_type_common_compare(seq_ft_a->element_ft,
3563 seq_ft_b->element_ft);
3564 if (ret == 1) {
3565 BT_LOGT("Sequence field types differ: different element field types: "
3566 "ft-a-element-ft-addr=%p, ft-b-element-ft-addr=%p",
3567 seq_ft_a->element_ft, seq_ft_b->element_ft);
3568 }
3569
3570 end:
3571 return ret;
3572 }
3573
3574 int bt_ctf_field_type_common_compare(struct bt_ctf_field_type_common *ft_a,
3575 struct bt_ctf_field_type_common *ft_b)
3576 {
3577 int ret = 1;
3578
3579 BT_CTF_ASSERT_PRE_NON_NULL(ft_a, "Field type A");
3580 BT_CTF_ASSERT_PRE_NON_NULL(ft_b, "Field type B");
3581
3582 if (ft_a == ft_b) {
3583 /* Same reference: equal (even if both are NULL) */
3584 ret = 0;
3585 goto end;
3586 }
3587
3588 if (!ft_a) {
3589 BT_LOGW_STR("Invalid parameter: field type A is NULL.");
3590 ret = -1;
3591 goto end;
3592 }
3593
3594 if (!ft_b) {
3595 BT_LOGW_STR("Invalid parameter: field type B is NULL.");
3596 ret = -1;
3597 goto end;
3598 }
3599
3600 if (ft_a->id != ft_b->id) {
3601 /* Different type IDs */
3602 BT_LOGT("Field types differ: different IDs: "
3603 "ft-a-addr=%p, ft-b-addr=%p, "
3604 "ft-a-id=%s, ft-b-id=%s",
3605 ft_a, ft_b,
3606 bt_ctf_field_type_id_string(ft_a->id),
3607 bt_ctf_field_type_id_string(ft_b->id));
3608 goto end;
3609 }
3610
3611 if (ft_a->id == BT_CTF_FIELD_TYPE_ID_UNKNOWN) {
3612 /* Both have unknown type IDs */
3613 BT_LOGW_STR("Invalid parameter: field type IDs are unknown.");
3614 goto end;
3615 }
3616
3617 BT_ASSERT_DBG(ft_a->methods->compare);
3618 ret = ft_a->methods->compare(ft_a, ft_b);
3619 if (ret == 1) {
3620 BT_LOGT("Field types differ: ft-a-addr=%p, ft-b-addr=%p",
3621 ft_a, ft_b);
3622 }
3623
3624 end:
3625 return ret;
3626 }
3627
3628 int64_t bt_ctf_field_type_common_get_field_count(struct bt_ctf_field_type_common *ft)
3629 {
3630 int64_t field_count = -1;
3631
3632 switch (ft->id) {
3633 case BT_CTF_FIELD_TYPE_ID_STRUCT:
3634 field_count =
3635 bt_ctf_field_type_common_structure_get_field_count(ft);
3636 break;
3637 case BT_CTF_FIELD_TYPE_ID_VARIANT:
3638 field_count =
3639 bt_ctf_field_type_common_variant_get_field_count(ft);
3640 break;
3641 case BT_CTF_FIELD_TYPE_ID_ARRAY:
3642 case BT_CTF_FIELD_TYPE_ID_SEQUENCE:
3643 /*
3644 * Array and sequence types always contain a single member
3645 * (the element type).
3646 */
3647 field_count = 1;
3648 break;
3649 default:
3650 break;
3651 }
3652
3653 return field_count;
3654 }
3655
3656 struct bt_ctf_field_type_common *bt_ctf_field_type_common_borrow_field_at_index(
3657 struct bt_ctf_field_type_common *ft, int index)
3658 {
3659 struct bt_ctf_field_type_common *field_type = NULL;
3660
3661 switch (ft->id) {
3662 case BT_CTF_FIELD_TYPE_ID_STRUCT:
3663 {
3664 int ret = bt_ctf_field_type_common_structure_borrow_field_by_index(
3665 ft, NULL, &field_type, index);
3666 if (ret) {
3667 field_type = NULL;
3668 goto end;
3669 }
3670 break;
3671 }
3672 case BT_CTF_FIELD_TYPE_ID_VARIANT:
3673 {
3674 int ret = bt_ctf_field_type_common_variant_borrow_field_by_index(
3675 ft, NULL, &field_type, index);
3676 if (ret) {
3677 field_type = NULL;
3678 goto end;
3679 }
3680 break;
3681 }
3682 case BT_CTF_FIELD_TYPE_ID_ARRAY:
3683 field_type =
3684 bt_ctf_field_type_common_array_borrow_element_field_type(ft);
3685 break;
3686 case BT_CTF_FIELD_TYPE_ID_SEQUENCE:
3687 field_type =
3688 bt_ctf_field_type_common_sequence_borrow_element_field_type(ft);
3689 break;
3690 default:
3691 break;
3692 }
3693
3694 end:
3695 return field_type;
3696 }
3697
3698 int bt_ctf_field_type_common_get_field_index(struct bt_ctf_field_type_common *ft,
3699 const char *name)
3700 {
3701 int field_index = -1;
3702
3703 switch (ft->id) {
3704 case BT_CTF_FIELD_TYPE_ID_STRUCT:
3705 field_index = bt_ctf_field_type_common_structure_get_field_name_index(
3706 ft, name);
3707 break;
3708 case BT_CTF_FIELD_TYPE_ID_VARIANT:
3709 field_index = bt_ctf_field_type_common_variant_get_field_name_index(
3710 ft, name);
3711 break;
3712 default:
3713 break;
3714 }
3715
3716 return field_index;
3717 }
3718
3719 struct bt_ctf_field_path *bt_ctf_field_type_common_variant_borrow_tag_field_path(
3720 struct bt_ctf_field_type_common *ft)
3721 {
3722 struct bt_ctf_field_type_common_variant *var_ft = BT_CTF_FROM_COMMON(ft);
3723
3724 BT_CTF_ASSERT_PRE_NON_NULL(ft, "Field type");
3725 BT_CTF_ASSERT_PRE_CTF_FT_COMMON_HAS_ID(ft, BT_CTF_FIELD_TYPE_ID_VARIANT,
3726 "Field type");
3727 return var_ft->tag_field_path;
3728 }
3729
3730 struct bt_ctf_field_path *bt_ctf_field_type_common_sequence_borrow_length_field_path(
3731 struct bt_ctf_field_type_common *ft)
3732 {
3733 struct bt_ctf_field_type_common_sequence *seq_ft = BT_CTF_FROM_COMMON(ft);
3734
3735 BT_CTF_ASSERT_PRE_NON_NULL(ft, "Field type");
3736 BT_CTF_ASSERT_PRE_CTF_FT_COMMON_HAS_ID(ft, BT_CTF_FIELD_TYPE_ID_SEQUENCE,
3737 "Field type");
3738 return seq_ft->length_field_path;
3739 }
3740
3741 int bt_ctf_field_type_common_validate_single_clock_class(
3742 struct bt_ctf_field_type_common *ft,
3743 struct bt_ctf_clock_class **expected_clock_class)
3744 {
3745 int ret = 0;
3746
3747 if (!ft) {
3748 goto end;
3749 }
3750
3751 BT_ASSERT_DBG(expected_clock_class);
3752
3753 switch (ft->id) {
3754 case BT_CTF_FIELD_TYPE_ID_INTEGER:
3755 {
3756 struct bt_ctf_clock_class *mapped_clock_class =
3757 bt_ctf_field_type_common_integer_borrow_mapped_clock_class(ft);
3758
3759 if (!mapped_clock_class) {
3760 goto end;
3761 }
3762
3763 if (!*expected_clock_class) {
3764 /* Move reference to output parameter */
3765 *expected_clock_class = bt_ctf_object_get_ref(mapped_clock_class);
3766 mapped_clock_class = NULL;
3767 BT_LOGT("Setting expected clock class: "
3768 "expected-clock-class-addr=%p",
3769 *expected_clock_class);
3770 } else {
3771 if (mapped_clock_class != *expected_clock_class) {
3772 BT_LOGW("Integer field type is not mapped to "
3773 "the expected clock class: "
3774 "mapped-clock-class-addr=%p, "
3775 "mapped-clock-class-name=\"%s\", "
3776 "expected-clock-class-addr=%p, "
3777 "expected-clock-class-name=\"%s\"",
3778 mapped_clock_class,
3779 bt_ctf_clock_class_get_name(mapped_clock_class),
3780 *expected_clock_class,
3781 bt_ctf_clock_class_get_name(*expected_clock_class));
3782 bt_ctf_object_put_ref(mapped_clock_class);
3783 ret = -1;
3784 goto end;
3785 }
3786 }
3787
3788 break;
3789 }
3790 case BT_CTF_FIELD_TYPE_ID_ENUM:
3791 case BT_CTF_FIELD_TYPE_ID_ARRAY:
3792 case BT_CTF_FIELD_TYPE_ID_SEQUENCE:
3793 {
3794 struct bt_ctf_field_type_common *sub_ft = NULL;
3795
3796 switch (ft->id) {
3797 case BT_CTF_FIELD_TYPE_ID_ENUM:
3798 sub_ft = bt_ctf_field_type_common_enumeration_borrow_container_field_type(
3799 ft);
3800 break;
3801 case BT_CTF_FIELD_TYPE_ID_ARRAY:
3802 sub_ft = bt_ctf_field_type_common_array_borrow_element_field_type(
3803 ft);
3804 break;
3805 case BT_CTF_FIELD_TYPE_ID_SEQUENCE:
3806 sub_ft = bt_ctf_field_type_common_sequence_borrow_element_field_type(
3807 ft);
3808 break;
3809 default:
3810 BT_LOGF("Unexpected field type ID: id=%d", ft->id);
3811 bt_common_abort();
3812 }
3813
3814 BT_ASSERT_DBG(sub_ft);
3815 ret = bt_ctf_field_type_common_validate_single_clock_class(sub_ft,
3816 expected_clock_class);
3817 break;
3818 }
3819 case BT_CTF_FIELD_TYPE_ID_STRUCT:
3820 {
3821 uint64_t i;
3822 int64_t count = bt_ctf_field_type_common_structure_get_field_count(
3823 ft);
3824
3825 for (i = 0; i < count; i++) {
3826 const char *name;
3827 struct bt_ctf_field_type_common *member_type;
3828
3829 ret = bt_ctf_field_type_common_structure_borrow_field_by_index(
3830 ft, &name, &member_type, i);
3831 BT_ASSERT_DBG(ret == 0);
3832 ret = bt_ctf_field_type_common_validate_single_clock_class(
3833 member_type, expected_clock_class);
3834 if (ret) {
3835 BT_LOGW("Structure field type's field's type "
3836 "is not recursively mapped to the "
3837 "expected clock class: "
3838 "field-ft-addr=%p, field-name=\"%s\"",
3839 member_type, name);
3840 goto end;
3841 }
3842 }
3843 break;
3844 }
3845 case BT_CTF_FIELD_TYPE_ID_VARIANT:
3846 {
3847 uint64_t i;
3848 int64_t count = bt_ctf_field_type_common_variant_get_field_count(
3849 ft);
3850
3851 for (i = 0; i < count; i++) {
3852 const char *name;
3853 struct bt_ctf_field_type_common *member_type;
3854
3855 ret = bt_ctf_field_type_common_variant_borrow_field_by_index(
3856 ft, &name, &member_type, i);
3857 BT_ASSERT_DBG(ret == 0);
3858 ret = bt_ctf_field_type_common_validate_single_clock_class(
3859 member_type, expected_clock_class);
3860 if (ret) {
3861 BT_LOGW("Variant field type's field's type "
3862 "is not recursively mapped to the "
3863 "expected clock class: "
3864 "field-ft-addr=%p, field-name=\"%s\"",
3865 member_type, name);
3866 goto end;
3867 }
3868 }
3869 break;
3870 }
3871 default:
3872 break;
3873 }
3874
3875 end:
3876 return ret;
3877 }
3878
3879 static
3880 struct bt_ctf_field_type *bt_ctf_field_type_integer_copy(
3881 struct bt_ctf_field_type *ft);
3882
3883 static
3884 struct bt_ctf_field_type *bt_ctf_field_type_enumeration_copy_recursive(
3885 struct bt_ctf_field_type *ft);
3886
3887 static
3888 struct bt_ctf_field_type *bt_ctf_field_type_floating_point_copy(
3889 struct bt_ctf_field_type *ft);
3890
3891 static
3892 struct bt_ctf_field_type *bt_ctf_field_type_structure_copy_recursive(
3893 struct bt_ctf_field_type *ft);
3894
3895 static
3896 struct bt_ctf_field_type *bt_ctf_field_type_variant_copy_recursive(
3897 struct bt_ctf_field_type *ft);
3898
3899 static
3900 struct bt_ctf_field_type *bt_ctf_field_type_array_copy_recursive(
3901 struct bt_ctf_field_type *ft);
3902
3903 static
3904 struct bt_ctf_field_type *bt_ctf_field_type_sequence_copy_recursive(
3905 struct bt_ctf_field_type *type);
3906
3907 static
3908 struct bt_ctf_field_type *bt_ctf_field_type_string_copy(
3909 struct bt_ctf_field_type *type);
3910
3911 static struct bt_ctf_field_type_common_methods bt_ctf_field_type_integer_methods = {
3912 .freeze = bt_ctf_field_type_common_generic_freeze,
3913 .validate = bt_ctf_field_type_common_integer_validate,
3914 .set_byte_order = bt_ctf_field_type_common_integer_set_byte_order,
3915 .copy = (bt_ctf_field_type_common_method_copy)
3916 bt_ctf_field_type_integer_copy,
3917 .compare = bt_ctf_field_type_common_integer_compare,
3918 };
3919
3920 static struct bt_ctf_field_type_common_methods bt_ctf_field_type_floating_point_methods = {
3921 .freeze = bt_ctf_field_type_common_generic_freeze,
3922 .validate = NULL,
3923 .set_byte_order = bt_ctf_field_type_common_floating_point_set_byte_order,
3924 .copy = (bt_ctf_field_type_common_method_copy)
3925 bt_ctf_field_type_floating_point_copy,
3926 .compare = bt_ctf_field_type_common_floating_point_compare,
3927 };
3928
3929 static struct bt_ctf_field_type_common_methods bt_ctf_field_type_enumeration_methods = {
3930 .freeze = bt_ctf_field_type_common_enumeration_freeze_recursive,
3931 .validate = bt_ctf_field_type_common_enumeration_validate_recursive,
3932 .set_byte_order = bt_ctf_field_type_common_enumeration_set_byte_order_recursive,
3933 .copy = (bt_ctf_field_type_common_method_copy)
3934 bt_ctf_field_type_enumeration_copy_recursive,
3935 .compare = bt_ctf_field_type_common_enumeration_compare_recursive,
3936 };
3937
3938 static struct bt_ctf_field_type_common_methods bt_ctf_field_type_string_methods = {
3939 .freeze = bt_ctf_field_type_common_generic_freeze,
3940 .validate = NULL,
3941 .set_byte_order = NULL,
3942 .copy = (bt_ctf_field_type_common_method_copy)
3943 bt_ctf_field_type_string_copy,
3944 .compare = bt_ctf_field_type_common_string_compare,
3945 };
3946
3947 static struct bt_ctf_field_type_common_methods bt_ctf_field_type_array_methods = {
3948 .freeze = bt_ctf_field_type_common_array_freeze_recursive,
3949 .validate = bt_ctf_field_type_common_array_validate_recursive,
3950 .set_byte_order = bt_ctf_field_type_common_array_set_byte_order_recursive,
3951 .copy = (bt_ctf_field_type_common_method_copy)
3952 bt_ctf_field_type_array_copy_recursive,
3953 .compare = bt_ctf_field_type_common_array_compare_recursive,
3954 };
3955
3956 static struct bt_ctf_field_type_common_methods bt_ctf_field_type_sequence_methods = {
3957 .freeze = bt_ctf_field_type_common_sequence_freeze_recursive,
3958 .validate = bt_ctf_field_type_common_sequence_validate_recursive,
3959 .set_byte_order = bt_ctf_field_type_common_sequence_set_byte_order_recursive,
3960 .copy = (bt_ctf_field_type_common_method_copy)
3961 bt_ctf_field_type_sequence_copy_recursive,
3962 .compare = bt_ctf_field_type_common_sequence_compare_recursive,
3963 };
3964
3965 static struct bt_ctf_field_type_common_methods bt_ctf_field_type_structure_methods = {
3966 .freeze = bt_ctf_field_type_common_structure_freeze_recursive,
3967 .validate = bt_ctf_field_type_common_structure_validate_recursive,
3968 .set_byte_order = bt_ctf_field_type_common_structure_set_byte_order_recursive,
3969 .copy = (bt_ctf_field_type_common_method_copy)
3970 bt_ctf_field_type_structure_copy_recursive,
3971 .compare = bt_ctf_field_type_common_structure_compare_recursive,
3972 };
3973
3974 static struct bt_ctf_field_type_common_methods bt_ctf_field_type_variant_methods = {
3975 .freeze = bt_ctf_field_type_common_variant_freeze_recursive,
3976 .validate = bt_ctf_field_type_common_variant_validate_recursive,
3977 .set_byte_order = bt_ctf_field_type_common_variant_set_byte_order_recursive,
3978 .copy = (bt_ctf_field_type_common_method_copy)
3979 bt_ctf_field_type_variant_copy_recursive,
3980 .compare = bt_ctf_field_type_common_variant_compare_recursive,
3981 };
3982
3983 typedef int (*bt_ctf_field_type_serialize_func)(struct bt_ctf_field_type_common *,
3984 struct metadata_context *);
3985
3986 int bt_ctf_field_type_serialize_recursive(struct bt_ctf_field_type *type,
3987 struct metadata_context *context)
3988 {
3989 int ret;
3990 struct bt_ctf_field_type_common *type_common = (void *) type;
3991 bt_ctf_field_type_serialize_func serialize_func;
3992
3993 BT_ASSERT_DBG(type);
3994 BT_ASSERT_DBG(context);
3995
3996 /* Make sure field type is valid before serializing it */
3997 ret = bt_ctf_field_type_common_validate((void *) type);
3998 if (ret) {
3999 BT_LOGW("Cannot serialize field type's metadata: field type is invalid: "
4000 "addr=%p", type);
4001 goto end;
4002 }
4003
4004 serialize_func = type_common->spec.writer.serialize_func;
4005 ret = serialize_func((void *) type, context);
4006
4007 end:
4008 return ret;
4009 }
4010
4011 static
4012 const char *get_encoding_string(enum bt_ctf_string_encoding encoding)
4013 {
4014 const char *encoding_string;
4015
4016 switch (encoding) {
4017 case BT_CTF_STRING_ENCODING_NONE:
4018 encoding_string = "none";
4019 break;
4020 case BT_CTF_STRING_ENCODING_ASCII:
4021 encoding_string = "ASCII";
4022 break;
4023 case BT_CTF_STRING_ENCODING_UTF8:
4024 encoding_string = "UTF8";
4025 break;
4026 default:
4027 encoding_string = "unknown";
4028 break;
4029 }
4030
4031 return encoding_string;
4032 }
4033
4034 static
4035 const char *get_integer_base_string(enum bt_ctf_integer_base base)
4036 {
4037 const char *base_string;
4038
4039 switch (base) {
4040 case BT_CTF_INTEGER_BASE_DECIMAL:
4041 case BT_CTF_INTEGER_BASE_UNSPECIFIED:
4042 base_string = "decimal";
4043 break;
4044 case BT_CTF_INTEGER_BASE_HEXADECIMAL:
4045 base_string = "hexadecimal";
4046 break;
4047 case BT_CTF_INTEGER_BASE_OCTAL:
4048 base_string = "octal";
4049 break;
4050 case BT_CTF_INTEGER_BASE_BINARY:
4051 base_string = "binary";
4052 break;
4053 default:
4054 base_string = "unknown";
4055 break;
4056 }
4057
4058 return base_string;
4059 }
4060
4061 static
4062 void append_field_name(struct metadata_context *context,
4063 const char *name)
4064 {
4065 g_string_append_c(context->string, ' ');
4066
4067 if (!bt_ctf_identifier_is_valid(name) || *name == '_') {
4068 g_string_append_c(context->string, '_');
4069 }
4070
4071 g_string_append(context->string, name);
4072 }
4073
4074 static
4075 int bt_ctf_field_type_integer_serialize(struct bt_ctf_field_type_common *type,
4076 struct metadata_context *context)
4077 {
4078 struct bt_ctf_field_type_common_integer *integer = BT_CTF_FROM_COMMON(type);
4079 int ret = 0;
4080
4081 BT_LOGD("Serializing CTF writer integer field type's metadata: "
4082 "ft-addr=%p, metadata-context-addr=%p", type, context);
4083 g_string_append_printf(context->string,
4084 "integer { size = %u; align = %u; signed = %s; encoding = %s; base = %s; byte_order = %s",
4085 integer->size, type->alignment,
4086 (integer->is_signed ? "true" : "false"),
4087 get_encoding_string(integer->encoding),
4088 get_integer_base_string(integer->base),
4089 bt_ctf_get_byte_order_string(integer->user_byte_order));
4090 if (integer->mapped_clock_class) {
4091 const char *clock_name = bt_ctf_clock_class_get_name(
4092 integer->mapped_clock_class);
4093
4094 BT_ASSERT_DBG(clock_name);
4095 g_string_append_printf(context->string,
4096 "; map = clock.%s.value", clock_name);
4097 }
4098
4099 g_string_append(context->string, "; }");
4100 return ret;
4101 }
4102
4103 static
4104 int bt_ctf_field_type_enumeration_serialize_recursive(
4105 struct bt_ctf_field_type_common *type,
4106 struct metadata_context *context)
4107 {
4108 size_t entry;
4109 int ret;
4110 struct bt_ctf_field_type_common_enumeration *enumeration =
4111 BT_CTF_FROM_COMMON(type);
4112 struct bt_ctf_field_type_common *container_type;
4113 int container_signed;
4114
4115 BT_LOGD("Serializing CTF writer enumeration field type's metadata: "
4116 "ft-addr=%p, metadata-context-addr=%p", type, context);
4117 container_type =
4118 bt_ctf_field_type_common_enumeration_borrow_container_field_type(type);
4119 BT_ASSERT_DBG(container_type);
4120 container_signed = bt_ctf_field_type_common_integer_is_signed(
4121 container_type);
4122 BT_ASSERT_DBG(container_signed >= 0);
4123 g_string_append(context->string, "enum : ");
4124 BT_LOGD_STR("Serializing CTF writer enumeration field type's container field type's metadata.");
4125 ret = bt_ctf_field_type_serialize_recursive(
4126 (void *) enumeration->container_ft, context);
4127 if (ret) {
4128 BT_LOGW("Cannot serialize CTF writer enumeration field type's container field type's metadata: "
4129 "container-ft-addr=%p", enumeration->container_ft);
4130 goto end;
4131 }
4132
4133 g_string_append(context->string, " { ");
4134 for (entry = 0; entry < enumeration->entries->len; entry++) {
4135 struct bt_ctf_enumeration_mapping *mapping =
4136 enumeration->entries->pdata[entry];
4137 const char *label = g_quark_to_string(mapping->string);
4138
4139 g_string_append(context->string, "\"");
4140
4141 if (!bt_ctf_identifier_is_valid(label) || label[0] == '_') {
4142 g_string_append(context->string, "_");
4143 }
4144
4145 g_string_append_printf(context->string, "%s\" = ", label);
4146
4147 if (container_signed) {
4148 if (mapping->range_start._signed ==
4149 mapping->range_end._signed) {
4150 g_string_append_printf(context->string,
4151 "%" PRId64,
4152 mapping->range_start._signed);
4153 } else {
4154 g_string_append_printf(context->string,
4155 "%" PRId64 " ... %" PRId64,
4156 mapping->range_start._signed,
4157 mapping->range_end._signed);
4158 }
4159 } else {
4160 if (mapping->range_start._unsigned ==
4161 mapping->range_end._unsigned) {
4162 g_string_append_printf(context->string,
4163 "%" PRIu64,
4164 mapping->range_start._unsigned);
4165 } else {
4166 g_string_append_printf(context->string,
4167 "%" PRIu64 " ... %" PRIu64,
4168 mapping->range_start._unsigned,
4169 mapping->range_end._unsigned);
4170 }
4171 }
4172
4173 g_string_append(context->string,
4174 ((entry != (enumeration->entries->len - 1)) ?
4175 ", " : " }"));
4176 }
4177
4178 if (context->field_name->len) {
4179 append_field_name(context,
4180 context->field_name->str);
4181 g_string_assign(context->field_name, "");
4182 }
4183
4184 end:
4185 return ret;
4186 }
4187
4188 static
4189 int bt_ctf_field_type_floating_point_serialize(struct bt_ctf_field_type_common *type,
4190 struct metadata_context *context)
4191 {
4192 struct bt_ctf_field_type_common_floating_point *floating_point =
4193 BT_CTF_FROM_COMMON(type);
4194
4195 BT_LOGD("Serializing CTF writer floating point number field type's metadata: "
4196 "ft-addr=%p, metadata-context-addr=%p", type, context);
4197 g_string_append_printf(context->string,
4198 "floating_point { exp_dig = %u; mant_dig = %u; byte_order = %s; align = %u; }",
4199 floating_point->exp_dig,
4200 floating_point->mant_dig,
4201 bt_ctf_get_byte_order_string(floating_point->user_byte_order),
4202 type->alignment);
4203 return 0;
4204 }
4205
4206 static
4207 int bt_ctf_field_type_structure_serialize_recursive(
4208 struct bt_ctf_field_type_common *type,
4209 struct metadata_context *context)
4210 {
4211 size_t i;
4212 unsigned int indent;
4213 int ret = 0;
4214 struct bt_ctf_field_type_common_structure *structure = BT_CTF_FROM_COMMON(type);
4215 GString *structure_field_name = context->field_name;
4216
4217 BT_LOGD("Serializing CTF writer structure field type's metadata: "
4218 "ft-addr=%p, metadata-context-addr=%p", type, context);
4219 context->field_name = g_string_new("");
4220
4221 context->current_indentation_level++;
4222 g_string_append(context->string, "struct {\n");
4223
4224 for (i = 0; i < structure->fields->len; i++) {
4225 struct bt_ctf_field_type_common_structure_field *field =
4226 BT_CTF_FIELD_TYPE_COMMON_STRUCTURE_FIELD_AT_INDEX(
4227 structure, i);
4228
4229 BT_LOGD("Serializing CTF writer structure field type's field metadata: "
4230 "index=%zu, "
4231 "field-ft-addr=%p, field-name=\"%s\"",
4232 i, field, g_quark_to_string(field->name));
4233
4234 for (indent = 0; indent < context->current_indentation_level;
4235 indent++) {
4236 g_string_append_c(context->string, '\t');
4237 }
4238
4239 g_string_assign(context->field_name,
4240 g_quark_to_string(field->name));
4241 ret = bt_ctf_field_type_serialize_recursive(
4242 (void *) field->type, context);
4243 if (ret) {
4244 BT_LOGW("Cannot serialize CTF writer structure field type's field's metadata: "
4245 "index=%zu, "
4246 "field-ft-addr=%p, field-name=\"%s\"",
4247 i, field->type,
4248 g_quark_to_string(field->name));
4249 goto end;
4250 }
4251
4252 if (context->field_name->len) {
4253 append_field_name(context,
4254 context->field_name->str);
4255 }
4256 g_string_append(context->string, ";\n");
4257 }
4258
4259 context->current_indentation_level--;
4260 for (indent = 0; indent < context->current_indentation_level;
4261 indent++) {
4262 g_string_append_c(context->string, '\t');
4263 }
4264
4265 g_string_append_printf(context->string, "} align(%u)",
4266 type->alignment);
4267
4268 end:
4269 g_string_free(context->field_name, TRUE);
4270 context->field_name = structure_field_name;
4271 return ret;
4272 }
4273
4274 static
4275 int bt_ctf_field_type_variant_serialize_recursive(
4276 struct bt_ctf_field_type_common *type,
4277 struct metadata_context *context)
4278 {
4279 size_t i;
4280 unsigned int indent;
4281 int ret = 0;
4282 struct bt_ctf_field_type_common_variant *variant = BT_CTF_FROM_COMMON(type);
4283 GString *variant_field_name = context->field_name;
4284
4285 BT_LOGD("Serializing CTF writer variant field type's metadata: "
4286 "ft-addr=%p, metadata-context-addr=%p", type, context);
4287 context->field_name = g_string_new("");
4288 if (variant->tag_name->len > 0) {
4289 g_string_append(context->string, "variant <");
4290 append_field_name(context, variant->tag_name->str);
4291 g_string_append(context->string, "> {\n");
4292 } else {
4293 g_string_append(context->string, "variant {\n");
4294 }
4295
4296 context->current_indentation_level++;
4297 for (i = 0; i < variant->choices->len; i++) {
4298 struct bt_ctf_field_type_common_variant_choice *field =
4299 BT_CTF_FIELD_TYPE_COMMON_VARIANT_CHOICE_AT_INDEX(
4300 variant, i);
4301
4302 BT_LOGD("Serializing CTF writer variant field type's field metadata: "
4303 "index=%zu, "
4304 "field-ft-addr=%p, field-name=\"%s\"",
4305 i, field, g_quark_to_string(field->name));
4306
4307 g_string_assign(context->field_name,
4308 g_quark_to_string(field->name));
4309 for (indent = 0; indent < context->current_indentation_level;
4310 indent++) {
4311 g_string_append_c(context->string, '\t');
4312 }
4313
4314 g_string_assign(context->field_name,
4315 g_quark_to_string(field->name));
4316 ret = bt_ctf_field_type_serialize_recursive(
4317 (void *) field->type, context);
4318 if (ret) {
4319 BT_LOGW("Cannot serialize CTF writer variant field type's field's metadata: "
4320 "index=%zu, "
4321 "field-ft-addr=%p, field-name=\"%s\"",
4322 i, field->type,
4323 g_quark_to_string(field->name));
4324 goto end;
4325 }
4326
4327 if (context->field_name->len) {
4328 append_field_name(context,
4329 context->field_name->str);
4330 g_string_append_c(context->string, ';');
4331 }
4332
4333 g_string_append_c(context->string, '\n');
4334 }
4335
4336 context->current_indentation_level--;
4337 for (indent = 0; indent < context->current_indentation_level;
4338 indent++) {
4339 g_string_append_c(context->string, '\t');
4340 }
4341
4342 g_string_append(context->string, "}");
4343
4344 end:
4345 g_string_free(context->field_name, TRUE);
4346 context->field_name = variant_field_name;
4347 return ret;
4348 }
4349
4350 static
4351 int bt_ctf_field_type_array_serialize_recursive(
4352 struct bt_ctf_field_type_common *type,
4353 struct metadata_context *context)
4354 {
4355 int ret = 0;
4356 struct bt_ctf_field_type_common_array *array = BT_CTF_FROM_COMMON(type);
4357
4358 BT_LOGD("Serializing CTF writer array field type's metadata: "
4359 "ft-addr=%p, metadata-context-addr=%p", type, context);
4360 BT_LOGD_STR("Serializing CTF writer array field type's element field type's metadata.");
4361 ret = bt_ctf_field_type_serialize_recursive(
4362 (void *) array->element_ft, context);
4363 if (ret) {
4364 BT_LOGW("Cannot serialize CTF writer array field type's element field type's metadata: "
4365 "element-ft-addr=%p", array->element_ft);
4366 goto end;
4367 }
4368
4369 if (context->field_name->len) {
4370 append_field_name(context,
4371 context->field_name->str);
4372
4373 g_string_append_printf(context->string, "[%u]", array->length);
4374 g_string_assign(context->field_name, "");
4375 } else {
4376 g_string_append_printf(context->string, "[%u]", array->length);
4377 }
4378
4379 end:
4380 return ret;
4381 }
4382
4383 static
4384 int bt_ctf_field_type_sequence_serialize_recursive(
4385 struct bt_ctf_field_type_common *type,
4386 struct metadata_context *context)
4387 {
4388 int ret = 0;
4389 struct bt_ctf_field_type_common_sequence *sequence = BT_CTF_FROM_COMMON(type);
4390
4391 BT_LOGD("Serializing CTF writer sequence field type's metadata: "
4392 "ft-addr=%p, metadata-context-addr=%p", type, context);
4393 BT_LOGD_STR("Serializing CTF writer sequence field type's element field type's metadata.");
4394 ret = bt_ctf_field_type_serialize_recursive(
4395 (void *) sequence->element_ft, context);
4396 if (ret) {
4397 BT_LOGW("Cannot serialize CTF writer sequence field type's element field type's metadata: "
4398 "element-ft-addr=%p", sequence->element_ft);
4399 goto end;
4400 }
4401
4402 if (context->field_name->len) {
4403 append_field_name(context, context->field_name->str);
4404 g_string_assign(context->field_name, "");
4405 }
4406 g_string_append(context->string, "[");
4407 append_field_name(context, sequence->length_field_name->str);
4408 g_string_append(context->string, "]");
4409
4410 end:
4411 return ret;
4412 }
4413
4414 static
4415 int bt_ctf_field_type_string_serialize(struct bt_ctf_field_type_common *type,
4416 struct metadata_context *context)
4417 {
4418 struct bt_ctf_field_type_common_string *string = BT_CTF_FROM_COMMON(type);
4419
4420 BT_LOGD("Serializing CTF writer string field type's metadata: "
4421 "ft-addr=%p, metadata-context-addr=%p", type, context);
4422 g_string_append_printf(context->string,
4423 "string { encoding = %s; }",
4424 get_encoding_string(string->encoding));
4425 return 0;
4426 }
4427
4428 BT_EXPORT
4429 struct bt_ctf_field_type *bt_ctf_field_type_integer_create(unsigned int size)
4430 {
4431 struct bt_ctf_field_type_common_integer *integer = NULL;
4432
4433 BT_LOGD("Creating CTF writer integer field type object: size=%u", size);
4434
4435 if (size == 0 || size > 64) {
4436 BT_LOGW("Invalid parameter: size must be between 1 and 64: "
4437 "size=%u", size);
4438 goto error;
4439 }
4440
4441 integer = g_new0(struct bt_ctf_field_type_common_integer, 1);
4442 if (!integer) {
4443 BT_LOGE_STR("Failed to allocate one integer field type.");
4444 goto error;
4445 }
4446
4447 bt_ctf_field_type_common_integer_initialize(BT_CTF_TO_COMMON(integer),
4448 size, bt_ctf_field_type_common_integer_destroy,
4449 &bt_ctf_field_type_integer_methods);
4450 integer->common.spec.writer.serialize_func =
4451 bt_ctf_field_type_integer_serialize;
4452 BT_LOGD("Created CTF writer integer field type object: addr=%p, size=%u",
4453 integer, size);
4454 goto end;
4455
4456 error:
4457 BT_CTF_OBJECT_PUT_REF_AND_RESET(integer);
4458
4459 end:
4460 return (void *) integer;
4461 }
4462
4463 BT_EXPORT
4464 int bt_ctf_field_type_integer_get_size(struct bt_ctf_field_type *ft)
4465 {
4466 return bt_ctf_field_type_common_integer_get_size((void *) ft);
4467 }
4468
4469 BT_EXPORT
4470 bt_ctf_bool bt_ctf_field_type_integer_is_signed(struct bt_ctf_field_type *ft)
4471 {
4472 return bt_ctf_field_type_common_integer_is_signed((void *) ft);
4473 }
4474
4475 BT_EXPORT
4476 int bt_ctf_field_type_integer_set_is_signed(struct bt_ctf_field_type *ft,
4477 bt_ctf_bool is_signed)
4478 {
4479 return bt_ctf_field_type_common_integer_set_is_signed((void *) ft,
4480 is_signed);
4481 }
4482
4483 BT_EXPORT
4484 int bt_ctf_field_type_integer_set_size(struct bt_ctf_field_type *ft,
4485 unsigned int size)
4486 {
4487 return bt_ctf_field_type_common_integer_set_size((void *) ft, size);
4488 }
4489
4490 BT_EXPORT
4491 enum bt_ctf_integer_base bt_ctf_field_type_integer_get_base(
4492 struct bt_ctf_field_type *ft)
4493 {
4494 return (int) bt_ctf_field_type_common_integer_get_base((void *) ft);
4495 }
4496
4497 BT_EXPORT
4498 int bt_ctf_field_type_integer_set_base(struct bt_ctf_field_type *ft,
4499 enum bt_ctf_integer_base base)
4500 {
4501 return bt_ctf_field_type_common_integer_set_base((void *) ft,
4502 (int) base);
4503 }
4504
4505 BT_EXPORT
4506 enum bt_ctf_string_encoding bt_ctf_field_type_integer_get_encoding(
4507 struct bt_ctf_field_type *ft)
4508 {
4509 return (int) bt_ctf_field_type_common_integer_get_encoding((void *) ft);
4510 }
4511
4512 BT_EXPORT
4513 int bt_ctf_field_type_integer_set_encoding(struct bt_ctf_field_type *ft,
4514 enum bt_ctf_string_encoding encoding)
4515 {
4516 return bt_ctf_field_type_common_integer_set_encoding((void *) ft,
4517 (int) encoding);
4518 }
4519
4520 BT_EXPORT
4521 struct bt_ctf_clock_class *bt_ctf_field_type_integer_get_mapped_clock_class(
4522 struct bt_ctf_field_type *ft)
4523 {
4524 return bt_ctf_object_get_ref(bt_ctf_field_type_common_integer_borrow_mapped_clock_class(
4525 (void *) ft));
4526 }
4527
4528 BT_EXPORT
4529 int bt_ctf_field_type_integer_set_mapped_clock_class(
4530 struct bt_ctf_field_type *ft,
4531 struct bt_ctf_clock_class *clock_class)
4532 {
4533 return bt_ctf_field_type_common_integer_set_mapped_clock_class((void *) ft,
4534 clock_class);
4535 }
4536
4537 BT_EXPORT
4538 int bt_ctf_field_type_enumeration_signed_get_mapping_by_index(
4539 struct bt_ctf_field_type *ft, uint64_t index,
4540 const char **mapping_name, int64_t *range_begin,
4541 int64_t *range_end)
4542 {
4543 return bt_ctf_field_type_common_enumeration_signed_get_mapping_by_index(
4544 (void *) ft, index, mapping_name, range_begin, range_end);
4545 }
4546
4547 BT_EXPORT
4548 int bt_ctf_field_type_enumeration_unsigned_get_mapping_by_index(
4549 struct bt_ctf_field_type *ft, uint64_t index,
4550 const char **mapping_name, uint64_t *range_begin,
4551 uint64_t *range_end)
4552 {
4553 return bt_ctf_field_type_common_enumeration_unsigned_get_mapping_by_index(
4554 (void *) ft, index, mapping_name, range_begin, range_end);
4555 }
4556
4557 BT_EXPORT
4558 struct bt_ctf_field_type *bt_ctf_field_type_enumeration_create(
4559 struct bt_ctf_field_type *container_ft)
4560 {
4561 struct bt_ctf_field_type_common_enumeration *enumeration = NULL;
4562 struct bt_ctf_field_type_common *int_ft = (void *) container_ft;
4563
4564 BT_LOGD("Creating CTF writer enumeration field type object: int-ft-addr=%p",
4565 container_ft);
4566
4567 if (!container_ft) {
4568 BT_LOGW_STR("Invalid parameter: field type is NULL.");
4569 goto error;
4570 }
4571
4572 if (int_ft->id != BT_CTF_FIELD_TYPE_ID_INTEGER) {
4573 BT_LOGW("Invalid parameter: container field type is not an integer field type: "
4574 "container-ft-addr=%p, container-ft-id=%s",
4575 container_ft, bt_ctf_field_type_id_string(int_ft->id));
4576 goto error;
4577 }
4578
4579 enumeration = g_new0(struct bt_ctf_field_type_common_enumeration, 1);
4580 if (!enumeration) {
4581 BT_LOGE_STR("Failed to allocate one enumeration field type.");
4582 goto error;
4583 }
4584
4585 bt_ctf_field_type_common_enumeration_initialize(BT_CTF_TO_COMMON(enumeration),
4586 int_ft, bt_ctf_field_type_common_enumeration_destroy_recursive,
4587 &bt_ctf_field_type_enumeration_methods);
4588 enumeration->common.spec.writer.serialize_func =
4589 bt_ctf_field_type_enumeration_serialize_recursive;
4590 BT_LOGD("Created CTF writer enumeration field type object: addr=%p, "
4591 "int-ft-addr=%p, int-ft-size=%u",
4592 enumeration, container_ft,
4593 bt_ctf_field_type_integer_get_size(container_ft));
4594 goto end;
4595
4596 error:
4597 BT_CTF_OBJECT_PUT_REF_AND_RESET(enumeration);
4598
4599 end:
4600 return (void *) enumeration;
4601 }
4602
4603 BT_EXPORT
4604 struct bt_ctf_field_type *bt_ctf_field_type_enumeration_get_container_field_type(
4605 struct bt_ctf_field_type *ft)
4606 {
4607 return bt_ctf_object_get_ref(
4608 bt_ctf_field_type_common_enumeration_borrow_container_field_type(
4609 (void *) ft));
4610 }
4611
4612 BT_EXPORT
4613 int bt_ctf_field_type_enumeration_signed_add_mapping(
4614 struct bt_ctf_field_type *ft, const char *string,
4615 int64_t range_start, int64_t range_end)
4616 {
4617 return bt_ctf_field_type_common_enumeration_signed_add_mapping(
4618 (void *) ft, string, range_start, range_end);
4619 }
4620
4621 BT_EXPORT
4622 int bt_ctf_field_type_enumeration_unsigned_add_mapping(
4623 struct bt_ctf_field_type *ft, const char *string,
4624 uint64_t range_start, uint64_t range_end)
4625 {
4626 return bt_ctf_field_type_common_enumeration_unsigned_add_mapping(
4627 (void *) ft, string, range_start, range_end);
4628 }
4629
4630 BT_EXPORT
4631 int64_t bt_ctf_field_type_enumeration_get_mapping_count(
4632 struct bt_ctf_field_type *ft)
4633 {
4634 return bt_ctf_field_type_common_enumeration_get_mapping_count((void *) ft);
4635 }
4636
4637 BT_EXPORT
4638 struct bt_ctf_field_type *bt_ctf_field_type_floating_point_create(void)
4639 {
4640 struct bt_ctf_field_type_common_floating_point *floating_point =
4641 g_new0(struct bt_ctf_field_type_common_floating_point, 1);
4642
4643 BT_LOGD_STR("Creating CTF writer floating point number field type object.");
4644
4645 if (!floating_point) {
4646 BT_LOGE_STR("Failed to allocate one floating point number field type.");
4647 goto end;
4648 }
4649
4650 bt_ctf_field_type_common_floating_point_initialize(
4651 BT_CTF_TO_COMMON(floating_point),
4652 bt_ctf_field_type_common_floating_point_destroy,
4653 &bt_ctf_field_type_floating_point_methods);
4654 floating_point->common.spec.writer.serialize_func =
4655 bt_ctf_field_type_floating_point_serialize;
4656 BT_LOGD("Created CTF writer floating point number field type object: addr=%p, "
4657 "exp-size=%u, mant-size=%u", floating_point,
4658 floating_point->exp_dig, floating_point->mant_dig);
4659
4660 end:
4661 return (void *) floating_point;
4662 }
4663
4664 BT_EXPORT
4665 int bt_ctf_field_type_floating_point_get_exponent_digits(
4666 struct bt_ctf_field_type *ft)
4667 {
4668 return bt_ctf_field_type_common_floating_point_get_exponent_digits(
4669 (void *) ft);
4670 }
4671
4672 BT_EXPORT
4673 int bt_ctf_field_type_floating_point_set_exponent_digits(
4674 struct bt_ctf_field_type *ft, unsigned int exponent_digits)
4675 {
4676 return bt_ctf_field_type_common_floating_point_set_exponent_digits(
4677 (void *) ft, exponent_digits);
4678 }
4679
4680 BT_EXPORT
4681 int bt_ctf_field_type_floating_point_get_mantissa_digits(
4682 struct bt_ctf_field_type *ft)
4683 {
4684 return bt_ctf_field_type_common_floating_point_get_mantissa_digits(
4685 (void *) ft);
4686 }
4687
4688 BT_EXPORT
4689 int bt_ctf_field_type_floating_point_set_mantissa_digits(
4690 struct bt_ctf_field_type *ft, unsigned int mantissa_digits)
4691 {
4692 return bt_ctf_field_type_common_floating_point_set_mantissa_digits(
4693 (void *) ft, mantissa_digits);
4694 }
4695
4696 BT_EXPORT
4697 struct bt_ctf_field_type *bt_ctf_field_type_structure_create(void)
4698 {
4699 struct bt_ctf_field_type_common_structure *structure =
4700 g_new0(struct bt_ctf_field_type_common_structure, 1);
4701
4702 BT_LOGD_STR("Creating CTF writer structure field type object.");
4703
4704 if (!structure) {
4705 BT_LOGE_STR("Failed to allocate one structure field type.");
4706 goto error;
4707 }
4708
4709 bt_ctf_field_type_common_structure_initialize(BT_CTF_TO_COMMON(structure),
4710 bt_ctf_field_type_common_structure_destroy_recursive,
4711 &bt_ctf_field_type_structure_methods);
4712 structure->common.spec.writer.serialize_func =
4713 bt_ctf_field_type_structure_serialize_recursive;
4714 BT_LOGD("Created CTF writer structure field type object: addr=%p",
4715 structure);
4716 goto end;
4717
4718 error:
4719 BT_CTF_OBJECT_PUT_REF_AND_RESET(structure);
4720
4721 end:
4722 return (void *) structure;
4723 }
4724
4725 BT_EXPORT
4726 int bt_ctf_field_type_structure_add_field(struct bt_ctf_field_type *ft,
4727 struct bt_ctf_field_type *field_type,
4728 const char *field_name)
4729 {
4730 return bt_ctf_field_type_common_structure_add_field((void *) ft,
4731 (void *) field_type, field_name);
4732 }
4733
4734 BT_EXPORT
4735 int64_t bt_ctf_field_type_structure_get_field_count(struct bt_ctf_field_type *ft)
4736 {
4737 return bt_ctf_field_type_common_structure_get_field_count((void *) ft);
4738 }
4739
4740 BT_EXPORT
4741 int bt_ctf_field_type_structure_get_field_by_index(
4742 struct bt_ctf_field_type *ft,
4743 const char **field_name,
4744 struct bt_ctf_field_type **field_type, uint64_t index)
4745 {
4746 int ret = bt_ctf_field_type_common_structure_borrow_field_by_index(
4747 (void *) ft, field_name, (void *) field_type, index);
4748
4749 if (ret == 0 && field_type) {
4750 bt_ctf_object_get_ref(*field_type);
4751 }
4752
4753 return ret;
4754 }
4755
4756 BT_EXPORT
4757 struct bt_ctf_field_type *bt_ctf_field_type_structure_get_field_type_by_name(
4758 struct bt_ctf_field_type *ft, const char *name)
4759 {
4760 return bt_ctf_object_get_ref(bt_ctf_field_type_common_structure_borrow_field_type_by_name(
4761 (void *) ft, name));
4762 }
4763
4764 BT_EXPORT
4765 struct bt_ctf_field_type *bt_ctf_field_type_variant_create(
4766 struct bt_ctf_field_type *tag_ft, const char *tag_name)
4767 {
4768 struct bt_ctf_field_type_common_variant *var_ft = NULL;
4769
4770 BT_LOGD("Creating CTF writer variant field type object: "
4771 "tag-ft-addr=%p, tag-field-name=\"%s\"",
4772 tag_ft, tag_name);
4773
4774 if (tag_name && !bt_ctf_identifier_is_valid(tag_name)) {
4775 BT_LOGW("Invalid parameter: tag field name is not a valid CTF identifier: "
4776 "tag-ft-addr=%p, tag-field-name=\"%s\"",
4777 tag_ft, tag_name);
4778 goto error;
4779 }
4780
4781 var_ft = g_new0(struct bt_ctf_field_type_common_variant, 1);
4782 if (!var_ft) {
4783 BT_LOGE_STR("Failed to allocate one variant field type.");
4784 goto error;
4785 }
4786
4787 bt_ctf_field_type_common_variant_initialize(BT_CTF_TO_COMMON(var_ft),
4788 (void *) tag_ft, tag_name,
4789 bt_ctf_field_type_common_variant_destroy_recursive,
4790 &bt_ctf_field_type_variant_methods);
4791 var_ft->common.spec.writer.serialize_func =
4792 bt_ctf_field_type_variant_serialize_recursive;
4793 BT_LOGD("Created CTF writer variant field type object: addr=%p, "
4794 "tag-ft-addr=%p, tag-field-name=\"%s\"",
4795 var_ft, tag_ft, tag_name);
4796 goto end;
4797
4798 error:
4799 BT_CTF_OBJECT_PUT_REF_AND_RESET(var_ft);
4800
4801 end:
4802 return (void *) var_ft;
4803 }
4804
4805 BT_EXPORT
4806 struct bt_ctf_field_type *bt_ctf_field_type_variant_get_tag_field_type(
4807 struct bt_ctf_field_type *ft)
4808 {
4809 return bt_ctf_object_get_ref(bt_ctf_field_type_common_variant_borrow_tag_field_type(
4810 (void *) ft));
4811 }
4812
4813 BT_EXPORT
4814 const char *bt_ctf_field_type_variant_get_tag_name(struct bt_ctf_field_type *ft)
4815 {
4816 return bt_ctf_field_type_common_variant_get_tag_name((void *) ft);
4817 }
4818
4819 BT_EXPORT
4820 int bt_ctf_field_type_variant_set_tag_name(
4821 struct bt_ctf_field_type *ft, const char *name)
4822 {
4823 return bt_ctf_field_type_common_variant_set_tag_name((void *) ft, name);
4824 }
4825
4826 BT_EXPORT
4827 int bt_ctf_field_type_variant_add_field(struct bt_ctf_field_type *ft,
4828 struct bt_ctf_field_type *field_type,
4829 const char *field_name)
4830 {
4831 return bt_ctf_field_type_common_variant_add_field((void *) ft,
4832 (void *) field_type, field_name);
4833 }
4834
4835 BT_EXPORT
4836 struct bt_ctf_field_type *bt_ctf_field_type_variant_get_field_type_by_name(
4837 struct bt_ctf_field_type *ft,
4838 const char *field_name)
4839 {
4840 return bt_ctf_object_get_ref(bt_ctf_field_type_common_variant_borrow_field_type_by_name(
4841 (void *) ft, field_name));
4842 }
4843
4844 BT_EXPORT
4845 struct bt_ctf_field_type *bt_ctf_field_type_variant_get_field_type_from_tag(
4846 struct bt_ctf_field_type *ft,
4847 struct bt_ctf_field *tag_field)
4848 {
4849 int ret;
4850 int64_t choice_index;
4851 struct bt_ctf_field *container;
4852 struct bt_ctf_field_type_common_variant *var_ft = (void *) ft;
4853 struct bt_ctf_field_type *ret_ft = NULL;
4854
4855 BT_CTF_ASSERT_PRE_NON_NULL(ft, "Field type");
4856 BT_CTF_ASSERT_PRE_CTF_FT_COMMON_HAS_ID(ft, BT_CTF_FIELD_TYPE_ID_VARIANT,
4857 "Field type");
4858 BT_CTF_ASSERT_PRE_NON_NULL(tag_field, "Tag field");
4859 BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(
4860 (struct bt_ctf_field_common *) tag_field,
4861 BT_CTF_FIELD_TYPE_ID_ENUM, "Tag field");
4862 BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_IS_SET((struct bt_ctf_field_common *) tag_field,
4863 "Tag field");
4864
4865 container = bt_ctf_field_enumeration_borrow_container(tag_field);
4866 BT_ASSERT_DBG(container);
4867
4868 if (var_ft->tag_ft->container_ft->is_signed) {
4869 int64_t val;
4870
4871 ret = bt_ctf_field_integer_signed_get_value(container,
4872 &val);
4873 BT_ASSERT_DBG(ret == 0);
4874 choice_index = bt_ctf_field_type_common_variant_find_choice_index(
4875 (void *) ft, (uint64_t) val, true);
4876 } else {
4877 uint64_t val;
4878
4879 ret = bt_ctf_field_integer_unsigned_get_value(container,
4880 &val);
4881 BT_ASSERT_DBG(ret == 0);
4882 choice_index = bt_ctf_field_type_common_variant_find_choice_index(
4883 (void *) ft, val, false);
4884 }
4885
4886 if (choice_index < 0) {
4887 BT_LOGW("Cannot find variant field type's field: "
4888 "var-ft-addr=%p, tag-field-addr=%p", ft, tag_field);
4889 goto end;
4890 }
4891
4892 ret = bt_ctf_field_type_variant_get_field_by_index(ft, NULL,
4893 &ret_ft, choice_index);
4894 BT_ASSERT_DBG(ret == 0);
4895
4896 end:
4897 return ret_ft;
4898 }
4899
4900 BT_EXPORT
4901 int64_t bt_ctf_field_type_variant_get_field_count(struct bt_ctf_field_type *ft)
4902 {
4903 return bt_ctf_field_type_common_variant_get_field_count((void *) ft);
4904 }
4905
4906 BT_EXPORT
4907 int bt_ctf_field_type_variant_get_field_by_index(struct bt_ctf_field_type *ft,
4908 const char **field_name, struct bt_ctf_field_type **field_type,
4909 uint64_t index)
4910 {
4911 int ret = bt_ctf_field_type_common_variant_borrow_field_by_index(
4912 (void *) ft, field_name, (void *) field_type, index);
4913
4914 if (ret == 0 && field_type) {
4915 bt_ctf_object_get_ref(*field_type);
4916 }
4917
4918 return ret;
4919 }
4920
4921 BT_EXPORT
4922 struct bt_ctf_field_type *bt_ctf_field_type_array_create(
4923 struct bt_ctf_field_type *element_ft, unsigned int length)
4924 {
4925 struct bt_ctf_field_type_common_array *array = NULL;
4926
4927 BT_LOGD("Creating CTF writer array field type object: element-ft-addr=%p, "
4928 "length=%u", element_ft, length);
4929
4930 if (!element_ft) {
4931 BT_LOGW_STR("Invalid parameter: element field type is NULL.");
4932 goto error;
4933 }
4934
4935 if (length == 0) {
4936 BT_LOGW_STR("Invalid parameter: length is zero.");
4937 goto error;
4938 }
4939
4940 array = g_new0(struct bt_ctf_field_type_common_array, 1);
4941 if (!array) {
4942 BT_LOGE_STR("Failed to allocate one array field type.");
4943 goto error;
4944 }
4945
4946 bt_ctf_field_type_common_array_initialize(BT_CTF_TO_COMMON(array),
4947 (void *) element_ft, length,
4948 bt_ctf_field_type_common_array_destroy_recursive,
4949 &bt_ctf_field_type_array_methods);
4950 array->common.spec.writer.serialize_func =
4951 bt_ctf_field_type_array_serialize_recursive;
4952 BT_LOGD("Created CTF writer array field type object: addr=%p, "
4953 "element-ft-addr=%p, length=%u",
4954 array, element_ft, length);
4955 goto end;
4956
4957 error:
4958 BT_CTF_OBJECT_PUT_REF_AND_RESET(array);
4959
4960 end:
4961 return (void *) array;
4962 }
4963
4964 BT_EXPORT
4965 struct bt_ctf_field_type *bt_ctf_field_type_array_get_element_field_type(
4966 struct bt_ctf_field_type *ft)
4967 {
4968 return bt_ctf_object_get_ref(bt_ctf_field_type_common_array_borrow_element_field_type(
4969 (void *) ft));
4970 }
4971
4972 BT_EXPORT
4973 int64_t bt_ctf_field_type_array_get_length(struct bt_ctf_field_type *ft)
4974 {
4975 return bt_ctf_field_type_common_array_get_length((void *) ft);
4976 }
4977
4978 BT_EXPORT
4979 struct bt_ctf_field_type *bt_ctf_field_type_sequence_create(
4980 struct bt_ctf_field_type *element_ft,
4981 const char *length_field_name)
4982 {
4983 struct bt_ctf_field_type_common_sequence *sequence = NULL;
4984
4985 BT_LOGD("Creating CTF writer sequence field type object: element-ft-addr=%p, "
4986 "length-field-name=\"%s\"", element_ft, length_field_name);
4987
4988 if (!element_ft) {
4989 BT_LOGW_STR("Invalid parameter: element field type is NULL.");
4990 goto error;
4991 }
4992
4993 if (!bt_ctf_identifier_is_valid(length_field_name)) {
4994 BT_LOGW("Invalid parameter: length field name is not a valid CTF identifier: "
4995 "length-field-name=\"%s\"", length_field_name);
4996 goto error;
4997 }
4998
4999 sequence = g_new0(struct bt_ctf_field_type_common_sequence, 1);
5000 if (!sequence) {
5001 BT_LOGE_STR("Failed to allocate one sequence field type.");
5002 goto error;
5003 }
5004
5005 bt_ctf_field_type_common_sequence_initialize(BT_CTF_TO_COMMON(sequence),
5006 (void *) element_ft, length_field_name,
5007 bt_ctf_field_type_common_sequence_destroy_recursive,
5008 &bt_ctf_field_type_sequence_methods);
5009 sequence->common.spec.writer.serialize_func =
5010 bt_ctf_field_type_sequence_serialize_recursive;
5011 BT_LOGD("Created CTF writer sequence field type object: addr=%p, "
5012 "element-ft-addr=%p, length-field-name=\"%s\"",
5013 sequence, element_ft, length_field_name);
5014 goto end;
5015
5016 error:
5017 BT_CTF_OBJECT_PUT_REF_AND_RESET(sequence);
5018
5019 end:
5020 return (void *) sequence;
5021 }
5022
5023 BT_EXPORT
5024 struct bt_ctf_field_type *bt_ctf_field_type_sequence_get_element_field_type(
5025 struct bt_ctf_field_type *ft)
5026 {
5027 return bt_ctf_object_get_ref(bt_ctf_field_type_common_sequence_borrow_element_field_type(
5028 (void *) ft));
5029 }
5030
5031 BT_EXPORT
5032 const char *bt_ctf_field_type_sequence_get_length_field_name(
5033 struct bt_ctf_field_type *ft)
5034 {
5035 return bt_ctf_field_type_common_sequence_get_length_field_name((void *) ft);
5036 }
5037
5038 BT_EXPORT
5039 struct bt_ctf_field_type *bt_ctf_field_type_string_create(void)
5040 {
5041 struct bt_ctf_field_type_common_string *string =
5042 g_new0(struct bt_ctf_field_type_common_string, 1);
5043
5044 BT_LOGD_STR("Creating CTF writer string field type object.");
5045
5046 if (!string) {
5047 BT_LOGE_STR("Failed to allocate one string field type.");
5048 return NULL;
5049 }
5050
5051 bt_ctf_field_type_common_string_initialize(BT_CTF_TO_COMMON(string),
5052 bt_ctf_field_type_common_string_destroy,
5053 &bt_ctf_field_type_string_methods);
5054 string->common.spec.writer.serialize_func =
5055 bt_ctf_field_type_string_serialize;
5056 BT_LOGD("Created CTF writer string field type object: addr=%p", string);
5057 return (void *) string;
5058 }
5059
5060 BT_EXPORT
5061 enum bt_ctf_string_encoding bt_ctf_field_type_string_get_encoding(
5062 struct bt_ctf_field_type *ft)
5063 {
5064 return (int) bt_ctf_field_type_common_string_get_encoding((void *) ft);
5065 }
5066
5067 BT_EXPORT
5068 int bt_ctf_field_type_string_set_encoding(struct bt_ctf_field_type *ft,
5069 enum bt_ctf_string_encoding encoding)
5070 {
5071 return bt_ctf_field_type_common_string_set_encoding((void *) ft,
5072 (int) encoding);
5073 }
5074
5075 BT_EXPORT
5076 int bt_ctf_field_type_get_alignment(struct bt_ctf_field_type *ft)
5077 {
5078 return bt_ctf_field_type_common_get_alignment((void *) ft);
5079 }
5080
5081 BT_EXPORT
5082 int bt_ctf_field_type_set_alignment(struct bt_ctf_field_type *ft,
5083 unsigned int alignment)
5084 {
5085 return bt_ctf_field_type_common_set_alignment((void *) ft, alignment);
5086 }
5087
5088 BT_EXPORT
5089 enum bt_ctf_byte_order bt_ctf_field_type_get_byte_order(
5090 struct bt_ctf_field_type *ft)
5091 {
5092 return (int) bt_ctf_field_type_common_get_byte_order((void *) ft);
5093 }
5094
5095 BT_EXPORT
5096 int bt_ctf_field_type_set_byte_order(struct bt_ctf_field_type *ft,
5097 enum bt_ctf_byte_order byte_order)
5098 {
5099 return bt_ctf_field_type_common_set_byte_order((void *) ft,
5100 (int) byte_order);
5101 }
5102
5103 BT_EXPORT
5104 enum bt_ctf_field_type_id bt_ctf_field_type_get_type_id(
5105 struct bt_ctf_field_type *ft)
5106 {
5107 return (int) bt_ctf_field_type_common_get_type_id((void *) ft);
5108 }
5109
5110 struct bt_ctf_field_type *bt_ctf_field_type_copy(struct bt_ctf_field_type *ft)
5111 {
5112 return (void *) bt_ctf_field_type_common_copy((void *) ft);
5113 }
5114
5115 static
5116 struct bt_ctf_field_type *bt_ctf_field_type_integer_copy(
5117 struct bt_ctf_field_type *ft)
5118 {
5119 struct bt_ctf_field_type_common_integer *int_ft = (void *) ft;
5120 struct bt_ctf_field_type_common_integer *copy_ft;
5121
5122 BT_LOGD("Copying CTF writer integer field type's: addr=%p", ft);
5123 copy_ft = (void *) bt_ctf_field_type_integer_create(int_ft->size);
5124 if (!copy_ft) {
5125 BT_LOGE_STR("Cannot create CTF writer integer field type.");
5126 goto end;
5127 }
5128
5129 copy_ft->mapped_clock_class = bt_ctf_object_get_ref(int_ft->mapped_clock_class);
5130 copy_ft->user_byte_order = int_ft->user_byte_order;
5131 copy_ft->is_signed = int_ft->is_signed;
5132 copy_ft->size = int_ft->size;
5133 copy_ft->base = int_ft->base;
5134 copy_ft->encoding = int_ft->encoding;
5135 BT_LOGD("Copied CTF writer integer field type: original-ft-addr=%p, copy-ft-addr=%p",
5136 ft, copy_ft);
5137
5138 end:
5139 return (void *) copy_ft;
5140 }
5141
5142 static
5143 struct bt_ctf_field_type *bt_ctf_field_type_enumeration_copy_recursive(
5144 struct bt_ctf_field_type *ft)
5145 {
5146 size_t i;
5147 struct bt_ctf_field_type_common_enumeration *enum_ft = (void *) ft;
5148 struct bt_ctf_field_type_common_enumeration *copy_ft = NULL;
5149 struct bt_ctf_field_type_common_enumeration *container_copy_ft;
5150
5151 BT_LOGD("Copying CTF writer enumeration field type's: addr=%p", ft);
5152
5153 /* Copy the source enumeration's container */
5154 BT_LOGD_STR("Copying CTF writer enumeration field type's container field type.");
5155 container_copy_ft = BT_CTF_FROM_COMMON(bt_ctf_field_type_common_copy(
5156 BT_CTF_TO_COMMON(enum_ft->container_ft)));
5157 if (!container_copy_ft) {
5158 BT_LOGE_STR("Cannot copy CTF writer enumeration field type's container field type.");
5159 goto end;
5160 }
5161
5162 copy_ft = (void *) bt_ctf_field_type_enumeration_create(
5163 (void *) container_copy_ft);
5164 if (!copy_ft) {
5165 BT_LOGE_STR("Cannot create CTF writer enumeration field type.");
5166 goto end;
5167 }
5168
5169 /* Copy all enumaration entries */
5170 for (i = 0; i < enum_ft->entries->len; i++) {
5171 struct bt_ctf_enumeration_mapping *mapping = g_ptr_array_index(
5172 enum_ft->entries, i);
5173 struct bt_ctf_enumeration_mapping *copy_mapping = g_new0(
5174 struct bt_ctf_enumeration_mapping, 1);
5175
5176 if (!copy_mapping) {
5177 BT_LOGE_STR("Failed to allocate one enumeration mapping.");
5178 goto error;
5179 }
5180
5181 *copy_mapping = *mapping;
5182 g_ptr_array_add(copy_ft->entries, copy_mapping);
5183 }
5184
5185 BT_LOGD("Copied CTF writer enumeration field type: original-ft-addr=%p, copy-ft-addr=%p",
5186 ft, copy_ft);
5187
5188 end:
5189 bt_ctf_object_put_ref(container_copy_ft);
5190 return (void *) copy_ft;
5191
5192 error:
5193 bt_ctf_object_put_ref(container_copy_ft);
5194 BT_CTF_OBJECT_PUT_REF_AND_RESET(copy_ft);
5195 return (void *) copy_ft;
5196 }
5197
5198 static
5199 struct bt_ctf_field_type *bt_ctf_field_type_floating_point_copy(
5200 struct bt_ctf_field_type *ft)
5201 {
5202 struct bt_ctf_field_type_common_floating_point *flt_ft = BT_CTF_FROM_COMMON(ft);
5203 struct bt_ctf_field_type_common_floating_point *copy_ft;
5204
5205 BT_LOGD("Copying CTF writer floating point number field type's: addr=%p", ft);
5206 copy_ft = (void *) bt_ctf_field_type_floating_point_create();
5207 if (!copy_ft) {
5208 BT_LOGE_STR("Cannot create CTF writer floating point number field type.");
5209 goto end;
5210 }
5211
5212 copy_ft->user_byte_order = flt_ft->user_byte_order;
5213 copy_ft->exp_dig = flt_ft->exp_dig;
5214 copy_ft->mant_dig = flt_ft->mant_dig;
5215 BT_LOGD("Copied CTF writer floating point number field type: original-ft-addr=%p, copy-ft-addr=%p",
5216 ft, copy_ft);
5217
5218 end:
5219 return (void *) copy_ft;
5220 }
5221
5222 static
5223 struct bt_ctf_field_type *bt_ctf_field_type_structure_copy_recursive(
5224 struct bt_ctf_field_type *ft)
5225 {
5226 int64_t i;
5227 GHashTableIter iter;
5228 gpointer key, value;
5229 struct bt_ctf_field_type_common_structure *struct_ft = (void *) ft;
5230 struct bt_ctf_field_type_common_structure *copy_ft;
5231
5232 BT_LOGD("Copying CTF writer structure field type's: addr=%p", ft);
5233 copy_ft = (void *) bt_ctf_field_type_structure_create();
5234 if (!copy_ft) {
5235 BT_LOGE_STR("Cannot create CTF writer structure field type.");
5236 goto end;
5237 }
5238
5239 /* Copy field_name_to_index */
5240 g_hash_table_iter_init(&iter, struct_ft->field_name_to_index);
5241 while (g_hash_table_iter_next(&iter, &key, &value)) {
5242 g_hash_table_insert(copy_ft->field_name_to_index,
5243 key, value);
5244 }
5245
5246 g_array_set_size(copy_ft->fields, struct_ft->fields->len);
5247
5248 for (i = 0; i < struct_ft->fields->len; i++) {
5249 struct bt_ctf_field_type_common_structure_field *entry, *copy_entry;
5250 struct bt_ctf_field_type_common *field_ft_copy;
5251
5252 entry = BT_CTF_FIELD_TYPE_COMMON_STRUCTURE_FIELD_AT_INDEX(
5253 struct_ft, i);
5254 copy_entry = BT_CTF_FIELD_TYPE_COMMON_STRUCTURE_FIELD_AT_INDEX(
5255 copy_ft, i);
5256 BT_LOGD("Copying CTF writer structure field type's field: "
5257 "index=%" PRId64 ", "
5258 "field-ft-addr=%p, field-name=\"%s\"",
5259 i, entry, g_quark_to_string(entry->name));
5260
5261 field_ft_copy = (void *) bt_ctf_field_type_copy(
5262 (void *) entry->type);
5263 if (!field_ft_copy) {
5264 BT_LOGE("Cannot copy CTF writer structure field type's field: "
5265 "index=%" PRId64 ", "
5266 "field-ft-addr=%p, field-name=\"%s\"",
5267 i, entry, g_quark_to_string(entry->name));
5268 goto error;
5269 }
5270
5271 copy_entry->name = entry->name;
5272 copy_entry->type = field_ft_copy;
5273 }
5274
5275 BT_LOGD("Copied CTF writer structure field type: original-ft-addr=%p, copy-ft-addr=%p",
5276 ft, copy_ft);
5277
5278 end:
5279 return (void *) copy_ft;
5280
5281 error:
5282 BT_CTF_OBJECT_PUT_REF_AND_RESET(copy_ft);
5283 return NULL;
5284 }
5285
5286 static
5287 struct bt_ctf_field_type *bt_ctf_field_type_variant_copy_recursive(
5288 struct bt_ctf_field_type *ft)
5289 {
5290 int64_t i;
5291 GHashTableIter iter;
5292 gpointer key, value;
5293 struct bt_ctf_field_type_common *tag_ft_copy = NULL;
5294 struct bt_ctf_field_type_common_variant *var_ft = (void *) ft;
5295 struct bt_ctf_field_type_common_variant *copy_ft = NULL;
5296
5297 BT_LOGD("Copying CTF writer variant field type's: addr=%p", ft);
5298 if (var_ft->tag_ft) {
5299 BT_LOGD_STR("Copying CTF writer variant field type's tag field type.");
5300 tag_ft_copy = bt_ctf_field_type_common_copy(
5301 BT_CTF_TO_COMMON(var_ft->tag_ft));
5302 if (!tag_ft_copy) {
5303 BT_LOGE_STR("Cannot copy CTF writer variant field type's tag field type.");
5304 goto end;
5305 }
5306 }
5307
5308 copy_ft = (void *) bt_ctf_field_type_variant_create(
5309 (void *) tag_ft_copy,
5310 var_ft->tag_name->len ? var_ft->tag_name->str : NULL);
5311 if (!copy_ft) {
5312 BT_LOGE_STR("Cannot create CTF writer variant field type.");
5313 goto end;
5314 }
5315
5316 /* Copy field_name_to_index */
5317 g_hash_table_iter_init(&iter, var_ft->choice_name_to_index);
5318 while (g_hash_table_iter_next(&iter, &key, &value)) {
5319 g_hash_table_insert(copy_ft->choice_name_to_index,
5320 key, value);
5321 }
5322
5323 g_array_set_size(copy_ft->choices, var_ft->choices->len);
5324
5325 for (i = 0; i < var_ft->choices->len; i++) {
5326 struct bt_ctf_field_type_common_variant_choice *entry, *copy_entry;
5327 struct bt_ctf_field_type_common *field_ft_copy;
5328 uint64_t range_i;
5329
5330 entry = BT_CTF_FIELD_TYPE_COMMON_VARIANT_CHOICE_AT_INDEX(var_ft, i);
5331 copy_entry = BT_CTF_FIELD_TYPE_COMMON_VARIANT_CHOICE_AT_INDEX(
5332 copy_ft, i);
5333 BT_LOGD("Copying CTF writer variant field type's field: "
5334 "index=%" PRId64 ", "
5335 "field-ft-addr=%p, field-name=\"%s\"",
5336 i, entry, g_quark_to_string(entry->name));
5337
5338 field_ft_copy = (void *) bt_ctf_field_type_copy(
5339 (void *) entry->type);
5340 if (!field_ft_copy) {
5341 BT_LOGE("Cannot copy CTF writer variant field type's field: "
5342 "index=%" PRId64 ", "
5343 "field-ft-addr=%p, field-name=\"%s\"",
5344 i, entry, g_quark_to_string(entry->name));
5345 g_free(copy_entry);
5346 goto error;
5347 }
5348
5349 copy_entry->name = entry->name;
5350 copy_entry->type = field_ft_copy;
5351
5352 /* Copy ranges */
5353 copy_entry->ranges = g_array_new(FALSE, TRUE,
5354 sizeof(struct bt_ctf_field_type_common_variant_choice_range));
5355 BT_ASSERT_DBG(copy_entry->ranges);
5356 g_array_set_size(copy_entry->ranges, entry->ranges->len);
5357
5358 for (range_i = 0; range_i < entry->ranges->len; range_i++) {
5359 copy_entry->ranges[range_i] = entry->ranges[range_i];
5360 }
5361 }
5362
5363 if (var_ft->tag_field_path) {
5364 BT_LOGD_STR("Copying CTF writer variant field type's tag field path.");
5365 copy_ft->tag_field_path = bt_ctf_field_path_copy(
5366 var_ft->tag_field_path);
5367 if (!copy_ft->tag_field_path) {
5368 BT_LOGE_STR("Cannot copy CTF writer variant field type's tag field path.");
5369 goto error;
5370 }
5371 }
5372
5373 copy_ft->choices_up_to_date = var_ft->choices_up_to_date;
5374 BT_LOGD("Copied CTF writer variant field type: original-ft-addr=%p, copy-ft-addr=%p",
5375 ft, copy_ft);
5376
5377 end:
5378 bt_ctf_object_put_ref(tag_ft_copy);
5379 return (void *) copy_ft;
5380
5381 error:
5382 bt_ctf_object_put_ref(tag_ft_copy);
5383 BT_CTF_OBJECT_PUT_REF_AND_RESET(copy_ft);
5384 return NULL;
5385 }
5386
5387 static
5388 struct bt_ctf_field_type *bt_ctf_field_type_array_copy_recursive(
5389 struct bt_ctf_field_type *ft)
5390 {
5391 struct bt_ctf_field_type_common *container_ft_copy = NULL;
5392 struct bt_ctf_field_type_common_array *array_ft = (void *) ft;
5393 struct bt_ctf_field_type_common_array *copy_ft = NULL;
5394
5395 BT_LOGD("Copying CTF writer array field type's: addr=%p", ft);
5396 BT_LOGD_STR("Copying CTF writer array field type's element field type.");
5397 container_ft_copy = bt_ctf_field_type_common_copy(array_ft->element_ft);
5398 if (!container_ft_copy) {
5399 BT_LOGE_STR("Cannot copy CTF writer array field type's element field type.");
5400 goto end;
5401 }
5402
5403 copy_ft = (void *) bt_ctf_field_type_array_create(
5404 (void *) container_ft_copy, array_ft->length);
5405 if (!copy_ft) {
5406 BT_LOGE_STR("Cannot create CTF writer array field type.");
5407 goto end;
5408 }
5409
5410 BT_LOGD("Copied CTF writer array field type: original-ft-addr=%p, copy-ft-addr=%p",
5411 ft, copy_ft);
5412
5413 end:
5414 bt_ctf_object_put_ref(container_ft_copy);
5415 return (void *) copy_ft;
5416 }
5417
5418 static
5419 struct bt_ctf_field_type *bt_ctf_field_type_sequence_copy_recursive(
5420 struct bt_ctf_field_type *ft)
5421 {
5422 struct bt_ctf_field_type_common *container_ft_copy = NULL;
5423 struct bt_ctf_field_type_common_sequence *seq_ft = (void *) ft;
5424 struct bt_ctf_field_type_common_sequence *copy_ft = NULL;
5425
5426 BT_LOGD("Copying CTF writer sequence field type's: addr=%p", ft);
5427 BT_LOGD_STR("Copying CTF writer sequence field type's element field type.");
5428 container_ft_copy = bt_ctf_field_type_common_copy(seq_ft->element_ft);
5429 if (!container_ft_copy) {
5430 BT_LOGE_STR("Cannot copy CTF writer sequence field type's element field type.");
5431 goto end;
5432 }
5433
5434 copy_ft = (void *) bt_ctf_field_type_sequence_create(
5435 (void *) container_ft_copy,
5436 seq_ft->length_field_name->len ?
5437 seq_ft->length_field_name->str : NULL);
5438 if (!copy_ft) {
5439 BT_LOGE_STR("Cannot create CTF writer sequence field type.");
5440 goto end;
5441 }
5442
5443 if (seq_ft->length_field_path) {
5444 BT_LOGD_STR("Copying CTF writer sequence field type's length field path.");
5445 copy_ft->length_field_path = bt_ctf_field_path_copy(
5446 seq_ft->length_field_path);
5447 if (!copy_ft->length_field_path) {
5448 BT_LOGE_STR("Cannot copy CTF writer sequence field type's length field path.");
5449 goto error;
5450 }
5451 }
5452
5453 BT_LOGD("Copied CTF writer sequence field type: original-ft-addr=%p, copy-ft-addr=%p",
5454 ft, copy_ft);
5455
5456 end:
5457 bt_ctf_object_put_ref(container_ft_copy);
5458 return (void *) copy_ft;
5459 error:
5460 bt_ctf_object_put_ref(container_ft_copy);
5461 BT_CTF_OBJECT_PUT_REF_AND_RESET(copy_ft);
5462 return NULL;
5463 }
5464
5465 static
5466 struct bt_ctf_field_type *bt_ctf_field_type_string_copy(struct bt_ctf_field_type *ft)
5467 {
5468 struct bt_ctf_field_type_common_string *string_ft = (void *) ft;
5469 struct bt_ctf_field_type_common_string *copy_ft = NULL;
5470
5471 BT_LOGD("Copying CTF writer string field type's: addr=%p", ft);
5472 copy_ft = (void *) bt_ctf_field_type_string_create();
5473 if (!copy_ft) {
5474 BT_LOGE_STR("Cannot create CTF writer string field type.");
5475 goto end;
5476 }
5477
5478 copy_ft->encoding = string_ft->encoding;
5479 BT_LOGD("Copied CTF writer string field type: original-ft-addr=%p, copy-ft-addr=%p",
5480 ft, copy_ft);
5481
5482 end:
5483 return (void *) copy_ft;
5484 }
This page took 0.171817 seconds and 4 git commands to generate.