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