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