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