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