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