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