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