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