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