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