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