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