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