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