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