lib: add internal object pool API and use it; adapt plugins/tests
[babeltrace.git] / lib / ctf-ir / field-types.c
CommitLineData
273b65be 1/*
2e33ac5a 2 * field-types.c
273b65be 3 *
d2dc44b6 4 * Babeltrace CTF IR - Event Types
273b65be 5 *
de9dd397 6 * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
273b65be
JG
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
4e8304f7
PP
29#define BT_LOG_TAG "FIELD-TYPES"
30#include <babeltrace/lib-logging-internal.h>
31
3dca2276 32#include <babeltrace/assert-pre-internal.h>
2e33ac5a 33#include <babeltrace/ctf-ir/field-types-internal.h>
b011f6b0 34#include <babeltrace/ctf-ir/field-path-internal.h>
3dca2276
PP
35#include <babeltrace/ctf-ir/fields-internal.h>
36#include <babeltrace/ctf-ir/fields.h>
654c1444 37#include <babeltrace/ctf-ir/utils.h>
3dca2276 38#include <babeltrace/ctf-ir/utils-internal.h>
83509119 39#include <babeltrace/ref.h>
ac0c6bdd
PP
40#include <babeltrace/ctf-ir/clock-class.h>
41#include <babeltrace/ctf-ir/clock-class-internal.h>
83509119
JG
42#include <babeltrace/object-internal.h>
43#include <babeltrace/ref.h>
3d9990ac
PP
44#include <babeltrace/compiler-internal.h>
45#include <babeltrace/endian-internal.h>
f6ccaed9 46#include <babeltrace/assert-internal.h>
273b65be
JG
47#include <float.h>
48#include <inttypes.h>
a39fa057 49#include <stdlib.h>
273b65be 50
273b65be 51static
3dca2276
PP
52struct bt_field_type *bt_field_type_integer_copy(
53 struct bt_field_type *ft);
273b65be
JG
54
55static
3dca2276
PP
56struct bt_field_type *bt_field_type_enumeration_copy_recursive(
57 struct bt_field_type *ft);
273b65be
JG
58
59static
3dca2276
PP
60struct bt_field_type *bt_field_type_floating_point_copy(
61 struct bt_field_type *ft);
273b65be
JG
62
63static
3dca2276
PP
64struct bt_field_type *bt_field_type_structure_copy_recursive(
65 struct bt_field_type *ft);
273b65be
JG
66
67static
3dca2276
PP
68struct bt_field_type *bt_field_type_variant_copy_recursive(
69 struct bt_field_type *ft);
273b65be
JG
70
71static
3dca2276
PP
72struct bt_field_type *bt_field_type_array_copy_recursive(
73 struct bt_field_type *ft);
273b65be
JG
74
75static
3dca2276
PP
76struct bt_field_type *bt_field_type_sequence_copy_recursive(
77 struct bt_field_type *type);
273b65be
JG
78
79static
3dca2276
PP
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,
273b65be
JG
89};
90
3dca2276
PP
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};
24724933 99
3dca2276
PP
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,
24724933
JG
107};
108
3dca2276
PP
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};
265e809c 117
3dca2276
PP
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,
265e809c
PP
125};
126
3dca2276
PP
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};
81e36fac 135
3dca2276
PP
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,
81e36fac
PP
152};
153
273b65be
JG
154static
155void destroy_enumeration_mapping(struct enumeration_mapping *mapping)
156{
157 g_free(mapping);
158}
159
3dca2276
PP
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;
312c056a
PP
270 struct_ft->fields = g_array_new(FALSE, TRUE,
271 sizeof(struct bt_field_type_common_structure_field));
3dca2276
PP
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);
312c056a
PP
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));
3dca2276
PP
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
312c056a
PP
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}
3dca2276
PP
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;
312c056a 429 uint64_t i;
3dca2276
PP
430
431 if (!ft) {
432 return;
433 }
434
435 BT_LOGD("Destroying structure field type object: addr=%p", ft);
312c056a
PP
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
3dca2276
PP
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
312c056a
PP
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
3dca2276
PP
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;
312c056a 510 uint64_t i;
3dca2276
PP
511
512 if (!ft) {
513 return;
514 }
515
516 BT_LOGD("Destroying variant field type object: addr=%p", ft);
312c056a
PP
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
3dca2276
PP
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
273b65be
JG
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
b92ddaaa 563 if (mapping->range_start._signed <= overlap_query->range_end._signed
4e8304f7
PP
564 && overlap_query->range_start._signed <=
565 mapping->range_end._signed) {
b92ddaaa
JG
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;
4e8304f7
PP
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 }
b92ddaaa
JG
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
4e8304f7
PP
595 && overlap_query->range_start._unsigned <=
596 mapping->range_end._unsigned) {
273b65be
JG
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;
4e8304f7
PP
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 }
273b65be
JG
617}
618
b92ddaaa
JG
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
273b65be 633static
312c056a 634int add_structure_variant_member(GArray *members,
273b65be 635 GHashTable *field_name_to_index,
312c056a
PP
636 struct bt_field_type_common *field_type, const char *field_name,
637 bool is_variant)
273b65be
JG
638{
639 int ret = 0;
640 GQuark name_quark = g_quark_from_string(field_name);
312c056a
PP
641 struct bt_field_type_common **member_ft;
642 GQuark *member_name;
273b65be
JG
643
644 /* Make sure structure does not contain a field of the same name */
fe0fe95c 645 if (g_hash_table_lookup_extended(field_name_to_index,
4e8304f7
PP
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);
273b65be
JG
649 ret = -1;
650 goto end;
651 }
652
312c056a
PP
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;
273b65be
JG
675 }
676
312c056a
PP
677 *member_name = name_quark;
678 *member_ft = bt_get(field_type);
273b65be 679 g_hash_table_insert(field_name_to_index,
312c056a
PP
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
273b65be
JG
685end:
686 return ret;
687}
688
3dca2276
PP
689BT_HIDDEN
690int bt_field_type_common_integer_validate(struct bt_field_type_common *ft)
b3dbeb52
PP
691{
692 int ret = 0;
3dca2276 693 struct bt_field_type_common_integer *int_ft = BT_FROM_COMMON(ft);
b3dbeb52 694
3dca2276 695 if (int_ft->mapped_clock_class && int_ft->is_signed) {
4e8304f7
PP
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\"",
3dca2276
PP
698 ft, int_ft->mapped_clock_class,
699 bt_clock_class_get_name(int_ft->mapped_clock_class));
b3dbeb52
PP
700 ret = -1;
701 goto end;
702 }
703
704end:
705 return ret;
706}
707
d49e1284 708static
3dca2276
PP
709struct enumeration_mapping *bt_field_type_common_enumeration_get_mapping_by_index(
710 struct bt_field_type_common *ft, uint64_t index)
d49e1284 711{
3dca2276 712 struct bt_field_type_common_enumeration *enum_ft = BT_FROM_COMMON(ft);
d49e1284 713 struct enumeration_mapping *mapping = NULL;
d49e1284 714
3dca2276 715 if (index >= enum_ft->entries->len) {
4e8304f7
PP
716 BT_LOGW("Invalid parameter: index is out of bounds: "
717 "addr=%p, index=%" PRIu64 ", count=%u",
3dca2276 718 ft, index, enum_ft->entries->len);
d49e1284
JG
719 goto end;
720 }
721
3dca2276
PP
722 mapping = g_ptr_array_index(enum_ft->entries, index);
723
d49e1284
JG
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
3dca2276
PP
733void bt_field_type_common_enumeration_set_range_overlap(
734 struct bt_field_type_common_enumeration *ft)
d49e1284 735{
4e8304f7 736 int64_t i, j, len;
d49e1284
JG
737 int is_signed;
738
4e8304f7 739 BT_LOGV("Setting enumeration field type's overlap flag: addr=%p",
3dca2276
PP
740 ft);
741 len = ft->entries->len;
742 is_signed = bt_field_type_common_integer_is_signed(
743 BT_TO_COMMON(ft->container_ft));
d49e1284
JG
744
745 for (i = 0; i < len; i++) {
746 for (j = i + 1; j < len; j++) {
747 struct enumeration_mapping *mapping[2];
748
3dca2276
PP
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);
d49e1284
JG
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) {
3dca2276 758 ft->has_overlapping_ranges = BT_TRUE;
dfc1504d 759 goto end;
d49e1284
JG
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) {
3dca2276 766 ft->has_overlapping_ranges = BT_TRUE;
dfc1504d 767 goto end;
d49e1284
JG
768 }
769 }
770 }
771 }
dfc1504d
PP
772
773end:
3dca2276 774 if (ft->has_overlapping_ranges) {
dfc1504d
PP
775 BT_LOGV_STR("Enumeration field type has overlapping ranges.");
776 } else {
777 BT_LOGV_STR("Enumeration field type has no overlapping ranges.");
778 }
d49e1284
JG
779}
780
3dca2276
PP
781BT_HIDDEN
782int bt_field_type_common_enumeration_validate_recursive(
783 struct bt_field_type_common *ft)
9ce21c30
JG
784{
785 int ret = 0;
3dca2276 786 struct bt_field_type_common_enumeration *enum_ft = BT_FROM_COMMON(ft);
9ce21c30 787
3dca2276
PP
788 ret = bt_field_type_common_integer_validate(
789 BT_TO_COMMON(enum_ft->container_ft));
81e36fac 790 if (ret) {
4e8304f7
PP
791 BT_LOGW("Invalid enumeration field type: container type is invalid: "
792 "enum-ft-addr=%p, int-ft-addr=%p",
3dca2276 793 ft, enum_ft->container_ft);
81e36fac
PP
794 goto end;
795 }
9ce21c30 796
81e36fac 797 /* Ensure enum has entries */
3dca2276 798 if (enum_ft->entries->len == 0) {
4e8304f7 799 BT_LOGW("Invalid enumeration field type: no entries: "
3dca2276 800 "addr=%p", ft);
4e8304f7
PP
801 ret = -1;
802 goto end;
803 }
81e36fac
PP
804
805end:
81e36fac
PP
806 return ret;
807}
808
3dca2276
PP
809BT_HIDDEN
810int bt_field_type_common_sequence_validate_recursive(
811 struct bt_field_type_common *ft)
81e36fac
PP
812{
813 int ret = 0;
3dca2276 814 struct bt_field_type_common_sequence *seq_ft = BT_FROM_COMMON(ft);
81e36fac
PP
815
816 /* Length field name should be set at this point */
3dca2276 817 if (seq_ft->length_field_name->len == 0) {
4e8304f7 818 BT_LOGW("Invalid sequence field type: no length field name: "
3dca2276 819 "addr=%p", ft);
81e36fac
PP
820 ret = -1;
821 goto end;
5d161ecc 822 }
81e36fac 823
3dca2276 824 ret = bt_field_type_common_validate(seq_ft->element_ft);
4e8304f7
PP
825 if (ret) {
826 BT_LOGW("Invalid sequence field type: invalid element field type: "
827 "seq-ft-addr=%p, element-ft-add=%p",
3dca2276 828 ft, seq_ft->element_ft);
4e8304f7 829 }
81e36fac
PP
830
831end:
81e36fac
PP
832 return ret;
833}
834
3dca2276
PP
835BT_HIDDEN
836int bt_field_type_common_array_validate_recursive(
837 struct bt_field_type_common *ft)
81e36fac
PP
838{
839 int ret = 0;
3dca2276 840 struct bt_field_type_common_array *array_ft = BT_FROM_COMMON(ft);
81e36fac 841
3dca2276 842 ret = bt_field_type_common_validate(array_ft->element_ft);
4e8304f7
PP
843 if (ret) {
844 BT_LOGW("Invalid array field type: invalid element field type: "
845 "array-ft-addr=%p, element-ft-add=%p",
3dca2276 846 ft, array_ft->element_ft);
4e8304f7 847 }
81e36fac 848
81e36fac
PP
849 return ret;
850}
851
3dca2276
PP
852BT_HIDDEN
853int bt_field_type_common_structure_validate_recursive(
854 struct bt_field_type_common *ft)
81e36fac
PP
855{
856 int ret = 0;
3dca2276
PP
857 struct bt_field_type_common *child_ft = NULL;
858 int64_t field_count =
859 bt_field_type_common_structure_get_field_count(ft);
544d0515 860 int64_t i;
81e36fac 861
f6ccaed9 862 BT_ASSERT(field_count >= 0);
81e36fac
PP
863
864 for (i = 0; i < field_count; ++i) {
4e8304f7 865 const char *field_name;
81e36fac 866
094ff7c0 867 ret = bt_field_type_common_structure_borrow_field_by_index(ft,
3dca2276 868 &field_name, &child_ft, i);
f6ccaed9 869 BT_ASSERT(ret == 0);
3dca2276 870 ret = bt_field_type_common_validate(child_ft);
81e36fac 871 if (ret) {
4e8304f7
PP
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,
3dca2276 876 ft, child_ft, field_name, i);
81e36fac
PP
877 goto end;
878 }
81e36fac
PP
879 }
880
881end:
81e36fac
PP
882 return ret;
883}
884
96e8f959 885static
3dca2276
PP
886bt_bool bt_field_type_common_enumeration_has_overlapping_ranges(
887 struct bt_field_type_common_enumeration *enum_ft)
96e8f959 888{
3dca2276
PP
889 if (!enum_ft->common.frozen) {
890 bt_field_type_common_enumeration_set_range_overlap(enum_ft);
d49e1284 891 }
3dca2276
PP
892
893 return enum_ft->has_overlapping_ranges;
96e8f959
MD
894}
895
3dca2276
PP
896BT_HIDDEN
897int bt_field_type_common_variant_validate_recursive(
898 struct bt_field_type_common *ft)
81e36fac
PP
899{
900 int ret = 0;
544d0515 901 int64_t field_count;
3dca2276
PP
902 struct bt_field_type_common *child_ft = NULL;
903 struct bt_field_type_common_variant *var_ft = BT_FROM_COMMON(ft);
544d0515 904 int64_t i;
c6c0ca42 905
3dca2276 906 if (var_ft->tag_name->len == 0) {
4e8304f7 907 BT_LOGW("Invalid variant field type: no tag field name: "
3dca2276 908 "addr=%p", ft);
4e8304f7
PP
909 ret = -1;
910 goto end;
911 }
912
3dca2276 913 if (!var_ft->tag_ft) {
4e8304f7 914 BT_LOGW("Invalid variant field type: no tag field type: "
3dca2276
PP
915 "addr=%p, tag-field-name=\"%s\"", var_ft,
916 var_ft->tag_name->str);
81e36fac
PP
917 ret = -1;
918 goto end;
919 }
920
3dca2276 921 if (bt_field_type_common_enumeration_has_overlapping_ranges(var_ft->tag_ft)) {
4e8304f7
PP
922 BT_LOGW("Invalid variant field type: enumeration tag field type has overlapping ranges: "
923 "variant-ft-addr=%p, tag-field-name=\"%s\", "
3dca2276
PP
924 "enum-ft-addr=%p", ft, var_ft->tag_name->str,
925 var_ft->tag_ft);
96e8f959
MD
926 ret = -1;
927 goto end;
928 }
929
e9eb537e 930 /*
2d4b0539
MD
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.
e9eb537e 934 *
2d4b0539
MD
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).
e9eb537e 943 */
3dca2276 944 field_count = bt_field_type_common_variant_get_field_count(ft);
81e36fac 945 if (field_count < 0) {
4e8304f7
PP
946 BT_LOGW("Invalid variant field type: no fields: "
947 "addr=%p, tag-field-name=\"%s\"",
3dca2276 948 ft, var_ft->tag_name->str);
81e36fac
PP
949 ret = -1;
950 goto end;
951 }
952
953 for (i = 0; i < field_count; ++i) {
4e8304f7 954 const char *field_name;
81e36fac 955
094ff7c0 956 ret = bt_field_type_common_variant_borrow_field_by_index(ft,
3dca2276 957 &field_name, &child_ft, i);
f6ccaed9 958 BT_ASSERT(ret == 0);
3dca2276 959 ret = bt_field_type_common_validate(child_ft);
81e36fac 960 if (ret) {
4e8304f7
PP
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,
3dca2276 966 ft, var_ft->tag_name->str, child_ft,
4e8304f7 967 field_name, i);
81e36fac
PP
968 goto end;
969 }
81e36fac
PP
970 }
971
972end:
81e36fac
PP
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
3dca2276 983int bt_field_type_common_validate(struct bt_field_type_common *ft)
81e36fac
PP
984{
985 int ret = 0;
81e36fac 986
3dca2276 987 BT_ASSERT(ft);
81e36fac 988
3dca2276 989 if (ft->valid) {
81e36fac
PP
990 /* Already marked as valid */
991 goto end;
992 }
993
3dca2276
PP
994 if (ft->methods->validate) {
995 ret = ft->methods->validate(ft);
81e36fac
PP
996 }
997
3dca2276 998 if (ret == 0 && ft->frozen) {
81e36fac 999 /* Field type is valid */
3dca2276
PP
1000 BT_LOGV("Marking field type as valid: addr=%p", ft);
1001 ft->valid = 1;
81e36fac
PP
1002 }
1003
9ce21c30
JG
1004end:
1005 return ret;
1006}
1007
50842bdc 1008struct bt_field_type *bt_field_type_integer_create(unsigned int size)
273b65be 1009{
3dca2276 1010 struct bt_field_type_common_integer *integer = NULL;
273b65be 1011
4e8304f7
PP
1012 BT_LOGD("Creating integer field type object: size=%u", size);
1013
4e8304f7
PP
1014 if (size == 0 || size > 64) {
1015 BT_LOGW("Invalid parameter: size must be between 1 and 64: "
1016 "size=%u", size);
3dca2276
PP
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;
273b65be
JG
1024 }
1025
3dca2276
PP
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);
4e8304f7 1029 BT_LOGD("Created integer field type object: addr=%p, size=%u",
3dca2276
PP
1030 integer, size);
1031 goto end;
1032
1033error:
1034 BT_PUT(integer);
1035
1036end:
1037 return (void *) integer;
273b65be
JG
1038}
1039
3dca2276
PP
1040BT_HIDDEN
1041int bt_field_type_common_integer_get_size(struct bt_field_type_common *ft)
b92ddaaa 1042{
3dca2276
PP
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}
b92ddaaa 1050
3dca2276
PP
1051int bt_field_type_integer_get_size(struct bt_field_type *ft)
1052{
1053 return bt_field_type_common_integer_get_size((void *) ft);
b92ddaaa
JG
1054}
1055
3dca2276
PP
1056BT_HIDDEN
1057bt_bool bt_field_type_common_integer_is_signed(struct bt_field_type_common *ft)
b92ddaaa 1058{
3dca2276 1059 struct bt_field_type_common_integer *int_ft = BT_FROM_COMMON(ft);
b92ddaaa 1060
3dca2276
PP
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;
b92ddaaa
JG
1065}
1066
3dca2276 1067bt_bool bt_field_type_integer_is_signed(struct bt_field_type *ft)
c14d64fa 1068{
3dca2276 1069 return bt_field_type_common_integer_is_signed((void *) ft);
c14d64fa
PP
1070}
1071
3dca2276
PP
1072BT_HIDDEN
1073int bt_field_type_common_integer_set_is_signed(struct bt_field_type_common *ft,
c14d64fa 1074 bt_bool is_signed)
273b65be
JG
1075{
1076 int ret = 0;
3dca2276 1077 struct bt_field_type_common_integer *int_ft = BT_FROM_COMMON(ft);
273b65be 1078
3dca2276 1079 if (!ft) {
4e8304f7
PP
1080 BT_LOGW_STR("Invalid parameter: field type is NULL.");
1081 ret = -1;
1082 goto end;
1083 }
1084
3dca2276 1085 if (ft->frozen) {
4e8304f7 1086 BT_LOGW("Invalid parameter: field type is frozen: addr=%p",
3dca2276 1087 ft);
4e8304f7
PP
1088 ret = -1;
1089 goto end;
1090 }
1091
3dca2276 1092 if (ft->id != BT_FIELD_TYPE_ID_INTEGER) {
4e8304f7 1093 BT_LOGW("Invalid parameter: field type is not an integer field type: "
3dca2276
PP
1094 "addr=%p, ft-id=%s", ft,
1095 bt_common_field_type_id_string(ft->id));
273b65be
JG
1096 ret = -1;
1097 goto end;
1098 }
1099
3dca2276 1100 int_ft->is_signed = !!is_signed;
dfc1504d 1101 BT_LOGV("Set integer field type's signedness: addr=%p, is-signed=%d",
3dca2276
PP
1102 ft, is_signed);
1103
273b65be
JG
1104end:
1105 return ret;
1106}
1107
3dca2276
PP
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,
3bc8ebda 1117 unsigned int size)
c3c35de4
JD
1118{
1119 int ret = 0;
3dca2276 1120 struct bt_field_type_common_integer *int_ft = BT_FROM_COMMON(ft);
c3c35de4 1121
3dca2276 1122 if (!ft) {
4e8304f7
PP
1123 BT_LOGW_STR("Invalid parameter: field type is NULL.");
1124 ret = -1;
1125 goto end;
1126 }
1127
3dca2276 1128 if (ft->frozen) {
4e8304f7 1129 BT_LOGW("Invalid parameter: field type is frozen: addr=%p",
3dca2276 1130 ft);
4e8304f7
PP
1131 ret = -1;
1132 goto end;
1133 }
1134
3dca2276 1135 if (ft->id != BT_FIELD_TYPE_ID_INTEGER) {
4e8304f7 1136 BT_LOGW("Invalid parameter: field type is not an integer field type: "
3dca2276
PP
1137 "addr=%p, ft-id=%s", ft,
1138 bt_common_field_type_id_string(ft->id));
4e8304f7
PP
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: "
3dca2276 1145 "addr=%p, size=%u", ft, size);
c3c35de4
JD
1146 ret = -1;
1147 goto end;
1148 }
1149
3dca2276 1150 int_ft->size = size;
3bc8ebda 1151 BT_LOGV("Set integer field type's size: addr=%p, size=%u",
3dca2276
PP
1152 ft, size);
1153
c3c35de4
JD
1154end:
1155 return ret;
1156}
1157
3dca2276
PP
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)
b92ddaaa 1167{
3dca2276
PP
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}
b92ddaaa 1175
3dca2276
PP
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);
b92ddaaa
JG
1180}
1181
3dca2276
PP
1182BT_HIDDEN
1183int bt_field_type_common_integer_set_base(struct bt_field_type_common *ft,
50842bdc 1184 enum bt_integer_base base)
273b65be
JG
1185{
1186 int ret = 0;
3dca2276 1187 struct bt_field_type_common_integer *int_ft = BT_FROM_COMMON(ft);
273b65be 1188
3dca2276 1189 if (!ft) {
4e8304f7
PP
1190 BT_LOGW_STR("Invalid parameter: field type is NULL.");
1191 ret = -1;
1192 goto end;
1193 }
1194
3dca2276 1195 if (ft->frozen) {
4e8304f7 1196 BT_LOGW("Invalid parameter: field type is frozen: addr=%p",
3dca2276 1197 ft);
4e8304f7
PP
1198 ret = -1;
1199 goto end;
1200 }
1201
3dca2276 1202 if (ft->id != BT_FIELD_TYPE_ID_INTEGER) {
4e8304f7 1203 BT_LOGW("Invalid parameter: field type is not an integer field type: "
3dca2276
PP
1204 "addr=%p, ft-id=%s", ft,
1205 bt_common_field_type_id_string(ft->id));
273b65be
JG
1206 ret = -1;
1207 goto end;
1208 }
1209
1210 switch (base) {
50842bdc
PP
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:
273b65be 1216 {
3dca2276 1217 int_ft->base = base;
273b65be
JG
1218 break;
1219 }
1220 default:
4e8304f7 1221 BT_LOGW("Invalid parameter: unknown integer field type base: "
3dca2276 1222 "addr=%p, base=%d", ft, base);
273b65be
JG
1223 ret = -1;
1224 }
dfc1504d
PP
1225
1226 BT_LOGV("Set integer field type's base: addr=%p, base=%s",
3dca2276 1227 ft, bt_common_integer_base_string(base));
dfc1504d 1228
273b65be
JG
1229end:
1230 return ret;
1231}
1232
3dca2276
PP
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)
b92ddaaa 1242{
3dca2276
PP
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}
b92ddaaa 1250
3dca2276
PP
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);
b92ddaaa
JG
1255}
1256
3dca2276
PP
1257BT_HIDDEN
1258int bt_field_type_common_integer_set_encoding(struct bt_field_type_common *ft,
50842bdc 1259 enum bt_string_encoding encoding)
273b65be
JG
1260{
1261 int ret = 0;
3dca2276 1262 struct bt_field_type_common_integer *int_ft = BT_FROM_COMMON(ft);
273b65be 1263
3dca2276 1264 if (!ft) {
4e8304f7
PP
1265 BT_LOGW_STR("Invalid parameter: field type is NULL.");
1266 ret = -1;
1267 goto end;
1268 }
1269
3dca2276 1270 if (ft->frozen) {
4e8304f7 1271 BT_LOGW("Invalid parameter: field type is frozen: addr=%p",
3dca2276 1272 ft);
4e8304f7
PP
1273 ret = -1;
1274 goto end;
1275 }
1276
3dca2276 1277 if (ft->id != BT_FIELD_TYPE_ID_INTEGER) {
4e8304f7 1278 BT_LOGW("Invalid parameter: field type is not an integer field type: "
3dca2276
PP
1279 "addr=%p, ft-id=%s", ft,
1280 bt_common_field_type_id_string(ft->id));
4e8304f7
PP
1281 ret = -1;
1282 goto end;
1283 }
1284
50842bdc
PP
1285 if (encoding != BT_STRING_ENCODING_UTF8 &&
1286 encoding != BT_STRING_ENCODING_ASCII &&
1287 encoding != BT_STRING_ENCODING_NONE) {
4e8304f7 1288 BT_LOGW("Invalid parameter: unknown string encoding: "
3dca2276 1289 "addr=%p, encoding=%d", ft, encoding);
273b65be
JG
1290 ret = -1;
1291 goto end;
1292 }
1293
3dca2276 1294 int_ft->encoding = encoding;
dfc1504d 1295 BT_LOGV("Set integer field type's encoding: addr=%p, encoding=%s",
3dca2276
PP
1296 ft, bt_common_string_encoding_string(encoding));
1297
273b65be
JG
1298end:
1299 return ret;
1300}
1301
3dca2276
PP
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
094ff7c0 1309struct bt_clock_class *bt_field_type_common_integer_borrow_mapped_clock_class(
3dca2276 1310 struct bt_field_type_common *ft)
6cfb906f 1311{
3dca2276
PP
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");
094ff7c0 1317 return int_ft->mapped_clock_class;
3dca2276 1318}
6cfb906f 1319
094ff7c0 1320struct bt_clock_class *bt_field_type_integer_borrow_mapped_clock_class(
3dca2276
PP
1321 struct bt_field_type *ft)
1322{
094ff7c0
PP
1323 return bt_field_type_common_integer_borrow_mapped_clock_class(
1324 (void *) ft);
6cfb906f
JG
1325}
1326
e011d2c1 1327BT_HIDDEN
3dca2276
PP
1328int bt_field_type_common_integer_set_mapped_clock_class_no_check_frozen(
1329 struct bt_field_type_common *ft,
50842bdc 1330 struct bt_clock_class *clock_class)
6cfb906f 1331{
3dca2276 1332 struct bt_field_type_common_integer *int_ft = BT_FROM_COMMON(ft);
6cfb906f
JG
1333 int ret = 0;
1334
4e8304f7
PP
1335 if (!clock_class) {
1336 BT_LOGW_STR("Invalid parameter: clock class is NULL.");
1337 ret = -1;
1338 goto end;
1339 }
1340
3dca2276 1341 if (ft->id != BT_FIELD_TYPE_ID_INTEGER) {
e011d2c1 1342 BT_LOGW("Invalid parameter: field type is not an integer field type: "
3dca2276
PP
1343 "addr=%p, ft-id=%s", ft,
1344 bt_common_field_type_id_string(ft->id));
4e8304f7
PP
1345 goto end;
1346 }
1347
50842bdc 1348 if (!bt_clock_class_is_valid(clock_class)) {
4e8304f7
PP
1349 BT_LOGW("Invalid parameter: clock class is invalid: ft-addr=%p"
1350 "clock-class-addr=%p, clock-class-name=\"%s\"",
3dca2276 1351 ft, clock_class,
50842bdc 1352 bt_clock_class_get_name(clock_class));
6cfb906f
JG
1353 ret = -1;
1354 goto end;
1355 }
1356
3dca2276
PP
1357 bt_put(int_ft->mapped_clock_class);
1358 int_ft->mapped_clock_class = bt_get(clock_class);
dfc1504d
PP
1359 BT_LOGV("Set integer field type's mapped clock class: ft-addr=%p, "
1360 "clock-class-addr=%p, clock-class-name=\"%s\"",
3dca2276
PP
1361 ft, clock_class, bt_clock_class_get_name(clock_class));
1362
6cfb906f
JG
1363end:
1364 return ret;
1365}
1366
3dca2276
PP
1367BT_HIDDEN
1368int bt_field_type_common_integer_set_mapped_clock_class(
1369 struct bt_field_type_common *ft,
50842bdc 1370 struct bt_clock_class *clock_class)
e011d2c1
PP
1371{
1372 int ret = 0;
1373
3dca2276 1374 if (!ft) {
e011d2c1
PP
1375 BT_LOGW_STR("Invalid parameter: field type is NULL.");
1376 ret = -1;
1377 goto end;
1378 }
1379
3dca2276 1380 if (ft->frozen) {
e011d2c1 1381 BT_LOGW("Invalid parameter: field type is frozen: addr=%p",
3dca2276 1382 ft);
e011d2c1
PP
1383 ret = -1;
1384 goto end;
1385 }
1386
3dca2276
PP
1387 ret = bt_field_type_common_integer_set_mapped_clock_class_no_check_frozen(
1388 ft, clock_class);
e011d2c1
PP
1389
1390end:
1391 return ret;
1392}
1393
3dca2276
PP
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
96e8f959 1401static
50842bdc 1402void bt_field_type_enum_iter_destroy(struct bt_object *obj)
96e8f959 1403{
50842bdc 1404 struct bt_field_type_enumeration_mapping_iterator *iter =
d49e1284 1405 container_of(obj,
50842bdc 1406 struct bt_field_type_enumeration_mapping_iterator,
d49e1284 1407 base);
96e8f959 1408
ec159b1e
PP
1409 BT_LOGD("Destroying enumeration field type mapping iterator: addr=%p",
1410 obj);
1411 BT_LOGD_STR("Putting parent enumeration field type.");
3dca2276 1412 bt_put(iter->enumeration_ft);
d49e1284
JG
1413 g_free(iter);
1414}
1415
1416static
50842bdc 1417struct bt_field_type_enumeration_mapping_iterator *
3dca2276
PP
1418bt_field_type_common_enumeration_find_mappings_type(
1419 struct bt_field_type_common *ft,
50842bdc 1420 enum bt_field_type_enumeration_mapping_iterator_type iterator_type)
d49e1284 1421{
50842bdc 1422 struct bt_field_type_enumeration_mapping_iterator *iter = NULL;
d49e1284 1423
3dca2276
PP
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");
50842bdc 1427 iter = g_new0(struct bt_field_type_enumeration_mapping_iterator, 1);
d49e1284 1428 if (!iter) {
4e8304f7 1429 BT_LOGE_STR("Failed to allocate one enumeration field type mapping.");
d49e1284
JG
1430 goto end;
1431 }
1432
50842bdc 1433 bt_object_init(&iter->base, bt_field_type_enum_iter_destroy);
3dca2276 1434 iter->enumeration_ft = bt_get(ft);
d49e1284
JG
1435 iter->index = -1;
1436 iter->type = iterator_type;
3dca2276 1437
96e8f959 1438end:
d49e1284 1439 return iter;
96e8f959
MD
1440}
1441
3dca2276 1442BT_HIDDEN
50842bdc 1443struct bt_field_type_enumeration_mapping_iterator *
3dca2276
PP
1444bt_field_type_common_enumeration_find_mappings_by_name(
1445 struct bt_field_type_common *ft, const char *name)
96e8f959 1446{
50842bdc 1447 struct bt_field_type_enumeration_mapping_iterator *iter;
96e8f959 1448
3dca2276
PP
1449 iter = bt_field_type_common_enumeration_find_mappings_type(
1450 ft, ITERATOR_BY_NAME);
d49e1284 1451 if (!iter) {
631234da 1452 BT_LOGW("Cannot create enumeration field type mapping iterator: "
3dca2276 1453 "ft-addr=%p, mapping-name=\"%s\"", ft, name);
d49e1284
JG
1454 goto error;
1455 }
1456
1457 iter->u.name_quark = g_quark_try_string(name);
1458 if (!iter->u.name_quark) {
74fb0452
JG
1459 /*
1460 * No results are possible, set the iterator's position at the
1461 * end.
1462 */
3dca2276 1463 iter->index = iter->enumeration_ft->entries->len;
d49e1284 1464 }
3dca2276 1465
d49e1284 1466 return iter;
3dca2276 1467
d49e1284
JG
1468error:
1469 bt_put(iter);
1470 return NULL;
96e8f959
MD
1471}
1472
3dca2276
PP
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
50842bdc
PP
1481int bt_field_type_enumeration_mapping_iterator_next(
1482 struct bt_field_type_enumeration_mapping_iterator *iter)
96e8f959 1483{
3dca2276 1484 struct bt_field_type_common_enumeration *enum_ft = iter->enumeration_ft;
96e8f959
MD
1485 int i, ret = 0, len;
1486
d975f66c 1487 BT_ASSERT_PRE_NON_NULL(iter, "Enumeration field type mapping iterator");
3dca2276 1488 len = enum_ft->entries->len;
96e8f959
MD
1489 for (i = iter->index + 1; i < len; i++) {
1490 struct enumeration_mapping *mapping =
3dca2276
PP
1491 bt_field_type_common_enumeration_get_mapping_by_index(
1492 BT_TO_COMMON(enum_ft), i);
96e8f959 1493
d49e1284 1494 switch (iter->type) {
96e8f959
MD
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:
ec159b1e
PP
1524 BT_LOGF("Invalid enumeration field type mapping iterator type: "
1525 "type=%d", iter->type);
96e8f959
MD
1526 abort();
1527 }
1528 }
1529
1530 ret = -1;
3dca2276 1531
96e8f959
MD
1532end:
1533 return ret;
1534}
1535
3dca2276 1536BT_HIDDEN
50842bdc 1537struct bt_field_type_enumeration_mapping_iterator *
3dca2276
PP
1538bt_field_type_common_enumeration_signed_find_mappings_by_value(
1539 struct bt_field_type_common *ft, int64_t value)
96e8f959 1540{
50842bdc 1541 struct bt_field_type_enumeration_mapping_iterator *iter;
96e8f959 1542
3dca2276
PP
1543 iter = bt_field_type_common_enumeration_find_mappings_type(
1544 ft, ITERATOR_BY_SIGNED_VALUE);
96e8f959 1545 if (!iter) {
631234da 1546 BT_LOGW("Cannot create enumeration field type mapping iterator: "
3dca2276 1547 "ft-addr=%p, value=%" PRId64, ft, value);
96e8f959
MD
1548 goto error;
1549 }
d49e1284 1550
3dca2276
PP
1551 if (bt_field_type_common_integer_is_signed(
1552 BT_TO_COMMON(iter->enumeration_ft->container_ft)) != 1) {
4e8304f7
PP
1553 BT_LOGW("Invalid parameter: enumeration field type is unsigned: "
1554 "enum-ft-addr=%p, int-ft-addr=%p",
3dca2276 1555 ft, iter->enumeration_ft->container_ft);
96e8f959
MD
1556 goto error;
1557 }
4e8304f7 1558
96e8f959 1559 iter->u.signed_value = value;
d49e1284 1560 return iter;
3dca2276 1561
96e8f959
MD
1562error:
1563 bt_put(iter);
1564 return NULL;
1565}
1566
50842bdc 1567struct bt_field_type_enumeration_mapping_iterator *
3dca2276
PP
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)
96e8f959 1579{
50842bdc 1580 struct bt_field_type_enumeration_mapping_iterator *iter;
96e8f959 1581
3dca2276
PP
1582 iter = bt_field_type_common_enumeration_find_mappings_type(
1583 ft, ITERATOR_BY_UNSIGNED_VALUE);
96e8f959 1584 if (!iter) {
631234da 1585 BT_LOGW("Cannot create enumeration field type mapping iterator: "
3dca2276 1586 "ft-addr=%p, value=%" PRIu64, ft, value);
96e8f959
MD
1587 goto error;
1588 }
d49e1284 1589
3dca2276
PP
1590 if (bt_field_type_common_integer_is_signed(
1591 BT_TO_COMMON(iter->enumeration_ft->container_ft)) != 0) {
4e8304f7
PP
1592 BT_LOGW("Invalid parameter: enumeration field type is signed: "
1593 "enum-ft-addr=%p, int-ft-addr=%p",
3dca2276 1594 ft, iter->enumeration_ft->container_ft);
96e8f959
MD
1595 goto error;
1596 }
3dca2276 1597
96e8f959 1598 iter->u.unsigned_value = value;
d49e1284 1599 return iter;
3dca2276 1600
96e8f959
MD
1601error:
1602 bt_put(iter);
1603 return NULL;
1604}
1605
3dca2276
PP
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(
50842bdc 1615 struct bt_field_type_enumeration_mapping_iterator *iter,
d49e1284
JG
1616 const char **mapping_name, int64_t *range_begin,
1617 int64_t *range_end)
1618{
d975f66c
PP
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);
3dca2276
PP
1623 return bt_field_type_common_enumeration_signed_get_mapping_by_index(
1624 (void *) iter->enumeration_ft, iter->index,
d49e1284 1625 mapping_name, range_begin, range_end);
d49e1284
JG
1626}
1627
3dca2276 1628int bt_field_type_enumeration_mapping_iterator_unsigned_get(
50842bdc 1629 struct bt_field_type_enumeration_mapping_iterator *iter,
d49e1284
JG
1630 const char **mapping_name, uint64_t *range_begin,
1631 uint64_t *range_end)
1632{
d975f66c
PP
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);
3dca2276
PP
1637 return bt_field_type_common_enumeration_unsigned_get_mapping_by_index(
1638 (void *) iter->enumeration_ft, iter->index,
d49e1284 1639 mapping_name, range_begin, range_end);
96e8f959
MD
1640}
1641
3dca2276
PP
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,
96e8f959
MD
1646 int64_t *range_end)
1647{
d49e1284 1648 int ret = 0;
96e8f959
MD
1649 struct enumeration_mapping *mapping;
1650
3dca2276
PP
1651 BT_ASSERT_PRE_NON_NULL(ft, "Field type");
1652 BT_ASSERT_PRE_FT_COMMON_HAS_ID(ft,
d975f66c 1653 BT_FIELD_TYPE_ID_ENUM, "Field type");
3dca2276
PP
1654 mapping = bt_field_type_common_enumeration_get_mapping_by_index(ft,
1655 index);
96e8f959 1656 if (!mapping) {
3dca2276 1657 /* bt_field_type_common_enumeration_get_mapping_by_index() logs errors */
d49e1284
JG
1658 ret = -1;
1659 goto end;
96e8f959 1660 }
d49e1284 1661
96e8f959
MD
1662 if (mapping_name) {
1663 *mapping_name = g_quark_to_string(mapping->string);
f6ccaed9 1664 BT_ASSERT(*mapping_name);
96e8f959 1665 }
d49e1284 1666
96e8f959
MD
1667 if (range_begin) {
1668 *range_begin = mapping->range_start._signed;
1669 }
d49e1284 1670
96e8f959
MD
1671 if (range_end) {
1672 *range_end = mapping->range_end._signed;
1673 }
d975f66c 1674
d49e1284
JG
1675end:
1676 return ret;
96e8f959
MD
1677}
1678
3dca2276
PP
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,
96e8f959
MD
1691 const char **mapping_name, uint64_t *range_begin,
1692 uint64_t *range_end)
1693{
d49e1284 1694 int ret = 0;
96e8f959
MD
1695 struct enumeration_mapping *mapping;
1696
3dca2276
PP
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);
96e8f959 1701 if (!mapping) {
3dca2276 1702 /* bt_field_type_common_enumeration_get_mapping_by_index() reports any error */
d49e1284
JG
1703 ret = -1;
1704 goto end;
96e8f959 1705 }
d49e1284 1706
96e8f959
MD
1707 if (mapping_name) {
1708 *mapping_name = g_quark_to_string(mapping->string);
f6ccaed9 1709 BT_ASSERT(*mapping_name);
96e8f959 1710 }
d49e1284 1711
96e8f959
MD
1712 if (range_begin) {
1713 *range_begin = mapping->range_start._unsigned;
1714 }
d49e1284 1715
96e8f959
MD
1716 if (range_end) {
1717 *range_end = mapping->range_end._unsigned;
1718 }
d975f66c 1719
d49e1284
JG
1720end:
1721 return ret;
96e8f959
MD
1722}
1723
3dca2276
PP
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
50842bdc 1733struct bt_field_type *bt_field_type_enumeration_create(
3dca2276 1734 struct bt_field_type *container_ft)
273b65be 1735{
3dca2276
PP
1736 struct bt_field_type_common_enumeration *enumeration = NULL;
1737 struct bt_field_type_common *int_ft = (void *) container_ft;
273b65be 1738
4e8304f7 1739 BT_LOGD("Creating enumeration field type object: int-ft-addr=%p",
3dca2276 1740 container_ft);
4e8304f7 1741
3dca2276 1742 if (!container_ft) {
4e8304f7 1743 BT_LOGW_STR("Invalid parameter: field type is NULL.");
273b65be
JG
1744 goto error;
1745 }
1746
3dca2276 1747 if (int_ft->id != BT_FIELD_TYPE_ID_INTEGER) {
4e8304f7
PP
1748 BT_LOGW("Invalid parameter: container field type is not an integer field type: "
1749 "container-ft-addr=%p, container-ft-id=%s",
3dca2276 1750 container_ft, bt_common_field_type_id_string(int_ft->id));
2a610bb7
JG
1751 goto error;
1752 }
1753
3dca2276 1754 enumeration = g_new0(struct bt_field_type_common_enumeration, 1);
273b65be 1755 if (!enumeration) {
4e8304f7 1756 BT_LOGE_STR("Failed to allocate one enumeration field type.");
273b65be
JG
1757 goto error;
1758 }
1759
3dca2276
PP
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);
4e8304f7
PP
1763 BT_LOGD("Created enumeration field type object: addr=%p, "
1764 "int-ft-addr=%p, int-ft-size=%u",
3dca2276
PP
1765 enumeration, container_ft,
1766 bt_field_type_integer_get_size(container_ft));
1767 goto end;
1768
273b65be 1769error:
3dca2276
PP
1770 BT_PUT(enumeration);
1771
1772end:
1773 return (void *) enumeration;
273b65be
JG
1774}
1775
3dca2276 1776BT_HIDDEN
094ff7c0
PP
1777struct bt_field_type_common *
1778bt_field_type_common_enumeration_borrow_container_field_type(
3dca2276 1779 struct bt_field_type_common *ft)
b92ddaaa 1780{
3dca2276
PP
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");
094ff7c0 1785 return BT_TO_COMMON(enum_ft->container_ft);
3dca2276 1786}
b92ddaaa 1787
094ff7c0 1788struct bt_field_type *bt_field_type_enumeration_borrow_container_field_type(
3dca2276
PP
1789 struct bt_field_type *ft)
1790{
094ff7c0 1791 return (void *) bt_field_type_common_enumeration_borrow_container_field_type(
3dca2276 1792 (void *) ft);
b92ddaaa
JG
1793}
1794
3dca2276
PP
1795BT_HIDDEN
1796int bt_field_type_common_enumeration_signed_add_mapping(
1797 struct bt_field_type_common *ft, const char *string,
273b65be
JG
1798 int64_t range_start, int64_t range_end)
1799{
1800 int ret = 0;
1801 GQuark mapping_name;
1802 struct enumeration_mapping *mapping;
3dca2276 1803 struct bt_field_type_common_enumeration *enum_ft = BT_FROM_COMMON(ft);
a39fa057 1804 char *escaped_string;
273b65be 1805
3dca2276 1806 if (!ft) {
4e8304f7
PP
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
3dca2276 1818 if (ft->frozen) {
4e8304f7 1819 BT_LOGW("Invalid parameter: field type is frozen: addr=%p",
3dca2276 1820 ft);
4e8304f7
PP
1821 ret = -1;
1822 goto end;
1823 }
1824
3dca2276 1825 if (ft->id != BT_FIELD_TYPE_ID_ENUM) {
4e8304f7 1826 BT_LOGW("Invalid parameter: field type is not an enumeration field type: "
3dca2276
PP
1827 "addr=%p, ft-id=%s", ft,
1828 bt_common_field_type_id_string(ft->id));
4e8304f7
PP
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,
3dca2276 1836 ft, range_start, range_end);
273b65be
JG
1837 ret = -1;
1838 goto end;
1839 }
1840
4e8304f7
PP
1841 if (strlen(string) == 0) {
1842 BT_LOGW("Invalid parameter: mapping name is an empty string: "
3dca2276 1843 "enum-ft-addr=%p, mapping-name-addr=%p", ft,
4e8304f7 1844 string);
273b65be
JG
1845 ret = -1;
1846 goto end;
1847 }
1848
a39fa057
JG
1849 escaped_string = g_strescape(string, NULL);
1850 if (!escaped_string) {
4e8304f7
PP
1851 BT_LOGE("Cannot escape mapping name: enum-ft-addr=%p, "
1852 "mapping-name-addr=%p, mapping-name=\"%s\"",
3dca2276 1853 ft, string, string);
a39fa057
JG
1854 ret = -1;
1855 goto end;
1856 }
1857
273b65be
JG
1858 mapping = g_new(struct enumeration_mapping, 1);
1859 if (!mapping) {
4e8304f7 1860 BT_LOGE_STR("Failed to allocate one enumeration mapping.");
273b65be 1861 ret = -1;
a39fa057 1862 goto error_free;
273b65be 1863 }
96e8f959 1864 mapping_name = g_quark_from_string(escaped_string);
b92ddaaa
JG
1865 *mapping = (struct enumeration_mapping) {
1866 .range_start._signed = range_start,
96e8f959
MD
1867 .range_end._signed = range_end,
1868 .string = mapping_name,
1869 };
3dca2276
PP
1870 g_ptr_array_add(enum_ft->entries, mapping);
1871 g_ptr_array_sort(enum_ft->entries,
1872 (GCompareFunc) compare_enumeration_mappings_signed);
dfc1504d
PP
1873 BT_LOGV("Added mapping to signed enumeration field type: addr=%p, "
1874 "name=\"%s\", range-start=%" PRId64 ", "
1875 "range-end=%" PRId64,
3dca2276
PP
1876 ft, string, range_start, range_end);
1877
b92ddaaa
JG
1878error_free:
1879 free(escaped_string);
3dca2276 1880
b92ddaaa
JG
1881end:
1882 return ret;
1883}
1884
3dca2276
PP
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,
b92ddaaa
JG
1896 uint64_t range_start, uint64_t range_end)
1897{
1898 int ret = 0;
1899 GQuark mapping_name;
1900 struct enumeration_mapping *mapping;
3dca2276 1901 struct bt_field_type_common_enumeration *enum_ft = BT_FROM_COMMON(ft);
b92ddaaa
JG
1902 char *escaped_string;
1903
3dca2276 1904 if (!ft) {
4e8304f7
PP
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
3dca2276 1916 if (ft->frozen) {
4e8304f7 1917 BT_LOGW("Invalid parameter: field type is frozen: addr=%p",
3dca2276 1918 ft);
4e8304f7
PP
1919 ret = -1;
1920 goto end;
1921 }
1922
3dca2276 1923 if (ft->id != BT_FIELD_TYPE_ID_ENUM) {
4e8304f7 1924 BT_LOGW("Invalid parameter: field type is not an enumeration field type: "
3dca2276
PP
1925 "addr=%p, ft-id=%s", ft,
1926 bt_common_field_type_id_string(ft->id));
4e8304f7
PP
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,
3dca2276 1934 ft, range_start, range_end);
b92ddaaa
JG
1935 ret = -1;
1936 goto end;
1937 }
1938
4e8304f7
PP
1939 if (strlen(string) == 0) {
1940 BT_LOGW("Invalid parameter: mapping name is an empty string: "
3dca2276 1941 "enum-ft-addr=%p, mapping-name-addr=%p", ft,
4e8304f7 1942 string);
b92ddaaa
JG
1943 ret = -1;
1944 goto end;
1945 }
1946
1947 escaped_string = g_strescape(string, NULL);
1948 if (!escaped_string) {
4e8304f7
PP
1949 BT_LOGE("Cannot escape mapping name: enum-ft-addr=%p, "
1950 "mapping-name-addr=%p, mapping-name=\"%s\"",
3dca2276 1951 ft, string, string);
b92ddaaa
JG
1952 ret = -1;
1953 goto end;
1954 }
1955
b92ddaaa
JG
1956 mapping = g_new(struct enumeration_mapping, 1);
1957 if (!mapping) {
4e8304f7 1958 BT_LOGE_STR("Failed to allocate one enumeration mapping.");
b92ddaaa
JG
1959 ret = -1;
1960 goto error_free;
1961 }
96e8f959 1962 mapping_name = g_quark_from_string(escaped_string);
b92ddaaa
JG
1963 *mapping = (struct enumeration_mapping) {
1964 .range_start._unsigned = range_start,
96e8f959
MD
1965 .range_end._unsigned = range_end,
1966 .string = mapping_name,
1967 };
3dca2276
PP
1968 g_ptr_array_add(enum_ft->entries, mapping);
1969 g_ptr_array_sort(enum_ft->entries,
1970 (GCompareFunc) compare_enumeration_mappings_unsigned);
dfc1504d
PP
1971 BT_LOGV("Added mapping to unsigned enumeration field type: addr=%p, "
1972 "name=\"%s\", range-start=%" PRIu64 ", "
1973 "range-end=%" PRIu64,
3dca2276
PP
1974 ft, string, range_start, range_end);
1975
a39fa057
JG
1976error_free:
1977 free(escaped_string);
3dca2276 1978
273b65be
JG
1979end:
1980 return ret;
1981}
1982
3dca2276
PP
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)
b92ddaaa 1986{
3dca2276
PP
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);
b92ddaaa 1996
3dca2276
PP
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);
b92ddaaa
JG
2006}
2007
50842bdc 2008struct bt_field_type *bt_field_type_floating_point_create(void)
273b65be 2009{
3dca2276
PP
2010 struct bt_field_type_common_floating_point *floating_point =
2011 g_new0(struct bt_field_type_common_floating_point, 1);
273b65be 2012
4e8304f7
PP
2013 BT_LOGD_STR("Creating floating point number field type object.");
2014
273b65be 2015 if (!floating_point) {
4e8304f7 2016 BT_LOGE_STR("Failed to allocate one floating point number field type.");
273b65be
JG
2017 goto end;
2018 }
2019
3dca2276
PP
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);
4e8304f7 2024 BT_LOGD("Created floating point number field type object: addr=%p, "
3dca2276 2025 "exp-size=%u, mant-size=%u", floating_point,
4e8304f7 2026 floating_point->exp_dig, floating_point->mant_dig);
3dca2276 2027
273b65be 2028end:
3dca2276 2029 return (void *) floating_point;
273b65be
JG
2030}
2031
3dca2276
PP
2032BT_HIDDEN
2033int bt_field_type_common_floating_point_get_exponent_digits(
2034 struct bt_field_type_common *ft)
b92ddaaa 2035{
3dca2276 2036 struct bt_field_type_common_floating_point *flt_ft = BT_FROM_COMMON(ft);
b92ddaaa 2037
3dca2276
PP
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;
b92ddaaa
JG
2042}
2043
3dca2276
PP
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)
273b65be
JG
2055{
2056 int ret = 0;
3dca2276 2057 struct bt_field_type_common_floating_point *flt_ft = BT_FROM_COMMON(ft);
273b65be 2058
3dca2276 2059 if (!ft) {
4e8304f7
PP
2060 BT_LOGW_STR("Invalid parameter: field type is NULL.");
2061 ret = -1;
2062 goto end;
2063 }
2064
3dca2276 2065 if (ft->frozen) {
4e8304f7 2066 BT_LOGW("Invalid parameter: field type is frozen: addr=%p",
3dca2276 2067 ft);
4e8304f7
PP
2068 ret = -1;
2069 goto end;
2070 }
2071
3dca2276 2072 if (ft->id != BT_FIELD_TYPE_ID_FLOAT) {
4e8304f7 2073 BT_LOGW("Invalid parameter: field type is not a floating point number field type: "
3dca2276
PP
2074 "addr=%p, ft-id=%s", ft,
2075 bt_common_field_type_id_string(ft->id));
273b65be
JG
2076 ret = -1;
2077 goto end;
2078 }
2079
273b65be
JG
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)) {
4e8304f7 2084 BT_LOGW("Invalid parameter: invalid exponent size: "
3dca2276 2085 "addr=%p, exp-size=%u", ft, exponent_digits);
273b65be
JG
2086 ret = -1;
2087 goto end;
2088 }
2089
3dca2276 2090 flt_ft->exp_dig = exponent_digits;
dfc1504d 2091 BT_LOGV("Set floating point number field type's exponent size: addr=%p, "
3dca2276
PP
2092 "exp-size=%u", ft, exponent_digits);
2093
273b65be
JG
2094end:
2095 return ret;
2096}
2097
3dca2276
PP
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)
b92ddaaa 2108{
3dca2276 2109 struct bt_field_type_common_floating_point *flt_ft = BT_FROM_COMMON(ft);
b92ddaaa 2110
3dca2276
PP
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;
b92ddaaa
JG
2115}
2116
3dca2276
PP
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)
273b65be
JG
2127{
2128 int ret = 0;
3dca2276 2129 struct bt_field_type_common_floating_point *flt_ft = BT_FROM_COMMON(ft);
273b65be 2130
3dca2276 2131 if (!ft) {
4e8304f7
PP
2132 BT_LOGW_STR("Invalid parameter: field type is NULL.");
2133 ret = -1;
2134 goto end;
2135 }
2136
3dca2276 2137 if (ft->frozen) {
4e8304f7 2138 BT_LOGW("Invalid parameter: field type is frozen: addr=%p",
3dca2276 2139 ft);
4e8304f7
PP
2140 ret = -1;
2141 goto end;
2142 }
2143
3dca2276 2144 if (ft->id != BT_FIELD_TYPE_ID_FLOAT) {
4e8304f7 2145 BT_LOGW("Invalid parameter: field type is not a floating point number field type: "
3dca2276
PP
2146 "addr=%p, ft-id=%s", ft,
2147 bt_common_field_type_id_string(ft->id));
273b65be
JG
2148 ret = -1;
2149 goto end;
2150 }
2151
273b65be
JG
2152 if ((mantissa_digits != FLT_MANT_DIG) &&
2153 (mantissa_digits != DBL_MANT_DIG) &&
2154 (mantissa_digits != LDBL_MANT_DIG)) {
4e8304f7 2155 BT_LOGW("Invalid parameter: invalid mantissa size: "
3dca2276 2156 "addr=%p, mant-size=%u", ft, mantissa_digits);
273b65be
JG
2157 ret = -1;
2158 goto end;
2159 }
2160
3dca2276 2161 flt_ft->mant_dig = mantissa_digits;
dfc1504d 2162 BT_LOGV("Set floating point number field type's mantissa size: addr=%p, "
3dca2276
PP
2163 "mant-size=%u", ft, mantissa_digits);
2164
273b65be
JG
2165end:
2166 return ret;
2167}
2168
3dca2276
PP
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
50842bdc 2176struct bt_field_type *bt_field_type_structure_create(void)
273b65be 2177{
3dca2276
PP
2178 struct bt_field_type_common_structure *structure =
2179 g_new0(struct bt_field_type_common_structure, 1);
273b65be 2180
4e8304f7
PP
2181 BT_LOGD_STR("Creating structure field type object.");
2182
273b65be 2183 if (!structure) {
4e8304f7 2184 BT_LOGE_STR("Failed to allocate one structure field type.");
273b65be
JG
2185 goto error;
2186 }
2187
3dca2276
PP
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);
4e8304f7 2191 BT_LOGD("Created structure field type object: addr=%p",
3dca2276
PP
2192 structure);
2193 goto end;
2194
273b65be 2195error:
3dca2276
PP
2196 BT_PUT(structure);
2197
2198end:
2199 return (void *) structure;
273b65be
JG
2200}
2201
79422a2b 2202BT_HIDDEN
3dca2276
PP
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)
79422a2b
PP
2207{
2208 int ret = 0;
3dca2276 2209 struct bt_field_type_common_structure *struct_ft = BT_FROM_COMMON(ft);
79422a2b
PP
2210 GQuark name_quark;
2211 uint64_t i;
2212
3dca2276 2213 BT_ASSERT(ft);
f6ccaed9
PP
2214 BT_ASSERT(field_name);
2215 BT_ASSERT(field_type);
3dca2276 2216 BT_ASSERT(ft->id == BT_FIELD_TYPE_ID_STRUCT);
79422a2b
PP
2217 name_quark = g_quark_from_string(field_name);
2218
3dca2276 2219 for (i = 0; i < struct_ft->fields->len; i++) {
312c056a
PP
2220 struct bt_field_type_common_structure_field *field =
2221 BT_FIELD_TYPE_COMMON_STRUCTURE_FIELD_AT_INDEX(ft, i);
79422a2b
PP
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
3dca2276
PP
2232BT_HIDDEN
2233int bt_field_type_common_structure_add_field(struct bt_field_type_common *ft,
2234 struct bt_field_type_common *field_type,
273b65be
JG
2235 const char *field_name)
2236{
2237 int ret = 0;
3dca2276 2238 struct bt_field_type_common_structure *struct_ft = BT_FROM_COMMON(ft);
273b65be 2239
73892edc
PP
2240 /*
2241 * TODO: check that `field_type` does not contain `type`,
2242 * recursively.
2243 */
3dca2276 2244 if (!ft) {
4e8304f7
PP
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
3dca2276 2256 if (ft->frozen) {
4e8304f7 2257 BT_LOGW("Invalid parameter: field type is frozen: addr=%p",
3dca2276 2258 ft);
4e8304f7
PP
2259 ret = -1;
2260 goto end;
2261 }
2262
3dca2276 2263 if (ft->id != BT_FIELD_TYPE_ID_STRUCT) {
4e8304f7 2264 BT_LOGW("Invalid parameter: field type is not a structure field type: "
3dca2276
PP
2265 "addr=%p, ft-id=%s", ft,
2266 bt_common_field_type_id_string(ft->id));
4e8304f7
PP
2267 ret = -1;
2268 goto end;
2269 }
2270
3dca2276 2271 if (ft == field_type) {
4e8304f7 2272 BT_LOGW("Invalid parameter: structure field type and field type to add are the same: "
3dca2276 2273 "addr=%p", ft);
e6235f1f 2274 ret = -1;
273b65be
JG
2275 goto end;
2276 }
2277
312c056a
PP
2278 if (add_structure_variant_member(struct_ft->fields,
2279 struct_ft->field_name_to_index, field_type, field_name,
2280 false)) {
4e8304f7
PP
2281 BT_LOGW("Cannot add field to structure field type: "
2282 "struct-ft-addr=%p, field-ft-addr=%p, field-name=\"%s\"",
3dca2276 2283 ft, field_type, field_name);
273b65be
JG
2284 ret = -1;
2285 goto end;
2286 }
dfc1504d
PP
2287
2288 BT_LOGV("Added structure field type field: struct-ft-addr=%p, "
3dca2276 2289 "field-ft-addr=%p, field-name=\"%s\"", ft,
dfc1504d 2290 field_type, field_name);
3dca2276 2291
b92ddaaa
JG
2292end:
2293 return ret;
2294}
2295
3dca2276
PP
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)
b92ddaaa 2307{
3dca2276 2308 struct bt_field_type_common_structure *struct_ft = BT_FROM_COMMON(ft);
b92ddaaa 2309
3dca2276
PP
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;
b92ddaaa
JG
2314}
2315
3dca2276 2316int64_t bt_field_type_structure_get_field_count(struct bt_field_type *ft)
b92ddaaa 2317{
3dca2276
PP
2318 return bt_field_type_common_structure_get_field_count((void *) ft);
2319}
b92ddaaa 2320
3dca2276 2321BT_HIDDEN
094ff7c0 2322int bt_field_type_common_structure_borrow_field_by_index(
3dca2276
PP
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);
312c056a 2328 struct bt_field_type_common_structure_field *field;
3dca2276
PP
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,
d975f66c 2334 "Index is out of bounds: index=%" PRIu64 ", "
3dca2276
PP
2335 "count=%u, %![ft-]+_F",
2336 index, struct_ft->fields->len, ft);
312c056a 2337 field = BT_FIELD_TYPE_COMMON_STRUCTURE_FIELD_AT_INDEX(struct_ft, index);
d975f66c 2338
f9b799fc
JG
2339 if (field_type) {
2340 *field_type = field->type;
f9b799fc 2341 }
d975f66c 2342
f9b799fc
JG
2343 if (field_name) {
2344 *field_name = g_quark_to_string(field->name);
f6ccaed9 2345 BT_ASSERT(*field_name);
f9b799fc 2346 }
d975f66c
PP
2347
2348 return 0;
b92ddaaa
JG
2349}
2350
094ff7c0 2351int bt_field_type_structure_borrow_field_by_index(
3dca2276
PP
2352 struct bt_field_type *ft,
2353 const char **field_name,
2354 struct bt_field_type **field_type, uint64_t index)
2355{
094ff7c0 2356 return bt_field_type_common_structure_borrow_field_by_index(
3dca2276
PP
2357 (void *) ft, field_name, (void *) field_type, index);
2358}
2359
2360BT_HIDDEN
094ff7c0
PP
2361struct bt_field_type_common *
2362bt_field_type_common_structure_borrow_field_type_by_name(
3dca2276 2363 struct bt_field_type_common *ft, const char *name)
b92ddaaa
JG
2364{
2365 size_t index;
2366 GQuark name_quark;
312c056a 2367 struct bt_field_type_common_structure_field *field;
3dca2276
PP
2368 struct bt_field_type_common_structure *struct_ft = BT_FROM_COMMON(ft);
2369 struct bt_field_type_common *field_type = NULL;
b92ddaaa 2370
3dca2276 2371 BT_ASSERT_PRE_NON_NULL(ft, "Field type");
d975f66c 2372 BT_ASSERT_PRE_NON_NULL(name, "Name");
3dca2276
PP
2373 BT_ASSERT_PRE_FT_COMMON_HAS_ID(ft, BT_FIELD_TYPE_ID_STRUCT,
2374 "Field type");
b92ddaaa
JG
2375 name_quark = g_quark_try_string(name);
2376 if (!name_quark) {
6fa8d37b
PP
2377 BT_LOGV("No such structure field type field name: "
2378 "ft-addr=%p, field-name=\"%s\"",
3dca2276 2379 ft, name);
b92ddaaa
JG
2380 goto end;
2381 }
2382
3dca2276
PP
2383 if (!g_hash_table_lookup_extended(struct_ft->field_name_to_index,
2384 GUINT_TO_POINTER(name_quark), NULL, (gpointer *) &index)) {
6fa8d37b
PP
2385 BT_LOGV("No such structure field type field name: "
2386 "ft-addr=%p, field-name=\"%s\"",
3dca2276 2387 ft, name);
b92ddaaa 2388 goto end;
273b65be 2389 }
b92ddaaa 2390
312c056a 2391 field = BT_FIELD_TYPE_COMMON_STRUCTURE_FIELD_AT_INDEX(ft, index);
b92ddaaa 2392 field_type = field->type;
d975f66c 2393
273b65be 2394end:
b92ddaaa 2395 return field_type;
273b65be
JG
2396}
2397
094ff7c0 2398struct bt_field_type *bt_field_type_structure_borrow_field_type_by_name(
3dca2276
PP
2399 struct bt_field_type *ft, const char *name)
2400{
094ff7c0 2401 return (void *) bt_field_type_common_structure_borrow_field_type_by_name(
3dca2276
PP
2402 (void *) ft, name);
2403}
2404
50842bdc 2405struct bt_field_type *bt_field_type_variant_create(
3dca2276 2406 struct bt_field_type *tag_ft, const char *tag_name)
273b65be 2407{
3dca2276 2408 struct bt_field_type_common_variant *var_ft = NULL;
273b65be 2409
4e8304f7
PP
2410 BT_LOGD("Creating variant field type object: "
2411 "tag-ft-addr=%p, tag-field-name=\"%s\"",
3dca2276 2412 tag_ft, tag_name);
4e8304f7 2413
f4cc9a21 2414 if (tag_name && !bt_identifier_is_valid(tag_name)) {
4e8304f7
PP
2415 BT_LOGW("Invalid parameter: tag field name is not a valid CTF identifier: "
2416 "tag-ft-addr=%p, tag-field-name=\"%s\"",
3dca2276 2417 tag_ft, tag_name);
273b65be
JG
2418 goto error;
2419 }
2420
3dca2276
PP
2421 var_ft = g_new0(struct bt_field_type_common_variant, 1);
2422 if (!var_ft) {
4e8304f7 2423 BT_LOGE_STR("Failed to allocate one variant field type.");
273b65be
JG
2424 goto error;
2425 }
2426
3dca2276
PP
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);
4e8304f7
PP
2431 BT_LOGD("Created variant field type object: addr=%p, "
2432 "tag-ft-addr=%p, tag-field-name=\"%s\"",
3dca2276
PP
2433 var_ft, tag_ft, tag_name);
2434 goto end;
2435
273b65be 2436error:
3dca2276
PP
2437 BT_PUT(var_ft);
2438
2439end:
2440 return (void *) var_ft;
273b65be
JG
2441}
2442
3dca2276 2443BT_HIDDEN
094ff7c0
PP
2444struct bt_field_type_common *
2445bt_field_type_common_variant_borrow_tag_field_type(
3dca2276 2446 struct bt_field_type_common *ft)
b92ddaaa 2447{
3dca2276
PP
2448 struct bt_field_type_common_variant *var_ft = BT_FROM_COMMON(ft);
2449 struct bt_field_type_common *tag_ft = NULL;
b92ddaaa 2450
3dca2276
PP
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) {
4e8304f7 2456 BT_LOGV("Variant field type has no tag field type: "
3dca2276 2457 "addr=%p", ft);
6964b7fd
JG
2458 goto end;
2459 }
2460
094ff7c0 2461 tag_ft = BT_TO_COMMON(var_ft->tag_ft);
d975f66c 2462
b92ddaaa 2463end:
3dca2276
PP
2464 return tag_ft;
2465}
2466
094ff7c0 2467struct bt_field_type *bt_field_type_variant_borrow_tag_field_type(
3dca2276
PP
2468 struct bt_field_type *ft)
2469{
094ff7c0 2470 return (void *) bt_field_type_common_variant_borrow_tag_field_type(
3dca2276 2471 (void *) ft);
b92ddaaa
JG
2472}
2473
3dca2276
PP
2474BT_HIDDEN
2475const char *bt_field_type_common_variant_get_tag_name(
2476 struct bt_field_type_common *ft)
b92ddaaa 2477{
3dca2276 2478 struct bt_field_type_common_variant *var_ft = BT_FROM_COMMON(ft);
b92ddaaa
JG
2479 const char *tag_name = NULL;
2480
3dca2276
PP
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) {
4e8304f7 2486 BT_LOGV("Variant field type has no tag field name: "
3dca2276 2487 "addr=%p", ft);
6964b7fd
JG
2488 goto end;
2489 }
2490
3dca2276
PP
2491 tag_name = var_ft->tag_name->str;
2492
b92ddaaa
JG
2493end:
2494 return tag_name;
2495}
2496
3dca2276
PP
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)
d9b1ab6d
JG
2505{
2506 int ret = 0;
3dca2276 2507 struct bt_field_type_common_variant *var_ft = BT_FROM_COMMON(ft);
d9b1ab6d 2508
3dca2276 2509 if (!ft) {
4e8304f7
PP
2510 BT_LOGW_STR("Invalid parameter: field type is NULL.");
2511 ret = -1;
2512 goto end;
2513 }
2514
3dca2276 2515 if (ft->frozen) {
4e8304f7 2516 BT_LOGW("Invalid parameter: field type is frozen: addr=%p",
3dca2276 2517 ft);
4e8304f7
PP
2518 ret = -1;
2519 goto end;
2520 }
2521
3dca2276 2522 if (ft->id != BT_FIELD_TYPE_ID_VARIANT) {
4e8304f7 2523 BT_LOGW("Invalid parameter: field type is not a variant field type: "
3dca2276 2524 "addr=%p, ft-id=%s", ft, bt_common_field_type_id_string(ft->id));
4e8304f7
PP
2525 ret = -1;
2526 goto end;
2527 }
2528
f4cc9a21 2529 if (!bt_identifier_is_valid(name)) {
4e8304f7
PP
2530 BT_LOGW("Invalid parameter: tag field name is not a valid CTF identifier: "
2531 "variant-ft-addr=%p, tag-field-name=\"%s\"",
3dca2276 2532 ft, name);
d9b1ab6d
JG
2533 ret = -1;
2534 goto end;
2535 }
2536
3dca2276 2537 g_string_assign(var_ft->tag_name, name);
dfc1504d 2538 BT_LOGV("Set variant field type's tag field name: addr=%p, "
3dca2276
PP
2539 "tag-field-name=\"%s\"", ft, name);
2540
d9b1ab6d
JG
2541end:
2542 return ret;
2543}
2544
3dca2276
PP
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,
4e8304f7
PP
2554 const char *field_name)
2555{
2556 size_t i;
2557 int ret = 0;
3dca2276 2558 struct bt_field_type_common_variant *var_ft = BT_FROM_COMMON(ft);
4e8304f7
PP
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 */
3dca2276 2565 if (!ft) {
4e8304f7
PP
2566 BT_LOGW_STR("Invalid parameter: field type is NULL.");
2567 ret = -1;
2568 goto end;
2569 }
2570
3dca2276 2571 if (ft->frozen) {
4e8304f7 2572 BT_LOGW("Invalid parameter: field type is frozen: addr=%p",
3dca2276 2573 ft);
4e8304f7
PP
2574 ret = -1;
2575 goto end;
2576 }
2577
3dca2276 2578 if (ft->id != BT_FIELD_TYPE_ID_VARIANT) {
4e8304f7 2579 BT_LOGW("Invalid parameter: field type is not a variant field type: "
3dca2276
PP
2580 "addr=%p, ft-id=%s", ft,
2581 bt_common_field_type_id_string(ft->id));
4e8304f7
PP
2582 ret = -1;
2583 goto end;
2584 }
273b65be 2585
3dca2276 2586 if (ft == field_type) {
4e8304f7 2587 BT_LOGW("Invalid parameter: variant field type and field type to add are the same: "
3dca2276 2588 "addr=%p", ft);
273b65be
JG
2589 ret = -1;
2590 goto end;
2591 }
2592
6964b7fd 2593 /* The user has explicitly provided a tag; validate against it. */
3dca2276 2594 if (var_ft->tag_ft) {
6964b7fd
JG
2595 int name_found = 0;
2596
2597 /* Make sure this name is present in the enum tag */
3dca2276 2598 for (i = 0; i < var_ft->tag_ft->entries->len; i++) {
6964b7fd 2599 struct enumeration_mapping *mapping =
3dca2276 2600 g_ptr_array_index(var_ft->tag_ft->entries, i);
6964b7fd
JG
2601
2602 if (mapping->string == field_name_quark) {
2603 name_found = 1;
2604 break;
2605 }
2606 }
2607
2608 if (!name_found) {
2609 /* Validation failed */
4e8304f7
PP
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\"",
3dca2276 2614 ft, var_ft->tag_ft, var_ft->tag_name->str,
4e8304f7 2615 field_type, field_name);
6964b7fd
JG
2616 ret = -1;
2617 goto end;
273b65be
JG
2618 }
2619 }
2620
312c056a
PP
2621 if (add_structure_variant_member(var_ft->choices,
2622 var_ft->choice_name_to_index, field_type,
2623 field_name, true)) {
4e8304f7
PP
2624 BT_LOGW("Cannot add field to variant field type: "
2625 "variant-ft-addr=%p, field-ft-addr=%p, field-name=\"%s\"",
3dca2276 2626 ft, field_type, field_name);
273b65be
JG
2627 ret = -1;
2628 goto end;
2629 }
dfc1504d
PP
2630
2631 BT_LOGV("Added variant field type field: variant-ft-addr=%p, "
3dca2276 2632 "field-ft-addr=%p, field-name=\"%s\"", ft,
dfc1504d
PP
2633 field_type, field_name);
2634
273b65be
JG
2635end:
2636 return ret;
2637}
2638
3dca2276
PP
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
094ff7c0
PP
2648struct bt_field_type_common *
2649bt_field_type_common_variant_borrow_field_type_by_name(
3dca2276 2650 struct bt_field_type_common *ft,
b92ddaaa
JG
2651 const char *field_name)
2652{
2653 size_t index;
2654 GQuark name_quark;
312c056a 2655 struct bt_field_type_common_variant_choice *choice;
3dca2276
PP
2656 struct bt_field_type_common_variant *var_ft = BT_FROM_COMMON(ft);
2657 struct bt_field_type_common *field_type = NULL;
b92ddaaa 2658
3dca2276 2659 BT_ASSERT_PRE_NON_NULL(ft, "Field type");
d975f66c 2660 BT_ASSERT_PRE_NON_NULL(field_name, "Name");
3dca2276
PP
2661 BT_ASSERT_PRE_FT_COMMON_HAS_ID(ft, BT_FIELD_TYPE_ID_VARIANT,
2662 "Field type");
b92ddaaa
JG
2663 name_quark = g_quark_try_string(field_name);
2664 if (!name_quark) {
6fa8d37b
PP
2665 BT_LOGV("No such variant field type field name: "
2666 "ft-addr=%p, field-name=\"%s\"",
3dca2276 2667 ft, field_name);
b92ddaaa
JG
2668 goto end;
2669 }
2670
312c056a 2671 if (!g_hash_table_lookup_extended(var_ft->choice_name_to_index,
3dca2276 2672 GUINT_TO_POINTER(name_quark), NULL, (gpointer *) &index)) {
6fa8d37b
PP
2673 BT_LOGV("No such variant field type field name: "
2674 "ft-addr=%p, field-name=\"%s\"",
3dca2276 2675 ft, field_name);
b92ddaaa
JG
2676 goto end;
2677 }
2678
312c056a
PP
2679 choice = BT_FIELD_TYPE_COMMON_VARIANT_CHOICE_AT_INDEX(ft, index);
2680 field_type = choice->type;
d975f66c 2681
b92ddaaa
JG
2682end:
2683 return field_type;
2684}
2685
094ff7c0 2686struct bt_field_type *bt_field_type_variant_borrow_field_type_by_name(
3dca2276
PP
2687 struct bt_field_type *ft,
2688 const char *field_name)
2689{
094ff7c0 2690 return (void *) bt_field_type_common_variant_borrow_field_type_by_name(
3dca2276
PP
2691 (void *) ft, field_name);
2692}
2693
3dca2276
PP
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");
312c056a 2703 return (int64_t) var_ft->choices->len;
3dca2276
PP
2704}
2705
2706int64_t bt_field_type_variant_get_field_count(struct bt_field_type *ft)
b92ddaaa 2707{
3dca2276
PP
2708 return bt_field_type_common_variant_get_field_count((void *) ft);
2709}
b92ddaaa 2710
3dca2276 2711BT_HIDDEN
094ff7c0 2712int bt_field_type_common_variant_borrow_field_by_index(
3dca2276
PP
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);
312c056a 2718 struct bt_field_type_common_variant_choice *choice;
3dca2276
PP
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");
312c056a 2723 BT_ASSERT_PRE(index < var_ft->choices->len,
d975f66c 2724 "Index is out of bounds: index=%" PRIu64 ", "
3dca2276 2725 "count=%u, %![ft-]+_F",
312c056a
PP
2726 index, var_ft->choices->len, ft);
2727 choice = BT_FIELD_TYPE_COMMON_VARIANT_CHOICE_AT_INDEX(ft, index);
d975f66c 2728
647f3b93 2729 if (field_type) {
312c056a 2730 *field_type = choice->type;
647f3b93 2731 }
d975f66c 2732
647f3b93 2733 if (field_name) {
312c056a 2734 *field_name = g_quark_to_string(choice->name);
f6ccaed9 2735 BT_ASSERT(*field_name);
647f3b93 2736 }
d975f66c
PP
2737
2738 return 0;
b92ddaaa
JG
2739}
2740
094ff7c0 2741int bt_field_type_variant_borrow_field_by_index(struct bt_field_type *ft,
3dca2276
PP
2742 const char **field_name, struct bt_field_type **field_type,
2743 uint64_t index)
2744{
094ff7c0 2745 return bt_field_type_common_variant_borrow_field_by_index((void *) ft,
3dca2276
PP
2746 field_name, (void *) field_type, index);
2747}
2748
312c056a
PP
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
50842bdc 2806struct bt_field_type *bt_field_type_array_create(
3dca2276 2807 struct bt_field_type *element_ft, unsigned int length)
273b65be 2808{
3dca2276 2809 struct bt_field_type_common_array *array = NULL;
273b65be 2810
4e8304f7 2811 BT_LOGD("Creating array field type object: element-ft-addr=%p, "
3dca2276 2812 "length=%u", element_ft, length);
4e8304f7 2813
3dca2276 2814 if (!element_ft) {
4e8304f7
PP
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.");
273b65be
JG
2821 goto error;
2822 }
2823
3dca2276 2824 array = g_new0(struct bt_field_type_common_array, 1);
273b65be 2825 if (!array) {
4e8304f7 2826 BT_LOGE_STR("Failed to allocate one array field type.");
273b65be
JG
2827 goto error;
2828 }
2829
3dca2276
PP
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);
4e8304f7
PP
2834 BT_LOGD("Created array field type object: addr=%p, "
2835 "element-ft-addr=%p, length=%u",
3dca2276
PP
2836 array, element_ft, length);
2837 goto end;
2838
273b65be 2839error:
3dca2276
PP
2840 BT_PUT(array);
2841
2842end:
2843 return (void *) array;
273b65be
JG
2844}
2845
3dca2276 2846BT_HIDDEN
094ff7c0
PP
2847struct bt_field_type_common *
2848bt_field_type_common_array_borrow_element_field_type(
3dca2276 2849 struct bt_field_type_common *ft)
b92ddaaa 2850{
3dca2276
PP
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);
094ff7c0 2857 return array_ft->element_ft;
3dca2276 2858}
b92ddaaa 2859
094ff7c0 2860struct bt_field_type *bt_field_type_array_borrow_element_field_type(
3dca2276
PP
2861 struct bt_field_type *ft)
2862{
094ff7c0 2863 return (void *) bt_field_type_common_array_borrow_element_field_type(
3dca2276 2864 (void *) ft);
b92ddaaa
JG
2865}
2866
626e93aa 2867BT_HIDDEN
3dca2276
PP
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)
626e93aa
PP
2871{
2872 int ret = 0;
3dca2276 2873 struct bt_field_type_common_array *array_ft = BT_FROM_COMMON(ft);
626e93aa 2874
3dca2276 2875 if (!ft) {
4e8304f7
PP
2876 BT_LOGW_STR("Invalid parameter: array field type is NULL.");
2877 ret = -1;
2878 goto end;
2879 }
2880
3dca2276 2881 if (!element_ft) {
4e8304f7
PP
2882 BT_LOGW_STR("Invalid parameter: element field type is NULL.");
2883 ret = -1;
2884 goto end;
2885 }
2886
3dca2276 2887 if (ft->id != BT_FIELD_TYPE_ID_ARRAY) {
4e8304f7 2888 BT_LOGW("Invalid parameter: field type is not an array field type: "
3dca2276
PP
2889 "addr=%p, ft-id=%s", ft,
2890 bt_common_field_type_id_string(ft->id));
626e93aa
PP
2891 ret = -1;
2892 goto end;
2893 }
2894
3dca2276
PP
2895 if (array_ft->element_ft) {
2896 BT_PUT(array_ft->element_ft);
626e93aa
PP
2897 }
2898
3dca2276 2899 array_ft->element_ft = bt_get(element_ft);
dfc1504d 2900 BT_LOGV("Set array field type's element field type: array-ft-addr=%p, "
3dca2276 2901 "element-ft-addr=%p", ft, element_ft);
626e93aa
PP
2902
2903end:
2904 return ret;
2905}
2906
3dca2276
PP
2907BT_HIDDEN
2908int64_t bt_field_type_common_array_get_length(struct bt_field_type_common *ft)
b92ddaaa 2909{
3dca2276 2910 struct bt_field_type_common_array *array_ft = BT_FROM_COMMON(ft);
b92ddaaa 2911
3dca2276
PP
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);
b92ddaaa
JG
2921}
2922
50842bdc 2923struct bt_field_type *bt_field_type_sequence_create(
3dca2276 2924 struct bt_field_type *element_ft,
273b65be
JG
2925 const char *length_field_name)
2926{
3dca2276 2927 struct bt_field_type_common_sequence *sequence = NULL;
273b65be 2928
4e8304f7 2929 BT_LOGD("Creating sequence field type object: element-ft-addr=%p, "
3dca2276 2930 "length-field-name=\"%s\"", element_ft, length_field_name);
4e8304f7 2931
3dca2276 2932 if (!element_ft) {
4e8304f7
PP
2933 BT_LOGW_STR("Invalid parameter: element field type is NULL.");
2934 goto error;
2935 }
2936
f4cc9a21 2937 if (!bt_identifier_is_valid(length_field_name)) {
4e8304f7
PP
2938 BT_LOGW("Invalid parameter: length field name is not a valid CTF identifier: "
2939 "length-field-name=\"%s\"", length_field_name);
273b65be
JG
2940 goto error;
2941 }
2942
3dca2276 2943 sequence = g_new0(struct bt_field_type_common_sequence, 1);
273b65be 2944 if (!sequence) {
4e8304f7 2945 BT_LOGE_STR("Failed to allocate one sequence field type.");
273b65be
JG
2946 goto error;
2947 }
2948
3dca2276
PP
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);
4e8304f7
PP
2953 BT_LOGD("Created sequence field type object: addr=%p, "
2954 "element-ft-addr=%p, length-field-name=\"%s\"",
3dca2276
PP
2955 sequence, element_ft, length_field_name);
2956 goto end;
2957
273b65be 2958error:
3dca2276
PP
2959 BT_PUT(sequence);
2960
2961end:
2962 return (void *) sequence;
273b65be
JG
2963}
2964
3dca2276 2965BT_HIDDEN
094ff7c0 2966struct bt_field_type_common *bt_field_type_common_sequence_borrow_element_field_type(
3dca2276 2967 struct bt_field_type_common *ft)
b92ddaaa 2968{
3dca2276
PP
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");
094ff7c0 2974 return seq_ft->element_ft;
3dca2276 2975}
b92ddaaa 2976
094ff7c0 2977struct bt_field_type *bt_field_type_sequence_borrow_element_field_type(
3dca2276
PP
2978 struct bt_field_type *ft)
2979{
094ff7c0 2980 return (void *) bt_field_type_common_sequence_borrow_element_field_type(
3dca2276 2981 (void *) ft);
b92ddaaa
JG
2982}
2983
626e93aa 2984BT_HIDDEN
3dca2276
PP
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)
626e93aa
PP
2988{
2989 int ret = 0;
3dca2276 2990 struct bt_field_type_common_sequence *seq_ft = BT_FROM_COMMON(ft);
626e93aa 2991
3dca2276 2992 if (!ft) {
4e8304f7 2993 BT_LOGW_STR("Invalid parameter: sequence field type is NULL.");
626e93aa
PP
2994 ret = -1;
2995 goto end;
2996 }
2997
3dca2276 2998 if (!element_ft) {
4e8304f7
PP
2999 BT_LOGW_STR("Invalid parameter: element field type is NULL.");
3000 ret = -1;
3001 goto end;
3002 }
3003
3dca2276 3004 if (ft->id != BT_FIELD_TYPE_ID_SEQUENCE) {
4e8304f7 3005 BT_LOGW("Invalid parameter: field type is not a sequence field type: "
3dca2276
PP
3006 "addr=%p, ft-id=%s", ft,
3007 bt_common_field_type_id_string(ft->id));
4e8304f7
PP
3008 ret = -1;
3009 goto end;
3010 }
626e93aa 3011
3dca2276
PP
3012 if (seq_ft->element_ft) {
3013 BT_PUT(seq_ft->element_ft);
626e93aa
PP
3014 }
3015
3dca2276
PP
3016 seq_ft->element_ft = element_ft;
3017 bt_get(seq_ft->element_ft);
dfc1504d 3018 BT_LOGV("Set sequence field type's element field type: sequence-ft-addr=%p, "
3dca2276 3019 "element-ft-addr=%p", ft, element_ft);
626e93aa
PP
3020
3021end:
3022 return ret;
3023}
3024
3dca2276
PP
3025BT_HIDDEN
3026const char *bt_field_type_common_sequence_get_length_field_name(
3027 struct bt_field_type_common *ft)
b92ddaaa 3028{
3dca2276
PP
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}
b92ddaaa 3037
3dca2276
PP
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);
b92ddaaa
JG
3042}
3043
50842bdc 3044struct bt_field_type *bt_field_type_string_create(void)
273b65be 3045{
3dca2276
PP
3046 struct bt_field_type_common_string *string =
3047 g_new0(struct bt_field_type_common_string, 1);
273b65be 3048
4e8304f7
PP
3049 BT_LOGD_STR("Creating string field type object.");
3050
273b65be 3051 if (!string) {
4e8304f7 3052 BT_LOGE_STR("Failed to allocate one string field type.");
273b65be
JG
3053 return NULL;
3054 }
3055
3dca2276
PP
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;
273b65be
JG
3061}
3062
3dca2276
PP
3063BT_HIDDEN
3064enum bt_string_encoding bt_field_type_common_string_get_encoding(
3065 struct bt_field_type_common *ft)
b92ddaaa 3066{
3dca2276 3067 struct bt_field_type_common_string *string_ft = BT_FROM_COMMON(ft);
b92ddaaa 3068
3dca2276
PP
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);
b92ddaaa
JG
3079}
3080
3dca2276
PP
3081BT_HIDDEN
3082int bt_field_type_common_string_set_encoding(struct bt_field_type_common *ft,
50842bdc 3083 enum bt_string_encoding encoding)
273b65be
JG
3084{
3085 int ret = 0;
3dca2276 3086 struct bt_field_type_common_string *string_ft = BT_FROM_COMMON(ft);
273b65be 3087
3dca2276 3088 if (!ft) {
4e8304f7
PP
3089 BT_LOGW_STR("Invalid parameter: field type is NULL.");
3090 ret = -1;
3091 goto end;
3092 }
3093
3dca2276 3094 if (ft->id != BT_FIELD_TYPE_ID_STRING) {
4e8304f7 3095 BT_LOGW("Invalid parameter: field type is not a string field type: "
3dca2276
PP
3096 "addr=%p, ft-id=%s", ft,
3097 bt_common_field_type_id_string(ft->id));
4e8304f7
PP
3098 ret = -1;
3099 goto end;
3100 }
3101
50842bdc
PP
3102 if (encoding != BT_STRING_ENCODING_UTF8 &&
3103 encoding != BT_STRING_ENCODING_ASCII) {
4e8304f7 3104 BT_LOGW("Invalid parameter: unknown string encoding: "
3dca2276 3105 "addr=%p, encoding=%d", ft, encoding);
273b65be
JG
3106 ret = -1;
3107 goto end;
3108 }
3109
3dca2276 3110 string_ft->encoding = encoding;
dfc1504d 3111 BT_LOGV("Set string field type's encoding: addr=%p, encoding=%s",
3dca2276
PP
3112 ft, bt_common_string_encoding_string(encoding));
3113
273b65be
JG
3114end:
3115 return ret;
3116}
3117
3dca2276
PP
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)
b92ddaaa
JG
3126{
3127 int ret;
50842bdc 3128 enum bt_field_type_id type_id;
b92ddaaa 3129
3dca2276 3130 BT_ASSERT_PRE_NON_NULL(ft, "Field type");
b92ddaaa 3131
3dca2276
PP
3132 if (ft->frozen) {
3133 ret = (int) ft->alignment;
3ffba961
JG
3134 goto end;
3135 }
3136
3dca2276 3137 type_id = bt_field_type_common_get_type_id(ft);
3ffba961 3138 switch (type_id) {
50842bdc 3139 case BT_FIELD_TYPE_ID_SEQUENCE:
3ffba961 3140 {
3dca2276 3141 struct bt_field_type_common *element_ft =
094ff7c0 3142 bt_field_type_common_sequence_borrow_element_field_type(ft);
3ffba961 3143
3dca2276
PP
3144 BT_ASSERT(element_ft);
3145 ret = bt_field_type_common_get_alignment(element_ft);
3ffba961
JG
3146 break;
3147 }
50842bdc 3148 case BT_FIELD_TYPE_ID_ARRAY:
3ffba961 3149 {
3dca2276 3150 struct bt_field_type_common *element_ft =
094ff7c0 3151 bt_field_type_common_array_borrow_element_field_type(ft);
3ffba961 3152
3dca2276
PP
3153 BT_ASSERT(element_ft);
3154 ret = bt_field_type_common_get_alignment(element_ft);
3ffba961
JG
3155 break;
3156 }
50842bdc 3157 case BT_FIELD_TYPE_ID_STRUCT:
3ffba961 3158 {
544d0515 3159 int64_t i, element_count;
3ffba961 3160
3dca2276
PP
3161 element_count = bt_field_type_common_structure_get_field_count(
3162 ft);
f6ccaed9 3163 BT_ASSERT(element_count >= 0);
3ffba961
JG
3164
3165 for (i = 0; i < element_count; i++) {
3dca2276 3166 struct bt_field_type_common *field = NULL;
3ffba961
JG
3167 int field_alignment;
3168
094ff7c0 3169 ret = bt_field_type_common_structure_borrow_field_by_index(
3dca2276 3170 ft, NULL, &field, i);
f6ccaed9
PP
3171 BT_ASSERT(ret == 0);
3172 BT_ASSERT(field);
3dca2276 3173 field_alignment = bt_field_type_common_get_alignment(
3ffba961 3174 field);
3ffba961
JG
3175 if (field_alignment < 0) {
3176 ret = field_alignment;
3177 goto end;
3178 }
3179
3dca2276 3180 ft->alignment = MAX(field_alignment, ft->alignment);
3ffba961 3181 }
3dca2276 3182 ret = (int) ft->alignment;
89e9af01
JG
3183 break;
3184 }
50842bdc 3185 case BT_FIELD_TYPE_ID_UNKNOWN:
4e8304f7 3186 BT_LOGW("Invalid parameter: unknown field type ID: "
3dca2276 3187 "addr=%p, ft-id=%d", ft, type_id);
3ffba961
JG
3188 ret = -1;
3189 break;
3190 default:
3dca2276 3191 ret = (int) ft->alignment;
3ffba961
JG
3192 break;
3193 }
3dca2276 3194
b92ddaaa
JG
3195end:
3196 return ret;
3197}
3198
3dca2276
PP
3199int bt_field_type_get_alignment(struct bt_field_type *ft)
3200{
3201 return bt_field_type_common_get_alignment((void *) ft);
3202}
3203
9ad2f879
PP
3204static inline
3205int is_power_of_two(unsigned int value)
3206{
3207 return ((value & (value - 1)) == 0) && value > 0;
3208}
3209
3dca2276
PP
3210BT_HIDDEN
3211int bt_field_type_common_set_alignment(struct bt_field_type_common *ft,
273b65be
JG
3212 unsigned int alignment)
3213{
3214 int ret = 0;
50842bdc 3215 enum bt_field_type_id type_id;
273b65be 3216
9ad2f879 3217 /* Alignment must be a power of two */
3dca2276 3218 if (!ft) {
4e8304f7
PP
3219 BT_LOGW_STR("Invalid parameter: field type is NULL.");
3220 ret = -1;
3221 goto end;
3222 }
3223
3dca2276 3224 if (ft->frozen) {
4e8304f7 3225 BT_LOGW("Invalid parameter: field type is frozen: addr=%p",
3dca2276 3226 ft);
4e8304f7
PP
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: "
3dca2276 3233 "addr=%p, align=%u", ft, alignment);
273b65be
JG
3234 ret = -1;
3235 goto end;
3236 }
3237
3dca2276 3238 type_id = bt_field_type_common_get_type_id(ft);
50842bdc 3239 if (type_id == BT_FIELD_TYPE_ID_UNKNOWN) {
4e8304f7 3240 BT_LOGW("Invalid parameter: unknown field type ID: "
3dca2276 3241 "addr=%p, ft-id=%d", ft, type_id);
6a43d732
JG
3242 ret = -1;
3243 goto end;
3244 }
3245
3dca2276 3246 if (ft->id == BT_FIELD_TYPE_ID_STRING && alignment != CHAR_BIT) {
4e8304f7 3247 BT_LOGW("Invalid parameter: alignment must be %u for a string field type: "
3dca2276 3248 "addr=%p, align=%u", CHAR_BIT, ft, alignment);
273b65be
JG
3249 ret = -1;
3250 goto end;
3251 }
3252
50842bdc
PP
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) {
6a43d732 3256 /* Setting an alignment on these types makes no sense */
4e8304f7 3257 BT_LOGW("Invalid parameter: cannot set the alignment of this field type: "
3dca2276
PP
3258 "addr=%p, ft-id=%s", ft,
3259 bt_common_field_type_id_string(ft->id));
6a43d732
JG
3260 ret = -1;
3261 goto end;
3262 }
3263
3dca2276 3264 ft->alignment = alignment;
273b65be 3265 ret = 0;
dfc1504d 3266 BT_LOGV("Set field type's alignment: addr=%p, align=%u",
3dca2276
PP
3267 ft, alignment);
3268
273b65be
JG
3269end:
3270 return ret;
3271}
3272
3dca2276
PP
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)
b92ddaaa 3282{
50842bdc 3283 enum bt_byte_order ret = BT_BYTE_ORDER_UNKNOWN;
b92ddaaa 3284
3dca2276 3285 BT_ASSERT_PRE_NON_NULL(ft, "Field type");
b92ddaaa 3286
3dca2276 3287 switch (ft->id) {
50842bdc 3288 case BT_FIELD_TYPE_ID_INTEGER:
b92ddaaa 3289 {
3dca2276
PP
3290 struct bt_field_type_common_integer *integer =
3291 BT_FROM_COMMON(ft);
3292
445c3471 3293 ret = integer->user_byte_order;
b92ddaaa
JG
3294 break;
3295 }
50842bdc 3296 case BT_FIELD_TYPE_ID_ENUM:
4b2da5f0 3297 {
3dca2276
PP
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));
4b2da5f0
PP
3303 break;
3304 }
50842bdc 3305 case BT_FIELD_TYPE_ID_FLOAT:
b92ddaaa 3306 {
3dca2276
PP
3307 struct bt_field_type_common_floating_point *floating_point =
3308 BT_FROM_COMMON(ft);
445c3471 3309 ret = floating_point->user_byte_order;
b92ddaaa
JG
3310 break;
3311 }
3312 default:
4e8304f7 3313 BT_LOGW("Invalid parameter: cannot get the byte order of this field type: "
3dca2276
PP
3314 "addr=%p, ft-id=%s", ft,
3315 bt_common_field_type_id_string(ft->id));
c35a1669
JG
3316 goto end;
3317 }
3318
f6ccaed9 3319 BT_ASSERT(ret == BT_BYTE_ORDER_NATIVE ||
50842bdc
PP
3320 ret == BT_BYTE_ORDER_LITTLE_ENDIAN ||
3321 ret == BT_BYTE_ORDER_BIG_ENDIAN ||
3322 ret == BT_BYTE_ORDER_NETWORK);
445c3471 3323
b92ddaaa
JG
3324end:
3325 return ret;
3326}
3327
3dca2276
PP
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,
50842bdc 3335 enum bt_byte_order byte_order)
273b65be
JG
3336{
3337 int ret = 0;
273b65be 3338
3dca2276 3339 if (!ft) {
4e8304f7
PP
3340 BT_LOGW_STR("Invalid parameter: field type is NULL.");
3341 ret = -1;
3342 goto end;
3343 }
3344
3dca2276 3345 if (ft->frozen) {
4e8304f7 3346 BT_LOGW("Invalid parameter: field type is frozen: addr=%p",
3dca2276 3347 ft);
273b65be
JG
3348 ret = -1;
3349 goto end;
3350 }
3351
50842bdc
PP
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) {
d41cff38 3356 BT_LOGW("Invalid parameter: invalid byte order: "
3dca2276
PP
3357 "addr=%p, bo=%s", ft,
3358 bt_common_byte_order_string(byte_order));
273b65be
JG
3359 ret = -1;
3360 goto end;
3361 }
3362
3dca2276
PP
3363 if (ft->methods->set_byte_order) {
3364 ft->methods->set_byte_order(ft, byte_order);
273b65be 3365 }
dfc1504d
PP
3366
3367 BT_LOGV("Set field type's byte order: addr=%p, bo=%s",
3dca2276 3368 ft, bt_common_byte_order_string(byte_order));
dfc1504d 3369
273b65be
JG
3370end:
3371 return ret;
3372}
3373
3dca2276
PP
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)
b92ddaaa 3389{
3dca2276 3390 return bt_field_type_common_get_type_id((void *) ft);
b92ddaaa 3391}
2f2d8e05 3392
50842bdc 3393int bt_field_type_is_integer(struct bt_field_type *type)
56db8d7a 3394{
50842bdc 3395 return bt_field_type_get_type_id(type) == BT_FIELD_TYPE_ID_INTEGER;
56db8d7a
PP
3396}
3397
50842bdc 3398int bt_field_type_is_floating_point(struct bt_field_type *type)
56db8d7a 3399{
50842bdc 3400 return bt_field_type_get_type_id(type) == BT_FIELD_TYPE_ID_FLOAT;
56db8d7a
PP
3401}
3402
50842bdc 3403int bt_field_type_is_enumeration(struct bt_field_type *type)
56db8d7a 3404{
50842bdc 3405 return bt_field_type_get_type_id(type) == BT_FIELD_TYPE_ID_ENUM;
56db8d7a
PP
3406}
3407
50842bdc 3408int bt_field_type_is_string(struct bt_field_type *type)
56db8d7a 3409{
50842bdc 3410 return bt_field_type_get_type_id(type) == BT_FIELD_TYPE_ID_STRING;
56db8d7a
PP
3411}
3412
50842bdc 3413int bt_field_type_is_structure(struct bt_field_type *type)
56db8d7a 3414{
50842bdc 3415 return bt_field_type_get_type_id(type) == BT_FIELD_TYPE_ID_STRUCT;
56db8d7a
PP
3416}
3417
50842bdc 3418int bt_field_type_is_array(struct bt_field_type *type)
56db8d7a 3419{
50842bdc 3420 return bt_field_type_get_type_id(type) == BT_FIELD_TYPE_ID_ARRAY;
56db8d7a
PP
3421}
3422
50842bdc 3423int bt_field_type_is_sequence(struct bt_field_type *type)
56db8d7a 3424{
50842bdc 3425 return bt_field_type_get_type_id(type) == BT_FIELD_TYPE_ID_SEQUENCE;
56db8d7a
PP
3426}
3427
50842bdc 3428int bt_field_type_is_variant(struct bt_field_type *type)
56db8d7a 3429{
50842bdc 3430 return bt_field_type_get_type_id(type) == BT_FIELD_TYPE_ID_VARIANT;
56db8d7a
PP
3431}
3432
3dca2276
PP
3433BT_HIDDEN
3434void _bt_field_type_common_freeze(struct bt_field_type_common *ft)
273b65be 3435{
3dca2276
PP
3436 if (!ft || ft->frozen) {
3437 return;
3438 }
273b65be 3439
3dca2276
PP
3440 BT_ASSERT(ft->methods->freeze);
3441 ft->methods->freeze(ft);
273b65be
JG
3442}
3443
3444BT_HIDDEN
3dca2276 3445void _bt_field_type_freeze(struct bt_field_type *ft)
273b65be 3446{
3dca2276 3447 _bt_field_type_common_freeze((void *) ft);
273b65be
JG
3448}
3449
3450BT_HIDDEN
094ff7c0
PP
3451struct bt_field_type_common *
3452bt_field_type_common_variant_borrow_field_type_signed(
3dca2276 3453 struct bt_field_type_common_variant *var_ft,
b92ddaaa 3454 int64_t tag_value)
273b65be 3455{
3dca2276 3456 struct bt_field_type_common *field_type = NULL;
b92ddaaa
JG
3457 GQuark field_name_quark;
3458 gpointer index;
312c056a 3459 struct bt_field_type_common_variant_choice *choice;
b92ddaaa
JG
3460 struct range_overlap_query query = {
3461 .range_start._signed = tag_value,
3462 .range_end._signed = tag_value,
96e8f959
MD
3463 .mapping_name = 0,
3464 .overlaps = 0,
3465 };
273b65be 3466
3dca2276 3467 g_ptr_array_foreach(var_ft->tag_ft->entries, check_ranges_overlap,
b92ddaaa
JG
3468 &query);
3469 if (!query.overlaps) {
273b65be
JG
3470 goto end;
3471 }
3472
b92ddaaa 3473 field_name_quark = query.mapping_name;
312c056a 3474 if (!g_hash_table_lookup_extended(var_ft->choice_name_to_index,
ec159b1e 3475 GUINT_TO_POINTER(field_name_quark), NULL, &index)) {
273b65be
JG
3476 goto end;
3477 }
3478
312c056a
PP
3479 choice = BT_FIELD_TYPE_COMMON_VARIANT_CHOICE_AT_INDEX(var_ft,
3480 (size_t) index);
3481 field_type = choice->type;
3dca2276 3482
273b65be 3483end:
3dca2276 3484 return field_type;
273b65be
JG
3485}
3486
3487BT_HIDDEN
094ff7c0
PP
3488struct bt_field_type_common *
3489bt_field_type_common_variant_borrow_field_type_unsigned(
3dca2276 3490 struct bt_field_type_common_variant *var_ft,
b92ddaaa 3491 uint64_t tag_value)
273b65be 3492{
3dca2276 3493 struct bt_field_type_common *field_type = NULL;
273b65be
JG
3494 GQuark field_name_quark;
3495 gpointer index;
312c056a 3496 struct bt_field_type_common_variant_choice *choice;
b92ddaaa
JG
3497 struct range_overlap_query query = {
3498 .range_start._unsigned = tag_value,
3499 .range_end._unsigned = tag_value,
96e8f959
MD
3500 .mapping_name = 0,
3501 .overlaps = 0,
3502 };
273b65be 3503
3dca2276
PP
3504 g_ptr_array_foreach(var_ft->tag_ft->entries,
3505 check_ranges_overlap_unsigned, &query);
273b65be
JG
3506 if (!query.overlaps) {
3507 goto end;
3508 }
3509
3510 field_name_quark = query.mapping_name;
312c056a 3511 if (!g_hash_table_lookup_extended(var_ft->choice_name_to_index,
273b65be
JG
3512 GUINT_TO_POINTER(field_name_quark), NULL, &index)) {
3513 goto end;
3514 }
3515
312c056a
PP
3516 choice = BT_FIELD_TYPE_COMMON_VARIANT_CHOICE_AT_INDEX(var_ft,
3517 (size_t) index);
3518 field_type = choice->type;
3519
273b65be 3520end:
3dca2276 3521 return field_type;
273b65be
JG
3522}
3523
3524BT_HIDDEN
3dca2276
PP
3525struct bt_field_type_common *bt_field_type_common_copy(
3526 struct bt_field_type_common *ft)
273b65be 3527{
3dca2276 3528 struct bt_field_type_common *ft_copy = NULL;
273b65be 3529
3dca2276
PP
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.");
81e36fac
PP
3535 goto end;
3536 }
3537
3dca2276
PP
3538 ft_copy->alignment = ft->alignment;
3539
273b65be 3540end:
3dca2276 3541 return ft_copy;
273b65be
JG
3542}
3543
3dca2276 3544struct bt_field_type *bt_field_type_copy(struct bt_field_type *ft)
24724933 3545{
3dca2276 3546 return (void *) bt_field_type_common_copy((void *) ft);
24724933
JG
3547}
3548
39a5e0db 3549BT_HIDDEN
3dca2276
PP
3550int bt_field_type_common_structure_get_field_name_index(
3551 struct bt_field_type_common *ft, const char *name)
39a5e0db
JG
3552{
3553 int ret;
3554 size_t index;
3555 GQuark name_quark;
3dca2276 3556 struct bt_field_type_common_structure *struct_ft = BT_FROM_COMMON(ft);
39a5e0db 3557
3dca2276 3558 BT_ASSERT_PRE_NON_NULL(ft, "Field type");
d975f66c 3559 BT_ASSERT_PRE_NON_NULL(name, "Name");
3dca2276
PP
3560 BT_ASSERT_PRE_FT_COMMON_HAS_ID(ft, BT_FIELD_TYPE_ID_STRUCT,
3561 "Field type");
39a5e0db
JG
3562
3563 name_quark = g_quark_try_string(name);
3564 if (!name_quark) {
6fa8d37b
PP
3565 BT_LOGV("No such structure field type field name: "
3566 "ft-addr=%p, field-name=\"%s\"",
3dca2276 3567 ft, name);
39a5e0db
JG
3568 ret = -1;
3569 goto end;
3570 }
3571
3dca2276 3572 if (!g_hash_table_lookup_extended(struct_ft->field_name_to_index,
ec159b1e 3573 GUINT_TO_POINTER(name_quark),
3dca2276 3574 NULL, (gpointer *) &index)) {
6fa8d37b
PP
3575 BT_LOGV("No such structure field type field name: "
3576 "ft-addr=%p, field-name=\"%s\"",
3dca2276 3577 ft, name);
39a5e0db
JG
3578 ret = -1;
3579 goto end;
3580 }
3dca2276 3581
39a5e0db 3582 ret = (int) index;
3dca2276 3583
39a5e0db
JG
3584end:
3585 return ret;
3586}
736133f1
JG
3587
3588BT_HIDDEN
3dca2276
PP
3589int bt_field_type_common_variant_get_field_name_index(
3590 struct bt_field_type_common *ft, const char *name)
736133f1
JG
3591{
3592 int ret;
3593 size_t index;
3594 GQuark name_quark;
3dca2276 3595 struct bt_field_type_common_variant *var_ft = BT_FROM_COMMON(ft);
736133f1 3596
3dca2276 3597 BT_ASSERT_PRE_NON_NULL(ft, "Field type");
d975f66c 3598 BT_ASSERT_PRE_NON_NULL(name, "Name");
3dca2276
PP
3599 BT_ASSERT_PRE_FT_COMMON_HAS_ID(ft, BT_FIELD_TYPE_ID_VARIANT,
3600 "Field type");
736133f1
JG
3601 name_quark = g_quark_try_string(name);
3602 if (!name_quark) {
6fa8d37b
PP
3603 BT_LOGV("No such variant field type field name: "
3604 "ft-addr=%p, field-name=\"%s\"",
3dca2276 3605 ft, name);
736133f1
JG
3606 ret = -1;
3607 goto end;
3608 }
3609
312c056a 3610 if (!g_hash_table_lookup_extended(var_ft->choice_name_to_index,
ec159b1e 3611 GUINT_TO_POINTER(name_quark),
3dca2276 3612 NULL, (gpointer *) &index)) {
6fa8d37b
PP
3613 BT_LOGV("No such variant field type field name: "
3614 "ft-addr=%p, field-name=\"%s\"",
3dca2276 3615 ft, name);
736133f1
JG
3616 ret = -1;
3617 goto end;
3618 }
3dca2276 3619
736133f1 3620 ret = (int) index;
3dca2276 3621
736133f1
JG
3622end:
3623 return ret;
3624}
aa4e271c
JG
3625
3626BT_HIDDEN
3dca2276
PP
3627int bt_field_type_common_sequence_set_length_field_path(
3628 struct bt_field_type_common *ft, struct bt_field_path *path)
aa4e271c
JG
3629{
3630 int ret = 0;
3dca2276 3631 struct bt_field_type_common_sequence *seq_ft = BT_FROM_COMMON(ft);
aa4e271c 3632
3dca2276 3633 if (!ft) {
4e8304f7
PP
3634 BT_LOGW_STR("Invalid parameter: field type is NULL.");
3635 ret = -1;
3636 goto end;
3637 }
3638
3dca2276 3639 if (ft->id != BT_FIELD_TYPE_ID_SEQUENCE) {
4e8304f7 3640 BT_LOGW("Invalid parameter: field type is not a sequence field type: "
3dca2276
PP
3641 "addr=%p, ft-id=%s", ft,
3642 bt_common_field_type_id_string(ft->id));
aa4e271c
JG
3643 ret = -1;
3644 goto end;
3645 }
3646
b011f6b0 3647 bt_get(path);
3dca2276 3648 BT_MOVE(seq_ft->length_field_path, path);
dfc1504d 3649 BT_LOGV("Set sequence field type's length field path: ft-addr=%p, "
3dca2276
PP
3650 "field-path-addr=%p", ft, path);
3651
aa4e271c
JG
3652end:
3653 return ret;
3654}
4a1e8671
JG
3655
3656BT_HIDDEN
3dca2276
PP
3657int bt_field_type_common_variant_set_tag_field_path(
3658 struct bt_field_type_common *ft,
50842bdc 3659 struct bt_field_path *path)
4a1e8671
JG
3660{
3661 int ret = 0;
3dca2276 3662 struct bt_field_type_common_variant *var_ft = BT_FROM_COMMON(ft);
4a1e8671 3663
3dca2276 3664 if (!ft) {
4e8304f7
PP
3665 BT_LOGW_STR("Invalid parameter: field type is NULL.");
3666 ret = -1;
3667 goto end;
3668 }
3669
3dca2276 3670 if (ft->id != BT_FIELD_TYPE_ID_VARIANT) {
4e8304f7 3671 BT_LOGW("Invalid parameter: field type is not a variant field type: "
3dca2276
PP
3672 "addr=%p, ft-id=%s", ft,
3673 bt_common_field_type_id_string(ft->id));
4a1e8671
JG
3674 ret = -1;
3675 goto end;
3676 }
3677
b011f6b0 3678 bt_get(path);
3dca2276 3679 BT_MOVE(var_ft->tag_field_path, path);
dfc1504d 3680 BT_LOGV("Set variant field type's tag field path: ft-addr=%p, "
3dca2276
PP
3681 "field-path-addr=%p", ft, path);
3682
4a1e8671
JG
3683end:
3684 return ret;
3685}
3f39933a
JG
3686
3687BT_HIDDEN
3dca2276
PP
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)
3f39933a
JG
3691{
3692 int ret = 0;
3dca2276 3693 struct bt_field_type_common_variant *var_ft = BT_FROM_COMMON(ft);
3f39933a 3694
3dca2276 3695 if (!ft) {
4e8304f7 3696 BT_LOGW_STR("Invalid parameter: variant field type is NULL.");
3f39933a
JG
3697 ret = -1;
3698 goto end;
3699 }
3700
3dca2276 3701 if (!tag_ft) {
4e8304f7
PP
3702 BT_LOGW_STR("Invalid parameter: tag field type is NULL.");
3703 ret = -1;
3704 goto end;
3f39933a 3705 }
5cec03e4 3706
3dca2276
PP
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));
5cec03e4
JG
3711 ret = -1;
3712 goto end;
3713 }
3714
3dca2276
PP
3715 bt_put(var_ft->tag_ft);
3716 var_ft->tag_ft = bt_get(tag_ft);
dfc1504d 3717 BT_LOGV("Set variant field type's tag field type: variant-ft-addr=%p, "
3dca2276
PP
3718 "tag-ft-addr=%p", ft, tag_ft);
3719
5cec03e4
JG
3720end:
3721 return ret;
3722}
3723
3dca2276
PP
3724BT_HIDDEN
3725void bt_field_type_common_generic_freeze(struct bt_field_type_common *ft)
273b65be 3726{
3dca2276 3727 ft->frozen = 1;
273b65be
JG
3728}
3729
3dca2276
PP
3730BT_HIDDEN
3731void bt_field_type_common_enumeration_freeze_recursive(
3732 struct bt_field_type_common *ft)
273b65be 3733{
3dca2276 3734 struct bt_field_type_common_enumeration *enum_ft = BT_FROM_COMMON(ft);
273b65be 3735
3dca2276
PP
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));
273b65be
JG
3742}
3743
3dca2276
PP
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);
312c056a 3749 uint64_t i;
273b65be 3750
3dca2276
PP
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);
312c056a
PP
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;
273b65be
JG
3822}
3823
3dca2276
PP
3824BT_HIDDEN
3825void bt_field_type_common_variant_freeze_recursive(
3826 struct bt_field_type_common *ft)
273b65be 3827{
3dca2276 3828 struct bt_field_type_common_variant *var_ft = BT_FROM_COMMON(ft);
312c056a 3829 uint64_t i;
273b65be 3830
3dca2276
PP
3831 BT_LOGD("Freezing variant field type object: addr=%p", ft);
3832 bt_field_type_common_generic_freeze(ft);
312c056a
PP
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 }
273b65be
JG
3843}
3844
3dca2276
PP
3845BT_HIDDEN
3846void bt_field_type_common_array_freeze_recursive(
3847 struct bt_field_type_common *ft)
273b65be 3848{
3dca2276 3849 struct bt_field_type_common_array *array_ft = BT_FROM_COMMON(ft);
273b65be 3850
3dca2276
PP
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);
273b65be
JG
3858}
3859
3dca2276
PP
3860BT_HIDDEN
3861void bt_field_type_common_sequence_freeze_recursive(
3862 struct bt_field_type_common *ft)
273b65be 3863{
3dca2276 3864 struct bt_field_type_common_sequence *seq_ft = BT_FROM_COMMON(ft);
273b65be 3865
3dca2276
PP
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);
273b65be
JG
3873}
3874
3dca2276
PP
3875BT_HIDDEN
3876void bt_field_type_common_integer_set_byte_order(
3877 struct bt_field_type_common *ft, enum bt_byte_order byte_order)
273b65be 3878{
3dca2276 3879 struct bt_field_type_common_integer *int_ft = BT_FROM_COMMON(ft);
273b65be 3880
3dca2276 3881 int_ft->user_byte_order = byte_order;
273b65be
JG
3882}
3883
3dca2276
PP
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)
273b65be 3887{
3dca2276 3888 struct bt_field_type_common_enumeration *enum_ft = BT_FROM_COMMON(ft);
273b65be 3889
3dca2276
PP
3890 bt_field_type_common_set_byte_order(BT_TO_COMMON(enum_ft->container_ft),
3891 byte_order);
273b65be
JG
3892}
3893
3dca2276
PP
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)
273b65be 3897{
3dca2276
PP
3898 struct bt_field_type_common_floating_point *flt_ft = BT_FROM_COMMON(ft);
3899
3900 flt_ft->user_byte_order = byte_order;
273b65be
JG
3901}
3902
3dca2276
PP
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)
586411e5 3907{
3dca2276
PP
3908 int i;
3909 struct bt_field_type_common_structure *struct_ft = BT_FROM_COMMON(ft);
586411e5 3910
3dca2276 3911 for (i = 0; i < struct_ft->fields->len; i++) {
312c056a
PP
3912 struct bt_field_type_common_structure_field *field =
3913 BT_FIELD_TYPE_COMMON_STRUCTURE_FIELD_AT_INDEX(
3914 struct_ft, i);
3dca2276 3915 struct bt_field_type_common *field_type = field->type;
4e8304f7 3916
3dca2276 3917 bt_field_type_common_set_byte_order(field_type, byte_order);
586411e5 3918 }
586411e5
PP
3919}
3920
3dca2276
PP
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)
273b65be 3925{
3dca2276
PP
3926 int i;
3927 struct bt_field_type_common_variant *var_ft = BT_FROM_COMMON(ft);
273b65be 3928
312c056a
PP
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;
273b65be 3934
3dca2276
PP
3935 bt_field_type_common_set_byte_order(field_type, byte_order);
3936 }
273b65be
JG
3937}
3938
3dca2276
PP
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)
273b65be 3943{
3dca2276 3944 struct bt_field_type_common_array *array_ft = BT_FROM_COMMON(ft);
273b65be 3945
3dca2276 3946 bt_field_type_common_set_byte_order(array_ft->element_ft, byte_order);
273b65be
JG
3947}
3948
3dca2276
PP
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)
273b65be 3953{
3dca2276 3954 struct bt_field_type_common_sequence *seq_ft = BT_FROM_COMMON(ft);
273b65be 3955
3dca2276 3956 bt_field_type_common_set_byte_order(seq_ft->element_ft, byte_order);
273b65be
JG
3957}
3958
273b65be 3959
3dca2276
PP
3960BT_HIDDEN
3961int bt_field_type_common_integer_compare(struct bt_field_type_common *ft_a,
3962 struct bt_field_type_common *ft_b)
273b65be 3963{
3dca2276
PP
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);
273b65be 3967
3dca2276
PP
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 }
273b65be 3975
3dca2276
PP
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 }
273b65be 3984
3dca2276
PP
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;
273b65be
JG
3992 }
3993
3dca2276
PP
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 }
273b65be 4002
3dca2276
PP
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 }
273b65be 4011
3dca2276
PP
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 }
6acddae3 4020
3dca2276
PP
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 }
6acddae3
PP
4032 }
4033
3dca2276
PP
4034 /* Equal */
4035 ret = 0;
273b65be 4036
3dca2276 4037end:
6cfb906f 4038 return ret;
273b65be
JG
4039}
4040
3dca2276
PP
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)
273b65be 4045{
3dca2276
PP
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));
4e8304f7 4058 goto end;
273b65be
JG
4059 }
4060
3dca2276
PP
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;
273b65be
JG
4067 }
4068
3dca2276
PP
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;
273b65be 4075 }
3dca2276
PP
4076
4077 /* Equal */
4078 ret = 0;
4079
273b65be
JG
4080end:
4081 return ret;
4082}
4083
4084static
3dca2276
PP
4085int compare_enumeration_mappings(struct enumeration_mapping *mapping_a,
4086 struct enumeration_mapping *mapping_b)
273b65be 4087{
3dca2276 4088 int ret = 1;
273b65be 4089
3dca2276
PP
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 }
273b65be 4098
3dca2276
PP
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;
273b65be
JG
4108 }
4109
3dca2276
PP
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;
273b65be
JG
4119 }
4120
3dca2276
PP
4121 /* Equal */
4122 ret = 0;
4123
273b65be 4124end:
273b65be
JG
4125 return ret;
4126}
4127
3dca2276
PP
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)
273b65be 4132{
3dca2276
PP
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;
6964b7fd
JG
4149 }
4150
3dca2276 4151 ret = 1;
273b65be 4152
3dca2276
PP
4153 /* Entries */
4154 if (enum_ft_a->entries->len != enum_ft_b->entries->len) {
4155 goto end;
4156 }
dfc1504d 4157
3dca2276
PP
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);
273b65be 4163
3dca2276
PP
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));
273b65be
JG
4171 goto end;
4172 }
273b65be
JG
4173 }
4174
3dca2276
PP
4175 /* Equal */
4176 ret = 0;
273b65be 4177
273b65be 4178end:
273b65be
JG
4179 return ret;
4180}
4181
3dca2276
PP
4182BT_HIDDEN
4183int bt_field_type_common_string_compare(struct bt_field_type_common *ft_a,
4184 struct bt_field_type_common *ft_b)
273b65be 4185{
3dca2276
PP
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);
273b65be 4189
3dca2276
PP
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));
273b65be
JG
4196 goto end;
4197 }
4198
3dca2276
PP
4199 /* Equal */
4200 ret = 0;
6acddae3 4201
273b65be
JG
4202end:
4203 return ret;
4204}
4205
4206static
312c056a
PP
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)
273b65be 4211{
3dca2276 4212 int ret = 1;
273b65be 4213
3dca2276 4214 /* Label */
312c056a 4215 if (member_a_name != member_b_name) {
3dca2276
PP
4216 BT_LOGV("Structure/variant field type fields differ: different names: "
4217 "field-a-name=%s, field-b-name=%s",
312c056a
PP
4218 g_quark_to_string(member_a_name),
4219 g_quark_to_string(member_b_name));
273b65be
JG
4220 goto end;
4221 }
4222
3dca2276 4223 /* Type */
312c056a 4224 ret = bt_field_type_common_compare(member_a_ft, member_b_ft);
3dca2276
PP
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",
312c056a
PP
4228 g_quark_to_string(member_a_name),
4229 member_a_ft, member_b_ft);
273b65be 4230 }
3dca2276 4231
273b65be
JG
4232end:
4233 return ret;
4234}
4235
3dca2276
PP
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)
273b65be 4240{
3dca2276
PP
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);
273b65be 4247
3dca2276
PP
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 }
273b65be 4257
3dca2276
PP
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 }
c35a1669 4265
3dca2276 4266 for (i = 0; i < struct_ft_a->fields->len; ++i) {
312c056a
PP
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);
3dca2276 4276 if (ret) {
312c056a 4277 /* compare_structure_variant_members() logs what differs */
3dca2276
PP
4278 BT_LOGV_STR("Structure field types differ: different fields.");
4279 goto end;
4280 }
4281 }
273b65be 4282
3dca2276
PP
4283 /* Equal */
4284 ret = 0;
273b65be 4285
3dca2276
PP
4286end:
4287 return ret;
c35a1669
JG
4288}
4289
3dca2276
PP
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)
c35a1669 4294{
3dca2276 4295 int ret = 1;
c35a1669 4296 int i;
3dca2276
PP
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;
c35a1669 4306 }
c35a1669 4307
3dca2276
PP
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;
c35a1669 4316 }
c35a1669 4317
3dca2276 4318 ret = 1;
c35a1669 4319
3dca2276 4320 /* Fields */
312c056a
PP
4321 if (var_ft_a->choices->len != var_ft_b->choices->len) {
4322 BT_LOGV("Variant field types differ: different field counts: "
3dca2276 4323 "ft-a-field-count=%u, ft-b-field-count=%u",
312c056a 4324 var_ft_a->choices->len, var_ft_b->choices->len);
3dca2276 4325 goto end;
c35a1669 4326 }
c35a1669 4327
312c056a
PP
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);
c35a1669 4335
312c056a
PP
4336 ret = compare_structure_variant_members(choice_a->type,
4337 choice_b->type, choice_a->name, choice_b->name);
3dca2276 4338 if (ret) {
312c056a 4339 /* compare_structure_variant_members() logs what differs */
3dca2276
PP
4340 BT_LOGV_STR("Variant field types differ: different fields.");
4341 goto end;
4342 }
24724933
JG
4343 }
4344
3dca2276
PP
4345 /* Equal */
4346 ret = 0;
445c3471 4347
24724933 4348end:
3dca2276 4349 return ret;
24724933
JG
4350}
4351
3dca2276
PP
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)
24724933 4356{
3dca2276
PP
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);
24724933 4360
3dca2276
PP
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);
24724933
JG
4366 goto end;
4367 }
24724933 4368
3dca2276
PP
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);
24724933
JG
4376 }
4377
24724933 4378end:
3dca2276 4379 return ret;
24724933
JG
4380}
4381
3dca2276
PP
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)
24724933 4386{
3dca2276
PP
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);
24724933 4390
3dca2276
PP
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);
24724933
JG
4399 goto end;
4400 }
4401
3dca2276
PP
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);
24724933
JG
4409 }
4410
24724933 4411end:
3dca2276 4412 return ret;
24724933
JG
4413}
4414
3dca2276
PP
4415BT_HIDDEN
4416int bt_field_type_common_compare(struct bt_field_type_common *ft_a,
4417 struct bt_field_type_common *ft_b)
24724933 4418{
3dca2276 4419 int ret = 1;
24724933 4420
3dca2276
PP
4421 BT_ASSERT_PRE_NON_NULL(ft_a, "Field type A");
4422 BT_ASSERT_PRE_NON_NULL(ft_b, "Field type B");
24724933 4423
3dca2276
PP
4424 if (ft_a == ft_b) {
4425 /* Same reference: equal (even if both are NULL) */
4426 ret = 0;
4427 goto end;
4a1e8671 4428 }
4e8304f7 4429
3dca2276
PP
4430 if (!ft_a) {
4431 BT_LOGW_STR("Invalid parameter: field type A is NULL.");
4432 ret = -1;
24724933
JG
4433 goto end;
4434 }
4435
3dca2276
PP
4436 if (!ft_b) {
4437 BT_LOGW_STR("Invalid parameter: field type B is NULL.");
4438 ret = -1;
24724933
JG
4439 goto end;
4440 }
4e8304f7 4441
3dca2276
PP
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));
24724933
JG
4450 goto end;
4451 }
4452
3dca2276
PP
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.");
24724933
JG
4456 goto end;
4457 }
4458
3dca2276
PP
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);
aa4e271c 4464 }
4e8304f7 4465
24724933 4466end:
3dca2276 4467 return ret;
24724933
JG
4468}
4469
3dca2276
PP
4470int bt_field_type_compare(struct bt_field_type *ft_a,
4471 struct bt_field_type *ft_b)
24724933 4472{
3dca2276 4473 return bt_field_type_common_compare((void *) ft_a, (void *) ft_b);
24724933 4474}
265e809c 4475
3dca2276
PP
4476BT_HIDDEN
4477int64_t bt_field_type_common_get_field_count(struct bt_field_type_common *ft)
265e809c 4478{
3dca2276 4479 int64_t field_count = -1;
265e809c 4480
3dca2276
PP
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;
265e809c
PP
4500 }
4501
3dca2276
PP
4502 return field_count;
4503}
265e809c 4504
3dca2276 4505BT_HIDDEN
094ff7c0 4506struct bt_field_type_common *bt_field_type_common_borrow_field_at_index(
3dca2276
PP
4507 struct bt_field_type_common *ft, int index)
4508{
4509 struct bt_field_type_common *field_type = NULL;
265e809c 4510
3dca2276
PP
4511 switch (ft->id) {
4512 case BT_FIELD_TYPE_ID_STRUCT:
4513 {
094ff7c0 4514 int ret = bt_field_type_common_structure_borrow_field_by_index(
3dca2276
PP
4515 ft, NULL, &field_type, index);
4516 if (ret) {
4517 field_type = NULL;
93dda901
PP
4518 goto end;
4519 }
3dca2276
PP
4520 break;
4521 }
4522 case BT_FIELD_TYPE_ID_VARIANT:
4523 {
094ff7c0 4524 int ret = bt_field_type_common_variant_borrow_field_by_index(
3dca2276
PP
4525 ft, NULL, &field_type, index);
4526 if (ret) {
4527 field_type = NULL;
93dda901
PP
4528 goto end;
4529 }
3dca2276
PP
4530 break;
4531 }
4532 case BT_FIELD_TYPE_ID_ARRAY:
094ff7c0
PP
4533 field_type =
4534 bt_field_type_common_array_borrow_element_field_type(ft);
3dca2276
PP
4535 break;
4536 case BT_FIELD_TYPE_ID_SEQUENCE:
094ff7c0
PP
4537 field_type =
4538 bt_field_type_common_sequence_borrow_element_field_type(ft);
3dca2276
PP
4539 break;
4540 default:
4541 break;
265e809c 4542 }
265e809c
PP
4543
4544end:
3dca2276 4545 return field_type;
265e809c
PP
4546}
4547
3dca2276
PP
4548BT_HIDDEN
4549int bt_field_type_common_get_field_index(struct bt_field_type_common *ft,
4550 const char *name)
265e809c 4551{
3dca2276 4552 int field_index = -1;
265e809c 4553
3dca2276
PP
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;
265e809c
PP
4565 }
4566
3dca2276
PP
4567 return field_index;
4568}
265e809c 4569
3dca2276 4570BT_HIDDEN
094ff7c0 4571struct bt_field_path *bt_field_type_common_variant_borrow_tag_field_path(
3dca2276
PP
4572 struct bt_field_type_common *ft)
4573{
4574 struct bt_field_type_common_variant *var_ft = BT_FROM_COMMON(ft);
265e809c 4575
3dca2276
PP
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");
094ff7c0 4579 return var_ft->tag_field_path;
3dca2276 4580}
265e809c 4581
094ff7c0 4582struct bt_field_path *bt_field_type_variant_borrow_tag_field_path(
3dca2276
PP
4583 struct bt_field_type *ft)
4584{
094ff7c0 4585 return bt_field_type_common_variant_borrow_tag_field_path((void *) ft);
265e809c
PP
4586}
4587
3dca2276 4588BT_HIDDEN
094ff7c0 4589struct bt_field_path *bt_field_type_common_sequence_borrow_length_field_path(
3dca2276 4590 struct bt_field_type_common *ft)
265e809c 4591{
3dca2276 4592 struct bt_field_type_common_sequence *seq_ft = BT_FROM_COMMON(ft);
265e809c 4593
3dca2276
PP
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");
094ff7c0 4597 return seq_ft->length_field_path;
3dca2276 4598}
265e809c 4599
094ff7c0 4600struct bt_field_path *bt_field_type_sequence_borrow_length_field_path(
3dca2276
PP
4601 struct bt_field_type *ft)
4602{
094ff7c0
PP
4603 return bt_field_type_common_sequence_borrow_length_field_path(
4604 (void *) ft);
3dca2276 4605}
265e809c 4606
3dca2276
PP
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) {
265e809c
PP
4615 goto end;
4616 }
4617
3dca2276 4618 BT_ASSERT(expected_clock_class);
265e809c 4619
3dca2276
PP
4620 switch (ft->id) {
4621 case BT_FIELD_TYPE_ID_INTEGER:
4622 {
4623 struct bt_clock_class *mapped_clock_class =
094ff7c0 4624 bt_field_type_common_integer_borrow_mapped_clock_class(ft);
265e809c 4625
3dca2276
PP
4626 if (!mapped_clock_class) {
4627 goto end;
4628 }
265e809c 4629
3dca2276
PP
4630 if (!*expected_clock_class) {
4631 /* Move reference to output parameter */
094ff7c0 4632 *expected_clock_class = bt_get(mapped_clock_class);
3dca2276
PP
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 }
265e809c 4654
3dca2276 4655 break;
265e809c 4656 }
3dca2276
PP
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;
265e809c 4662
3dca2276
PP
4663 switch (ft->id) {
4664 case BT_FIELD_TYPE_ID_ENUM:
094ff7c0 4665 sub_ft = bt_field_type_common_enumeration_borrow_container_field_type(
3dca2276
PP
4666 ft);
4667 break;
4668 case BT_FIELD_TYPE_ID_ARRAY:
094ff7c0 4669 sub_ft = bt_field_type_common_array_borrow_element_field_type(
3dca2276
PP
4670 ft);
4671 break;
4672 case BT_FIELD_TYPE_ID_SEQUENCE:
094ff7c0 4673 sub_ft = bt_field_type_common_sequence_borrow_element_field_type(
3dca2276
PP
4674 ft);
4675 break;
4676 default:
4677 BT_LOGF("Unexpected field type ID: id=%d", ft->id);
4678 abort();
4679 }
265e809c 4680
3dca2276
PP
4681 BT_ASSERT(sub_ft);
4682 ret = bt_field_type_common_validate_single_clock_class(sub_ft,
4683 expected_clock_class);
3dca2276 4684 break;
265e809c 4685 }
3dca2276
PP
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);
265e809c 4691
3dca2276
PP
4692 for (i = 0; i < count; i++) {
4693 const char *name;
4694 struct bt_field_type_common *member_type;
265e809c 4695
094ff7c0 4696 ret = bt_field_type_common_structure_borrow_field_by_index(
3dca2276
PP
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);
3dca2276
PP
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 }
265e809c 4709 }
3dca2276 4710 break;
265e809c 4711 }
3dca2276
PP
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);
265e809c 4717
3dca2276
PP
4718 for (i = 0; i < count; i++) {
4719 const char *name;
4720 struct bt_field_type_common *member_type;
265e809c 4721
094ff7c0 4722 ret = bt_field_type_common_variant_borrow_field_by_index(
3dca2276
PP
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);
3dca2276
PP
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;
265e809c 4740 }
265e809c
PP
4741
4742end:
4743 return ret;
4744}
4745
4746static
3dca2276
PP
4747struct bt_field_type *bt_field_type_integer_copy(
4748 struct bt_field_type *ft)
265e809c 4749{
3dca2276
PP
4750 struct bt_field_type_common_integer *int_ft = (void *) ft;
4751 struct bt_field_type_common_integer *copy_ft;
265e809c 4752
312c056a 4753 BT_LOGD("Copying integer field type's: addr=%p", ft);
3dca2276
PP
4754 copy_ft = (void *) bt_field_type_integer_create(int_ft->size);
4755 if (!copy_ft) {
312c056a 4756 BT_LOGE_STR("Cannot create integer field type.");
265e809c
PP
4757 goto end;
4758 }
4759
3dca2276
PP
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;
312c056a 4766 BT_LOGD("Copied integer field type: original-ft-addr=%p, copy-ft-addr=%p",
3dca2276 4767 ft, copy_ft);
265e809c
PP
4768
4769end:
3dca2276 4770 return (void *) copy_ft;
265e809c
PP
4771}
4772
4773static
3dca2276
PP
4774struct bt_field_type *bt_field_type_enumeration_copy_recursive(
4775 struct bt_field_type *ft)
265e809c 4776{
3dca2276
PP
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;
265e809c 4781
312c056a 4782 BT_LOGD("Copying enumeration field type's: addr=%p", ft);
265e809c 4783
3dca2276 4784 /* Copy the source enumeration's container */
312c056a 4785 BT_LOGD_STR("Copying enumeration field type's container field type.");
3dca2276
PP
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) {
312c056a 4789 BT_LOGE_STR("Cannot copy enumeration field type's container field type.");
265e809c
PP
4790 goto end;
4791 }
4792
3dca2276
PP
4793 copy_ft = (void *) bt_field_type_enumeration_create(
4794 (void *) container_copy_ft);
4795 if (!copy_ft) {
312c056a 4796 BT_LOGE_STR("Cannot create enumeration field type.");
265e809c
PP
4797 goto end;
4798 }
4799
3dca2276
PP
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);
265e809c 4806
3dca2276
PP
4807 if (!copy_mapping) {
4808 BT_LOGE_STR("Failed to allocate one enumeration mapping.");
4809 goto error;
265e809c 4810 }
3dca2276
PP
4811
4812 *copy_mapping = *mapping;
4813 g_ptr_array_add(copy_ft->entries, copy_mapping);
265e809c
PP
4814 }
4815
312c056a 4816 BT_LOGD("Copied enumeration field type: original-ft-addr=%p, copy-ft-addr=%p",
3dca2276 4817 ft, copy_ft);
265e809c
PP
4818
4819end:
3dca2276
PP
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;
265e809c
PP
4827}
4828
4829static
3dca2276
PP
4830struct bt_field_type *bt_field_type_floating_point_copy(
4831 struct bt_field_type *ft)
265e809c 4832{
3dca2276
PP
4833 struct bt_field_type_common_floating_point *flt_ft = BT_FROM_COMMON(ft);
4834 struct bt_field_type_common_floating_point *copy_ft;
265e809c 4835
312c056a 4836 BT_LOGD("Copying floating point number field type's: addr=%p", ft);
3dca2276
PP
4837 copy_ft = (void *) bt_field_type_floating_point_create();
4838 if (!copy_ft) {
312c056a 4839 BT_LOGE_STR("Cannot create floating point number field type.");
265e809c
PP
4840 goto end;
4841 }
4842
3dca2276
PP
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;
312c056a 4846 BT_LOGD("Copied floating point number field type: original-ft-addr=%p, copy-ft-addr=%p",
3dca2276 4847 ft, copy_ft);
265e809c 4848
3dca2276
PP
4849end:
4850 return (void *) copy_ft;
4851}
265e809c 4852
3dca2276
PP
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
312c056a 4863 BT_LOGD("Copying structure field type's: addr=%p", ft);
3dca2276
PP
4864 copy_ft = (void *) bt_field_type_structure_create();
4865 if (!copy_ft) {
312c056a 4866 BT_LOGE_STR("Cannot create structure field type.");
265e809c
PP
4867 goto end;
4868 }
4869
3dca2276
PP
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
312c056a
PP
4877 g_array_set_size(copy_ft->fields, struct_ft->fields->len);
4878
3dca2276 4879 for (i = 0; i < struct_ft->fields->len; i++) {
312c056a 4880 struct bt_field_type_common_structure_field *entry, *copy_entry;
3dca2276 4881 struct bt_field_type_common *field_ft_copy;
265e809c 4882
312c056a
PP
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: "
3dca2276
PP
4888 "index=%" PRId64 ", "
4889 "field-ft-addr=%p, field-name=\"%s\"",
4890 i, entry, g_quark_to_string(entry->name));
3dca2276
PP
4891
4892 field_ft_copy = (void *) bt_field_type_copy(
4893 (void *) entry->type);
4894 if (!field_ft_copy) {
312c056a 4895 BT_LOGE("Cannot copy structure field type's field: "
3dca2276
PP
4896 "index=%" PRId64 ", "
4897 "field-ft-addr=%p, field-name=\"%s\"",
4898 i, entry, g_quark_to_string(entry->name));
3dca2276 4899 goto error;
265e809c 4900 }
3dca2276
PP
4901
4902 copy_entry->name = entry->name;
4903 copy_entry->type = field_ft_copy;
265e809c
PP
4904 }
4905
312c056a 4906 BT_LOGD("Copied structure field type: original-ft-addr=%p, copy-ft-addr=%p",
3dca2276 4907 ft, copy_ft);
265e809c
PP
4908
4909end:
3dca2276
PP
4910 return (void *) copy_ft;
4911
4912error:
4913 BT_PUT(copy_ft);
4914 return NULL;
265e809c
PP
4915}
4916
4917static
3dca2276
PP
4918struct bt_field_type *bt_field_type_variant_copy_recursive(
4919 struct bt_field_type *ft)
265e809c 4920{
3dca2276
PP
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
312c056a 4928 BT_LOGD("Copying variant field type's: addr=%p", ft);
3dca2276 4929 if (var_ft->tag_ft) {
312c056a 4930 BT_LOGD_STR("Copying variant field type's tag field type.");
3dca2276
PP
4931 tag_ft_copy = bt_field_type_common_copy(
4932 BT_TO_COMMON(var_ft->tag_ft));
4933 if (!tag_ft_copy) {
312c056a 4934 BT_LOGE_STR("Cannot copy variant field type's tag field type.");
3dca2276
PP
4935 goto end;
4936 }
4937 }
265e809c 4938
3dca2276
PP
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) {
312c056a 4943 BT_LOGE_STR("Cannot create variant field type.");
265e809c
PP
4944 goto end;
4945 }
4946
3dca2276 4947 /* Copy field_name_to_index */
312c056a 4948 g_hash_table_iter_init(&iter, var_ft->choice_name_to_index);
3dca2276 4949 while (g_hash_table_iter_next(&iter, &key, &value)) {
312c056a 4950 g_hash_table_insert(copy_ft->choice_name_to_index,
3dca2276 4951 key, value);
4e8304f7 4952 }
265e809c 4953
312c056a
PP
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;
3dca2276 4958 struct bt_field_type_common *field_ft_copy;
312c056a 4959 uint64_t range_i;
265e809c 4960
312c056a
PP
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: "
3dca2276
PP
4965 "index=%" PRId64 ", "
4966 "field-ft-addr=%p, field-name=\"%s\"",
4967 i, entry, g_quark_to_string(entry->name));
265e809c 4968
3dca2276
PP
4969 field_ft_copy = (void *) bt_field_type_copy(
4970 (void *) entry->type);
4971 if (!field_ft_copy) {
312c056a 4972 BT_LOGE("Cannot copy variant field type's field: "
3dca2276
PP
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 }
265e809c 4979
3dca2276
PP
4980 copy_entry->name = entry->name;
4981 copy_entry->type = field_ft_copy;
312c056a
PP
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 }
265e809c
PP
4992 }
4993
3dca2276 4994 if (var_ft->tag_field_path) {
312c056a 4995 BT_LOGD_STR("Copying variant field type's tag field path.");
3dca2276
PP
4996 copy_ft->tag_field_path = bt_field_path_copy(
4997 var_ft->tag_field_path);
4998 if (!copy_ft->tag_field_path) {
312c056a 4999 BT_LOGE_STR("Cannot copy variant field type's tag field path.");
3dca2276
PP
5000 goto error;
5001 }
4e8304f7 5002 }
265e809c 5003
312c056a 5004 copy_ft->choices_up_to_date = var_ft->choices_up_to_date;
3dca2276
PP
5005 BT_LOGD("Copied variant field type: original-ft-addr=%p, copy-ft-addr=%p",
5006 ft, copy_ft);
5007
265e809c 5008end:
3dca2276
PP
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;
265e809c
PP
5016}
5017
3dca2276
PP
5018static
5019struct bt_field_type *bt_field_type_array_copy_recursive(
5020 struct bt_field_type *ft)
265e809c 5021{
3dca2276
PP
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;
265e809c 5025
312c056a
PP
5026 BT_LOGD("Copying array field type's: addr=%p", ft);
5027 BT_LOGD_STR("Copying array field type's element field type.");
3dca2276
PP
5028 container_ft_copy = bt_field_type_common_copy(array_ft->element_ft);
5029 if (!container_ft_copy) {
312c056a 5030 BT_LOGE_STR("Cannot copy array field type's element field type.");
265e809c
PP
5031 goto end;
5032 }
5033
3dca2276
PP
5034 copy_ft = (void *) bt_field_type_array_create(
5035 (void *) container_ft_copy, array_ft->length);
5036 if (!copy_ft) {
312c056a 5037 BT_LOGE_STR("Cannot create array field type.");
265e809c
PP
5038 goto end;
5039 }
5040
312c056a 5041 BT_LOGD("Copied array field type: original-ft-addr=%p, copy-ft-addr=%p",
3dca2276 5042 ft, copy_ft);
265e809c
PP
5043
5044end:
3dca2276
PP
5045 bt_put(container_ft_copy);
5046 return (void *) copy_ft;
265e809c 5047}
09840de5 5048
3dca2276
PP
5049static
5050struct bt_field_type *bt_field_type_sequence_copy_recursive(
5051 struct bt_field_type *ft)
09840de5 5052{
3dca2276
PP
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;
09840de5 5056
312c056a
PP
5057 BT_LOGD("Copying sequence field type's: addr=%p", ft);
5058 BT_LOGD_STR("Copying sequence field type's element field type.");
3dca2276
PP
5059 container_ft_copy = bt_field_type_common_copy(seq_ft->element_ft);
5060 if (!container_ft_copy) {
312c056a 5061 BT_LOGE_STR("Cannot copy sequence field type's element field type.");
3dca2276 5062 goto end;
09840de5
PP
5063 }
5064
3dca2276
PP
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) {
312c056a 5070 BT_LOGE_STR("Cannot create sequence field type.");
3dca2276 5071 goto end;
aa15981c 5072 }
3dca2276
PP
5073
5074 if (seq_ft->length_field_path) {
312c056a 5075 BT_LOGD_STR("Copying sequence field type's length field path.");
3dca2276
PP
5076 copy_ft->length_field_path = bt_field_path_copy(
5077 seq_ft->length_field_path);
5078 if (!copy_ft->length_field_path) {
312c056a 5079 BT_LOGE_STR("Cannot copy sequence field type's length field path.");
3dca2276 5080 goto error;
8f3a93d9 5081 }
09840de5 5082 }
09840de5 5083
312c056a 5084 BT_LOGD("Copied sequence field type: original-ft-addr=%p, copy-ft-addr=%p",
3dca2276 5085 ft, copy_ft);
09840de5 5086
3dca2276
PP
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;
09840de5 5094}
b011f6b0 5095
3dca2276
PP
5096static
5097struct bt_field_type *bt_field_type_string_copy(struct bt_field_type *ft)
b011f6b0 5098{
3dca2276
PP
5099 struct bt_field_type_common_string *string_ft = (void *) ft;
5100 struct bt_field_type_common_string *copy_ft = NULL;
b011f6b0 5101
312c056a 5102 BT_LOGD("Copying string field type's: addr=%p", ft);
3dca2276
PP
5103 copy_ft = (void *) bt_field_type_string_create();
5104 if (!copy_ft) {
312c056a 5105 BT_LOGE_STR("Cannot create string field type.");
3dca2276
PP
5106 goto end;
5107 }
b011f6b0 5108
3dca2276 5109 copy_ft->encoding = string_ft->encoding;
312c056a 5110 BT_LOGD("Copied string field type: original-ft-addr=%p, copy-ft-addr=%p",
3dca2276 5111 ft, copy_ft);
b011f6b0 5112
3dca2276
PP
5113end:
5114 return (void *) copy_ft;
b011f6b0 5115}
This page took 0.32488 seconds and 4 git commands to generate.