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