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