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