lib: fully detach CTF IR and CTF writer implementations
[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
3fea54f6 168 bt_object_init_shared(&ft->base, release_func);
3dca2276
PP
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
3fea54f6 1433 bt_object_init_shared(&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
3dca2276 3393BT_HIDDEN
5ea30b28 3394void bt_field_type_common_freeze(struct bt_field_type_common *ft)
273b65be 3395{
3dca2276
PP
3396 if (!ft || ft->frozen) {
3397 return;
3398 }
273b65be 3399
3dca2276
PP
3400 BT_ASSERT(ft->methods->freeze);
3401 ft->methods->freeze(ft);
273b65be
JG
3402}
3403
3404BT_HIDDEN
5ea30b28 3405void bt_field_type_freeze(struct bt_field_type *ft)
273b65be 3406{
5ea30b28 3407 bt_field_type_common_freeze((void *) ft);
273b65be
JG
3408}
3409
3410BT_HIDDEN
094ff7c0
PP
3411struct bt_field_type_common *
3412bt_field_type_common_variant_borrow_field_type_signed(
3dca2276 3413 struct bt_field_type_common_variant *var_ft,
b92ddaaa 3414 int64_t tag_value)
273b65be 3415{
3dca2276 3416 struct bt_field_type_common *field_type = NULL;
b92ddaaa
JG
3417 GQuark field_name_quark;
3418 gpointer index;
312c056a 3419 struct bt_field_type_common_variant_choice *choice;
b92ddaaa
JG
3420 struct range_overlap_query query = {
3421 .range_start._signed = tag_value,
3422 .range_end._signed = tag_value,
96e8f959
MD
3423 .mapping_name = 0,
3424 .overlaps = 0,
3425 };
273b65be 3426
3dca2276 3427 g_ptr_array_foreach(var_ft->tag_ft->entries, check_ranges_overlap,
b92ddaaa
JG
3428 &query);
3429 if (!query.overlaps) {
273b65be
JG
3430 goto end;
3431 }
3432
b92ddaaa 3433 field_name_quark = query.mapping_name;
312c056a 3434 if (!g_hash_table_lookup_extended(var_ft->choice_name_to_index,
ec159b1e 3435 GUINT_TO_POINTER(field_name_quark), NULL, &index)) {
273b65be
JG
3436 goto end;
3437 }
3438
312c056a
PP
3439 choice = BT_FIELD_TYPE_COMMON_VARIANT_CHOICE_AT_INDEX(var_ft,
3440 (size_t) index);
3441 field_type = choice->type;
3dca2276 3442
273b65be 3443end:
3dca2276 3444 return field_type;
273b65be
JG
3445}
3446
3447BT_HIDDEN
094ff7c0
PP
3448struct bt_field_type_common *
3449bt_field_type_common_variant_borrow_field_type_unsigned(
3dca2276 3450 struct bt_field_type_common_variant *var_ft,
b92ddaaa 3451 uint64_t tag_value)
273b65be 3452{
3dca2276 3453 struct bt_field_type_common *field_type = NULL;
273b65be
JG
3454 GQuark field_name_quark;
3455 gpointer index;
312c056a 3456 struct bt_field_type_common_variant_choice *choice;
b92ddaaa
JG
3457 struct range_overlap_query query = {
3458 .range_start._unsigned = tag_value,
3459 .range_end._unsigned = tag_value,
96e8f959
MD
3460 .mapping_name = 0,
3461 .overlaps = 0,
3462 };
273b65be 3463
3dca2276
PP
3464 g_ptr_array_foreach(var_ft->tag_ft->entries,
3465 check_ranges_overlap_unsigned, &query);
273b65be
JG
3466 if (!query.overlaps) {
3467 goto end;
3468 }
3469
3470 field_name_quark = query.mapping_name;
312c056a 3471 if (!g_hash_table_lookup_extended(var_ft->choice_name_to_index,
273b65be
JG
3472 GUINT_TO_POINTER(field_name_quark), NULL, &index)) {
3473 goto end;
3474 }
3475
312c056a
PP
3476 choice = BT_FIELD_TYPE_COMMON_VARIANT_CHOICE_AT_INDEX(var_ft,
3477 (size_t) index);
3478 field_type = choice->type;
3479
273b65be 3480end:
3dca2276 3481 return field_type;
273b65be
JG
3482}
3483
3484BT_HIDDEN
3dca2276
PP
3485struct bt_field_type_common *bt_field_type_common_copy(
3486 struct bt_field_type_common *ft)
273b65be 3487{
3dca2276 3488 struct bt_field_type_common *ft_copy = NULL;
273b65be 3489
3dca2276
PP
3490 BT_ASSERT_PRE_NON_NULL(ft, "Field type");
3491 BT_ASSERT(ft->methods->copy);
3492 ft_copy = ft->methods->copy(ft);
3493 if (!ft_copy) {
3494 BT_LOGE_STR("Cannot copy field type.");
81e36fac
PP
3495 goto end;
3496 }
3497
3dca2276
PP
3498 ft_copy->alignment = ft->alignment;
3499
273b65be 3500end:
3dca2276 3501 return ft_copy;
273b65be
JG
3502}
3503
3dca2276 3504struct bt_field_type *bt_field_type_copy(struct bt_field_type *ft)
24724933 3505{
3dca2276 3506 return (void *) bt_field_type_common_copy((void *) ft);
24724933
JG
3507}
3508
39a5e0db 3509BT_HIDDEN
3dca2276
PP
3510int bt_field_type_common_structure_get_field_name_index(
3511 struct bt_field_type_common *ft, const char *name)
39a5e0db
JG
3512{
3513 int ret;
3514 size_t index;
3515 GQuark name_quark;
3dca2276 3516 struct bt_field_type_common_structure *struct_ft = BT_FROM_COMMON(ft);
39a5e0db 3517
3dca2276 3518 BT_ASSERT_PRE_NON_NULL(ft, "Field type");
d975f66c 3519 BT_ASSERT_PRE_NON_NULL(name, "Name");
3dca2276
PP
3520 BT_ASSERT_PRE_FT_COMMON_HAS_ID(ft, BT_FIELD_TYPE_ID_STRUCT,
3521 "Field type");
39a5e0db
JG
3522
3523 name_quark = g_quark_try_string(name);
3524 if (!name_quark) {
6fa8d37b
PP
3525 BT_LOGV("No such structure field type field name: "
3526 "ft-addr=%p, field-name=\"%s\"",
3dca2276 3527 ft, name);
39a5e0db
JG
3528 ret = -1;
3529 goto end;
3530 }
3531
3dca2276 3532 if (!g_hash_table_lookup_extended(struct_ft->field_name_to_index,
ec159b1e 3533 GUINT_TO_POINTER(name_quark),
3dca2276 3534 NULL, (gpointer *) &index)) {
6fa8d37b
PP
3535 BT_LOGV("No such structure field type field name: "
3536 "ft-addr=%p, field-name=\"%s\"",
3dca2276 3537 ft, name);
39a5e0db
JG
3538 ret = -1;
3539 goto end;
3540 }
3dca2276 3541
39a5e0db 3542 ret = (int) index;
3dca2276 3543
39a5e0db
JG
3544end:
3545 return ret;
3546}
736133f1
JG
3547
3548BT_HIDDEN
3dca2276
PP
3549int bt_field_type_common_variant_get_field_name_index(
3550 struct bt_field_type_common *ft, const char *name)
736133f1
JG
3551{
3552 int ret;
3553 size_t index;
3554 GQuark name_quark;
3dca2276 3555 struct bt_field_type_common_variant *var_ft = BT_FROM_COMMON(ft);
736133f1 3556
3dca2276 3557 BT_ASSERT_PRE_NON_NULL(ft, "Field type");
d975f66c 3558 BT_ASSERT_PRE_NON_NULL(name, "Name");
3dca2276
PP
3559 BT_ASSERT_PRE_FT_COMMON_HAS_ID(ft, BT_FIELD_TYPE_ID_VARIANT,
3560 "Field type");
736133f1
JG
3561 name_quark = g_quark_try_string(name);
3562 if (!name_quark) {
6fa8d37b
PP
3563 BT_LOGV("No such variant field type field name: "
3564 "ft-addr=%p, field-name=\"%s\"",
3dca2276 3565 ft, name);
736133f1
JG
3566 ret = -1;
3567 goto end;
3568 }
3569
312c056a 3570 if (!g_hash_table_lookup_extended(var_ft->choice_name_to_index,
ec159b1e 3571 GUINT_TO_POINTER(name_quark),
3dca2276 3572 NULL, (gpointer *) &index)) {
6fa8d37b
PP
3573 BT_LOGV("No such variant field type field name: "
3574 "ft-addr=%p, field-name=\"%s\"",
3dca2276 3575 ft, name);
736133f1
JG
3576 ret = -1;
3577 goto end;
3578 }
3dca2276 3579
736133f1 3580 ret = (int) index;
3dca2276 3581
736133f1
JG
3582end:
3583 return ret;
3584}
aa4e271c
JG
3585
3586BT_HIDDEN
3dca2276
PP
3587int bt_field_type_common_sequence_set_length_field_path(
3588 struct bt_field_type_common *ft, struct bt_field_path *path)
aa4e271c
JG
3589{
3590 int ret = 0;
3dca2276 3591 struct bt_field_type_common_sequence *seq_ft = BT_FROM_COMMON(ft);
aa4e271c 3592
3dca2276 3593 if (!ft) {
4e8304f7
PP
3594 BT_LOGW_STR("Invalid parameter: field type is NULL.");
3595 ret = -1;
3596 goto end;
3597 }
3598
3dca2276 3599 if (ft->id != BT_FIELD_TYPE_ID_SEQUENCE) {
4e8304f7 3600 BT_LOGW("Invalid parameter: field type is not a sequence field type: "
3dca2276
PP
3601 "addr=%p, ft-id=%s", ft,
3602 bt_common_field_type_id_string(ft->id));
aa4e271c
JG
3603 ret = -1;
3604 goto end;
3605 }
3606
b011f6b0 3607 bt_get(path);
3dca2276 3608 BT_MOVE(seq_ft->length_field_path, path);
dfc1504d 3609 BT_LOGV("Set sequence field type's length field path: ft-addr=%p, "
3dca2276
PP
3610 "field-path-addr=%p", ft, path);
3611
aa4e271c
JG
3612end:
3613 return ret;
3614}
4a1e8671
JG
3615
3616BT_HIDDEN
3dca2276
PP
3617int bt_field_type_common_variant_set_tag_field_path(
3618 struct bt_field_type_common *ft,
50842bdc 3619 struct bt_field_path *path)
4a1e8671
JG
3620{
3621 int ret = 0;
3dca2276 3622 struct bt_field_type_common_variant *var_ft = BT_FROM_COMMON(ft);
4a1e8671 3623
3dca2276 3624 if (!ft) {
4e8304f7
PP
3625 BT_LOGW_STR("Invalid parameter: field type is NULL.");
3626 ret = -1;
3627 goto end;
3628 }
3629
3dca2276 3630 if (ft->id != BT_FIELD_TYPE_ID_VARIANT) {
4e8304f7 3631 BT_LOGW("Invalid parameter: field type is not a variant field type: "
3dca2276
PP
3632 "addr=%p, ft-id=%s", ft,
3633 bt_common_field_type_id_string(ft->id));
4a1e8671
JG
3634 ret = -1;
3635 goto end;
3636 }
3637
b011f6b0 3638 bt_get(path);
3dca2276 3639 BT_MOVE(var_ft->tag_field_path, path);
dfc1504d 3640 BT_LOGV("Set variant field type's tag field path: ft-addr=%p, "
3dca2276
PP
3641 "field-path-addr=%p", ft, path);
3642
4a1e8671
JG
3643end:
3644 return ret;
3645}
3f39933a
JG
3646
3647BT_HIDDEN
3dca2276
PP
3648int bt_field_type_common_variant_set_tag_field_type(
3649 struct bt_field_type_common *ft,
3650 struct bt_field_type_common *tag_ft)
3f39933a
JG
3651{
3652 int ret = 0;
3dca2276 3653 struct bt_field_type_common_variant *var_ft = BT_FROM_COMMON(ft);
3f39933a 3654
3dca2276 3655 if (!ft) {
4e8304f7 3656 BT_LOGW_STR("Invalid parameter: variant field type is NULL.");
3f39933a
JG
3657 ret = -1;
3658 goto end;
3659 }
3660
3dca2276 3661 if (!tag_ft) {
4e8304f7
PP
3662 BT_LOGW_STR("Invalid parameter: tag field type is NULL.");
3663 ret = -1;
3664 goto end;
3f39933a 3665 }
5cec03e4 3666
3dca2276
PP
3667 if (tag_ft->id != BT_FIELD_TYPE_ID_ENUM) {
3668 BT_LOGW("Invalid parameter: tag field type is not an enumeration field type: "
3669 "addr=%p, ft-id=%s", tag_ft,
3670 bt_common_field_type_id_string(tag_ft->id));
5cec03e4
JG
3671 ret = -1;
3672 goto end;
3673 }
3674
3dca2276
PP
3675 bt_put(var_ft->tag_ft);
3676 var_ft->tag_ft = bt_get(tag_ft);
dfc1504d 3677 BT_LOGV("Set variant field type's tag field type: variant-ft-addr=%p, "
3dca2276
PP
3678 "tag-ft-addr=%p", ft, tag_ft);
3679
5cec03e4
JG
3680end:
3681 return ret;
3682}
3683
3dca2276
PP
3684BT_HIDDEN
3685void bt_field_type_common_generic_freeze(struct bt_field_type_common *ft)
273b65be 3686{
3dca2276 3687 ft->frozen = 1;
273b65be
JG
3688}
3689
3dca2276
PP
3690BT_HIDDEN
3691void bt_field_type_common_enumeration_freeze_recursive(
3692 struct bt_field_type_common *ft)
273b65be 3693{
3dca2276 3694 struct bt_field_type_common_enumeration *enum_ft = BT_FROM_COMMON(ft);
273b65be 3695
3dca2276
PP
3696 BT_LOGD("Freezing enumeration field type object: addr=%p", ft);
3697 bt_field_type_common_enumeration_set_range_overlap(enum_ft);
3698 bt_field_type_common_generic_freeze(ft);
3699 BT_LOGD("Freezing enumeration field type object's container field type: int-ft-addr=%p",
3700 enum_ft->container_ft);
3701 bt_field_type_common_freeze(BT_TO_COMMON(enum_ft->container_ft));
273b65be
JG
3702}
3703
3dca2276
PP
3704BT_HIDDEN
3705void bt_field_type_common_structure_freeze_recursive(
3706 struct bt_field_type_common *ft)
3707{
3708 struct bt_field_type_common_structure *struct_ft = BT_FROM_COMMON(ft);
312c056a 3709 uint64_t i;
273b65be 3710
3dca2276
PP
3711 /* Cache the alignment */
3712 BT_LOGD("Freezing structure field type object: addr=%p", ft);
3713 ft->alignment = bt_field_type_common_get_alignment(ft);
3714 bt_field_type_common_generic_freeze(ft);
312c056a
PP
3715
3716 for (i = 0; i < struct_ft->fields->len; i++) {
3717 struct bt_field_type_common_structure_field *field =
3718 BT_FIELD_TYPE_COMMON_STRUCTURE_FIELD_AT_INDEX(ft, i);
3719
3720 BT_LOGD("Freezing structure field type field: "
3721 "ft-addr=%p, name=\"%s\"",
3722 field->type, g_quark_to_string(field->name));
3723 bt_field_type_common_freeze(field->type);
3724 }
3725}
3726
3727BT_HIDDEN
3728int bt_field_type_common_variant_update_choices(struct bt_field_type_common *ft)
3729{
3730 struct bt_field_type_common_variant *var_ft = BT_FROM_COMMON(ft);
3731 uint64_t i;
3732 int ret = 0;
3733 bool is_signed;
3734
3735 if (ft->frozen && var_ft->choices_up_to_date) {
3736 goto end;
3737 }
3738
3739 BT_ASSERT(var_ft->tag_ft);
3740 is_signed = !!var_ft->tag_ft->container_ft->is_signed;
3741
3742 for (i = 0; i < var_ft->choices->len; i++) {
3743 struct bt_field_type_common_variant_choice *choice =
3744 BT_FIELD_TYPE_COMMON_VARIANT_CHOICE_AT_INDEX(ft, i);
3745 const char *choice_name = g_quark_to_string(choice->name);
3746 struct bt_field_type_enumeration_mapping_iterator *iter =
3747 bt_field_type_common_enumeration_find_mappings_by_name(
3748 BT_TO_COMMON(var_ft->tag_ft), choice_name);
3749
3750 if (!iter) {
3751 ret = -1;
3752 goto end;
3753 }
3754
3755 BT_ASSERT(choice->ranges);
3756 g_array_set_size(choice->ranges, 0);
3757
3758 while (bt_field_type_enumeration_mapping_iterator_next(iter) == 0) {
3759 struct bt_field_type_common_variant_choice_range range;
3760
3761 if (is_signed) {
3762 ret = bt_field_type_enumeration_mapping_iterator_signed_get(
3763 iter, NULL,
3764 &range.lower.i, &range.upper.i);
3765 } else {
3766 ret = bt_field_type_enumeration_mapping_iterator_unsigned_get(
3767 iter, NULL,
3768 &range.lower.u, &range.upper.u);
3769 }
3770
3771 BT_ASSERT(ret == 0);
3772 g_array_append_val(choice->ranges, range);
3773 }
3774
3775 bt_put(iter);
3776 }
3777
3778 var_ft->choices_up_to_date = true;
3779
3780end:
3781 return ret;
273b65be
JG
3782}
3783
3dca2276
PP
3784BT_HIDDEN
3785void bt_field_type_common_variant_freeze_recursive(
3786 struct bt_field_type_common *ft)
273b65be 3787{
3dca2276 3788 struct bt_field_type_common_variant *var_ft = BT_FROM_COMMON(ft);
312c056a 3789 uint64_t i;
273b65be 3790
3dca2276
PP
3791 BT_LOGD("Freezing variant field type object: addr=%p", ft);
3792 bt_field_type_common_generic_freeze(ft);
312c056a
PP
3793
3794 for (i = 0; i < var_ft->choices->len; i++) {
3795 struct bt_field_type_common_variant_choice *choice =
3796 BT_FIELD_TYPE_COMMON_VARIANT_CHOICE_AT_INDEX(ft, i);
3797
3798 BT_LOGD("Freezing variant field type member: "
3799 "ft-addr=%p, name=\"%s\"",
3800 choice->type, g_quark_to_string(choice->name));
3801 bt_field_type_common_freeze(choice->type);
3802 }
273b65be
JG
3803}
3804
3dca2276
PP
3805BT_HIDDEN
3806void bt_field_type_common_array_freeze_recursive(
3807 struct bt_field_type_common *ft)
273b65be 3808{
3dca2276 3809 struct bt_field_type_common_array *array_ft = BT_FROM_COMMON(ft);
273b65be 3810
3dca2276
PP
3811 /* Cache the alignment */
3812 BT_LOGD("Freezing array field type object: addr=%p", ft);
3813 ft->alignment = bt_field_type_common_get_alignment(ft);
3814 bt_field_type_common_generic_freeze(ft);
3815 BT_LOGD("Freezing array field type object's element field type: element-ft-addr=%p",
3816 array_ft->element_ft);
3817 bt_field_type_common_freeze(array_ft->element_ft);
273b65be
JG
3818}
3819
3dca2276
PP
3820BT_HIDDEN
3821void bt_field_type_common_sequence_freeze_recursive(
3822 struct bt_field_type_common *ft)
273b65be 3823{
3dca2276 3824 struct bt_field_type_common_sequence *seq_ft = BT_FROM_COMMON(ft);
273b65be 3825
3dca2276
PP
3826 /* Cache the alignment */
3827 BT_LOGD("Freezing sequence field type object: addr=%p", ft);
3828 ft->alignment = bt_field_type_common_get_alignment(ft);
3829 bt_field_type_common_generic_freeze(ft);
3830 BT_LOGD("Freezing sequence field type object's element field type: element-ft-addr=%p",
3831 seq_ft->element_ft);
3832 bt_field_type_common_freeze(seq_ft->element_ft);
273b65be
JG
3833}
3834
3dca2276
PP
3835BT_HIDDEN
3836void bt_field_type_common_integer_set_byte_order(
3837 struct bt_field_type_common *ft, enum bt_byte_order byte_order)
273b65be 3838{
3dca2276 3839 struct bt_field_type_common_integer *int_ft = BT_FROM_COMMON(ft);
273b65be 3840
3dca2276 3841 int_ft->user_byte_order = byte_order;
273b65be
JG
3842}
3843
3dca2276
PP
3844BT_HIDDEN
3845void bt_field_type_common_enumeration_set_byte_order_recursive(
3846 struct bt_field_type_common *ft, enum bt_byte_order byte_order)
273b65be 3847{
3dca2276 3848 struct bt_field_type_common_enumeration *enum_ft = BT_FROM_COMMON(ft);
273b65be 3849
3dca2276
PP
3850 bt_field_type_common_set_byte_order(BT_TO_COMMON(enum_ft->container_ft),
3851 byte_order);
273b65be
JG
3852}
3853
3dca2276
PP
3854BT_HIDDEN
3855void bt_field_type_common_floating_point_set_byte_order(
3856 struct bt_field_type_common *ft, enum bt_byte_order byte_order)
273b65be 3857{
3dca2276
PP
3858 struct bt_field_type_common_floating_point *flt_ft = BT_FROM_COMMON(ft);
3859
3860 flt_ft->user_byte_order = byte_order;
273b65be
JG
3861}
3862
3dca2276
PP
3863BT_HIDDEN
3864void bt_field_type_common_structure_set_byte_order_recursive(
3865 struct bt_field_type_common *ft,
3866 enum bt_byte_order byte_order)
586411e5 3867{
3dca2276
PP
3868 int i;
3869 struct bt_field_type_common_structure *struct_ft = BT_FROM_COMMON(ft);
586411e5 3870
3dca2276 3871 for (i = 0; i < struct_ft->fields->len; i++) {
312c056a
PP
3872 struct bt_field_type_common_structure_field *field =
3873 BT_FIELD_TYPE_COMMON_STRUCTURE_FIELD_AT_INDEX(
3874 struct_ft, i);
3dca2276 3875 struct bt_field_type_common *field_type = field->type;
4e8304f7 3876
3dca2276 3877 bt_field_type_common_set_byte_order(field_type, byte_order);
586411e5 3878 }
586411e5
PP
3879}
3880
3dca2276
PP
3881BT_HIDDEN
3882void bt_field_type_common_variant_set_byte_order_recursive(
3883 struct bt_field_type_common *ft,
3884 enum bt_byte_order byte_order)
273b65be 3885{
3dca2276
PP
3886 int i;
3887 struct bt_field_type_common_variant *var_ft = BT_FROM_COMMON(ft);
273b65be 3888
312c056a
PP
3889 for (i = 0; i < var_ft->choices->len; i++) {
3890 struct bt_field_type_common_variant_choice *choice =
3891 BT_FIELD_TYPE_COMMON_VARIANT_CHOICE_AT_INDEX(
3892 var_ft, i);
3893 struct bt_field_type_common *field_type = choice->type;
273b65be 3894
3dca2276
PP
3895 bt_field_type_common_set_byte_order(field_type, byte_order);
3896 }
273b65be
JG
3897}
3898
3dca2276
PP
3899BT_HIDDEN
3900void bt_field_type_common_array_set_byte_order_recursive(
3901 struct bt_field_type_common *ft,
3902 enum bt_byte_order byte_order)
273b65be 3903{
3dca2276 3904 struct bt_field_type_common_array *array_ft = BT_FROM_COMMON(ft);
273b65be 3905
3dca2276 3906 bt_field_type_common_set_byte_order(array_ft->element_ft, byte_order);
273b65be
JG
3907}
3908
3dca2276
PP
3909BT_HIDDEN
3910void bt_field_type_common_sequence_set_byte_order_recursive(
3911 struct bt_field_type_common *ft,
3912 enum bt_byte_order byte_order)
273b65be 3913{
3dca2276 3914 struct bt_field_type_common_sequence *seq_ft = BT_FROM_COMMON(ft);
273b65be 3915
3dca2276 3916 bt_field_type_common_set_byte_order(seq_ft->element_ft, byte_order);
273b65be
JG
3917}
3918
273b65be 3919
3dca2276
PP
3920BT_HIDDEN
3921int bt_field_type_common_integer_compare(struct bt_field_type_common *ft_a,
3922 struct bt_field_type_common *ft_b)
273b65be 3923{
3dca2276
PP
3924 int ret = 1;
3925 struct bt_field_type_common_integer *int_ft_a = BT_FROM_COMMON(ft_a);
3926 struct bt_field_type_common_integer *int_ft_b = BT_FROM_COMMON(ft_b);
273b65be 3927
3dca2276
PP
3928 /* Length */
3929 if (int_ft_a->size != int_ft_b->size) {
3930 BT_LOGV("Integer field types differ: different sizes: "
3931 "ft-a-size=%u, ft-b-size=%u",
3932 int_ft_a->size, int_ft_b->size);
3933 goto end;
3934 }
273b65be 3935
3dca2276
PP
3936 /* Byte order */
3937 if (int_ft_a->user_byte_order != int_ft_b->user_byte_order) {
3938 BT_LOGV("Integer field types differ: different byte orders: "
3939 "ft-a-bo=%s, ft-b-bo=%s",
3940 bt_common_byte_order_string(int_ft_a->user_byte_order),
3941 bt_common_byte_order_string(int_ft_b->user_byte_order));
3942 goto end;
3943 }
273b65be 3944
3dca2276
PP
3945 /* Signedness */
3946 if (int_ft_a->is_signed != int_ft_b->is_signed) {
3947 BT_LOGV("Integer field types differ: different signedness: "
3948 "ft-a-is-signed=%d, ft-b-is-signed=%d",
3949 int_ft_a->is_signed,
3950 int_ft_b->is_signed);
3951 goto end;
273b65be
JG
3952 }
3953
3dca2276
PP
3954 /* Base */
3955 if (int_ft_a->base != int_ft_b->base) {
3956 BT_LOGV("Integer field types differ: different bases: "
3957 "ft-a-base=%s, ft-b-base=%s",
3958 bt_common_integer_base_string(int_ft_a->base),
3959 bt_common_integer_base_string(int_ft_b->base));
3960 goto end;
3961 }
273b65be 3962
3dca2276
PP
3963 /* Encoding */
3964 if (int_ft_a->encoding != int_ft_b->encoding) {
3965 BT_LOGV("Integer field types differ: different encodings: "
3966 "ft-a-encoding=%s, ft-b-encoding=%s",
3967 bt_common_string_encoding_string(int_ft_a->encoding),
3968 bt_common_string_encoding_string(int_ft_b->encoding));
3969 goto end;
3970 }
273b65be 3971
3dca2276
PP
3972 /* Mapped clock class */
3973 if (int_ft_a->mapped_clock_class) {
3974 if (!int_ft_b->mapped_clock_class) {
3975 BT_LOGV_STR("Integer field types differ: field type A "
3976 "has a mapped clock class, but field type B "
3977 "does not.");
3978 goto end;
3979 }
6acddae3 3980
3dca2276
PP
3981 if (bt_clock_class_compare(int_ft_a->mapped_clock_class,
3982 int_ft_b->mapped_clock_class) != 0) {
3983 BT_LOGV_STR("Integer field types differ: different "
3984 "mapped clock classes.");
3985 }
3986 } else {
3987 if (int_ft_b->mapped_clock_class) {
3988 BT_LOGV_STR("Integer field types differ: field type A "
3989 "has no description, but field type B has one.");
3990 goto end;
3991 }
6acddae3
PP
3992 }
3993
3dca2276
PP
3994 /* Equal */
3995 ret = 0;
273b65be 3996
3dca2276 3997end:
6cfb906f 3998 return ret;
273b65be
JG
3999}
4000
3dca2276
PP
4001BT_HIDDEN
4002int bt_field_type_common_floating_point_compare(
4003 struct bt_field_type_common *ft_a,
4004 struct bt_field_type_common *ft_b)
273b65be 4005{
3dca2276
PP
4006 int ret = 1;
4007 struct bt_field_type_common_floating_point *flt_ft_a =
4008 BT_FROM_COMMON(ft_a);
4009 struct bt_field_type_common_floating_point *flt_ft_b =
4010 BT_FROM_COMMON(ft_b);
4011
4012 /* Byte order */
4013 if (flt_ft_a->user_byte_order != flt_ft_b->user_byte_order) {
4014 BT_LOGV("Floating point number field types differ: different byte orders: "
4015 "ft-a-bo=%s, ft-b-bo=%s",
4016 bt_common_byte_order_string(flt_ft_a->user_byte_order),
4017 bt_common_byte_order_string(flt_ft_b->user_byte_order));
4e8304f7 4018 goto end;
273b65be
JG
4019 }
4020
3dca2276
PP
4021 /* Exponent length */
4022 if (flt_ft_a->exp_dig != flt_ft_b->exp_dig) {
4023 BT_LOGV("Floating point number field types differ: different exponent sizes: "
4024 "ft-a-exp-size=%u, ft-b-exp-size=%u",
4025 flt_ft_a->exp_dig, flt_ft_b->exp_dig);
4026 goto end;
273b65be
JG
4027 }
4028
3dca2276
PP
4029 /* Mantissa length */
4030 if (flt_ft_a->mant_dig != flt_ft_b->mant_dig) {
4031 BT_LOGV("Floating point number field types differ: different mantissa sizes: "
4032 "ft-a-mant-size=%u, ft-b-mant-size=%u",
4033 flt_ft_a->mant_dig, flt_ft_b->mant_dig);
4034 goto end;
273b65be 4035 }
3dca2276
PP
4036
4037 /* Equal */
4038 ret = 0;
4039
273b65be
JG
4040end:
4041 return ret;
4042}
4043
4044static
3dca2276
PP
4045int compare_enumeration_mappings(struct enumeration_mapping *mapping_a,
4046 struct enumeration_mapping *mapping_b)
273b65be 4047{
3dca2276 4048 int ret = 1;
273b65be 4049
3dca2276
PP
4050 /* Label */
4051 if (mapping_a->string != mapping_b->string) {
4052 BT_LOGV("Enumeration field type mappings differ: different names: "
4053 "mapping-a-name=\"%s\", mapping-b-name=\"%s\"",
4054 g_quark_to_string(mapping_a->string),
4055 g_quark_to_string(mapping_b->string));
4056 goto end;
4057 }
273b65be 4058
3dca2276
PP
4059 /* Range start */
4060 if (mapping_a->range_start._unsigned !=
4061 mapping_b->range_start._unsigned) {
4062 BT_LOGV("Enumeration field type mappings differ: different starts of range: "
4063 "mapping-a-range-start-unsigned=%" PRIu64 ", "
4064 "mapping-b-range-start-unsigned=%" PRIu64,
4065 mapping_a->range_start._unsigned,
4066 mapping_b->range_start._unsigned);
4067 goto end;
273b65be
JG
4068 }
4069
3dca2276
PP
4070 /* Range end */
4071 if (mapping_a->range_end._unsigned !=
4072 mapping_b->range_end._unsigned) {
4073 BT_LOGV("Enumeration field type mappings differ: different ends of range: "
4074 "mapping-a-range-end-unsigned=%" PRIu64 ", "
4075 "mapping-b-range-end-unsigned=%" PRIu64,
4076 mapping_a->range_end._unsigned,
4077 mapping_b->range_end._unsigned);
4078 goto end;
273b65be
JG
4079 }
4080
3dca2276
PP
4081 /* Equal */
4082 ret = 0;
4083
273b65be 4084end:
273b65be
JG
4085 return ret;
4086}
4087
3dca2276
PP
4088BT_HIDDEN
4089int bt_field_type_common_enumeration_compare_recursive(
4090 struct bt_field_type_common *ft_a,
4091 struct bt_field_type_common *ft_b)
273b65be 4092{
3dca2276
PP
4093 int ret = 1;
4094 int i;
4095 struct bt_field_type_common_enumeration *enum_ft_a =
4096 BT_FROM_COMMON(ft_a);
4097 struct bt_field_type_common_enumeration *enum_ft_b =
4098 BT_FROM_COMMON(ft_b);
4099
4100 /* Container field type */
4101 ret = bt_field_type_common_compare(
4102 BT_TO_COMMON(enum_ft_a->container_ft),
4103 BT_TO_COMMON(enum_ft_b->container_ft));
4104 if (ret) {
4105 BT_LOGV("Enumeration field types differ: different container field types: "
4106 "ft-a-container-ft-addr=%p, ft-b-container-ft-addr=%p",
4107 enum_ft_a->container_ft, enum_ft_b->container_ft);
4108 goto end;
6964b7fd
JG
4109 }
4110
3dca2276 4111 ret = 1;
273b65be 4112
3dca2276
PP
4113 /* Entries */
4114 if (enum_ft_a->entries->len != enum_ft_b->entries->len) {
4115 goto end;
4116 }
dfc1504d 4117
3dca2276
PP
4118 for (i = 0; i < enum_ft_a->entries->len; ++i) {
4119 struct enumeration_mapping *mapping_a =
4120 g_ptr_array_index(enum_ft_a->entries, i);
4121 struct enumeration_mapping *mapping_b =
4122 g_ptr_array_index(enum_ft_b->entries, i);
273b65be 4123
3dca2276
PP
4124 if (compare_enumeration_mappings(mapping_a, mapping_b)) {
4125 BT_LOGV("Enumeration field types differ: different mappings: "
4126 "ft-a-mapping-addr=%p, ft-b-mapping-addr=%p, "
4127 "ft-a-mapping-name=\"%s\", ft-b-mapping-name=\"%s\"",
4128 mapping_a, mapping_b,
4129 g_quark_to_string(mapping_a->string),
4130 g_quark_to_string(mapping_b->string));
273b65be
JG
4131 goto end;
4132 }
273b65be
JG
4133 }
4134
3dca2276
PP
4135 /* Equal */
4136 ret = 0;
273b65be 4137
273b65be 4138end:
273b65be
JG
4139 return ret;
4140}
4141
3dca2276
PP
4142BT_HIDDEN
4143int bt_field_type_common_string_compare(struct bt_field_type_common *ft_a,
4144 struct bt_field_type_common *ft_b)
273b65be 4145{
3dca2276
PP
4146 int ret = 1;
4147 struct bt_field_type_common_string *string_ft_a = BT_FROM_COMMON(ft_a);
4148 struct bt_field_type_common_string *string_ft_b = BT_FROM_COMMON(ft_b);
273b65be 4149
3dca2276
PP
4150 /* Encoding */
4151 if (string_ft_a->encoding != string_ft_b->encoding) {
4152 BT_LOGV("String field types differ: different encodings: "
4153 "ft-a-encoding=%s, ft-b-encoding=%s",
4154 bt_common_string_encoding_string(string_ft_a->encoding),
4155 bt_common_string_encoding_string(string_ft_b->encoding));
273b65be
JG
4156 goto end;
4157 }
4158
3dca2276
PP
4159 /* Equal */
4160 ret = 0;
6acddae3 4161
273b65be
JG
4162end:
4163 return ret;
4164}
4165
4166static
312c056a
PP
4167int compare_structure_variant_members(
4168 struct bt_field_type_common *member_a_ft,
4169 struct bt_field_type_common *member_b_ft,
4170 GQuark member_a_name, GQuark member_b_name)
273b65be 4171{
3dca2276 4172 int ret = 1;
273b65be 4173
3dca2276 4174 /* Label */
312c056a 4175 if (member_a_name != member_b_name) {
3dca2276
PP
4176 BT_LOGV("Structure/variant field type fields differ: different names: "
4177 "field-a-name=%s, field-b-name=%s",
312c056a
PP
4178 g_quark_to_string(member_a_name),
4179 g_quark_to_string(member_b_name));
273b65be
JG
4180 goto end;
4181 }
4182
3dca2276 4183 /* Type */
312c056a 4184 ret = bt_field_type_common_compare(member_a_ft, member_b_ft);
3dca2276
PP
4185 if (ret == 1) {
4186 BT_LOGV("Structure/variant field type fields differ: different field types: "
4187 "field-name=\"%s\", field-a-ft-addr=%p, field-b-ft-addr=%p",
312c056a
PP
4188 g_quark_to_string(member_a_name),
4189 member_a_ft, member_b_ft);
273b65be 4190 }
3dca2276 4191
273b65be
JG
4192end:
4193 return ret;
4194}
4195
3dca2276
PP
4196BT_HIDDEN
4197int bt_field_type_common_structure_compare_recursive(
4198 struct bt_field_type_common *ft_a,
4199 struct bt_field_type_common *ft_b)
273b65be 4200{
3dca2276
PP
4201 int ret = 1;
4202 int i;
4203 struct bt_field_type_common_structure *struct_ft_a =
4204 BT_FROM_COMMON(ft_a);
4205 struct bt_field_type_common_structure *struct_ft_b =
4206 BT_FROM_COMMON(ft_b);
273b65be 4207
3dca2276
PP
4208 /* Alignment */
4209 if (bt_field_type_common_get_alignment(ft_a) !=
4210 bt_field_type_common_get_alignment(ft_b)) {
4211 BT_LOGV("Structure field types differ: different alignments: "
4212 "ft-a-align=%u, ft-b-align=%u",
4213 bt_field_type_common_get_alignment(ft_a),
4214 bt_field_type_common_get_alignment(ft_b));
4215 goto end;
4216 }
273b65be 4217
3dca2276
PP
4218 /* Fields */
4219 if (struct_ft_a->fields->len != struct_ft_b->fields->len) {
4220 BT_LOGV("Structure field types differ: different field counts: "
4221 "ft-a-field-count=%u, ft-b-field-count=%u",
4222 struct_ft_a->fields->len, struct_ft_b->fields->len);
4223 goto end;
4224 }
c35a1669 4225
3dca2276 4226 for (i = 0; i < struct_ft_a->fields->len; ++i) {
312c056a
PP
4227 struct bt_field_type_common_structure_field *field_a =
4228 BT_FIELD_TYPE_COMMON_STRUCTURE_FIELD_AT_INDEX(
4229 struct_ft_a, i);
4230 struct bt_field_type_common_structure_field *field_b =
4231 BT_FIELD_TYPE_COMMON_STRUCTURE_FIELD_AT_INDEX(
4232 struct_ft_b, i);
4233
4234 ret = compare_structure_variant_members(field_a->type,
4235 field_b->type, field_a->name, field_b->name);
3dca2276 4236 if (ret) {
312c056a 4237 /* compare_structure_variant_members() logs what differs */
3dca2276
PP
4238 BT_LOGV_STR("Structure field types differ: different fields.");
4239 goto end;
4240 }
4241 }
273b65be 4242
3dca2276
PP
4243 /* Equal */
4244 ret = 0;
273b65be 4245
3dca2276
PP
4246end:
4247 return ret;
c35a1669
JG
4248}
4249
3dca2276
PP
4250BT_HIDDEN
4251int bt_field_type_common_variant_compare_recursive(
4252 struct bt_field_type_common *ft_a,
4253 struct bt_field_type_common *ft_b)
c35a1669 4254{
3dca2276 4255 int ret = 1;
c35a1669 4256 int i;
3dca2276
PP
4257 struct bt_field_type_common_variant *var_ft_a = BT_FROM_COMMON(ft_a);
4258 struct bt_field_type_common_variant *var_ft_b = BT_FROM_COMMON(ft_b);
4259
4260 /* Tag name */
4261 if (strcmp(var_ft_a->tag_name->str, var_ft_b->tag_name->str)) {
4262 BT_LOGV("Variant field types differ: different tag field names: "
4263 "ft-a-tag-field-name=\"%s\", ft-b-tag-field-name=\"%s\"",
4264 var_ft_a->tag_name->str, var_ft_b->tag_name->str);
4265 goto end;
c35a1669 4266 }
c35a1669 4267
3dca2276
PP
4268 /* Tag type */
4269 ret = bt_field_type_common_compare(BT_TO_COMMON(var_ft_a->tag_ft),
4270 BT_TO_COMMON(var_ft_b->tag_ft));
4271 if (ret) {
4272 BT_LOGV("Variant field types differ: different tag field types: "
4273 "ft-a-tag-ft-addr=%p, ft-b-tag-ft-addr=%p",
4274 var_ft_a->tag_ft, var_ft_b->tag_ft);
4275 goto end;
c35a1669 4276 }
c35a1669 4277
3dca2276 4278 ret = 1;
c35a1669 4279
3dca2276 4280 /* Fields */
312c056a
PP
4281 if (var_ft_a->choices->len != var_ft_b->choices->len) {
4282 BT_LOGV("Variant field types differ: different field counts: "
3dca2276 4283 "ft-a-field-count=%u, ft-b-field-count=%u",
312c056a 4284 var_ft_a->choices->len, var_ft_b->choices->len);
3dca2276 4285 goto end;
c35a1669 4286 }
c35a1669 4287
312c056a
PP
4288 for (i = 0; i < var_ft_a->choices->len; ++i) {
4289 struct bt_field_type_common_variant_choice *choice_a =
4290 BT_FIELD_TYPE_COMMON_VARIANT_CHOICE_AT_INDEX(
4291 var_ft_a, i);
4292 struct bt_field_type_common_variant_choice *choice_b =
4293 BT_FIELD_TYPE_COMMON_VARIANT_CHOICE_AT_INDEX(
4294 var_ft_b, i);
c35a1669 4295
312c056a
PP
4296 ret = compare_structure_variant_members(choice_a->type,
4297 choice_b->type, choice_a->name, choice_b->name);
3dca2276 4298 if (ret) {
312c056a 4299 /* compare_structure_variant_members() logs what differs */
3dca2276
PP
4300 BT_LOGV_STR("Variant field types differ: different fields.");
4301 goto end;
4302 }
24724933
JG
4303 }
4304
3dca2276
PP
4305 /* Equal */
4306 ret = 0;
445c3471 4307
24724933 4308end:
3dca2276 4309 return ret;
24724933
JG
4310}
4311
3dca2276
PP
4312BT_HIDDEN
4313int bt_field_type_common_array_compare_recursive(
4314 struct bt_field_type_common *ft_a,
4315 struct bt_field_type_common *ft_b)
24724933 4316{
3dca2276
PP
4317 int ret = 1;
4318 struct bt_field_type_common_array *array_ft_a = BT_FROM_COMMON(ft_a);
4319 struct bt_field_type_common_array *array_ft_b = BT_FROM_COMMON(ft_b);
24724933 4320
3dca2276
PP
4321 /* Length */
4322 if (array_ft_a->length != array_ft_b->length) {
4323 BT_LOGV("Structure field types differ: different lengths: "
4324 "ft-a-length=%u, ft-b-length=%u",
4325 array_ft_a->length, array_ft_b->length);
24724933
JG
4326 goto end;
4327 }
24724933 4328
3dca2276
PP
4329 /* Element type */
4330 ret = bt_field_type_common_compare(array_ft_a->element_ft,
4331 array_ft_b->element_ft);
4332 if (ret == 1) {
4333 BT_LOGV("Array field types differ: different element field types: "
4334 "ft-a-element-ft-addr=%p, ft-b-element-ft-addr=%p",
4335 array_ft_a->element_ft, array_ft_b->element_ft);
24724933
JG
4336 }
4337
24724933 4338end:
3dca2276 4339 return ret;
24724933
JG
4340}
4341
3dca2276
PP
4342BT_HIDDEN
4343int bt_field_type_common_sequence_compare_recursive(
4344 struct bt_field_type_common *ft_a,
4345 struct bt_field_type_common *ft_b)
24724933 4346{
3dca2276
PP
4347 int ret = -1;
4348 struct bt_field_type_common_sequence *seq_ft_a = BT_FROM_COMMON(ft_a);
4349 struct bt_field_type_common_sequence *seq_ft_b = BT_FROM_COMMON(ft_b);
24724933 4350
3dca2276
PP
4351 /* Length name */
4352 if (strcmp(seq_ft_a->length_field_name->str,
4353 seq_ft_b->length_field_name->str)) {
4354 BT_LOGV("Sequence field types differ: different length field names: "
4355 "ft-a-length-field-name=\"%s\", "
4356 "ft-b-length-field-name=\"%s\"",
4357 seq_ft_a->length_field_name->str,
4358 seq_ft_b->length_field_name->str);
24724933
JG
4359 goto end;
4360 }
4361
3dca2276
PP
4362 /* Element type */
4363 ret = bt_field_type_common_compare(seq_ft_a->element_ft,
4364 seq_ft_b->element_ft);
4365 if (ret == 1) {
4366 BT_LOGV("Sequence field types differ: different element field types: "
4367 "ft-a-element-ft-addr=%p, ft-b-element-ft-addr=%p",
4368 seq_ft_a->element_ft, seq_ft_b->element_ft);
24724933
JG
4369 }
4370
24724933 4371end:
3dca2276 4372 return ret;
24724933
JG
4373}
4374
3dca2276
PP
4375BT_HIDDEN
4376int bt_field_type_common_compare(struct bt_field_type_common *ft_a,
4377 struct bt_field_type_common *ft_b)
24724933 4378{
3dca2276 4379 int ret = 1;
24724933 4380
3dca2276
PP
4381 BT_ASSERT_PRE_NON_NULL(ft_a, "Field type A");
4382 BT_ASSERT_PRE_NON_NULL(ft_b, "Field type B");
24724933 4383
3dca2276
PP
4384 if (ft_a == ft_b) {
4385 /* Same reference: equal (even if both are NULL) */
4386 ret = 0;
4387 goto end;
4a1e8671 4388 }
4e8304f7 4389
3dca2276
PP
4390 if (!ft_a) {
4391 BT_LOGW_STR("Invalid parameter: field type A is NULL.");
4392 ret = -1;
24724933
JG
4393 goto end;
4394 }
4395
3dca2276
PP
4396 if (!ft_b) {
4397 BT_LOGW_STR("Invalid parameter: field type B is NULL.");
4398 ret = -1;
24724933
JG
4399 goto end;
4400 }
4e8304f7 4401
3dca2276
PP
4402 if (ft_a->id != ft_b->id) {
4403 /* Different type IDs */
4404 BT_LOGV("Field types differ: different IDs: "
4405 "ft-a-addr=%p, ft-b-addr=%p, "
4406 "ft-a-id=%s, ft-b-id=%s",
4407 ft_a, ft_b,
4408 bt_common_field_type_id_string(ft_a->id),
4409 bt_common_field_type_id_string(ft_b->id));
24724933
JG
4410 goto end;
4411 }
4412
3dca2276
PP
4413 if (ft_a->id == BT_FIELD_TYPE_ID_UNKNOWN) {
4414 /* Both have unknown type IDs */
4415 BT_LOGW_STR("Invalid parameter: field type IDs are unknown.");
24724933
JG
4416 goto end;
4417 }
4418
3dca2276
PP
4419 BT_ASSERT(ft_a->methods->compare);
4420 ret = ft_a->methods->compare(ft_a, ft_b);
4421 if (ret == 1) {
4422 BT_LOGV("Field types differ: ft-a-addr=%p, ft-b-addr=%p",
4423 ft_a, ft_b);
aa4e271c 4424 }
4e8304f7 4425
24724933 4426end:
3dca2276 4427 return ret;
24724933
JG
4428}
4429
3dca2276
PP
4430int bt_field_type_compare(struct bt_field_type *ft_a,
4431 struct bt_field_type *ft_b)
24724933 4432{
3dca2276 4433 return bt_field_type_common_compare((void *) ft_a, (void *) ft_b);
24724933 4434}
265e809c 4435
3dca2276
PP
4436BT_HIDDEN
4437int64_t bt_field_type_common_get_field_count(struct bt_field_type_common *ft)
265e809c 4438{
3dca2276 4439 int64_t field_count = -1;
265e809c 4440
3dca2276
PP
4441 switch (ft->id) {
4442 case BT_FIELD_TYPE_ID_STRUCT:
4443 field_count =
4444 bt_field_type_common_structure_get_field_count(ft);
4445 break;
4446 case BT_FIELD_TYPE_ID_VARIANT:
4447 field_count =
4448 bt_field_type_common_variant_get_field_count(ft);
4449 break;
4450 case BT_FIELD_TYPE_ID_ARRAY:
4451 case BT_FIELD_TYPE_ID_SEQUENCE:
4452 /*
4453 * Array and sequence types always contain a single member
4454 * (the element type).
4455 */
4456 field_count = 1;
4457 break;
4458 default:
4459 break;
265e809c
PP
4460 }
4461
3dca2276
PP
4462 return field_count;
4463}
265e809c 4464
3dca2276 4465BT_HIDDEN
094ff7c0 4466struct bt_field_type_common *bt_field_type_common_borrow_field_at_index(
3dca2276
PP
4467 struct bt_field_type_common *ft, int index)
4468{
4469 struct bt_field_type_common *field_type = NULL;
265e809c 4470
3dca2276
PP
4471 switch (ft->id) {
4472 case BT_FIELD_TYPE_ID_STRUCT:
4473 {
094ff7c0 4474 int ret = bt_field_type_common_structure_borrow_field_by_index(
3dca2276
PP
4475 ft, NULL, &field_type, index);
4476 if (ret) {
4477 field_type = NULL;
93dda901
PP
4478 goto end;
4479 }
3dca2276
PP
4480 break;
4481 }
4482 case BT_FIELD_TYPE_ID_VARIANT:
4483 {
094ff7c0 4484 int ret = bt_field_type_common_variant_borrow_field_by_index(
3dca2276
PP
4485 ft, NULL, &field_type, index);
4486 if (ret) {
4487 field_type = NULL;
93dda901
PP
4488 goto end;
4489 }
3dca2276
PP
4490 break;
4491 }
4492 case BT_FIELD_TYPE_ID_ARRAY:
094ff7c0
PP
4493 field_type =
4494 bt_field_type_common_array_borrow_element_field_type(ft);
3dca2276
PP
4495 break;
4496 case BT_FIELD_TYPE_ID_SEQUENCE:
094ff7c0
PP
4497 field_type =
4498 bt_field_type_common_sequence_borrow_element_field_type(ft);
3dca2276
PP
4499 break;
4500 default:
4501 break;
265e809c 4502 }
265e809c
PP
4503
4504end:
3dca2276 4505 return field_type;
265e809c
PP
4506}
4507
3dca2276
PP
4508BT_HIDDEN
4509int bt_field_type_common_get_field_index(struct bt_field_type_common *ft,
4510 const char *name)
265e809c 4511{
3dca2276 4512 int field_index = -1;
265e809c 4513
3dca2276
PP
4514 switch (ft->id) {
4515 case BT_FIELD_TYPE_ID_STRUCT:
4516 field_index = bt_field_type_common_structure_get_field_name_index(
4517 ft, name);
4518 break;
4519 case BT_FIELD_TYPE_ID_VARIANT:
4520 field_index = bt_field_type_common_variant_get_field_name_index(
4521 ft, name);
4522 break;
4523 default:
4524 break;
265e809c
PP
4525 }
4526
3dca2276
PP
4527 return field_index;
4528}
265e809c 4529
3dca2276 4530BT_HIDDEN
094ff7c0 4531struct bt_field_path *bt_field_type_common_variant_borrow_tag_field_path(
3dca2276
PP
4532 struct bt_field_type_common *ft)
4533{
4534 struct bt_field_type_common_variant *var_ft = BT_FROM_COMMON(ft);
265e809c 4535
3dca2276
PP
4536 BT_ASSERT_PRE_NON_NULL(ft, "Field type");
4537 BT_ASSERT_PRE_FT_COMMON_HAS_ID(ft, BT_FIELD_TYPE_ID_VARIANT,
4538 "Field type");
094ff7c0 4539 return var_ft->tag_field_path;
3dca2276 4540}
265e809c 4541
094ff7c0 4542struct bt_field_path *bt_field_type_variant_borrow_tag_field_path(
3dca2276
PP
4543 struct bt_field_type *ft)
4544{
094ff7c0 4545 return bt_field_type_common_variant_borrow_tag_field_path((void *) ft);
265e809c
PP
4546}
4547
3dca2276 4548BT_HIDDEN
094ff7c0 4549struct bt_field_path *bt_field_type_common_sequence_borrow_length_field_path(
3dca2276 4550 struct bt_field_type_common *ft)
265e809c 4551{
3dca2276 4552 struct bt_field_type_common_sequence *seq_ft = BT_FROM_COMMON(ft);
265e809c 4553
3dca2276
PP
4554 BT_ASSERT_PRE_NON_NULL(ft, "Field type");
4555 BT_ASSERT_PRE_FT_COMMON_HAS_ID(ft, BT_FIELD_TYPE_ID_SEQUENCE,
4556 "Field type");
094ff7c0 4557 return seq_ft->length_field_path;
3dca2276 4558}
265e809c 4559
094ff7c0 4560struct bt_field_path *bt_field_type_sequence_borrow_length_field_path(
3dca2276
PP
4561 struct bt_field_type *ft)
4562{
094ff7c0
PP
4563 return bt_field_type_common_sequence_borrow_length_field_path(
4564 (void *) ft);
3dca2276 4565}
265e809c 4566
3dca2276
PP
4567BT_HIDDEN
4568int bt_field_type_common_validate_single_clock_class(
4569 struct bt_field_type_common *ft,
4570 struct bt_clock_class **expected_clock_class)
4571{
4572 int ret = 0;
4573
4574 if (!ft) {
265e809c
PP
4575 goto end;
4576 }
4577
3dca2276 4578 BT_ASSERT(expected_clock_class);
265e809c 4579
3dca2276
PP
4580 switch (ft->id) {
4581 case BT_FIELD_TYPE_ID_INTEGER:
4582 {
4583 struct bt_clock_class *mapped_clock_class =
094ff7c0 4584 bt_field_type_common_integer_borrow_mapped_clock_class(ft);
265e809c 4585
3dca2276
PP
4586 if (!mapped_clock_class) {
4587 goto end;
4588 }
265e809c 4589
3dca2276
PP
4590 if (!*expected_clock_class) {
4591 /* Move reference to output parameter */
094ff7c0 4592 *expected_clock_class = bt_get(mapped_clock_class);
3dca2276
PP
4593 mapped_clock_class = NULL;
4594 BT_LOGV("Setting expected clock class: "
4595 "expected-clock-class-addr=%p",
4596 *expected_clock_class);
4597 } else {
4598 if (mapped_clock_class != *expected_clock_class) {
4599 BT_LOGW("Integer field type is not mapped to "
4600 "the expected clock class: "
4601 "mapped-clock-class-addr=%p, "
4602 "mapped-clock-class-name=\"%s\", "
4603 "expected-clock-class-addr=%p, "
4604 "expected-clock-class-name=\"%s\"",
4605 mapped_clock_class,
4606 bt_clock_class_get_name(mapped_clock_class),
4607 *expected_clock_class,
4608 bt_clock_class_get_name(*expected_clock_class));
4609 bt_put(mapped_clock_class);
4610 ret = -1;
4611 goto end;
4612 }
4613 }
265e809c 4614
3dca2276 4615 break;
265e809c 4616 }
3dca2276
PP
4617 case BT_FIELD_TYPE_ID_ENUM:
4618 case BT_FIELD_TYPE_ID_ARRAY:
4619 case BT_FIELD_TYPE_ID_SEQUENCE:
4620 {
4621 struct bt_field_type_common *sub_ft = NULL;
265e809c 4622
3dca2276
PP
4623 switch (ft->id) {
4624 case BT_FIELD_TYPE_ID_ENUM:
094ff7c0 4625 sub_ft = bt_field_type_common_enumeration_borrow_container_field_type(
3dca2276
PP
4626 ft);
4627 break;
4628 case BT_FIELD_TYPE_ID_ARRAY:
094ff7c0 4629 sub_ft = bt_field_type_common_array_borrow_element_field_type(
3dca2276
PP
4630 ft);
4631 break;
4632 case BT_FIELD_TYPE_ID_SEQUENCE:
094ff7c0 4633 sub_ft = bt_field_type_common_sequence_borrow_element_field_type(
3dca2276
PP
4634 ft);
4635 break;
4636 default:
4637 BT_LOGF("Unexpected field type ID: id=%d", ft->id);
4638 abort();
4639 }
265e809c 4640
3dca2276
PP
4641 BT_ASSERT(sub_ft);
4642 ret = bt_field_type_common_validate_single_clock_class(sub_ft,
4643 expected_clock_class);
3dca2276 4644 break;
265e809c 4645 }
3dca2276
PP
4646 case BT_FIELD_TYPE_ID_STRUCT:
4647 {
4648 uint64_t i;
4649 int64_t count = bt_field_type_common_structure_get_field_count(
4650 ft);
265e809c 4651
3dca2276
PP
4652 for (i = 0; i < count; i++) {
4653 const char *name;
4654 struct bt_field_type_common *member_type;
265e809c 4655
094ff7c0 4656 ret = bt_field_type_common_structure_borrow_field_by_index(
3dca2276
PP
4657 ft, &name, &member_type, i);
4658 BT_ASSERT(ret == 0);
4659 ret = bt_field_type_common_validate_single_clock_class(
4660 member_type, expected_clock_class);
3dca2276
PP
4661 if (ret) {
4662 BT_LOGW("Structure field type's field's type "
4663 "is not recursively mapped to the "
4664 "expected clock class: "
4665 "field-ft-addr=%p, field-name=\"%s\"",
4666 member_type, name);
4667 goto end;
4668 }
265e809c 4669 }
3dca2276 4670 break;
265e809c 4671 }
3dca2276
PP
4672 case BT_FIELD_TYPE_ID_VARIANT:
4673 {
4674 uint64_t i;
4675 int64_t count = bt_field_type_common_variant_get_field_count(
4676 ft);
265e809c 4677
3dca2276
PP
4678 for (i = 0; i < count; i++) {
4679 const char *name;
4680 struct bt_field_type_common *member_type;
265e809c 4681
094ff7c0 4682 ret = bt_field_type_common_variant_borrow_field_by_index(
3dca2276
PP
4683 ft, &name, &member_type, i);
4684 BT_ASSERT(ret == 0);
4685 ret = bt_field_type_common_validate_single_clock_class(
4686 member_type, expected_clock_class);
3dca2276
PP
4687 if (ret) {
4688 BT_LOGW("Variant field type's field's type "
4689 "is not recursively mapped to the "
4690 "expected clock class: "
4691 "field-ft-addr=%p, field-name=\"%s\"",
4692 member_type, name);
4693 goto end;
4694 }
4695 }
4696 break;
4697 }
4698 default:
4699 break;
265e809c 4700 }
265e809c
PP
4701
4702end:
4703 return ret;
4704}
4705
4706static
3dca2276
PP
4707struct bt_field_type *bt_field_type_integer_copy(
4708 struct bt_field_type *ft)
265e809c 4709{
3dca2276
PP
4710 struct bt_field_type_common_integer *int_ft = (void *) ft;
4711 struct bt_field_type_common_integer *copy_ft;
265e809c 4712
312c056a 4713 BT_LOGD("Copying integer field type's: addr=%p", ft);
3dca2276
PP
4714 copy_ft = (void *) bt_field_type_integer_create(int_ft->size);
4715 if (!copy_ft) {
312c056a 4716 BT_LOGE_STR("Cannot create integer field type.");
265e809c
PP
4717 goto end;
4718 }
4719
3dca2276
PP
4720 copy_ft->mapped_clock_class = bt_get(int_ft->mapped_clock_class);
4721 copy_ft->user_byte_order = int_ft->user_byte_order;
4722 copy_ft->is_signed = int_ft->is_signed;
4723 copy_ft->size = int_ft->size;
4724 copy_ft->base = int_ft->base;
4725 copy_ft->encoding = int_ft->encoding;
312c056a 4726 BT_LOGD("Copied integer field type: original-ft-addr=%p, copy-ft-addr=%p",
3dca2276 4727 ft, copy_ft);
265e809c
PP
4728
4729end:
3dca2276 4730 return (void *) copy_ft;
265e809c
PP
4731}
4732
4733static
3dca2276
PP
4734struct bt_field_type *bt_field_type_enumeration_copy_recursive(
4735 struct bt_field_type *ft)
265e809c 4736{
3dca2276
PP
4737 size_t i;
4738 struct bt_field_type_common_enumeration *enum_ft = (void *) ft;
4739 struct bt_field_type_common_enumeration *copy_ft = NULL;
4740 struct bt_field_type_common_enumeration *container_copy_ft;
265e809c 4741
312c056a 4742 BT_LOGD("Copying enumeration field type's: addr=%p", ft);
265e809c 4743
3dca2276 4744 /* Copy the source enumeration's container */
312c056a 4745 BT_LOGD_STR("Copying enumeration field type's container field type.");
3dca2276
PP
4746 container_copy_ft = BT_FROM_COMMON(bt_field_type_common_copy(
4747 BT_TO_COMMON(enum_ft->container_ft)));
4748 if (!container_copy_ft) {
312c056a 4749 BT_LOGE_STR("Cannot copy enumeration field type's container field type.");
265e809c
PP
4750 goto end;
4751 }
4752
3dca2276
PP
4753 copy_ft = (void *) bt_field_type_enumeration_create(
4754 (void *) container_copy_ft);
4755 if (!copy_ft) {
312c056a 4756 BT_LOGE_STR("Cannot create enumeration field type.");
265e809c
PP
4757 goto end;
4758 }
4759
3dca2276
PP
4760 /* Copy all enumaration entries */
4761 for (i = 0; i < enum_ft->entries->len; i++) {
4762 struct enumeration_mapping *mapping = g_ptr_array_index(
4763 enum_ft->entries, i);
4764 struct enumeration_mapping *copy_mapping = g_new0(
4765 struct enumeration_mapping, 1);
265e809c 4766
3dca2276
PP
4767 if (!copy_mapping) {
4768 BT_LOGE_STR("Failed to allocate one enumeration mapping.");
4769 goto error;
265e809c 4770 }
3dca2276
PP
4771
4772 *copy_mapping = *mapping;
4773 g_ptr_array_add(copy_ft->entries, copy_mapping);
265e809c
PP
4774 }
4775
312c056a 4776 BT_LOGD("Copied enumeration field type: original-ft-addr=%p, copy-ft-addr=%p",
3dca2276 4777 ft, copy_ft);
265e809c
PP
4778
4779end:
3dca2276
PP
4780 bt_put(container_copy_ft);
4781 return (void *) copy_ft;
4782
4783error:
4784 bt_put(container_copy_ft);
4785 BT_PUT(copy_ft);
4786 return (void *) copy_ft;
265e809c
PP
4787}
4788
4789static
3dca2276
PP
4790struct bt_field_type *bt_field_type_floating_point_copy(
4791 struct bt_field_type *ft)
265e809c 4792{
3dca2276
PP
4793 struct bt_field_type_common_floating_point *flt_ft = BT_FROM_COMMON(ft);
4794 struct bt_field_type_common_floating_point *copy_ft;
265e809c 4795
312c056a 4796 BT_LOGD("Copying floating point number field type's: addr=%p", ft);
3dca2276
PP
4797 copy_ft = (void *) bt_field_type_floating_point_create();
4798 if (!copy_ft) {
312c056a 4799 BT_LOGE_STR("Cannot create floating point number field type.");
265e809c
PP
4800 goto end;
4801 }
4802
3dca2276
PP
4803 copy_ft->user_byte_order = flt_ft->user_byte_order;
4804 copy_ft->exp_dig = flt_ft->exp_dig;
4805 copy_ft->mant_dig = flt_ft->mant_dig;
312c056a 4806 BT_LOGD("Copied floating point number field type: original-ft-addr=%p, copy-ft-addr=%p",
3dca2276 4807 ft, copy_ft);
265e809c 4808
3dca2276
PP
4809end:
4810 return (void *) copy_ft;
4811}
265e809c 4812
3dca2276
PP
4813static
4814struct bt_field_type *bt_field_type_structure_copy_recursive(
4815 struct bt_field_type *ft)
4816{
4817 int64_t i;
4818 GHashTableIter iter;
4819 gpointer key, value;
4820 struct bt_field_type_common_structure *struct_ft = (void *) ft;
4821 struct bt_field_type_common_structure *copy_ft;
4822
312c056a 4823 BT_LOGD("Copying structure field type's: addr=%p", ft);
3dca2276
PP
4824 copy_ft = (void *) bt_field_type_structure_create();
4825 if (!copy_ft) {
312c056a 4826 BT_LOGE_STR("Cannot create structure field type.");
265e809c
PP
4827 goto end;
4828 }
4829
3dca2276
PP
4830 /* Copy field_name_to_index */
4831 g_hash_table_iter_init(&iter, struct_ft->field_name_to_index);
4832 while (g_hash_table_iter_next(&iter, &key, &value)) {
4833 g_hash_table_insert(copy_ft->field_name_to_index,
4834 key, value);
4835 }
4836
312c056a
PP
4837 g_array_set_size(copy_ft->fields, struct_ft->fields->len);
4838
3dca2276 4839 for (i = 0; i < struct_ft->fields->len; i++) {
312c056a 4840 struct bt_field_type_common_structure_field *entry, *copy_entry;
3dca2276 4841 struct bt_field_type_common *field_ft_copy;
265e809c 4842
312c056a
PP
4843 entry = BT_FIELD_TYPE_COMMON_STRUCTURE_FIELD_AT_INDEX(
4844 struct_ft, i);
4845 copy_entry = BT_FIELD_TYPE_COMMON_STRUCTURE_FIELD_AT_INDEX(
4846 copy_ft, i);
4847 BT_LOGD("Copying structure field type's field: "
3dca2276
PP
4848 "index=%" PRId64 ", "
4849 "field-ft-addr=%p, field-name=\"%s\"",
4850 i, entry, g_quark_to_string(entry->name));
3dca2276
PP
4851
4852 field_ft_copy = (void *) bt_field_type_copy(
4853 (void *) entry->type);
4854 if (!field_ft_copy) {
312c056a 4855 BT_LOGE("Cannot copy structure field type's field: "
3dca2276
PP
4856 "index=%" PRId64 ", "
4857 "field-ft-addr=%p, field-name=\"%s\"",
4858 i, entry, g_quark_to_string(entry->name));
3dca2276 4859 goto error;
265e809c 4860 }
3dca2276
PP
4861
4862 copy_entry->name = entry->name;
4863 copy_entry->type = field_ft_copy;
265e809c
PP
4864 }
4865
312c056a 4866 BT_LOGD("Copied structure field type: original-ft-addr=%p, copy-ft-addr=%p",
3dca2276 4867 ft, copy_ft);
265e809c
PP
4868
4869end:
3dca2276
PP
4870 return (void *) copy_ft;
4871
4872error:
4873 BT_PUT(copy_ft);
4874 return NULL;
265e809c
PP
4875}
4876
4877static
3dca2276
PP
4878struct bt_field_type *bt_field_type_variant_copy_recursive(
4879 struct bt_field_type *ft)
265e809c 4880{
3dca2276
PP
4881 int64_t i;
4882 GHashTableIter iter;
4883 gpointer key, value;
4884 struct bt_field_type_common *tag_ft_copy = NULL;
4885 struct bt_field_type_common_variant *var_ft = (void *) ft;
4886 struct bt_field_type_common_variant *copy_ft = NULL;
4887
312c056a 4888 BT_LOGD("Copying variant field type's: addr=%p", ft);
3dca2276 4889 if (var_ft->tag_ft) {
312c056a 4890 BT_LOGD_STR("Copying variant field type's tag field type.");
3dca2276
PP
4891 tag_ft_copy = bt_field_type_common_copy(
4892 BT_TO_COMMON(var_ft->tag_ft));
4893 if (!tag_ft_copy) {
312c056a 4894 BT_LOGE_STR("Cannot copy variant field type's tag field type.");
3dca2276
PP
4895 goto end;
4896 }
4897 }
265e809c 4898
3dca2276
PP
4899 copy_ft = (void *) bt_field_type_variant_create(
4900 (void *) tag_ft_copy,
4901 var_ft->tag_name->len ? var_ft->tag_name->str : NULL);
4902 if (!copy_ft) {
312c056a 4903 BT_LOGE_STR("Cannot create variant field type.");
265e809c
PP
4904 goto end;
4905 }
4906
3dca2276 4907 /* Copy field_name_to_index */
312c056a 4908 g_hash_table_iter_init(&iter, var_ft->choice_name_to_index);
3dca2276 4909 while (g_hash_table_iter_next(&iter, &key, &value)) {
312c056a 4910 g_hash_table_insert(copy_ft->choice_name_to_index,
3dca2276 4911 key, value);
4e8304f7 4912 }
265e809c 4913
312c056a
PP
4914 g_array_set_size(copy_ft->choices, var_ft->choices->len);
4915
4916 for (i = 0; i < var_ft->choices->len; i++) {
4917 struct bt_field_type_common_variant_choice *entry, *copy_entry;
3dca2276 4918 struct bt_field_type_common *field_ft_copy;
312c056a 4919 uint64_t range_i;
265e809c 4920
312c056a
PP
4921 entry = BT_FIELD_TYPE_COMMON_VARIANT_CHOICE_AT_INDEX(var_ft, i);
4922 copy_entry = BT_FIELD_TYPE_COMMON_VARIANT_CHOICE_AT_INDEX(
4923 copy_ft, i);
4924 BT_LOGD("Copying variant field type's field: "
3dca2276
PP
4925 "index=%" PRId64 ", "
4926 "field-ft-addr=%p, field-name=\"%s\"",
4927 i, entry, g_quark_to_string(entry->name));
265e809c 4928
3dca2276
PP
4929 field_ft_copy = (void *) bt_field_type_copy(
4930 (void *) entry->type);
4931 if (!field_ft_copy) {
312c056a 4932 BT_LOGE("Cannot copy variant field type's field: "
3dca2276
PP
4933 "index=%" PRId64 ", "
4934 "field-ft-addr=%p, field-name=\"%s\"",
4935 i, entry, g_quark_to_string(entry->name));
4936 g_free(copy_entry);
4937 goto error;
4938 }
265e809c 4939
3dca2276
PP
4940 copy_entry->name = entry->name;
4941 copy_entry->type = field_ft_copy;
312c056a
PP
4942
4943 /* Copy ranges */
4944 copy_entry->ranges = g_array_new(FALSE, TRUE,
4945 sizeof(struct bt_field_type_common_variant_choice_range));
4946 BT_ASSERT(copy_entry->ranges);
4947 g_array_set_size(copy_entry->ranges, entry->ranges->len);
4948
4949 for (range_i = 0; range_i < entry->ranges->len; range_i++) {
4950 copy_entry->ranges[range_i] = entry->ranges[range_i];
4951 }
265e809c
PP
4952 }
4953
3dca2276 4954 if (var_ft->tag_field_path) {
312c056a 4955 BT_LOGD_STR("Copying variant field type's tag field path.");
3dca2276
PP
4956 copy_ft->tag_field_path = bt_field_path_copy(
4957 var_ft->tag_field_path);
4958 if (!copy_ft->tag_field_path) {
312c056a 4959 BT_LOGE_STR("Cannot copy variant field type's tag field path.");
3dca2276
PP
4960 goto error;
4961 }
4e8304f7 4962 }
265e809c 4963
312c056a 4964 copy_ft->choices_up_to_date = var_ft->choices_up_to_date;
3dca2276
PP
4965 BT_LOGD("Copied variant field type: original-ft-addr=%p, copy-ft-addr=%p",
4966 ft, copy_ft);
4967
265e809c 4968end:
3dca2276
PP
4969 bt_put(tag_ft_copy);
4970 return (void *) copy_ft;
4971
4972error:
4973 bt_put(tag_ft_copy);
4974 BT_PUT(copy_ft);
4975 return NULL;
265e809c
PP
4976}
4977
3dca2276
PP
4978static
4979struct bt_field_type *bt_field_type_array_copy_recursive(
4980 struct bt_field_type *ft)
265e809c 4981{
3dca2276
PP
4982 struct bt_field_type_common *container_ft_copy = NULL;
4983 struct bt_field_type_common_array *array_ft = (void *) ft;
4984 struct bt_field_type_common_array *copy_ft = NULL;
265e809c 4985
312c056a
PP
4986 BT_LOGD("Copying array field type's: addr=%p", ft);
4987 BT_LOGD_STR("Copying array field type's element field type.");
3dca2276
PP
4988 container_ft_copy = bt_field_type_common_copy(array_ft->element_ft);
4989 if (!container_ft_copy) {
312c056a 4990 BT_LOGE_STR("Cannot copy array field type's element field type.");
265e809c
PP
4991 goto end;
4992 }
4993
3dca2276
PP
4994 copy_ft = (void *) bt_field_type_array_create(
4995 (void *) container_ft_copy, array_ft->length);
4996 if (!copy_ft) {
312c056a 4997 BT_LOGE_STR("Cannot create array field type.");
265e809c
PP
4998 goto end;
4999 }
5000
312c056a 5001 BT_LOGD("Copied array field type: original-ft-addr=%p, copy-ft-addr=%p",
3dca2276 5002 ft, copy_ft);
265e809c
PP
5003
5004end:
3dca2276
PP
5005 bt_put(container_ft_copy);
5006 return (void *) copy_ft;
265e809c 5007}
09840de5 5008
3dca2276
PP
5009static
5010struct bt_field_type *bt_field_type_sequence_copy_recursive(
5011 struct bt_field_type *ft)
09840de5 5012{
3dca2276
PP
5013 struct bt_field_type_common *container_ft_copy = NULL;
5014 struct bt_field_type_common_sequence *seq_ft = (void *) ft;
5015 struct bt_field_type_common_sequence *copy_ft = NULL;
09840de5 5016
312c056a
PP
5017 BT_LOGD("Copying sequence field type's: addr=%p", ft);
5018 BT_LOGD_STR("Copying sequence field type's element field type.");
3dca2276
PP
5019 container_ft_copy = bt_field_type_common_copy(seq_ft->element_ft);
5020 if (!container_ft_copy) {
312c056a 5021 BT_LOGE_STR("Cannot copy sequence field type's element field type.");
3dca2276 5022 goto end;
09840de5
PP
5023 }
5024
3dca2276
PP
5025 copy_ft = (void *) bt_field_type_sequence_create(
5026 (void *) container_ft_copy,
5027 seq_ft->length_field_name->len ?
5028 seq_ft->length_field_name->str : NULL);
5029 if (!copy_ft) {
312c056a 5030 BT_LOGE_STR("Cannot create sequence field type.");
3dca2276 5031 goto end;
aa15981c 5032 }
3dca2276
PP
5033
5034 if (seq_ft->length_field_path) {
312c056a 5035 BT_LOGD_STR("Copying sequence field type's length field path.");
3dca2276
PP
5036 copy_ft->length_field_path = bt_field_path_copy(
5037 seq_ft->length_field_path);
5038 if (!copy_ft->length_field_path) {
312c056a 5039 BT_LOGE_STR("Cannot copy sequence field type's length field path.");
3dca2276 5040 goto error;
8f3a93d9 5041 }
09840de5 5042 }
09840de5 5043
312c056a 5044 BT_LOGD("Copied sequence field type: original-ft-addr=%p, copy-ft-addr=%p",
3dca2276 5045 ft, copy_ft);
09840de5 5046
3dca2276
PP
5047end:
5048 bt_put(container_ft_copy);
5049 return (void *) copy_ft;
5050error:
5051 bt_put(container_ft_copy);
5052 BT_PUT(copy_ft);
5053 return NULL;
09840de5 5054}
b011f6b0 5055
3dca2276
PP
5056static
5057struct bt_field_type *bt_field_type_string_copy(struct bt_field_type *ft)
b011f6b0 5058{
3dca2276
PP
5059 struct bt_field_type_common_string *string_ft = (void *) ft;
5060 struct bt_field_type_common_string *copy_ft = NULL;
b011f6b0 5061
312c056a 5062 BT_LOGD("Copying string field type's: addr=%p", ft);
3dca2276
PP
5063 copy_ft = (void *) bt_field_type_string_create();
5064 if (!copy_ft) {
312c056a 5065 BT_LOGE_STR("Cannot create string field type.");
3dca2276
PP
5066 goto end;
5067 }
b011f6b0 5068
3dca2276 5069 copy_ft->encoding = string_ft->encoding;
312c056a 5070 BT_LOGD("Copied string field type: original-ft-addr=%p, copy-ft-addr=%p",
3dca2276 5071 ft, copy_ft);
b011f6b0 5072
3dca2276
PP
5073end:
5074 return (void *) copy_ft;
b011f6b0 5075}
This page took 0.347396 seconds and 4 git commands to generate.