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