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