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