Add internal BT_ASSERT() and BT_ASSERT_PRE() helpers
[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
50842bdc 62void bt_field_type_destroy(struct bt_object *);
273b65be 63static
50842bdc 64void bt_field_type_integer_destroy(struct bt_field_type *);
273b65be 65static
50842bdc 66void bt_field_type_enumeration_destroy(struct bt_field_type *);
273b65be 67static
50842bdc 68void bt_field_type_floating_point_destroy(struct bt_field_type *);
273b65be 69static
50842bdc 70void bt_field_type_structure_destroy(struct bt_field_type *);
273b65be 71static
50842bdc 72void bt_field_type_variant_destroy(struct bt_field_type *);
273b65be 73static
50842bdc 74void bt_field_type_array_destroy(struct bt_field_type *);
273b65be 75static
50842bdc 76void bt_field_type_sequence_destroy(struct bt_field_type *);
273b65be 77static
50842bdc 78void bt_field_type_string_destroy(struct bt_field_type *);
273b65be
JG
79
80static
50842bdc
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
50842bdc 95void generic_field_type_freeze(struct bt_field_type *);
273b65be 96static
50842bdc 97void bt_field_type_integer_freeze(struct bt_field_type *);
586411e5 98static
50842bdc 99void bt_field_type_enumeration_freeze(struct bt_field_type *);
273b65be 100static
50842bdc 101void bt_field_type_structure_freeze(struct bt_field_type *);
273b65be 102static
50842bdc 103void bt_field_type_variant_freeze(struct bt_field_type *);
273b65be 104static
50842bdc 105void bt_field_type_array_freeze(struct bt_field_type *);
273b65be 106static
50842bdc 107void bt_field_type_sequence_freeze(struct bt_field_type *);
273b65be
JG
108
109static
110type_freeze_func const type_freeze_funcs[] = {
50842bdc
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
50842bdc 122int bt_field_type_integer_serialize(struct bt_field_type *,
273b65be
JG
123 struct metadata_context *);
124static
50842bdc 125int bt_field_type_enumeration_serialize(struct bt_field_type *,
273b65be
JG
126 struct metadata_context *);
127static
50842bdc
PP
128int bt_field_type_floating_point_serialize(
129 struct bt_field_type *, struct metadata_context *);
273b65be 130static
50842bdc 131int bt_field_type_structure_serialize(struct bt_field_type *,
273b65be
JG
132 struct metadata_context *);
133static
50842bdc 134int bt_field_type_variant_serialize(struct bt_field_type *,
273b65be
JG
135 struct metadata_context *);
136static
50842bdc 137int bt_field_type_array_serialize(struct bt_field_type *,
273b65be
JG
138 struct metadata_context *);
139static
50842bdc 140int bt_field_type_sequence_serialize(struct bt_field_type *,
273b65be
JG
141 struct metadata_context *);
142static
50842bdc 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[] = {
50842bdc
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
50842bdc
PP
162void bt_field_type_integer_set_byte_order(struct bt_field_type *,
163 enum bt_byte_order byte_order);
c35a1669 164static
50842bdc
PP
165void bt_field_type_enumeration_set_byte_order(struct bt_field_type *,
166 enum bt_byte_order byte_order);
273b65be 167static
50842bdc
PP
168void bt_field_type_floating_point_set_byte_order(
169 struct bt_field_type *, enum bt_byte_order byte_order);
c35a1669 170static
50842bdc
PP
171void bt_field_type_structure_set_byte_order(struct bt_field_type *,
172 enum bt_byte_order byte_order);
c35a1669 173static
50842bdc
PP
174void bt_field_type_variant_set_byte_order(struct bt_field_type *,
175 enum bt_byte_order byte_order);
c35a1669 176static
50842bdc
PP
177void bt_field_type_array_set_byte_order(struct bt_field_type *,
178 enum bt_byte_order byte_order);
c35a1669 179static
50842bdc
PP
180void bt_field_type_sequence_set_byte_order(struct bt_field_type *,
181 enum bt_byte_order byte_order);
273b65be
JG
182
183static
50842bdc
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
50842bdc
PP
200struct bt_field_type *bt_field_type_integer_copy(
201 struct bt_field_type *);
24724933 202static
50842bdc
PP
203struct bt_field_type *bt_field_type_enumeration_copy(
204 struct bt_field_type *);
24724933 205static
50842bdc
PP
206struct bt_field_type *bt_field_type_floating_point_copy(
207 struct bt_field_type *);
24724933 208static
50842bdc
PP
209struct bt_field_type *bt_field_type_structure_copy(
210 struct bt_field_type *);
24724933 211static
50842bdc
PP
212struct bt_field_type *bt_field_type_variant_copy(
213 struct bt_field_type *);
24724933 214static
50842bdc
PP
215struct bt_field_type *bt_field_type_array_copy(
216 struct bt_field_type *);
24724933 217static
50842bdc
PP
218struct bt_field_type *bt_field_type_sequence_copy(
219 struct bt_field_type *);
24724933 220static
50842bdc
PP
221struct bt_field_type *bt_field_type_string_copy(
222 struct bt_field_type *);
24724933
JG
223
224static
50842bdc
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
50842bdc
PP
238int bt_field_type_integer_compare(struct bt_field_type *,
239 struct bt_field_type *);
265e809c 240static
50842bdc
PP
241int bt_field_type_floating_point_compare(struct bt_field_type *,
242 struct bt_field_type *);
265e809c 243static
50842bdc
PP
244int bt_field_type_enumeration_compare(struct bt_field_type *,
245 struct bt_field_type *);
265e809c 246static
50842bdc
PP
247int bt_field_type_string_compare(struct bt_field_type *,
248 struct bt_field_type *);
265e809c 249static
50842bdc
PP
250int bt_field_type_structure_compare(struct bt_field_type *,
251 struct bt_field_type *);
265e809c 252static
50842bdc
PP
253int bt_field_type_variant_compare(struct bt_field_type *,
254 struct bt_field_type *);
265e809c 255static
50842bdc
PP
256int bt_field_type_array_compare(struct bt_field_type *,
257 struct bt_field_type *);
265e809c 258static
50842bdc
PP
259int bt_field_type_sequence_compare(struct bt_field_type *,
260 struct bt_field_type *);
265e809c
PP
261
262static
50842bdc
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
50842bdc 276int bt_field_type_integer_validate(struct bt_field_type *);
81e36fac 277static
50842bdc 278int bt_field_type_enumeration_validate(struct bt_field_type *);
81e36fac 279static
50842bdc 280int bt_field_type_structure_validate(struct bt_field_type *);
81e36fac 281static
50842bdc 282int bt_field_type_variant_validate(struct bt_field_type *);
81e36fac 283static
50842bdc 284int bt_field_type_array_validate(struct bt_field_type *);
81e36fac 285static
50842bdc 286int bt_field_type_sequence_validate(struct bt_field_type *);
81e36fac
PP
287
288static
50842bdc
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
50842bdc 398void bt_field_type_init(struct bt_field_type *type, bt_bool init_bo)
273b65be 399{
50842bdc
PP
400 assert(type && (type->id > BT_FIELD_TYPE_ID_UNKNOWN) &&
401 (type->id < BT_FIELD_TYPE_ID_NR));
273b65be 402
50842bdc 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;
50842bdc 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",
50842bdc
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,
50842bdc 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
50842bdc 460void bt_field_type_destroy(struct bt_object *obj)
2f2d8e05 461{
50842bdc
PP
462 struct bt_field_type *type;
463 enum bt_field_type_id type_id;
2f2d8e05 464
50842bdc 465 type = container_of(obj, struct bt_field_type, base);
dc3fffef 466 type_id = type->id;
50842bdc
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
50842bdc 473int bt_field_type_integer_validate(struct bt_field_type *type)
b3dbeb52
PP
474{
475 int ret = 0;
476
50842bdc
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,
50842bdc 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(
50842bdc 496 struct bt_field_type *type, uint64_t index)
d49e1284
JG
497{
498 struct enumeration_mapping *mapping = NULL;
50842bdc 499 struct bt_field_type_enumeration *enumeration;
d49e1284 500
50842bdc 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(
50842bdc 521 struct bt_field_type *type)
d49e1284 522{
4e8304f7 523 int64_t i, j, len;
50842bdc
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,
50842bdc 531 struct bt_field_type_enumeration, parent);
d49e1284
JG
532
533 len = enumeration_type->entries->len;
534 container_type = enumeration_type->container;
50842bdc 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
50842bdc 572int bt_field_type_enumeration_validate(struct bt_field_type *type)
9ce21c30
JG
573{
574 int ret = 0;
575
50842bdc
PP
576 struct bt_field_type_enumeration *enumeration =
577 container_of(type, struct bt_field_type_enumeration,
81e36fac 578 parent);
50842bdc
PP
579 struct bt_field_type *container_type =
580 bt_field_type_enumeration_get_container_type(type);
81e36fac 581
4e8304f7 582 assert(container_type);
50842bdc 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
50842bdc 605int bt_field_type_sequence_validate(struct bt_field_type *type)
81e36fac
PP
606{
607 int ret = 0;
50842bdc
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
50842bdc 621 element_type = bt_field_type_sequence_get_element_type(type);
4e8304f7 622 assert(element_type);
50842bdc 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
50842bdc 637int bt_field_type_array_validate(struct bt_field_type *type)
81e36fac
PP
638{
639 int ret = 0;
50842bdc 640 struct bt_field_type *element_type = NULL;
81e36fac 641
50842bdc 642 element_type = bt_field_type_array_get_element_type(type);
4e8304f7 643 assert(element_type);
50842bdc 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
50842bdc 656int bt_field_type_structure_validate(struct bt_field_type *type)
81e36fac
PP
657{
658 int ret = 0;
50842bdc
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
50842bdc 668 ret = bt_field_type_structure_get_field_by_index(type,
4e8304f7
PP
669 &field_name, &child_type, i);
670 assert(ret == 0);
50842bdc 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
50842bdc
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
50842bdc 701int bt_field_type_variant_validate(struct bt_field_type *type)
81e36fac
PP
702{
703 int ret = 0;
544d0515 704 int64_t field_count;
50842bdc
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
50842bdc 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 /*
2d4b0539
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 *
2d4b0539
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 */
50842bdc 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
50842bdc 762 ret = bt_field_type_variant_get_field_by_index(type,
4e8304f7
PP
763 &field_name, &child_type, i);
764 assert(ret == 0);
50842bdc 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
50842bdc 793int bt_field_type_validate(struct bt_field_type *type)
81e36fac
PP
794{
795 int ret = 0;
50842bdc 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
50842bdc 819struct bt_field_type *bt_field_type_integer_create(unsigned int size)
273b65be 820{
50842bdc
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
50842bdc 837 integer->parent.id = BT_FIELD_TYPE_ID_INTEGER;
dc3fffef 838 integer->size = size;
50842bdc
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
50842bdc 847int bt_field_type_integer_get_size(struct bt_field_type *type)
b92ddaaa
JG
848{
849 int ret = 0;
50842bdc 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
50842bdc 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,
50842bdc 861 bt_field_type_id_string(type->id));
b92ddaaa
JG
862 ret = -1;
863 goto end;
864 }
865
50842bdc 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
50842bdc 872int bt_ctf_field_type_integer_get_signed(struct bt_field_type *type)
b92ddaaa
JG
873{
874 int ret = 0;
50842bdc 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
50842bdc 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,
50842bdc 886 bt_field_type_id_string(type->id));
b92ddaaa
JG
887 ret = -1;
888 goto end;
889 }
890
50842bdc 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
50842bdc
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
50842bdc 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;
50842bdc 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
50842bdc 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,
50842bdc 926 bt_field_type_id_string(type->id));
273b65be
JG
927 ret = -1;
928 goto end;
929 }
930
50842bdc 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
50842bdc 939int bt_field_type_integer_set_size(struct bt_field_type *type,
3bc8ebda 940 unsigned int size)
c3c35de4
JD
941{
942 int ret = 0;
50842bdc 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
50842bdc 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,
50842bdc 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
50842bdc 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
50842bdc
PP
981enum bt_integer_base bt_field_type_integer_get_base(
982 struct bt_field_type *type)
b92ddaaa 983{
50842bdc
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
50842bdc 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,
50842bdc 995 bt_field_type_id_string(type->id));
b92ddaaa
JG
996 goto end;
997 }
998
50842bdc 999 integer = container_of(type, struct bt_field_type_integer, parent);
dc3fffef 1000 ret = integer->base;
b92ddaaa
JG
1001end:
1002 return ret;
1003}
1004
50842bdc
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
50842bdc 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,
50842bdc 1026 bt_field_type_id_string(type->id));
273b65be
JG
1027 ret = -1;
1028 goto end;
1029 }
1030
1031 switch (base) {
50842bdc
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 {
50842bdc
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",
50842bdc 1050 type, bt_integer_base_string(base));
dfc1504d 1051
273b65be
JG
1052end:
1053 return ret;
1054}
1055
50842bdc
PP
1056enum bt_string_encoding bt_field_type_integer_get_encoding(
1057 struct bt_field_type *type)
b92ddaaa 1058{
50842bdc
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
50842bdc 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,
50842bdc 1070 bt_field_type_id_string(type->id));
b92ddaaa
JG
1071 goto end;
1072 }
1073
50842bdc 1074 integer = container_of(type, struct bt_field_type_integer, parent);
dc3fffef 1075 ret = integer->encoding;
b92ddaaa
JG
1076end:
1077 return ret;
1078}
1079
50842bdc
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;
50842bdc 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
50842bdc 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,
50842bdc 1102 bt_field_type_id_string(type->id));
4e8304f7
PP
1103 ret = -1;
1104 goto end;
1105 }
1106
50842bdc
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
50842bdc 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",
50842bdc 1119 type, bt_string_encoding_string(encoding));
273b65be
JG
1120end:
1121 return ret;
1122}
1123
50842bdc
PP
1124struct bt_clock_class *bt_field_type_integer_get_mapped_clock_class(
1125 struct bt_field_type *type)
6cfb906f 1126{
50842bdc
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
50842bdc 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
50842bdc
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{
50842bdc 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
50842bdc 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,
50842bdc 1165 bt_field_type_id_string(type->id));
4e8304f7
PP
1166 goto end;
1167 }
1168
50842bdc 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,
50842bdc 1173 bt_clock_class_get_name(clock_class));
6cfb906f
JG
1174 ret = -1;
1175 goto end;
1176 }
1177
50842bdc 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\"",
50842bdc 1183 type, clock_class, bt_clock_class_get_name(clock_class));
6cfb906f
JG
1184end:
1185 return ret;
1186}
1187
50842bdc
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
50842bdc 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
50842bdc 1215void bt_field_type_enum_iter_destroy(struct bt_object *obj)
96e8f959 1216{
50842bdc 1217 struct bt_field_type_enumeration_mapping_iterator *iter =
d49e1284 1218 container_of(obj,
50842bdc 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
50842bdc
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{
50842bdc
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
50842bdc 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,
50842bdc 1246 bt_field_type_id_string(type->id));
96e8f959
MD
1247 goto end;
1248 }
1249
d49e1284 1250 enumeration_type = container_of(type,
50842bdc
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
50842bdc 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
50842bdc
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{
50842bdc 1271 struct bt_field_type_enumeration_mapping_iterator *iter;
96e8f959 1272
50842bdc 1273 iter = bt_field_type_enumeration_find_mappings_type(
d49e1284
JG
1274 type, ITERATOR_BY_NAME);
1275 if (!iter) {
631234da 1276 BT_LOGW("Cannot create enumeration field type mapping iterator: "
4e8304f7 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) {
74fb0452
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
50842bdc
PP
1295int bt_field_type_enumeration_mapping_iterator_next(
1296 struct bt_field_type_enumeration_mapping_iterator *iter)
96e8f959 1297{
50842bdc
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
50842bdc
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{
50842bdc 1360 struct bt_field_type_enumeration_mapping_iterator *iter;
96e8f959 1361
50842bdc 1362 iter = bt_field_type_enumeration_find_mappings_type(
96e8f959
MD
1363 type, ITERATOR_BY_SIGNED_VALUE);
1364 if (!iter) {
631234da 1365 BT_LOGW("Cannot create enumeration field type mapping iterator: "
4e8304f7 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
50842bdc
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{
50842bdc 1389 struct bt_field_type_enumeration_mapping_iterator *iter;
96e8f959 1390
50842bdc 1391 iter = bt_field_type_enumeration_find_mappings_type(
96e8f959
MD
1392 type, ITERATOR_BY_UNSIGNED_VALUE);
1393 if (!iter) {
631234da 1394 BT_LOGW("Cannot create enumeration field type mapping iterator: "
4e8304f7 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
50842bdc
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
74fb0452
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
50842bdc 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
50842bdc
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
74fb0452
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
50842bdc 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
50842bdc
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
50842bdc
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
50842bdc
PP
1540struct bt_field_type *bt_field_type_enumeration_create(
1541 struct bt_field_type *integer_container_type)
273b65be 1542{
50842bdc 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
50842bdc 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,
50842bdc 1557 bt_field_type_id_string(integer_container_type->id));
2a610bb7
JG
1558 goto error;
1559 }
1560
50842bdc 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
50842bdc 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);
50842bdc 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,
50842bdc 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
50842bdc
PP
1583struct bt_field_type *bt_field_type_enumeration_get_container_type(
1584 struct bt_field_type *type)
b92ddaaa 1585{
50842bdc
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
50842bdc 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,
50842bdc 1597 bt_field_type_id_string(type->id));
b92ddaaa
JG
1598 goto end;
1599 }
1600
1601 enumeration_type = container_of(type,
50842bdc 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
50842bdc
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;
50842bdc 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
50842bdc 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,
50842bdc 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 };
50842bdc 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
50842bdc
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;
50842bdc 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
50842bdc 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,
50842bdc 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 };
50842bdc 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
50842bdc
PP
1787int64_t bt_field_type_enumeration_get_mapping_count(
1788 struct bt_field_type *type)
b92ddaaa 1789{
544d0515 1790 int64_t ret = 0;
50842bdc 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
50842bdc 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,
50842bdc 1802 bt_field_type_id_string(type->id));
9ac68eb1 1803 ret = (int64_t) -1;
b92ddaaa
JG
1804 goto end;
1805 }
1806
50842bdc 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
50842bdc 1814struct bt_field_type *bt_field_type_floating_point_create(void)
273b65be 1815{
50842bdc
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
50842bdc 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;
50842bdc 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
50842bdc
PP
1837int bt_field_type_floating_point_get_exponent_digits(
1838 struct bt_field_type *type)
b92ddaaa
JG
1839{
1840 int ret = 0;
50842bdc 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
50842bdc 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,
50842bdc 1852 bt_field_type_id_string(type->id));
b92ddaaa
JG
1853 ret = -1;
1854 goto end;
1855 }
1856
1857 floating_point = container_of(type,
50842bdc 1858 struct bt_field_type_floating_point, parent);
dc3fffef 1859 ret = (int) floating_point->exp_dig;
b92ddaaa
JG
1860end:
1861 return ret;
1862}
1863
50842bdc
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;
50842bdc 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
50842bdc 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,
50842bdc 1887 bt_field_type_id_string(type->id));
273b65be
JG
1888 ret = -1;
1889 goto end;
1890 }
1891
1892 floating_point = container_of(type,
50842bdc 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
50842bdc
PP
1911int bt_field_type_floating_point_get_mantissa_digits(
1912 struct bt_field_type *type)
b92ddaaa
JG
1913{
1914 int ret = 0;
50842bdc 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
50842bdc 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,
50842bdc 1926 bt_field_type_id_string(type->id));
b92ddaaa
JG
1927 ret = -1;
1928 goto end;
1929 }
1930
1931 floating_point = container_of(type,
50842bdc 1932 struct bt_field_type_floating_point, parent);
dc3fffef 1933 ret = (int) floating_point->mant_dig;
b92ddaaa
JG
1934end:
1935 return ret;
1936}
1937
50842bdc
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;
50842bdc 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
50842bdc 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,
50842bdc 1961 bt_field_type_id_string(type->id));
273b65be
JG
1962 ret = -1;
1963 goto end;
1964 }
1965
1966 floating_point = container_of(type,
50842bdc 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
50842bdc 1985struct bt_field_type *bt_field_type_structure_create(void)
273b65be 1986{
50842bdc
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
50842bdc 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);
50842bdc 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
79422a2b
PP
2009BT_HIDDEN
2010int bt_field_type_structure_replace_field(struct bt_field_type *type,
2011 const char *field_name, struct bt_field_type *field_type)
2012{
2013 int ret = 0;
2014 struct bt_field_type_structure *structure;
2015 GQuark name_quark;
2016 uint64_t i;
2017
2018 assert(type);
2019 assert(field_name);
2020 assert(field_type);
2021 assert(type->id == BT_FIELD_TYPE_ID_STRUCT);
2022 structure = container_of(type, struct bt_field_type_structure, parent);
2023 name_quark = g_quark_from_string(field_name);
2024
2025 for (i = 0; i < structure->fields->len; i++) {
2026 struct structure_field *field = g_ptr_array_index(
2027 structure->fields, i);
2028
2029 if (field->name == name_quark) {
2030 bt_put(field->type);
2031 field->type = bt_get(field_type);
2032 }
2033 }
2034
2035 return ret;
2036}
2037
50842bdc
PP
2038int bt_field_type_structure_add_field(struct bt_field_type *type,
2039 struct bt_field_type *field_type,
273b65be
JG
2040 const char *field_name)
2041{
2042 int ret = 0;
50842bdc 2043 struct bt_field_type_structure *structure;
273b65be 2044
73892edc
PP
2045 /*
2046 * TODO: check that `field_type` does not contain `type`,
2047 * recursively.
2048 */
4e8304f7
PP
2049 if (!type) {
2050 BT_LOGW_STR("Invalid parameter: field type is NULL.");
2051 ret = -1;
2052 goto end;
2053 }
2054
2055 if (!field_name) {
2056 BT_LOGW_STR("Invalid parameter: field name is NULL.");
2057 ret = -1;
2058 goto end;
2059 }
2060
2061 if (type->frozen) {
2062 BT_LOGW("Invalid parameter: field type is frozen: addr=%p",
2063 type);
2064 ret = -1;
2065 goto end;
2066 }
2067
50842bdc 2068 if (type->id != BT_FIELD_TYPE_ID_STRUCT) {
4e8304f7
PP
2069 BT_LOGW("Invalid parameter: field type is not a structure field type: "
2070 "addr=%p, ft-id=%s", type,
50842bdc 2071 bt_field_type_id_string(type->id));
4e8304f7
PP
2072 ret = -1;
2073 goto end;
2074 }
2075
2076 if (type == field_type) {
2077 BT_LOGW("Invalid parameter: structure field type and field type to add are the same: "
2078 "addr=%p", type);
e6235f1f 2079 ret = -1;
273b65be
JG
2080 goto end;
2081 }
2082
2083 structure = container_of(type,
50842bdc 2084 struct bt_field_type_structure, parent);
273b65be 2085 if (add_structure_field(structure->fields,
4e8304f7
PP
2086 structure->field_name_to_index, field_type, field_name)) {
2087 BT_LOGW("Cannot add field to structure field type: "
2088 "struct-ft-addr=%p, field-ft-addr=%p, field-name=\"%s\"",
2089 type, field_type, field_name);
273b65be
JG
2090 ret = -1;
2091 goto end;
2092 }
dfc1504d
PP
2093
2094 BT_LOGV("Added structure field type field: struct-ft-addr=%p, "
2095 "field-ft-addr=%p, field-name=\"%s\"", type,
2096 field_type, field_name);
b92ddaaa
JG
2097end:
2098 return ret;
2099}
2100
50842bdc
PP
2101int64_t bt_field_type_structure_get_field_count(
2102 struct bt_field_type *type)
b92ddaaa 2103{
544d0515 2104 int64_t ret = 0;
50842bdc 2105 struct bt_field_type_structure *structure;
b92ddaaa 2106
4e8304f7
PP
2107 if (!type) {
2108 BT_LOGW_STR("Invalid parameter: field type is NULL.");
2109 ret = (int64_t) -1;
2110 goto end;
2111 }
2112
50842bdc 2113 if (type->id != BT_FIELD_TYPE_ID_STRUCT) {
4e8304f7
PP
2114 BT_LOGW("Invalid parameter: field type is not a structure field type: "
2115 "addr=%p, ft-id=%s", type,
50842bdc 2116 bt_field_type_id_string(type->id));
9ac68eb1 2117 ret = (int64_t) -1;
b92ddaaa
JG
2118 goto end;
2119 }
2120
50842bdc 2121 structure = container_of(type, struct bt_field_type_structure,
b92ddaaa 2122 parent);
544d0515 2123 ret = (int64_t) structure->fields->len;
b92ddaaa
JG
2124end:
2125 return ret;
2126}
2127
50842bdc
PP
2128int bt_field_type_structure_get_field_by_index(
2129 struct bt_field_type *type,
2130 const char **field_name, struct bt_field_type **field_type,
9ac68eb1 2131 uint64_t index)
b92ddaaa 2132{
50842bdc 2133 struct bt_field_type_structure *structure;
b92ddaaa
JG
2134 struct structure_field *field;
2135 int ret = 0;
2136
4e8304f7
PP
2137 if (!type) {
2138 BT_LOGW_STR("Invalid parameter: field type is NULL.");
2139 ret = -1;
2140 goto end;
2141 }
2142
50842bdc 2143 if (type->id != BT_FIELD_TYPE_ID_STRUCT) {
4e8304f7
PP
2144 BT_LOGW("Invalid parameter: field type is not a structure field type: "
2145 "addr=%p, ft-id=%s", type,
50842bdc 2146 bt_field_type_id_string(type->id));
b92ddaaa
JG
2147 ret = -1;
2148 goto end;
2149 }
2150
50842bdc 2151 structure = container_of(type, struct bt_field_type_structure,
b92ddaaa
JG
2152 parent);
2153 if (index >= structure->fields->len) {
4e8304f7
PP
2154 BT_LOGW("Invalid parameter: index is out of bounds: "
2155 "addr=%p, index=%" PRIu64 ", count=%u",
2156 type, index, structure->fields->len);
b92ddaaa
JG
2157 ret = -1;
2158 goto end;
2159 }
2160
2161 field = g_ptr_array_index(structure->fields, index);
f9b799fc
JG
2162 if (field_type) {
2163 *field_type = field->type;
83509119 2164 bt_get(field->type);
f9b799fc
JG
2165 }
2166 if (field_name) {
2167 *field_name = g_quark_to_string(field->name);
ec159b1e 2168 assert(*field_name);
f9b799fc 2169 }
b92ddaaa
JG
2170end:
2171 return ret;
2172}
2173
50842bdc
PP
2174struct bt_field_type *bt_field_type_structure_get_field_type_by_name(
2175 struct bt_field_type *type,
b92ddaaa
JG
2176 const char *name)
2177{
2178 size_t index;
2179 GQuark name_quark;
2180 struct structure_field *field;
50842bdc
PP
2181 struct bt_field_type_structure *structure;
2182 struct bt_field_type *field_type = NULL;
b92ddaaa 2183
4e8304f7
PP
2184 if (!type) {
2185 BT_LOGW_STR("Invalid parameter: field type is NULL.");
2186 goto end;
2187 }
2188
2189 if (!name) {
2190 BT_LOGW_STR("Invalid parameter: name is NULL.");
b92ddaaa
JG
2191 goto end;
2192 }
2193
2194 name_quark = g_quark_try_string(name);
2195 if (!name_quark) {
6fa8d37b
PP
2196 BT_LOGV("No such structure field type field name: "
2197 "ft-addr=%p, field-name=\"%s\"",
2198 type, name);
b92ddaaa
JG
2199 goto end;
2200 }
2201
50842bdc 2202 structure = container_of(type, struct bt_field_type_structure,
b92ddaaa
JG
2203 parent);
2204 if (!g_hash_table_lookup_extended(structure->field_name_to_index,
6fa8d37b
PP
2205 GUINT_TO_POINTER(name_quark), NULL, (gpointer *)&index)) {
2206 BT_LOGV("No such structure field type field name: "
2207 "ft-addr=%p, field-name=\"%s\"",
2208 type, name);
b92ddaaa 2209 goto end;
273b65be 2210 }
b92ddaaa
JG
2211
2212 field = structure->fields->pdata[index];
2213 field_type = field->type;
83509119 2214 bt_get(field_type);
273b65be 2215end:
b92ddaaa 2216 return field_type;
273b65be
JG
2217}
2218
50842bdc
PP
2219struct bt_field_type *bt_field_type_variant_create(
2220 struct bt_field_type *enum_tag, const char *tag_name)
273b65be 2221{
50842bdc 2222 struct bt_field_type_variant *variant = NULL;
273b65be 2223
4e8304f7
PP
2224 BT_LOGD("Creating variant field type object: "
2225 "tag-ft-addr=%p, tag-field-name=\"%s\"",
2226 enum_tag, tag_name);
2227
f4cc9a21 2228 if (tag_name && !bt_identifier_is_valid(tag_name)) {
4e8304f7
PP
2229 BT_LOGW("Invalid parameter: tag field name is not a valid CTF identifier: "
2230 "tag-ft-addr=%p, tag-field-name=\"%s\"",
2231 enum_tag, tag_name);
273b65be
JG
2232 goto error;
2233 }
2234
50842bdc 2235 variant = g_new0(struct bt_field_type_variant, 1);
273b65be 2236 if (!variant) {
4e8304f7 2237 BT_LOGE_STR("Failed to allocate one variant field type.");
273b65be
JG
2238 goto error;
2239 }
2240
50842bdc 2241 variant->parent.id = BT_FIELD_TYPE_ID_VARIANT;
273b65be 2242 variant->tag_name = g_string_new(tag_name);
273b65be
JG
2243 variant->field_name_to_index = g_hash_table_new(NULL, NULL);
2244 variant->fields = g_ptr_array_new_with_free_func(
83509119 2245 (GDestroyNotify) destroy_structure_field);
6964b7fd 2246 if (enum_tag) {
83509119 2247 bt_get(enum_tag);
6964b7fd 2248 variant->tag = container_of(enum_tag,
50842bdc 2249 struct bt_field_type_enumeration, parent);
6964b7fd
JG
2250 }
2251
50842bdc 2252 bt_field_type_init(&variant->parent, TRUE);
46caf2cb 2253 /* A variant's alignment is undefined */
dc3fffef 2254 variant->parent.alignment = 0;
4e8304f7
PP
2255 BT_LOGD("Created variant field type object: addr=%p, "
2256 "tag-ft-addr=%p, tag-field-name=\"%s\"",
2257 &variant->parent, enum_tag, tag_name);
273b65be
JG
2258 return &variant->parent;
2259error:
2260 return NULL;
2261}
2262
50842bdc
PP
2263struct bt_field_type *bt_field_type_variant_get_tag_type(
2264 struct bt_field_type *type)
b92ddaaa 2265{
50842bdc
PP
2266 struct bt_field_type_variant *variant;
2267 struct bt_field_type *tag_type = NULL;
b92ddaaa 2268
4e8304f7
PP
2269 if (!type) {
2270 BT_LOGW_STR("Invalid parameter: field type is NULL.");
2271 goto end;
2272 }
2273
50842bdc 2274 if (type->id != BT_FIELD_TYPE_ID_VARIANT) {
4e8304f7
PP
2275 BT_LOGW("Invalid parameter: field type is not a variant field type: "
2276 "addr=%p, ft-id=%s", type,
50842bdc 2277 bt_field_type_id_string(type->id));
b92ddaaa
JG
2278 goto end;
2279 }
2280
50842bdc 2281 variant = container_of(type, struct bt_field_type_variant, parent);
6964b7fd 2282 if (!variant->tag) {
4e8304f7
PP
2283 BT_LOGV("Variant field type has no tag field type: "
2284 "addr=%p", type);
6964b7fd
JG
2285 goto end;
2286 }
2287
b92ddaaa 2288 tag_type = &variant->tag->parent;
83509119 2289 bt_get(tag_type);
b92ddaaa
JG
2290end:
2291 return tag_type;
2292}
2293
50842bdc
PP
2294const char *bt_field_type_variant_get_tag_name(
2295 struct bt_field_type *type)
b92ddaaa 2296{
50842bdc 2297 struct bt_field_type_variant *variant;
b92ddaaa
JG
2298 const char *tag_name = NULL;
2299
4e8304f7
PP
2300 if (!type) {
2301 BT_LOGW_STR("Invalid parameter: field type is NULL.");
2302 goto end;
2303 }
2304
50842bdc 2305 if (type->id != BT_FIELD_TYPE_ID_VARIANT) {
4e8304f7
PP
2306 BT_LOGW("Invalid parameter: field type is not a variant field type: "
2307 "addr=%p, ft-id=%s", type,
50842bdc 2308 bt_field_type_id_string(type->id));
b92ddaaa
JG
2309 goto end;
2310 }
2311
50842bdc 2312 variant = container_of(type, struct bt_field_type_variant, parent);
6964b7fd 2313 if (variant->tag_name->len == 0) {
4e8304f7
PP
2314 BT_LOGV("Variant field type has no tag field name: "
2315 "addr=%p", type);
6964b7fd
JG
2316 goto end;
2317 }
2318
b92ddaaa
JG
2319 tag_name = variant->tag_name->str;
2320end:
2321 return tag_name;
2322}
2323
50842bdc
PP
2324int bt_field_type_variant_set_tag_name(
2325 struct bt_field_type *type, const char *name)
d9b1ab6d
JG
2326{
2327 int ret = 0;
50842bdc 2328 struct bt_field_type_variant *variant;
d9b1ab6d 2329
4e8304f7
PP
2330 if (!type) {
2331 BT_LOGW_STR("Invalid parameter: field type is NULL.");
2332 ret = -1;
2333 goto end;
2334 }
2335
2336 if (type->frozen) {
2337 BT_LOGW("Invalid parameter: field type is frozen: addr=%p",
2338 type);
2339 ret = -1;
2340 goto end;
2341 }
2342
50842bdc 2343 if (type->id != BT_FIELD_TYPE_ID_VARIANT) {
4e8304f7
PP
2344 BT_LOGW("Invalid parameter: field type is not a variant field type: "
2345 "addr=%p, ft-id=%s", type,
50842bdc 2346 bt_field_type_id_string(type->id));
4e8304f7
PP
2347 ret = -1;
2348 goto end;
2349 }
2350
f4cc9a21 2351 if (!bt_identifier_is_valid(name)) {
4e8304f7
PP
2352 BT_LOGW("Invalid parameter: tag field name is not a valid CTF identifier: "
2353 "variant-ft-addr=%p, tag-field-name=\"%s\"",
2354 type, name);
d9b1ab6d
JG
2355 ret = -1;
2356 goto end;
2357 }
2358
50842bdc 2359 variant = container_of(type, struct bt_field_type_variant, parent);
d9b1ab6d 2360 g_string_assign(variant->tag_name, name);
dfc1504d
PP
2361 BT_LOGV("Set variant field type's tag field name: addr=%p, "
2362 "tag-field-name=\"%s\"", type, name);
d9b1ab6d
JG
2363end:
2364 return ret;
2365}
2366
50842bdc
PP
2367int bt_field_type_variant_add_field(struct bt_field_type *type,
2368 struct bt_field_type *field_type,
4e8304f7
PP
2369 const char *field_name)
2370{
2371 size_t i;
2372 int ret = 0;
50842bdc 2373 struct bt_field_type_variant *variant;
4e8304f7
PP
2374 GQuark field_name_quark = g_quark_from_string(field_name);
2375
2376 /*
2377 * TODO: check that `field_type` does not contain `type`,
2378 * recursively.
2379 */
2380 if (!type) {
2381 BT_LOGW_STR("Invalid parameter: field type is NULL.");
2382 ret = -1;
2383 goto end;
2384 }
2385
2386 if (type->frozen) {
2387 BT_LOGW("Invalid parameter: field type is frozen: addr=%p",
2388 type);
2389 ret = -1;
2390 goto end;
2391 }
2392
50842bdc 2393 if (type->id != BT_FIELD_TYPE_ID_VARIANT) {
4e8304f7
PP
2394 BT_LOGW("Invalid parameter: field type is not a variant field type: "
2395 "addr=%p, ft-id=%s", type,
50842bdc 2396 bt_field_type_id_string(type->id));
4e8304f7
PP
2397 ret = -1;
2398 goto end;
2399 }
273b65be 2400
4e8304f7
PP
2401 if (type == field_type) {
2402 BT_LOGW("Invalid parameter: variant field type and field type to add are the same: "
2403 "addr=%p", type);
273b65be
JG
2404 ret = -1;
2405 goto end;
2406 }
2407
50842bdc 2408 variant = container_of(type, struct bt_field_type_variant, parent);
273b65be 2409
6964b7fd
JG
2410 /* The user has explicitly provided a tag; validate against it. */
2411 if (variant->tag) {
2412 int name_found = 0;
2413
2414 /* Make sure this name is present in the enum tag */
2415 for (i = 0; i < variant->tag->entries->len; i++) {
2416 struct enumeration_mapping *mapping =
2417 g_ptr_array_index(variant->tag->entries, i);
2418
2419 if (mapping->string == field_name_quark) {
2420 name_found = 1;
2421 break;
2422 }
2423 }
2424
2425 if (!name_found) {
2426 /* Validation failed */
4e8304f7
PP
2427 BT_LOGW("Invalid parameter: field name does not name a tag field type's mapping: "
2428 "variant-ft-addr=%p, tag-ft-addr=%p, "
2429 "tag-field-name=\"%s\""
2430 "field-ft-addr=%p, field-name=\"%s\"",
2431 type, variant->tag, variant->tag_name->str,
2432 field_type, field_name);
6964b7fd
JG
2433 ret = -1;
2434 goto end;
273b65be
JG
2435 }
2436 }
2437
6964b7fd 2438 if (add_structure_field(variant->fields, variant->field_name_to_index,
4e8304f7
PP
2439 field_type, field_name)) {
2440 BT_LOGW("Cannot add field to variant field type: "
2441 "variant-ft-addr=%p, field-ft-addr=%p, field-name=\"%s\"",
2442 type, field_type, field_name);
273b65be
JG
2443 ret = -1;
2444 goto end;
2445 }
dfc1504d
PP
2446
2447 BT_LOGV("Added variant field type field: variant-ft-addr=%p, "
2448 "field-ft-addr=%p, field-name=\"%s\"", type,
2449 field_type, field_name);
2450
273b65be
JG
2451end:
2452 return ret;
2453}
2454
50842bdc
PP
2455struct bt_field_type *bt_field_type_variant_get_field_type_by_name(
2456 struct bt_field_type *type,
b92ddaaa
JG
2457 const char *field_name)
2458{
2459 size_t index;
2460 GQuark name_quark;
2461 struct structure_field *field;
50842bdc
PP
2462 struct bt_field_type_variant *variant;
2463 struct bt_field_type *field_type = NULL;
b92ddaaa 2464
4e8304f7
PP
2465 if (!type) {
2466 BT_LOGW_STR("Invalid parameter: field type is NULL.");
2467 goto end;
2468 }
2469
2470 if (!field_name) {
2471 BT_LOGW_STR("Invalid parameter: field name is NULL.");
b92ddaaa
JG
2472 goto end;
2473 }
2474
2475 name_quark = g_quark_try_string(field_name);
2476 if (!name_quark) {
6fa8d37b
PP
2477 BT_LOGV("No such variant field type field name: "
2478 "ft-addr=%p, field-name=\"%s\"",
2479 type, field_name);
b92ddaaa
JG
2480 goto end;
2481 }
2482
50842bdc 2483 variant = container_of(type, struct bt_field_type_variant, parent);
b92ddaaa 2484 if (!g_hash_table_lookup_extended(variant->field_name_to_index,
6fa8d37b
PP
2485 GUINT_TO_POINTER(name_quark), NULL, (gpointer *)&index)) {
2486 BT_LOGV("No such variant field type field name: "
2487 "ft-addr=%p, field-name=\"%s\"",
2488 type, field_name);
b92ddaaa
JG
2489 goto end;
2490 }
2491
2492 field = g_ptr_array_index(variant->fields, index);
2493 field_type = field->type;
83509119 2494 bt_get(field_type);
b92ddaaa
JG
2495end:
2496 return field_type;
2497}
2498
50842bdc
PP
2499struct bt_field_type *bt_field_type_variant_get_field_type_from_tag(
2500 struct bt_field_type *type,
2501 struct bt_field *tag)
b92ddaaa 2502{
e0f15669 2503 int ret;
b92ddaaa 2504 const char *enum_value;
50842bdc
PP
2505 struct bt_field_type *field_type = NULL;
2506 struct bt_field_type_enumeration_mapping_iterator *iter = NULL;
b92ddaaa 2507
4e8304f7
PP
2508 if (!type) {
2509 BT_LOGW_STR("Invalid parameter: variant field type is NULL.");
2510 goto end;
2511 }
2512
2513 if (!tag) {
2514 BT_LOGW_STR("Invalid parameter: tag field is NULL.");
2515 goto end;
2516 }
2517
50842bdc 2518 if (type->id != BT_FIELD_TYPE_ID_VARIANT) {
4e8304f7
PP
2519 BT_LOGW("Invalid parameter: field type is not a variant field type: "
2520 "addr=%p, ft-id=%s", type,
50842bdc 2521 bt_field_type_id_string(type->id));
b92ddaaa
JG
2522 goto end;
2523 }
2524
50842bdc
PP
2525 iter = bt_field_enumeration_get_mappings(tag);
2526 ret = bt_field_type_enumeration_mapping_iterator_next(iter);
74fb0452 2527 if (!iter || ret) {
631234da 2528 BT_LOGW("Cannot get enumeration field type mapping iterator from enumeration field: "
4e8304f7 2529 "enum-field-addr=%p", tag);
e0f15669
JG
2530 goto end;
2531 }
2532
50842bdc 2533 ret = bt_field_type_enumeration_mapping_iterator_get_signed(iter,
5c3f3b7e 2534 &enum_value, NULL, NULL);
e0f15669 2535 if (ret) {
4e8304f7
PP
2536 BT_LOGW("Cannot get enumeration field type mapping iterator's current mapping: "
2537 "iter-addr=%p", iter);
b92ddaaa
JG
2538 goto end;
2539 }
2540
50842bdc 2541 field_type = bt_field_type_variant_get_field_type_by_name(
b92ddaaa
JG
2542 type, enum_value);
2543end:
e0f15669 2544 bt_put(iter);
b92ddaaa
JG
2545 return field_type;
2546}
2547
50842bdc 2548int64_t bt_field_type_variant_get_field_count(struct bt_field_type *type)
b92ddaaa 2549{
544d0515 2550 int64_t ret = 0;
50842bdc 2551 struct bt_field_type_variant *variant;
b92ddaaa 2552
4e8304f7
PP
2553 if (!type) {
2554 BT_LOGW_STR("Invalid parameter: field type is NULL.");
2555 ret = (int64_t) -1;
2556 goto end;
2557 }
2558
50842bdc 2559 if (type->id != BT_FIELD_TYPE_ID_VARIANT) {
4e8304f7
PP
2560 BT_LOGW("Invalid parameter: field type is not a variant field type: "
2561 "addr=%p, ft-id=%s", type,
50842bdc 2562 bt_field_type_id_string(type->id));
9ac68eb1 2563 ret = (int64_t) -1;
b92ddaaa
JG
2564 goto end;
2565 }
2566
50842bdc 2567 variant = container_of(type, struct bt_field_type_variant,
b92ddaaa 2568 parent);
544d0515 2569 ret = (int64_t) variant->fields->len;
b92ddaaa
JG
2570end:
2571 return ret;
2572
2573}
2574
50842bdc
PP
2575int bt_field_type_variant_get_field_by_index(struct bt_field_type *type,
2576 const char **field_name, struct bt_field_type **field_type,
9ac68eb1 2577 uint64_t index)
b92ddaaa 2578{
50842bdc 2579 struct bt_field_type_variant *variant;
b92ddaaa
JG
2580 struct structure_field *field;
2581 int ret = 0;
2582
4e8304f7
PP
2583 if (!type) {
2584 BT_LOGW_STR("Invalid parameter: field type is NULL.");
2585 ret = -1;
2586 goto end;
2587 }
2588
50842bdc 2589 if (type->id != BT_FIELD_TYPE_ID_VARIANT) {
4e8304f7
PP
2590 BT_LOGW("Invalid parameter: field type is not a variant field type: "
2591 "addr=%p, ft-id=%s", type,
50842bdc 2592 bt_field_type_id_string(type->id));
b92ddaaa
JG
2593 ret = -1;
2594 goto end;
2595 }
2596
50842bdc 2597 variant = container_of(type, struct bt_field_type_variant,
b92ddaaa
JG
2598 parent);
2599 if (index >= variant->fields->len) {
4e8304f7
PP
2600 BT_LOGW("Invalid parameter: index is out of bounds: "
2601 "addr=%p, index=%" PRIu64 ", count=%u",
2602 type, index, variant->fields->len);
b92ddaaa
JG
2603 ret = -1;
2604 goto end;
2605 }
2606
2607 field = g_ptr_array_index(variant->fields, index);
647f3b93
JG
2608 if (field_type) {
2609 *field_type = field->type;
83509119 2610 bt_get(field->type);
647f3b93
JG
2611 }
2612 if (field_name) {
2613 *field_name = g_quark_to_string(field->name);
ec159b1e 2614 assert(*field_name);
647f3b93 2615 }
b92ddaaa
JG
2616end:
2617 return ret;
2618}
2619
50842bdc
PP
2620struct bt_field_type *bt_field_type_array_create(
2621 struct bt_field_type *element_type,
273b65be
JG
2622 unsigned int length)
2623{
50842bdc 2624 struct bt_field_type_array *array = NULL;
273b65be 2625
4e8304f7
PP
2626 BT_LOGD("Creating array field type object: element-ft-addr=%p, "
2627 "length=%u", element_type, length);
2628
2629 if (!element_type) {
2630 BT_LOGW_STR("Invalid parameter: element field type is NULL.");
2631 goto error;
2632 }
2633
2634 if (length == 0) {
2635 BT_LOGW_STR("Invalid parameter: length is zero.");
273b65be
JG
2636 goto error;
2637 }
2638
50842bdc 2639 array = g_new0(struct bt_field_type_array, 1);
273b65be 2640 if (!array) {
4e8304f7 2641 BT_LOGE_STR("Failed to allocate one array field type.");
273b65be
JG
2642 goto error;
2643 }
2644
50842bdc 2645 array->parent.id = BT_FIELD_TYPE_ID_ARRAY;
83509119 2646 bt_get(element_type);
273b65be
JG
2647 array->element_type = element_type;
2648 array->length = length;
50842bdc 2649 bt_field_type_init(&array->parent, FALSE);
4e8304f7
PP
2650 BT_LOGD("Created array field type object: addr=%p, "
2651 "element-ft-addr=%p, length=%u",
2652 &array->parent, element_type, length);
273b65be
JG
2653 return &array->parent;
2654error:
2655 return NULL;
2656}
2657
50842bdc
PP
2658struct bt_field_type *bt_field_type_array_get_element_type(
2659 struct bt_field_type *type)
b92ddaaa 2660{
50842bdc
PP
2661 struct bt_field_type *ret = NULL;
2662 struct bt_field_type_array *array;
b92ddaaa 2663
4e8304f7
PP
2664 if (!type) {
2665 BT_LOGW_STR("Invalid parameter: field type is NULL.");
2666 goto end;
2667 }
2668
50842bdc 2669 if (type->id != BT_FIELD_TYPE_ID_ARRAY) {
4e8304f7
PP
2670 BT_LOGW("Invalid parameter: field type is not an array field type: "
2671 "addr=%p, ft-id=%s", type,
50842bdc 2672 bt_field_type_id_string(type->id));
b92ddaaa
JG
2673 goto end;
2674 }
2675
50842bdc 2676 array = container_of(type, struct bt_field_type_array, parent);
b92ddaaa 2677 ret = array->element_type;
83509119 2678 bt_get(ret);
b92ddaaa
JG
2679end:
2680 return ret;
2681}
2682
626e93aa 2683BT_HIDDEN
50842bdc
PP
2684int bt_field_type_array_set_element_type(struct bt_field_type *type,
2685 struct bt_field_type *element_type)
626e93aa
PP
2686{
2687 int ret = 0;
50842bdc 2688 struct bt_field_type_array *array;
626e93aa 2689
4e8304f7
PP
2690 if (!type) {
2691 BT_LOGW_STR("Invalid parameter: array field type is NULL.");
2692 ret = -1;
2693 goto end;
2694 }
2695
2696 if (!element_type) {
2697 BT_LOGW_STR("Invalid parameter: element field type is NULL.");
2698 ret = -1;
2699 goto end;
2700 }
2701
50842bdc 2702 if (type->id != BT_FIELD_TYPE_ID_ARRAY) {
4e8304f7
PP
2703 BT_LOGW("Invalid parameter: field type is not an array field type: "
2704 "addr=%p, ft-id=%s", type,
50842bdc 2705 bt_field_type_id_string(type->id));
626e93aa
PP
2706 ret = -1;
2707 goto end;
2708 }
2709
50842bdc 2710 array = container_of(type, struct bt_field_type_array, parent);
626e93aa
PP
2711
2712 if (array->element_type) {
2713 BT_PUT(array->element_type);
2714 }
2715
2716 array->element_type = element_type;
2717 bt_get(array->element_type);
dfc1504d
PP
2718 BT_LOGV("Set array field type's element field type: array-ft-addr=%p, "
2719 "element-ft-addr=%p", type, element_type);
626e93aa
PP
2720
2721end:
2722 return ret;
2723}
2724
50842bdc 2725int64_t bt_field_type_array_get_length(struct bt_field_type *type)
b92ddaaa
JG
2726{
2727 int64_t ret;
50842bdc 2728 struct bt_field_type_array *array;
b92ddaaa 2729
4e8304f7
PP
2730 if (!type) {
2731 BT_LOGW_STR("Invalid parameter: field type is NULL.");
2732 ret = (int64_t) -1;
2733 goto end;
2734 }
2735
50842bdc 2736 if (type->id != BT_FIELD_TYPE_ID_ARRAY) {
4e8304f7
PP
2737 BT_LOGW("Invalid parameter: field type is not an array field type: "
2738 "addr=%p, ft-id=%s", type,
50842bdc 2739 bt_field_type_id_string(type->id));
9ac68eb1 2740 ret = (int64_t) -1;
b92ddaaa
JG
2741 goto end;
2742 }
2743
50842bdc 2744 array = container_of(type, struct bt_field_type_array, parent);
b92ddaaa
JG
2745 ret = (int64_t) array->length;
2746end:
2747 return ret;
2748}
2749
50842bdc
PP
2750struct bt_field_type *bt_field_type_sequence_create(
2751 struct bt_field_type *element_type,
273b65be
JG
2752 const char *length_field_name)
2753{
50842bdc 2754 struct bt_field_type_sequence *sequence = NULL;
273b65be 2755
4e8304f7
PP
2756 BT_LOGD("Creating sequence field type object: element-ft-addr=%p, "
2757 "length-field-name=\"%s\"", element_type, length_field_name);
2758
2759 if (!element_type) {
2760 BT_LOGW_STR("Invalid parameter: element field type is NULL.");
2761 goto error;
2762 }
2763
f4cc9a21 2764 if (!bt_identifier_is_valid(length_field_name)) {
4e8304f7
PP
2765 BT_LOGW("Invalid parameter: length field name is not a valid CTF identifier: "
2766 "length-field-name=\"%s\"", length_field_name);
273b65be
JG
2767 goto error;
2768 }
2769
50842bdc 2770 sequence = g_new0(struct bt_field_type_sequence, 1);
273b65be 2771 if (!sequence) {
4e8304f7 2772 BT_LOGE_STR("Failed to allocate one sequence field type.");
273b65be
JG
2773 goto error;
2774 }
2775
50842bdc 2776 sequence->parent.id = BT_FIELD_TYPE_ID_SEQUENCE;
83509119 2777 bt_get(element_type);
273b65be
JG
2778 sequence->element_type = element_type;
2779 sequence->length_field_name = g_string_new(length_field_name);
50842bdc 2780 bt_field_type_init(&sequence->parent, FALSE);
4e8304f7
PP
2781 BT_LOGD("Created sequence field type object: addr=%p, "
2782 "element-ft-addr=%p, length-field-name=\"%s\"",
2783 &sequence->parent, element_type, length_field_name);
273b65be
JG
2784 return &sequence->parent;
2785error:
2786 return NULL;
2787}
2788
50842bdc
PP
2789struct bt_field_type *bt_field_type_sequence_get_element_type(
2790 struct bt_field_type *type)
b92ddaaa 2791{
50842bdc
PP
2792 struct bt_field_type *ret = NULL;
2793 struct bt_field_type_sequence *sequence;
b92ddaaa 2794
4e8304f7
PP
2795 if (!type) {
2796 BT_LOGW_STR("Invalid parameter: field type is NULL.");
2797 goto end;
2798 }
2799
50842bdc 2800 if (type->id != BT_FIELD_TYPE_ID_SEQUENCE) {
4e8304f7
PP
2801 BT_LOGW("Invalid parameter: field type is not a sequence field type: "
2802 "addr=%p, ft-id=%s", type,
50842bdc 2803 bt_field_type_id_string(type->id));
b92ddaaa
JG
2804 goto end;
2805 }
2806
50842bdc 2807 sequence = container_of(type, struct bt_field_type_sequence,
b92ddaaa
JG
2808 parent);
2809 ret = sequence->element_type;
83509119 2810 bt_get(ret);
b92ddaaa
JG
2811end:
2812 return ret;
2813}
2814
626e93aa 2815BT_HIDDEN
50842bdc
PP
2816int bt_field_type_sequence_set_element_type(struct bt_field_type *type,
2817 struct bt_field_type *element_type)
626e93aa
PP
2818{
2819 int ret = 0;
50842bdc 2820 struct bt_field_type_sequence *sequence;
626e93aa 2821
4e8304f7
PP
2822 if (!type) {
2823 BT_LOGW_STR("Invalid parameter: sequence field type is NULL.");
626e93aa
PP
2824 ret = -1;
2825 goto end;
2826 }
2827
4e8304f7
PP
2828 if (!element_type) {
2829 BT_LOGW_STR("Invalid parameter: element field type is NULL.");
2830 ret = -1;
2831 goto end;
2832 }
2833
50842bdc 2834 if (type->id != BT_FIELD_TYPE_ID_SEQUENCE) {
4e8304f7
PP
2835 BT_LOGW("Invalid parameter: field type is not a sequence field type: "
2836 "addr=%p, ft-id=%s", type,
50842bdc 2837 bt_field_type_id_string(type->id));
4e8304f7
PP
2838 ret = -1;
2839 goto end;
2840 }
626e93aa 2841
50842bdc 2842 sequence = container_of(type, struct bt_field_type_sequence, parent);
626e93aa
PP
2843 if (sequence->element_type) {
2844 BT_PUT(sequence->element_type);
2845 }
2846
2847 sequence->element_type = element_type;
2848 bt_get(sequence->element_type);
dfc1504d
PP
2849 BT_LOGV("Set sequence field type's element field type: sequence-ft-addr=%p, "
2850 "element-ft-addr=%p", type, element_type);
626e93aa
PP
2851
2852end:
2853 return ret;
2854}
2855
50842bdc
PP
2856const char *bt_field_type_sequence_get_length_field_name(
2857 struct bt_field_type *type)
b92ddaaa
JG
2858{
2859 const char *ret = NULL;
50842bdc 2860 struct bt_field_type_sequence *sequence;
b92ddaaa 2861
4e8304f7
PP
2862 if (!type) {
2863 BT_LOGW_STR("Invalid parameter: field type is NULL.");
2864 goto end;
2865 }
2866
50842bdc 2867 if (type->id != BT_FIELD_TYPE_ID_SEQUENCE) {
4e8304f7
PP
2868 BT_LOGW("Invalid parameter: field type is not a sequence field type: "
2869 "addr=%p, ft-id=%s", type,
50842bdc 2870 bt_field_type_id_string(type->id));
b92ddaaa
JG
2871 goto end;
2872 }
2873
50842bdc 2874 sequence = container_of(type, struct bt_field_type_sequence,
b92ddaaa
JG
2875 parent);
2876 ret = sequence->length_field_name->str;
2877end:
2878 return ret;
2879}
2880
50842bdc 2881struct bt_field_type *bt_field_type_string_create(void)
273b65be 2882{
50842bdc
PP
2883 struct bt_field_type_string *string =
2884 g_new0(struct bt_field_type_string, 1);
273b65be 2885
4e8304f7
PP
2886 BT_LOGD_STR("Creating string field type object.");
2887
273b65be 2888 if (!string) {
4e8304f7 2889 BT_LOGE_STR("Failed to allocate one string field type.");
273b65be
JG
2890 return NULL;
2891 }
2892
50842bdc
PP
2893 string->parent.id = BT_FIELD_TYPE_ID_STRING;
2894 bt_field_type_init(&string->parent, TRUE);
2895 string->encoding = BT_STRING_ENCODING_UTF8;
dc3fffef 2896 string->parent.alignment = CHAR_BIT;
4e8304f7 2897 BT_LOGD("Created string field type object: addr=%p", &string->parent);
273b65be
JG
2898 return &string->parent;
2899}
2900
50842bdc
PP
2901enum bt_string_encoding bt_field_type_string_get_encoding(
2902 struct bt_field_type *type)
b92ddaaa 2903{
50842bdc
PP
2904 struct bt_field_type_string *string;
2905 enum bt_string_encoding ret = BT_STRING_ENCODING_UNKNOWN;
b92ddaaa 2906
4e8304f7
PP
2907 if (!type) {
2908 BT_LOGW_STR("Invalid parameter: field type is NULL.");
2909 goto end;
2910 }
2911
50842bdc 2912 if (type->id != BT_FIELD_TYPE_ID_STRING) {
4e8304f7
PP
2913 BT_LOGW("Invalid parameter: field type is not a string field type: "
2914 "addr=%p, ft-id=%s", type,
50842bdc 2915 bt_field_type_id_string(type->id));
b92ddaaa
JG
2916 goto end;
2917 }
2918
50842bdc 2919 string = container_of(type, struct bt_field_type_string,
b92ddaaa 2920 parent);
dc3fffef 2921 ret = string->encoding;
b92ddaaa
JG
2922end:
2923 return ret;
2924}
2925
50842bdc
PP
2926int bt_field_type_string_set_encoding(struct bt_field_type *type,
2927 enum bt_string_encoding encoding)
273b65be
JG
2928{
2929 int ret = 0;
50842bdc 2930 struct bt_field_type_string *string;
273b65be 2931
4e8304f7
PP
2932 if (!type) {
2933 BT_LOGW_STR("Invalid parameter: field type is NULL.");
2934 ret = -1;
2935 goto end;
2936 }
2937
50842bdc 2938 if (type->id != BT_FIELD_TYPE_ID_STRING) {
4e8304f7
PP
2939 BT_LOGW("Invalid parameter: field type is not a string field type: "
2940 "addr=%p, ft-id=%s", type,
50842bdc 2941 bt_field_type_id_string(type->id));
4e8304f7
PP
2942 ret = -1;
2943 goto end;
2944 }
2945
50842bdc
PP
2946 if (encoding != BT_STRING_ENCODING_UTF8 &&
2947 encoding != BT_STRING_ENCODING_ASCII) {
4e8304f7
PP
2948 BT_LOGW("Invalid parameter: unknown string encoding: "
2949 "addr=%p, encoding=%d", type, encoding);
273b65be
JG
2950 ret = -1;
2951 goto end;
2952 }
2953
50842bdc 2954 string = container_of(type, struct bt_field_type_string, parent);
dc3fffef 2955 string->encoding = encoding;
dfc1504d 2956 BT_LOGV("Set string field type's encoding: addr=%p, encoding=%s",
50842bdc 2957 type, bt_string_encoding_string(encoding));
273b65be
JG
2958end:
2959 return ret;
2960}
2961
50842bdc 2962int bt_field_type_get_alignment(struct bt_field_type *type)
b92ddaaa
JG
2963{
2964 int ret;
50842bdc 2965 enum bt_field_type_id type_id;
b92ddaaa
JG
2966
2967 if (!type) {
4e8304f7 2968 BT_LOGW_STR("Invalid parameter: field type is NULL.");
b92ddaaa
JG
2969 ret = -1;
2970 goto end;
2971 }
2972
3ffba961 2973 if (type->frozen) {
dc3fffef 2974 ret = (int) type->alignment;
3ffba961
JG
2975 goto end;
2976 }
2977
50842bdc 2978 type_id = bt_field_type_get_type_id(type);
3ffba961 2979 switch (type_id) {
50842bdc 2980 case BT_FIELD_TYPE_ID_SEQUENCE:
3ffba961 2981 {
50842bdc
PP
2982 struct bt_field_type *element =
2983 bt_field_type_sequence_get_element_type(type);
3ffba961 2984
4e8304f7 2985 assert(element);
50842bdc 2986 ret = bt_field_type_get_alignment(element);
83509119 2987 bt_put(element);
3ffba961
JG
2988 break;
2989 }
50842bdc 2990 case BT_FIELD_TYPE_ID_ARRAY:
3ffba961 2991 {
50842bdc
PP
2992 struct bt_field_type *element =
2993 bt_field_type_array_get_element_type(type);
3ffba961 2994
4e8304f7 2995 assert(element);
50842bdc 2996 ret = bt_field_type_get_alignment(element);
83509119 2997 bt_put(element);
3ffba961
JG
2998 break;
2999 }
50842bdc 3000 case BT_FIELD_TYPE_ID_STRUCT:
3ffba961 3001 {
544d0515 3002 int64_t i, element_count;
3ffba961 3003
50842bdc 3004 element_count = bt_field_type_structure_get_field_count(
3ffba961 3005 type);
4e8304f7 3006 assert(element_count >= 0);
3ffba961
JG
3007
3008 for (i = 0; i < element_count; i++) {
bc85036f 3009 struct bt_field_type *field = NULL;
3ffba961
JG
3010 int field_alignment;
3011
50842bdc 3012 ret = bt_field_type_structure_get_field_by_index(
9ac68eb1 3013 type, NULL, &field, i);
4e8304f7 3014 assert(ret == 0);
3ffba961 3015 assert(field);
50842bdc 3016 field_alignment = bt_field_type_get_alignment(
3ffba961 3017 field);
83509119 3018 bt_put(field);
3ffba961
JG
3019 if (field_alignment < 0) {
3020 ret = field_alignment;
3021 goto end;
3022 }
3023
dc3fffef 3024 type->alignment = MAX(field_alignment, type->alignment);
3ffba961 3025 }
dc3fffef 3026 ret = (int) type->alignment;
3ffba961
JG
3027 break;
3028 }
89e9af01
JG
3029 case BT_FIELD_TYPE_ID_ENUM:
3030 {
3031 struct bt_field_type *container =
3032 bt_field_type_enumeration_get_container_type(type);
3033
3034 ret = bt_field_type_get_alignment(container);
3035 bt_put(container);
3036 break;
3037 }
50842bdc 3038 case BT_FIELD_TYPE_ID_UNKNOWN:
4e8304f7
PP
3039 BT_LOGW("Invalid parameter: unknown field type ID: "
3040 "addr=%p, ft-id=%d", type, type_id);
3ffba961
JG
3041 ret = -1;
3042 break;
3043 default:
dc3fffef 3044 ret = (int) type->alignment;
3ffba961
JG
3045 break;
3046 }
b92ddaaa
JG
3047end:
3048 return ret;
3049}
3050
9ad2f879
PP
3051static inline
3052int is_power_of_two(unsigned int value)
3053{
3054 return ((value & (value - 1)) == 0) && value > 0;
3055}
3056
50842bdc 3057int bt_field_type_set_alignment(struct bt_field_type *type,
273b65be
JG
3058 unsigned int alignment)
3059{
3060 int ret = 0;
50842bdc 3061 enum bt_field_type_id type_id;
273b65be 3062
9ad2f879 3063 /* Alignment must be a power of two */
4e8304f7
PP
3064 if (!type) {
3065 BT_LOGW_STR("Invalid parameter: field type is NULL.");
3066 ret = -1;
3067 goto end;
3068 }
3069
3070 if (type->frozen) {
3071 BT_LOGW("Invalid parameter: field type is frozen: addr=%p",
3072 type);
3073 ret = -1;
3074 goto end;
3075 }
3076
3077 if (!is_power_of_two(alignment)) {
3078 BT_LOGW("Invalid parameter: alignment is not a power of two: "
3079 "addr=%p, align=%u", type, alignment);
273b65be
JG
3080 ret = -1;
3081 goto end;
3082 }
3083
50842bdc
PP
3084 type_id = bt_field_type_get_type_id(type);
3085 if (type_id == BT_FIELD_TYPE_ID_UNKNOWN) {
4e8304f7
PP
3086 BT_LOGW("Invalid parameter: unknown field type ID: "
3087 "addr=%p, ft-id=%d", type, type_id);
6a43d732
JG
3088 ret = -1;
3089 goto end;
3090 }
3091
50842bdc 3092 if (type->id == BT_FIELD_TYPE_ID_STRING &&
4e8304f7
PP
3093 alignment != CHAR_BIT) {
3094 BT_LOGW("Invalid parameter: alignment must be %u for a string field type: "
3095 "addr=%p, align=%u", CHAR_BIT, type, alignment);
273b65be
JG
3096 ret = -1;
3097 goto end;
3098 }
3099
50842bdc
PP
3100 if (type_id == BT_FIELD_TYPE_ID_VARIANT ||
3101 type_id == BT_FIELD_TYPE_ID_SEQUENCE ||
3102 type_id == BT_FIELD_TYPE_ID_ARRAY) {
6a43d732 3103 /* Setting an alignment on these types makes no sense */
4e8304f7
PP
3104 BT_LOGW("Invalid parameter: cannot set the alignment of this field type: "
3105 "addr=%p, ft-id=%s", type,
50842bdc 3106 bt_field_type_id_string(type->id));
6a43d732
JG
3107 ret = -1;
3108 goto end;
3109 }
3110
dc3fffef 3111 type->alignment = alignment;
273b65be 3112 ret = 0;
dfc1504d
PP
3113 BT_LOGV("Set field type's alignment: addr=%p, align=%u",
3114 type, alignment);
273b65be
JG
3115end:
3116 return ret;
3117}
3118
50842bdc
PP
3119enum bt_byte_order bt_field_type_get_byte_order(
3120 struct bt_field_type *type)
b92ddaaa 3121{
50842bdc 3122 enum bt_byte_order ret = BT_BYTE_ORDER_UNKNOWN;
b92ddaaa
JG
3123
3124 if (!type) {
4e8304f7 3125 BT_LOGW_STR("Invalid parameter: field type is NULL.");
b92ddaaa
JG
3126 goto end;
3127 }
3128
dc3fffef 3129 switch (type->id) {
50842bdc 3130 case BT_FIELD_TYPE_ID_INTEGER:
b92ddaaa 3131 {
50842bdc
PP
3132 struct bt_field_type_integer *integer = container_of(
3133 type, struct bt_field_type_integer, parent);
445c3471 3134 ret = integer->user_byte_order;
b92ddaaa
JG
3135 break;
3136 }
50842bdc 3137 case BT_FIELD_TYPE_ID_ENUM:
4b2da5f0 3138 {
50842bdc
PP
3139 struct bt_field_type_enumeration *enum_ft = container_of(
3140 type, struct bt_field_type_enumeration, parent);
3141 ret = bt_field_type_get_byte_order(enum_ft->container);
4b2da5f0
PP
3142 break;
3143 }
50842bdc 3144 case BT_FIELD_TYPE_ID_FLOAT:
b92ddaaa 3145 {
50842bdc 3146 struct bt_field_type_floating_point *floating_point =
b92ddaaa 3147 container_of(type,
50842bdc 3148 struct bt_field_type_floating_point,
b92ddaaa 3149 parent);
445c3471 3150 ret = floating_point->user_byte_order;
b92ddaaa
JG
3151 break;
3152 }
3153 default:
4e8304f7
PP
3154 BT_LOGW("Invalid parameter: cannot get the byte order of this field type: "
3155 "addr=%p, ft-id=%s", type,
50842bdc 3156 bt_field_type_id_string(type->id));
c35a1669
JG
3157 goto end;
3158 }
3159
50842bdc
PP
3160 assert(ret == BT_BYTE_ORDER_NATIVE ||
3161 ret == BT_BYTE_ORDER_LITTLE_ENDIAN ||
3162 ret == BT_BYTE_ORDER_BIG_ENDIAN ||
3163 ret == BT_BYTE_ORDER_NETWORK);
445c3471 3164
b92ddaaa
JG
3165end:
3166 return ret;
3167}
3168
50842bdc
PP
3169int bt_field_type_set_byte_order(struct bt_field_type *type,
3170 enum bt_byte_order byte_order)
273b65be
JG
3171{
3172 int ret = 0;
273b65be 3173
4e8304f7
PP
3174 if (!type) {
3175 BT_LOGW_STR("Invalid parameter: field type is NULL.");
3176 ret = -1;
3177 goto end;
3178 }
3179
3180 if (type->frozen) {
3181 BT_LOGW("Invalid parameter: field type is frozen: addr=%p",
3182 type);
273b65be
JG
3183 ret = -1;
3184 goto end;
3185 }
3186
50842bdc
PP
3187 if (byte_order != BT_BYTE_ORDER_NATIVE &&
3188 byte_order != BT_BYTE_ORDER_LITTLE_ENDIAN &&
3189 byte_order != BT_BYTE_ORDER_BIG_ENDIAN &&
3190 byte_order != BT_BYTE_ORDER_NETWORK) {
d41cff38 3191 BT_LOGW("Invalid parameter: invalid byte order: "
4e8304f7 3192 "addr=%p, bo=%s", type,
50842bdc 3193 bt_byte_order_string(byte_order));
273b65be
JG
3194 ret = -1;
3195 goto end;
3196 }
3197
dc3fffef
PP
3198 if (set_byte_order_funcs[type->id]) {
3199 set_byte_order_funcs[type->id](type, byte_order);
273b65be 3200 }
dfc1504d
PP
3201
3202 BT_LOGV("Set field type's byte order: addr=%p, bo=%s",
50842bdc 3203 type, bt_byte_order_string(byte_order));
dfc1504d 3204
273b65be
JG
3205end:
3206 return ret;
3207}
3208
50842bdc
PP
3209enum bt_field_type_id bt_field_type_get_type_id(
3210 struct bt_field_type *type)
b92ddaaa
JG
3211{
3212 if (!type) {
4e8304f7 3213 BT_LOGW_STR("Invalid parameter: field type is NULL.");
50842bdc 3214 return BT_FIELD_TYPE_ID_UNKNOWN;
b92ddaaa
JG
3215 }
3216
dc3fffef 3217 return type->id;
b92ddaaa 3218}
2f2d8e05 3219
50842bdc 3220int bt_field_type_is_integer(struct bt_field_type *type)
56db8d7a 3221{
50842bdc 3222 return bt_field_type_get_type_id(type) == BT_FIELD_TYPE_ID_INTEGER;
56db8d7a
PP
3223}
3224
50842bdc 3225int bt_field_type_is_floating_point(struct bt_field_type *type)
56db8d7a 3226{
50842bdc 3227 return bt_field_type_get_type_id(type) == BT_FIELD_TYPE_ID_FLOAT;
56db8d7a
PP
3228}
3229
50842bdc 3230int bt_field_type_is_enumeration(struct bt_field_type *type)
56db8d7a 3231{
50842bdc 3232 return bt_field_type_get_type_id(type) == BT_FIELD_TYPE_ID_ENUM;
56db8d7a
PP
3233}
3234
50842bdc 3235int bt_field_type_is_string(struct bt_field_type *type)
56db8d7a 3236{
50842bdc 3237 return bt_field_type_get_type_id(type) == BT_FIELD_TYPE_ID_STRING;
56db8d7a
PP
3238}
3239
50842bdc 3240int bt_field_type_is_structure(struct bt_field_type *type)
56db8d7a 3241{
50842bdc 3242 return bt_field_type_get_type_id(type) == BT_FIELD_TYPE_ID_STRUCT;
56db8d7a
PP
3243}
3244
50842bdc 3245int bt_field_type_is_array(struct bt_field_type *type)
56db8d7a 3246{
50842bdc 3247 return bt_field_type_get_type_id(type) == BT_FIELD_TYPE_ID_ARRAY;
56db8d7a
PP
3248}
3249
50842bdc 3250int bt_field_type_is_sequence(struct bt_field_type *type)
56db8d7a 3251{
50842bdc 3252 return bt_field_type_get_type_id(type) == BT_FIELD_TYPE_ID_SEQUENCE;
56db8d7a
PP
3253}
3254
50842bdc 3255int bt_field_type_is_variant(struct bt_field_type *type)
56db8d7a 3256{
50842bdc 3257 return bt_field_type_get_type_id(type) == BT_FIELD_TYPE_ID_VARIANT;
56db8d7a
PP
3258}
3259
4e8304f7 3260/* Pre-2.0 CTF writer backward compatibility */
50842bdc 3261void bt_ctf_field_type_get(struct bt_field_type *type)
273b65be 3262{
83509119 3263 bt_get(type);
273b65be
JG
3264}
3265
4e8304f7 3266/* Pre-2.0 CTF writer backward compatibility */
50842bdc 3267void bt_ctf_field_type_put(struct bt_field_type *type)
273b65be 3268{
83509119 3269 bt_put(type);
273b65be
JG
3270}
3271
3272BT_HIDDEN
50842bdc 3273void bt_field_type_freeze(struct bt_field_type *type)
273b65be 3274{
4e8304f7 3275 if (!type || type->frozen) {
273b65be
JG
3276 return;
3277 }
3278
3279 type->freeze(type);
3280}
3281
3282BT_HIDDEN
50842bdc
PP
3283struct bt_field_type *bt_field_type_variant_get_field_type_signed(
3284 struct bt_field_type_variant *variant,
b92ddaaa 3285 int64_t tag_value)
273b65be 3286{
50842bdc 3287 struct bt_field_type *type = NULL;
b92ddaaa
JG
3288 GQuark field_name_quark;
3289 gpointer index;
3290 struct structure_field *field_entry;
3291 struct range_overlap_query query = {
3292 .range_start._signed = tag_value,
3293 .range_end._signed = tag_value,
96e8f959
MD
3294 .mapping_name = 0,
3295 .overlaps = 0,
3296 };
273b65be 3297
b92ddaaa
JG
3298 g_ptr_array_foreach(variant->tag->entries, check_ranges_overlap,
3299 &query);
3300 if (!query.overlaps) {
273b65be
JG
3301 goto end;
3302 }
3303
b92ddaaa
JG
3304 field_name_quark = query.mapping_name;
3305 if (!g_hash_table_lookup_extended(variant->field_name_to_index,
ec159b1e 3306 GUINT_TO_POINTER(field_name_quark), NULL, &index)) {
273b65be
JG
3307 goto end;
3308 }
3309
e54fab7e 3310 field_entry = g_ptr_array_index(variant->fields, (size_t) index);
b92ddaaa 3311 type = field_entry->type;
273b65be
JG
3312end:
3313 return type;
3314}
3315
3316BT_HIDDEN
50842bdc
PP
3317struct bt_field_type *bt_field_type_variant_get_field_type_unsigned(
3318 struct bt_field_type_variant *variant,
b92ddaaa 3319 uint64_t tag_value)
273b65be 3320{
50842bdc 3321 struct bt_field_type *type = NULL;
273b65be
JG
3322 GQuark field_name_quark;
3323 gpointer index;
3324 struct structure_field *field_entry;
b92ddaaa
JG
3325 struct range_overlap_query query = {
3326 .range_start._unsigned = tag_value,
3327 .range_end._unsigned = tag_value,
96e8f959
MD
3328 .mapping_name = 0,
3329 .overlaps = 0,
3330 };
273b65be 3331
b92ddaaa
JG
3332 g_ptr_array_foreach(variant->tag->entries,
3333 check_ranges_overlap_unsigned,
273b65be
JG
3334 &query);
3335 if (!query.overlaps) {
3336 goto end;
3337 }
3338
3339 field_name_quark = query.mapping_name;
3340 if (!g_hash_table_lookup_extended(variant->field_name_to_index,
3341 GUINT_TO_POINTER(field_name_quark), NULL, &index)) {
3342 goto end;
3343 }
3344
3345 field_entry = g_ptr_array_index(variant->fields, (size_t)index);
3346 type = field_entry->type;
3347end:
3348 return type;
3349}
3350
3351BT_HIDDEN
50842bdc 3352int bt_field_type_serialize(struct bt_field_type *type,
273b65be
JG
3353 struct metadata_context *context)
3354{
3355 int ret;
3356
4e8304f7
PP
3357 assert(type);
3358 assert(context);
3359
81e36fac 3360 /* Make sure field type is valid before serializing it */
50842bdc 3361 ret = bt_field_type_validate(type);
81e36fac 3362 if (ret) {
f45cd48c
PP
3363 BT_LOGW("Cannot serialize field type's metadata: field type is invalid: "
3364 "addr=%p", type);
81e36fac
PP
3365 goto end;
3366 }
3367
273b65be
JG
3368 ret = type->serialize(type, context);
3369end:
3370 return ret;
3371}
3372
50842bdc 3373struct bt_field_type *bt_field_type_copy(struct bt_field_type *type)
24724933 3374{
50842bdc 3375 struct bt_field_type *copy = NULL;
24724933
JG
3376
3377 if (!type) {
4e8304f7 3378 BT_LOGW_STR("Invalid parameter: field type is NULL.");
24724933
JG
3379 goto end;
3380 }
3381
dc3fffef 3382 copy = type_copy_funcs[type->id](type);
4e8304f7
PP
3383 if (!copy) {
3384 BT_LOGE_STR("Cannot copy field type.");
3385 goto end;
3386 }
3387
dc3fffef 3388 copy->alignment = type->alignment;
24724933
JG
3389end:
3390 return copy;
3391}
3392
39a5e0db 3393BT_HIDDEN
50842bdc
PP
3394int bt_field_type_structure_get_field_name_index(
3395 struct bt_field_type *type, const char *name)
39a5e0db
JG
3396{
3397 int ret;
3398 size_t index;
3399 GQuark name_quark;
50842bdc 3400 struct bt_field_type_structure *structure;
39a5e0db 3401
4e8304f7
PP
3402 if (!type) {
3403 BT_LOGW_STR("Invalid parameter: field type is NULL.");
3404 ret = -1;
3405 goto end;
3406 }
3407
3408 if (!name) {
3409 BT_LOGW_STR("Invalid parameter: field name is NULL.");
3410 ret = -1;
3411 goto end;
3412 }
3413
50842bdc 3414 if (bt_field_type_get_type_id(type) != BT_FIELD_TYPE_ID_STRUCT) {
4e8304f7
PP
3415 BT_LOGW("Invalid parameter: field type is not a structure field type: "
3416 "addr=%p, ft-id=%s", type,
50842bdc 3417 bt_field_type_id_string(type->id));
39a5e0db
JG
3418 ret = -1;
3419 goto end;
3420 }
3421
3422 name_quark = g_quark_try_string(name);
3423 if (!name_quark) {
6fa8d37b
PP
3424 BT_LOGV("No such structure field type field name: "
3425 "ft-addr=%p, field-name=\"%s\"",
3426 type, name);
39a5e0db
JG
3427 ret = -1;
3428 goto end;
3429 }
3430
50842bdc 3431 structure = container_of(type, struct bt_field_type_structure,
39a5e0db
JG
3432 parent);
3433 if (!g_hash_table_lookup_extended(structure->field_name_to_index,
ec159b1e
PP
3434 GUINT_TO_POINTER(name_quark),
3435 NULL, (gpointer *)&index)) {
6fa8d37b
PP
3436 BT_LOGV("No such structure field type field name: "
3437 "ft-addr=%p, field-name=\"%s\"",
3438 type, name);
39a5e0db
JG
3439 ret = -1;
3440 goto end;
3441 }
3442 ret = (int) index;
3443end:
3444 return ret;
3445}
736133f1
JG
3446
3447BT_HIDDEN
50842bdc
PP
3448int bt_field_type_variant_get_field_name_index(
3449 struct bt_field_type *type, const char *name)
736133f1
JG
3450{
3451 int ret;
3452 size_t index;
3453 GQuark name_quark;
50842bdc 3454 struct bt_field_type_variant *variant;
736133f1 3455
4e8304f7
PP
3456 if (!type) {
3457 BT_LOGW_STR("Invalid parameter: variant field type is NULL.");
3458 ret = -1;
3459 goto end;
3460 }
3461
3462 if (!name) {
3463 BT_LOGW_STR("Invalid parameter: field name is NULL.");
3464 ret = -1;
3465 goto end;
3466 }
3467
50842bdc 3468 if (bt_field_type_get_type_id(type) != BT_FIELD_TYPE_ID_VARIANT) {
4e8304f7
PP
3469 BT_LOGW("Invalid parameter: field type is not a variant field type: "
3470 "addr=%p, ft-id=%s", type,
50842bdc 3471 bt_field_type_id_string(type->id));
736133f1
JG
3472 ret = -1;
3473 goto end;
3474 }
3475
3476 name_quark = g_quark_try_string(name);
3477 if (!name_quark) {
6fa8d37b
PP
3478 BT_LOGV("No such variant field type field name: "
3479 "ft-addr=%p, field-name=\"%s\"",
3480 type, name);
736133f1
JG
3481 ret = -1;
3482 goto end;
3483 }
3484
50842bdc 3485 variant = container_of(type, struct bt_field_type_variant,
736133f1
JG
3486 parent);
3487 if (!g_hash_table_lookup_extended(variant->field_name_to_index,
ec159b1e
PP
3488 GUINT_TO_POINTER(name_quark),
3489 NULL, (gpointer *)&index)) {
6fa8d37b
PP
3490 BT_LOGV("No such variant field type field name: "
3491 "ft-addr=%p, field-name=\"%s\"",
3492 type, name);
736133f1
JG
3493 ret = -1;
3494 goto end;
3495 }
3496 ret = (int) index;
3497end:
3498 return ret;
3499}
aa4e271c
JG
3500
3501BT_HIDDEN
50842bdc
PP
3502int bt_field_type_sequence_set_length_field_path(
3503 struct bt_field_type *type,
3504 struct bt_field_path *path)
aa4e271c
JG
3505{
3506 int ret = 0;
50842bdc 3507 struct bt_field_type_sequence *sequence;
aa4e271c 3508
4e8304f7
PP
3509 if (!type) {
3510 BT_LOGW_STR("Invalid parameter: field type is NULL.");
3511 ret = -1;
3512 goto end;
3513 }
3514
50842bdc 3515 if (bt_field_type_get_type_id(type) != BT_FIELD_TYPE_ID_SEQUENCE) {
4e8304f7
PP
3516 BT_LOGW("Invalid parameter: field type is not a sequence field type: "
3517 "addr=%p, ft-id=%s", type,
50842bdc 3518 bt_field_type_id_string(type->id));
aa4e271c
JG
3519 ret = -1;
3520 goto end;
3521 }
3522
50842bdc 3523 sequence = container_of(type, struct bt_field_type_sequence,
aa4e271c 3524 parent);
b011f6b0
PP
3525 bt_get(path);
3526 BT_MOVE(sequence->length_field_path, path);
dfc1504d
PP
3527 BT_LOGV("Set sequence field type's length field path: ft-addr=%p, "
3528 "field-path-addr=%p", type, path);
aa4e271c
JG
3529end:
3530 return ret;
3531}
4a1e8671
JG
3532
3533BT_HIDDEN
50842bdc
PP
3534int bt_field_type_variant_set_tag_field_path(struct bt_field_type *type,
3535 struct bt_field_path *path)
4a1e8671
JG
3536{
3537 int ret = 0;
50842bdc 3538 struct bt_field_type_variant *variant;
4a1e8671 3539
4e8304f7
PP
3540 if (!type) {
3541 BT_LOGW_STR("Invalid parameter: field type is NULL.");
3542 ret = -1;
3543 goto end;
3544 }
3545
50842bdc 3546 if (bt_field_type_get_type_id(type) != BT_FIELD_TYPE_ID_VARIANT) {
4e8304f7
PP
3547 BT_LOGW("Invalid parameter: field type is not a variant field type: "
3548 "addr=%p, ft-id=%s", type,
50842bdc 3549 bt_field_type_id_string(type->id));
4a1e8671
JG
3550 ret = -1;
3551 goto end;
3552 }
3553
50842bdc 3554 variant = container_of(type, struct bt_field_type_variant,
4a1e8671 3555 parent);
b011f6b0
PP
3556 bt_get(path);
3557 BT_MOVE(variant->tag_field_path, path);
dfc1504d
PP
3558 BT_LOGV("Set variant field type's tag field path: ft-addr=%p, "
3559 "field-path-addr=%p", type, path);
4a1e8671
JG
3560end:
3561 return ret;
3562}
3f39933a
JG
3563
3564BT_HIDDEN
50842bdc
PP
3565int bt_field_type_variant_set_tag_field_type(struct bt_field_type *type,
3566 struct bt_field_type *tag)
3f39933a
JG
3567{
3568 int ret = 0;
50842bdc 3569 struct bt_field_type_variant *variant;
3f39933a 3570
4e8304f7
PP
3571 if (!type) {
3572 BT_LOGW_STR("Invalid parameter: variant field type is NULL.");
3f39933a
JG
3573 ret = -1;
3574 goto end;
3575 }
3576
4e8304f7
PP
3577 if (!tag) {
3578 BT_LOGW_STR("Invalid parameter: tag field type is NULL.");
3579 ret = -1;
3580 goto end;
3f39933a 3581 }
5cec03e4 3582
50842bdc 3583 if (bt_field_type_get_type_id(tag) != BT_FIELD_TYPE_ID_ENUM) {
4e8304f7
PP
3584 BT_LOGW("Invalid parameter: field type is not an enumeration field type: "
3585 "addr=%p, ft-id=%s", type,
50842bdc 3586 bt_field_type_id_string(type->id));
5cec03e4
JG
3587 ret = -1;
3588 goto end;
3589 }
3590
50842bdc 3591 variant = container_of(type, struct bt_field_type_variant,
5cec03e4 3592 parent);
4e8304f7
PP
3593 bt_get(tag);
3594 if (variant->tag) {
3595 bt_put(&variant->tag->parent);
5cec03e4 3596 }
50842bdc 3597 variant->tag = container_of(tag, struct bt_field_type_enumeration,
4e8304f7 3598 parent);
dfc1504d
PP
3599 BT_LOGV("Set variant field type's tag field type: variant-ft-addr=%p, "
3600 "tag-ft-addr=%p", type, tag);
5cec03e4
JG
3601end:
3602 return ret;
3603}
3604
273b65be 3605static
50842bdc 3606void bt_field_type_integer_destroy(struct bt_field_type *type)
273b65be 3607{
50842bdc
PP
3608 struct bt_field_type_integer *integer =
3609 (struct bt_field_type_integer *) type;
273b65be 3610
de3dd40e 3611 if (!type) {
273b65be
JG
3612 return;
3613 }
3614
4e8304f7 3615 BT_LOGD("Destroying integer field type object: addr=%p", type);
ec159b1e 3616 BT_LOGD_STR("Putting mapped clock class.");
83509119 3617 bt_put(integer->mapped_clock);
273b65be
JG
3618 g_free(integer);
3619}
3620
3621static
50842bdc 3622void bt_field_type_enumeration_destroy(struct bt_field_type *type)
273b65be 3623{
50842bdc
PP
3624 struct bt_field_type_enumeration *enumeration =
3625 (struct bt_field_type_enumeration *) type;
273b65be 3626
de3dd40e 3627 if (!type) {
273b65be
JG
3628 return;
3629 }
3630
4e8304f7 3631 BT_LOGD("Destroying enumeration field type object: addr=%p", type);
273b65be 3632 g_ptr_array_free(enumeration->entries, TRUE);
ec159b1e 3633 BT_LOGD_STR("Putting container field type.");
83509119 3634 bt_put(enumeration->container);
273b65be
JG
3635 g_free(enumeration);
3636}
3637
3638static
50842bdc 3639void bt_field_type_floating_point_destroy(struct bt_field_type *type)
273b65be 3640{
50842bdc
PP
3641 struct bt_field_type_floating_point *floating_point =
3642 (struct bt_field_type_floating_point *) type;
273b65be 3643
de3dd40e 3644 if (!type) {
273b65be
JG
3645 return;
3646 }
3647
4e8304f7 3648 BT_LOGD("Destroying floating point number field type object: addr=%p", type);
273b65be
JG
3649 g_free(floating_point);
3650}
3651
3652static
50842bdc 3653void bt_field_type_structure_destroy(struct bt_field_type *type)
273b65be 3654{
50842bdc
PP
3655 struct bt_field_type_structure *structure =
3656 (struct bt_field_type_structure *) type;
273b65be 3657
de3dd40e 3658 if (!type) {
273b65be
JG
3659 return;
3660 }
3661
4e8304f7 3662 BT_LOGD("Destroying structure field type object: addr=%p", type);
273b65be
JG
3663 g_ptr_array_free(structure->fields, TRUE);
3664 g_hash_table_destroy(structure->field_name_to_index);
3665 g_free(structure);
3666}
3667
3668static
50842bdc 3669void bt_field_type_variant_destroy(struct bt_field_type *type)
273b65be 3670{
50842bdc
PP
3671 struct bt_field_type_variant *variant =
3672 (struct bt_field_type_variant *) type;
273b65be 3673
de3dd40e 3674 if (!type) {
273b65be
JG
3675 return;
3676 }
3677
4e8304f7 3678 BT_LOGD("Destroying variant field type object: addr=%p", type);
273b65be
JG
3679 g_ptr_array_free(variant->fields, TRUE);
3680 g_hash_table_destroy(variant->field_name_to_index);
3681 g_string_free(variant->tag_name, TRUE);
ec159b1e 3682 BT_LOGD_STR("Putting tag field type.");
83509119 3683 bt_put(&variant->tag->parent);
b011f6b0 3684 BT_PUT(variant->tag_field_path);
273b65be
JG
3685 g_free(variant);
3686}
3687
3688static
50842bdc 3689void bt_field_type_array_destroy(struct bt_field_type *type)
273b65be 3690{
50842bdc
PP
3691 struct bt_field_type_array *array =
3692 (struct bt_field_type_array *) type;
273b65be 3693
de3dd40e 3694 if (!type) {
273b65be
JG
3695 return;
3696 }
3697
4e8304f7 3698 BT_LOGD("Destroying array field type object: addr=%p", type);
ec159b1e 3699 BT_LOGD_STR("Putting element field type.");
83509119 3700 bt_put(array->element_type);
273b65be
JG
3701 g_free(array);
3702}
3703
3704static
50842bdc 3705void bt_field_type_sequence_destroy(struct bt_field_type *type)
273b65be 3706{
50842bdc
PP
3707 struct bt_field_type_sequence *sequence =
3708 (struct bt_field_type_sequence *) type;
273b65be 3709
de3dd40e 3710 if (!type) {
273b65be
JG
3711 return;
3712 }
3713
4e8304f7 3714 BT_LOGD("Destroying sequence field type object: addr=%p", type);
ec159b1e 3715 BT_LOGD_STR("Putting element field type.");
83509119 3716 bt_put(sequence->element_type);
273b65be 3717 g_string_free(sequence->length_field_name, TRUE);
ec159b1e 3718 BT_LOGD_STR("Putting length field path.");
b011f6b0 3719 BT_PUT(sequence->length_field_path);
273b65be
JG
3720 g_free(sequence);
3721}
3722
3723static
50842bdc 3724void bt_field_type_string_destroy(struct bt_field_type *type)
273b65be 3725{
50842bdc
PP
3726 struct bt_field_type_string *string =
3727 (struct bt_field_type_string *) type;
273b65be 3728
de3dd40e 3729 if (!type) {
273b65be
JG
3730 return;
3731 }
3732
4e8304f7 3733 BT_LOGD("Destroying string field type object: addr=%p", type);
273b65be
JG
3734 g_free(string);
3735}
3736
3737static
50842bdc 3738void generic_field_type_freeze(struct bt_field_type *type)
273b65be
JG
3739{
3740 type->frozen = 1;
3741}
3742
586411e5 3743static
50842bdc 3744void bt_field_type_integer_freeze(struct bt_field_type *type)
586411e5 3745{
50842bdc
PP
3746 struct bt_field_type_integer *integer_type = container_of(
3747 type, struct bt_field_type_integer, parent);
586411e5 3748
4e8304f7
PP
3749 BT_LOGD("Freezing integer field type object: addr=%p", type);
3750
586411e5 3751 if (integer_type->mapped_clock) {
ec159b1e 3752 BT_LOGD_STR("Freezing integer field type's mapped clock class.");
50842bdc 3753 bt_clock_class_freeze(integer_type->mapped_clock);
586411e5
PP
3754 }
3755
3756 generic_field_type_freeze(type);
3757}
3758
273b65be 3759static
50842bdc 3760void bt_field_type_enumeration_freeze(struct bt_field_type *type)
273b65be 3761{
50842bdc
PP
3762 struct bt_field_type_enumeration *enumeration_type = container_of(
3763 type, struct bt_field_type_enumeration, parent);
273b65be 3764
4e8304f7 3765 BT_LOGD("Freezing enumeration field type object: addr=%p", type);
89e9af01 3766 type->alignment = bt_field_type_get_alignment(type);
d49e1284 3767 set_enumeration_range_overlap(type);
273b65be 3768 generic_field_type_freeze(type);
225f3384
PP
3769 BT_LOGD("Freezing enumeration field type object's container field type: int-ft-addr=%p",
3770 enumeration_type->container);
50842bdc 3771 bt_field_type_freeze(enumeration_type->container);
273b65be
JG
3772}
3773
3774static
3775void freeze_structure_field(struct structure_field *field)
3776{
225f3384
PP
3777 BT_LOGD("Freezing structure/variant field type field: field-addr=%p, "
3778 "field-ft-addr=%p, field-name=\"%s\"", field,
3779 field->type, g_quark_to_string(field->name));
50842bdc 3780 bt_field_type_freeze(field->type);
273b65be
JG
3781}
3782
3783static
50842bdc 3784void bt_field_type_structure_freeze(struct bt_field_type *type)
273b65be 3785{
50842bdc
PP
3786 struct bt_field_type_structure *structure_type = container_of(
3787 type, struct bt_field_type_structure, parent);
273b65be 3788
3ffba961 3789 /* Cache the alignment */
4e8304f7 3790 BT_LOGD("Freezing structure field type object: addr=%p", type);
50842bdc 3791 type->alignment = bt_field_type_get_alignment(type);
273b65be 3792 generic_field_type_freeze(type);
3ffba961
JG
3793 g_ptr_array_foreach(structure_type->fields,
3794 (GFunc) freeze_structure_field, NULL);
273b65be
JG
3795}
3796
3797static
50842bdc 3798void bt_field_type_variant_freeze(struct bt_field_type *type)
273b65be 3799{
50842bdc
PP
3800 struct bt_field_type_variant *variant_type = container_of(
3801 type, struct bt_field_type_variant, parent);
273b65be 3802
4e8304f7 3803 BT_LOGD("Freezing variant field type object: addr=%p", type);
273b65be 3804 generic_field_type_freeze(type);
3ffba961
JG
3805 g_ptr_array_foreach(variant_type->fields,
3806 (GFunc) freeze_structure_field, NULL);
273b65be
JG
3807}
3808
3809static
50842bdc 3810void bt_field_type_array_freeze(struct bt_field_type *type)
273b65be 3811{
50842bdc
PP
3812 struct bt_field_type_array *array_type = container_of(
3813 type, struct bt_field_type_array, parent);
273b65be 3814
3ffba961 3815 /* Cache the alignment */
4e8304f7 3816 BT_LOGD("Freezing array field type object: addr=%p", type);
50842bdc 3817 type->alignment = bt_field_type_get_alignment(type);
273b65be 3818 generic_field_type_freeze(type);
225f3384
PP
3819 BT_LOGD("Freezing array field type object's element field type: element-ft-addr=%p",
3820 array_type->element_type);
50842bdc 3821 bt_field_type_freeze(array_type->element_type);
273b65be
JG
3822}
3823
3824static
50842bdc 3825void bt_field_type_sequence_freeze(struct bt_field_type *type)
273b65be 3826{
50842bdc
PP
3827 struct bt_field_type_sequence *sequence_type = container_of(
3828 type, struct bt_field_type_sequence, parent);
273b65be 3829
3ffba961 3830 /* Cache the alignment */
4e8304f7 3831 BT_LOGD("Freezing sequence field type object: addr=%p", type);
50842bdc 3832 type->alignment = bt_field_type_get_alignment(type);
273b65be 3833 generic_field_type_freeze(type);
225f3384
PP
3834 BT_LOGD("Freezing sequence field type object's element field type: element-ft-addr=%p",
3835 sequence_type->element_type);
50842bdc 3836 bt_field_type_freeze(sequence_type->element_type);
273b65be
JG
3837}
3838
3839static
50842bdc 3840const char *get_encoding_string(enum bt_string_encoding encoding)
273b65be
JG
3841{
3842 const char *encoding_string;
3843
3844 switch (encoding) {
50842bdc 3845 case BT_STRING_ENCODING_NONE:
273b65be
JG
3846 encoding_string = "none";
3847 break;
50842bdc 3848 case BT_STRING_ENCODING_ASCII:
273b65be
JG
3849 encoding_string = "ASCII";
3850 break;
50842bdc 3851 case BT_STRING_ENCODING_UTF8:
273b65be
JG
3852 encoding_string = "UTF8";
3853 break;
3854 default:
3855 encoding_string = "unknown";
3856 break;
3857 }
3858
3859 return encoding_string;
3860}
3861
3862static
50842bdc 3863const char *get_integer_base_string(enum bt_integer_base base)
273b65be
JG
3864{
3865 const char *base_string;
3866
3867 switch (base) {
50842bdc
PP
3868 case BT_INTEGER_BASE_DECIMAL:
3869 case BT_INTEGER_BASE_UNSPECIFIED:
273b65be
JG
3870 base_string = "decimal";
3871 break;
50842bdc 3872 case BT_INTEGER_BASE_HEXADECIMAL:
273b65be
JG
3873 base_string = "hexadecimal";
3874 break;
50842bdc 3875 case BT_INTEGER_BASE_OCTAL:
273b65be
JG
3876 base_string = "octal";
3877 break;
50842bdc 3878 case BT_INTEGER_BASE_BINARY:
273b65be
JG
3879 base_string = "binary";
3880 break;
3881 default:
3882 base_string = "unknown";
3883 break;
3884 }
3885
3886 return base_string;
3887}
3888
6acddae3 3889static
27e326eb 3890void append_field_name(struct metadata_context *context,
6acddae3
PP
3891 const char *name)
3892{
3893 g_string_append_c(context->string, ' ');
3894
f4cc9a21 3895 if (!bt_identifier_is_valid(name) || *name == '_') {
6acddae3
PP
3896 g_string_append_c(context->string, '_');
3897 }
3898
3899 g_string_append(context->string, name);
3900}
3901
273b65be 3902static
50842bdc 3903int bt_field_type_integer_serialize(struct bt_field_type *type,
273b65be
JG
3904 struct metadata_context *context)
3905{
50842bdc
PP
3906 struct bt_field_type_integer *integer = container_of(type,
3907 struct bt_field_type_integer, parent);
6cfb906f 3908 int ret = 0;
273b65be 3909
4e8304f7
PP
3910 BT_LOGD("Serializing integer field type's metadata: "
3911 "ft-addr=%p, metadata-context-addr=%p", type, context);
273b65be 3912 g_string_append_printf(context->string,
dc3fffef
PP
3913 "integer { size = %u; align = %u; signed = %s; encoding = %s; base = %s; byte_order = %s",
3914 integer->size, type->alignment,
3915 (integer->is_signed ? "true" : "false"),
3916 get_encoding_string(integer->encoding),
3917 get_integer_base_string(integer->base),
3918 get_byte_order_string(integer->user_byte_order));
6cfb906f 3919 if (integer->mapped_clock) {
50842bdc 3920 const char *clock_name = bt_clock_class_get_name(
6cfb906f
JG
3921 integer->mapped_clock);
3922
4e8304f7 3923 assert(clock_name);
6cfb906f 3924 g_string_append_printf(context->string,
4ebdec03 3925 "; map = clock.%s.value", clock_name);
6cfb906f
JG
3926 }
3927
3928 g_string_append(context->string, "; }");
6cfb906f 3929 return ret;
273b65be
JG
3930}
3931
3932static
50842bdc 3933int bt_field_type_enumeration_serialize(struct bt_field_type *type,
273b65be
JG
3934 struct metadata_context *context)
3935{
3936 size_t entry;
9ce21c30 3937 int ret;
50842bdc
PP
3938 struct bt_field_type_enumeration *enumeration = container_of(type,
3939 struct bt_field_type_enumeration, parent);
3940 struct bt_field_type *container_type;
b92ddaaa 3941 int container_signed;
273b65be 3942
4e8304f7
PP
3943 BT_LOGD("Serializing enumeration field type's metadata: "
3944 "ft-addr=%p, metadata-context-addr=%p", type, context);
50842bdc 3945 container_type = bt_field_type_enumeration_get_container_type(type);
4e8304f7 3946 assert(container_type);
b92ddaaa 3947 container_signed = bt_ctf_field_type_integer_get_signed(container_type);
4e8304f7 3948 assert(container_signed >= 0);
273b65be 3949 g_string_append(context->string, "enum : ");
ec159b1e 3950 BT_LOGD_STR("Serializing enumeration field type's container field type's metadata.");
50842bdc 3951 ret = bt_field_type_serialize(enumeration->container, context);
273b65be 3952 if (ret) {
4e8304f7
PP
3953 BT_LOGW("Cannot serialize enumeration field type's container field type's metadata: "
3954 "container-ft-addr=%p", enumeration->container);
3955 goto end;
273b65be
JG
3956 }
3957
3958 g_string_append(context->string, " { ");
3959 for (entry = 0; entry < enumeration->entries->len; entry++) {
3960 struct enumeration_mapping *mapping =
3961 enumeration->entries->pdata[entry];
f4cc9a21
PP
3962 const char *label = g_quark_to_string(mapping->string);
3963
3964 g_string_append(context->string, "\"");
3965
3966 if (!bt_identifier_is_valid(label) || label[0] == '_') {
3967 g_string_append(context->string, "_");
3968 }
3969
3970 g_string_append_printf(context->string, "%s\" = ", label);
273b65be 3971
b92ddaaa
JG
3972 if (container_signed) {
3973 if (mapping->range_start._signed ==
3974 mapping->range_end._signed) {
3975 g_string_append_printf(context->string,
f4cc9a21 3976 "%" PRId64,
b92ddaaa
JG
3977 mapping->range_start._signed);
3978 } else {
3979 g_string_append_printf(context->string,
f4cc9a21 3980 "%" PRId64 " ... %" PRId64,
b92ddaaa
JG
3981 mapping->range_start._signed,
3982 mapping->range_end._signed);
3983 }
273b65be 3984 } else {
b92ddaaa
JG
3985 if (mapping->range_start._unsigned ==
3986 mapping->range_end._unsigned) {
3987 g_string_append_printf(context->string,
f4cc9a21 3988 "%" PRIu64,
b92ddaaa
JG
3989 mapping->range_start._unsigned);
3990 } else {
3991 g_string_append_printf(context->string,
f4cc9a21 3992 "%" PRIu64 " ... %" PRIu64,
b92ddaaa
JG
3993 mapping->range_start._unsigned,
3994 mapping->range_end._unsigned);
3995 }
273b65be
JG
3996 }
3997
3998 g_string_append(context->string,
3999 ((entry != (enumeration->entries->len - 1)) ?
4000 ", " : " }"));
4001 }
4002
4003 if (context->field_name->len) {
27e326eb 4004 append_field_name(context,
273b65be
JG
4005 context->field_name->str);
4006 g_string_assign(context->field_name, "");
4007 }
4008end:
4e8304f7 4009 bt_put(container_type);
273b65be
JG
4010 return ret;
4011}
4012
4013static
50842bdc 4014int bt_field_type_floating_point_serialize(struct bt_field_type *type,
273b65be
JG
4015 struct metadata_context *context)
4016{
50842bdc
PP
4017 struct bt_field_type_floating_point *floating_point = container_of(
4018 type, struct bt_field_type_floating_point, parent);
273b65be 4019
4e8304f7
PP
4020 BT_LOGD("Serializing floating point number field type's metadata: "
4021 "ft-addr=%p, metadata-context-addr=%p", type, context);
273b65be 4022 g_string_append_printf(context->string,
dc3fffef
PP
4023 "floating_point { exp_dig = %u; mant_dig = %u; byte_order = %s; align = %u; }",
4024 floating_point->exp_dig,
4025 floating_point->mant_dig,
4026 get_byte_order_string(floating_point->user_byte_order),
4027 type->alignment);
273b65be
JG
4028 return 0;
4029}
4030
4031static
50842bdc 4032int bt_field_type_structure_serialize(struct bt_field_type *type,
273b65be
JG
4033 struct metadata_context *context)
4034{
4035 size_t i;
4036 unsigned int indent;
5286528d 4037 int ret = 0;
50842bdc
PP
4038 struct bt_field_type_structure *structure = container_of(type,
4039 struct bt_field_type_structure, parent);
273b65be
JG
4040 GString *structure_field_name = context->field_name;
4041
4e8304f7
PP
4042 BT_LOGD("Serializing structure field type's metadata: "
4043 "ft-addr=%p, metadata-context-addr=%p", type, context);
273b65be
JG
4044 context->field_name = g_string_new("");
4045
4046 context->current_indentation_level++;
4047 g_string_append(context->string, "struct {\n");
4048
4049 for (i = 0; i < structure->fields->len; i++) {
dfc1504d
PP
4050 struct structure_field *field = structure->fields->pdata[i];
4051
ec159b1e 4052 BT_LOGD("Serializing structure field type's field metadata: "
1974687e 4053 "index=%zu, "
dfc1504d
PP
4054 "field-ft-addr=%p, field-name=\"%s\"",
4055 i, field, g_quark_to_string(field->name));
273b65be
JG
4056
4057 for (indent = 0; indent < context->current_indentation_level;
4058 indent++) {
4059 g_string_append_c(context->string, '\t');
4060 }
4061
273b65be
JG
4062 g_string_assign(context->field_name,
4063 g_quark_to_string(field->name));
50842bdc 4064 ret = bt_field_type_serialize(field->type, context);
273b65be 4065 if (ret) {
4e8304f7 4066 BT_LOGW("Cannot serialize structure field type's field's metadata: "
1974687e 4067 "index=%zu, "
4e8304f7
PP
4068 "field-ft-addr=%p, field-name=\"%s\"",
4069 i, field->type,
4070 g_quark_to_string(field->name));
273b65be
JG
4071 goto end;
4072 }
4073
4074 if (context->field_name->len) {
27e326eb 4075 append_field_name(context,
273b65be
JG
4076 context->field_name->str);
4077 }
4078 g_string_append(context->string, ";\n");
4079 }
4080
4081 context->current_indentation_level--;
4082 for (indent = 0; indent < context->current_indentation_level;
4083 indent++) {
4084 g_string_append_c(context->string, '\t');
4085 }
4086
dc3fffef
PP
4087 g_string_append_printf(context->string, "} align(%u)",
4088 type->alignment);
273b65be
JG
4089end:
4090 g_string_free(context->field_name, TRUE);
4091 context->field_name = structure_field_name;
4092 return ret;
4093}
4094
4095static
50842bdc 4096int bt_field_type_variant_serialize(struct bt_field_type *type,
273b65be
JG
4097 struct metadata_context *context)
4098{
4099 size_t i;
4100 unsigned int indent;
4101 int ret = 0;
50842bdc
PP
4102 struct bt_field_type_variant *variant = container_of(
4103 type, struct bt_field_type_variant, parent);
273b65be
JG
4104 GString *variant_field_name = context->field_name;
4105
4e8304f7
PP
4106 BT_LOGD("Serializing variant field type's metadata: "
4107 "ft-addr=%p, metadata-context-addr=%p", type, context);
273b65be 4108 context->field_name = g_string_new("");
6964b7fd 4109 if (variant->tag_name->len > 0) {
27e326eb
JG
4110 g_string_append(context->string, "variant <");
4111 append_field_name(context, variant->tag_name->str);
4112 g_string_append(context->string, "> {\n");
6964b7fd
JG
4113 } else {
4114 g_string_append(context->string, "variant {\n");
4115 }
4116
273b65be
JG
4117 context->current_indentation_level++;
4118 for (i = 0; i < variant->fields->len; i++) {
4119 struct structure_field *field = variant->fields->pdata[i];
4120
ec159b1e 4121 BT_LOGD("Serializing variant field type's field metadata: "
1974687e 4122 "index=%zu, "
dfc1504d
PP
4123 "field-ft-addr=%p, field-name=\"%s\"",
4124 i, field, g_quark_to_string(field->name));
4125
273b65be
JG
4126 g_string_assign(context->field_name,
4127 g_quark_to_string(field->name));
4128 for (indent = 0; indent < context->current_indentation_level;
4129 indent++) {
4130 g_string_append_c(context->string, '\t');
4131 }
4132
4133 g_string_assign(context->field_name,
4134 g_quark_to_string(field->name));
50842bdc 4135 ret = bt_field_type_serialize(field->type, context);
273b65be 4136 if (ret) {
4e8304f7 4137 BT_LOGW("Cannot serialize variant field type's field's metadata: "
1974687e 4138 "index=%zu, "
4e8304f7
PP
4139 "field-ft-addr=%p, field-name=\"%s\"",
4140 i, field->type,
4141 g_quark_to_string(field->name));
273b65be
JG
4142 goto end;
4143 }
4144
4145 if (context->field_name->len) {
27e326eb 4146 append_field_name(context,
273b65be 4147 context->field_name->str);
6acddae3 4148 g_string_append_c(context->string, ';');
273b65be
JG
4149 }
4150
4151 g_string_append_c(context->string, '\n');
4152 }
4153
4154 context->current_indentation_level--;
4155 for (indent = 0; indent < context->current_indentation_level;
4156 indent++) {
4157 g_string_append_c(context->string, '\t');
4158 }
4159
4160 g_string_append(context->string, "}");
4161end:
4162 g_string_free(context->field_name, TRUE);
4163 context->field_name = variant_field_name;
4164 return ret;
4165}
4166
4167static
50842bdc 4168int bt_field_type_array_serialize(struct bt_field_type *type,
273b65be
JG
4169 struct metadata_context *context)
4170{
4171 int ret = 0;
50842bdc
PP
4172 struct bt_field_type_array *array = container_of(type,
4173 struct bt_field_type_array, parent);
273b65be 4174
4e8304f7
PP
4175 BT_LOGD("Serializing array field type's metadata: "
4176 "ft-addr=%p, metadata-context-addr=%p", type, context);
ec159b1e 4177 BT_LOGD_STR("Serializing array field type's element field type's metadata.");
50842bdc 4178 ret = bt_field_type_serialize(array->element_type, context);
273b65be 4179 if (ret) {
4e8304f7
PP
4180 BT_LOGW("Cannot serialize array field type's element field type's metadata: "
4181 "element-ft-addr=%p", array->element_type);
273b65be
JG
4182 goto end;
4183 }
4184
4185 if (context->field_name->len) {
27e326eb 4186 append_field_name(context,
6acddae3
PP
4187 context->field_name->str);
4188
4189 g_string_append_printf(context->string, "[%u]", array->length);
273b65be
JG
4190 g_string_assign(context->field_name, "");
4191 } else {
4192 g_string_append_printf(context->string, "[%u]", array->length);
4193 }
4194end:
4195 return ret;
4196}
4197
4198static
50842bdc 4199int bt_field_type_sequence_serialize(struct bt_field_type *type,
273b65be
JG
4200 struct metadata_context *context)
4201{
4202 int ret = 0;
50842bdc
PP
4203 struct bt_field_type_sequence *sequence = container_of(
4204 type, struct bt_field_type_sequence, parent);
273b65be 4205
4e8304f7
PP
4206 BT_LOGD("Serializing sequence field type's metadata: "
4207 "ft-addr=%p, metadata-context-addr=%p", type, context);
ec159b1e 4208 BT_LOGD_STR("Serializing sequence field type's element field type's metadata.");
50842bdc 4209 ret = bt_field_type_serialize(sequence->element_type, context);
273b65be 4210 if (ret) {
4e8304f7
PP
4211 BT_LOGW("Cannot serialize sequence field type's element field type's metadata: "
4212 "element-ft-addr=%p", sequence->element_type);
273b65be
JG
4213 goto end;
4214 }
4215
4216 if (context->field_name->len) {
27e326eb 4217 append_field_name(context, context->field_name->str);
273b65be 4218 g_string_assign(context->field_name, "");
273b65be 4219 }
27e326eb
JG
4220 g_string_append(context->string, "[");
4221 append_field_name(context, sequence->length_field_name->str);
4222 g_string_append(context->string, "]");
273b65be
JG
4223end:
4224 return ret;
4225}
4226
4227static
50842bdc 4228int bt_field_type_string_serialize(struct bt_field_type *type,
273b65be
JG
4229 struct metadata_context *context)
4230{
50842bdc
PP
4231 struct bt_field_type_string *string = container_of(
4232 type, struct bt_field_type_string, parent);
273b65be 4233
4e8304f7
PP
4234 BT_LOGD("Serializing string field type's metadata: "
4235 "ft-addr=%p, metadata-context-addr=%p", type, context);
273b65be
JG
4236 g_string_append_printf(context->string,
4237 "string { encoding = %s; }",
dc3fffef 4238 get_encoding_string(string->encoding));
273b65be
JG
4239 return 0;
4240}
4241
4242static
50842bdc
PP
4243void bt_field_type_integer_set_byte_order(struct bt_field_type *type,
4244 enum bt_byte_order byte_order)
273b65be 4245{
50842bdc
PP
4246 struct bt_field_type_integer *integer_type = container_of(type,
4247 struct bt_field_type_integer, parent);
273b65be 4248
dc3fffef 4249 integer_type->user_byte_order = byte_order;
c35a1669
JG
4250}
4251
4252static
50842bdc
PP
4253void bt_field_type_enumeration_set_byte_order(
4254 struct bt_field_type *type, enum bt_byte_order byte_order)
c35a1669 4255{
50842bdc
PP
4256 struct bt_field_type_enumeration *enum_type = container_of(type,
4257 struct bt_field_type_enumeration, parent);
c35a1669
JG
4258
4259 /* Safe to assume that container is an integer */
50842bdc 4260 bt_field_type_integer_set_byte_order(enum_type->container,
dc3fffef 4261 byte_order);
273b65be
JG
4262}
4263
4264static
50842bdc
PP
4265void bt_field_type_floating_point_set_byte_order(
4266 struct bt_field_type *type, enum bt_byte_order byte_order)
273b65be 4267{
50842bdc
PP
4268 struct bt_field_type_floating_point *floating_point_type =
4269 container_of(type, struct bt_field_type_floating_point,
273b65be
JG
4270 parent);
4271
dc3fffef 4272 floating_point_type->user_byte_order = byte_order;
c35a1669
JG
4273}
4274
4275static
50842bdc
PP
4276void bt_field_type_structure_set_byte_order(struct bt_field_type *type,
4277 enum bt_byte_order byte_order)
c35a1669
JG
4278{
4279 int i;
50842bdc
PP
4280 struct bt_field_type_structure *structure_type =
4281 container_of(type, struct bt_field_type_structure,
c35a1669
JG
4282 parent);
4283
4284 for (i = 0; i < structure_type->fields->len; i++) {
4285 struct structure_field *field = g_ptr_array_index(
4286 structure_type->fields, i);
50842bdc 4287 struct bt_field_type *field_type = field->type;
c35a1669 4288
dc3fffef
PP
4289 if (set_byte_order_funcs[field_type->id]) {
4290 set_byte_order_funcs[field_type->id](
4291 field_type, byte_order);
c35a1669
JG
4292 }
4293 }
4294}
4295
4296static
50842bdc
PP
4297void bt_field_type_variant_set_byte_order(struct bt_field_type *type,
4298 enum bt_byte_order byte_order)
c35a1669
JG
4299{
4300 int i;
50842bdc
PP
4301 struct bt_field_type_variant *variant_type =
4302 container_of(type, struct bt_field_type_variant,
c35a1669
JG
4303 parent);
4304
4305 for (i = 0; i < variant_type->fields->len; i++) {
4306 struct structure_field *field = g_ptr_array_index(
4307 variant_type->fields, i);
50842bdc 4308 struct bt_field_type *field_type = field->type;
c35a1669 4309
dc3fffef
PP
4310 if (set_byte_order_funcs[field_type->id]) {
4311 set_byte_order_funcs[field_type->id](
4312 field_type, byte_order);
c35a1669
JG
4313 }
4314 }
4315}
4316
4317static
50842bdc
PP
4318void bt_field_type_array_set_byte_order(struct bt_field_type *type,
4319 enum bt_byte_order byte_order)
c35a1669 4320{
50842bdc
PP
4321 struct bt_field_type_array *array_type =
4322 container_of(type, struct bt_field_type_array,
c35a1669
JG
4323 parent);
4324
dc3fffef
PP
4325 if (set_byte_order_funcs[array_type->element_type->id]) {
4326 set_byte_order_funcs[array_type->element_type->id](
4327 array_type->element_type, byte_order);
c35a1669
JG
4328 }
4329}
4330
4331static
50842bdc
PP
4332void bt_field_type_sequence_set_byte_order(struct bt_field_type *type,
4333 enum bt_byte_order byte_order)
c35a1669 4334{
50842bdc
PP
4335 struct bt_field_type_sequence *sequence_type =
4336 container_of(type, struct bt_field_type_sequence,
c35a1669
JG
4337 parent);
4338
4339 if (set_byte_order_funcs[
dc3fffef 4340 sequence_type->element_type->id]) {
c35a1669 4341 set_byte_order_funcs[
dc3fffef
PP
4342 sequence_type->element_type->id](
4343 sequence_type->element_type, byte_order);
c35a1669 4344 }
273b65be 4345}
24724933
JG
4346
4347static
50842bdc
PP
4348struct bt_field_type *bt_field_type_integer_copy(
4349 struct bt_field_type *type)
24724933 4350{
50842bdc
PP
4351 struct bt_field_type *copy;
4352 struct bt_field_type_integer *integer, *copy_integer;
24724933 4353
4e8304f7 4354 BT_LOGD("Copying integer field type's: addr=%p", type);
50842bdc
PP
4355 integer = container_of(type, struct bt_field_type_integer, parent);
4356 copy = bt_field_type_integer_create(integer->size);
24724933 4357 if (!copy) {
4e8304f7 4358 BT_LOGE_STR("Cannot create integer field type.");
24724933
JG
4359 goto end;
4360 }
4361
50842bdc 4362 copy_integer = container_of(copy, struct bt_field_type_integer,
24724933 4363 parent);
dc3fffef 4364 copy_integer->mapped_clock = bt_get(integer->mapped_clock);
445c3471 4365 copy_integer->user_byte_order = integer->user_byte_order;
dc3fffef
PP
4366 copy_integer->is_signed = integer->is_signed;
4367 copy_integer->size = integer->size;
4368 copy_integer->base = integer->base;
4369 copy_integer->encoding = integer->encoding;
4e8304f7
PP
4370 BT_LOGD("Copied integer field type: original-ft-addr=%p, copy-ft-addr=%p",
4371 type, copy);
445c3471 4372
24724933
JG
4373end:
4374 return copy;
4375}
4376
4377static
50842bdc
PP
4378struct bt_field_type *bt_field_type_enumeration_copy(
4379 struct bt_field_type *type)
24724933
JG
4380{
4381 size_t i;
50842bdc
PP
4382 struct bt_field_type *copy = NULL, *copy_container;
4383 struct bt_field_type_enumeration *enumeration, *copy_enumeration;
24724933 4384
4e8304f7 4385 BT_LOGD("Copying enumeration field type's: addr=%p", type);
50842bdc 4386 enumeration = container_of(type, struct bt_field_type_enumeration,
24724933
JG
4387 parent);
4388
4389 /* Copy the source enumeration's container */
ec159b1e 4390 BT_LOGD_STR("Copying enumeration field type's container field type.");
50842bdc 4391 copy_container = bt_field_type_copy(enumeration->container);
24724933 4392 if (!copy_container) {
4e8304f7 4393 BT_LOGE_STR("Cannot copy enumeration field type's container field type.");
24724933
JG
4394 goto end;
4395 }
4396
50842bdc 4397 copy = bt_field_type_enumeration_create(copy_container);
24724933 4398 if (!copy) {
4e8304f7 4399 BT_LOGE_STR("Cannot create enumeration field type.");
24724933
JG
4400 goto end;
4401 }
4402 copy_enumeration = container_of(copy,
50842bdc 4403 struct bt_field_type_enumeration, parent);
24724933
JG
4404
4405 /* Copy all enumaration entries */
4406 for (i = 0; i < enumeration->entries->len; i++) {
4407 struct enumeration_mapping *mapping = g_ptr_array_index(
4408 enumeration->entries, i);
96e8f959 4409 struct enumeration_mapping *copy_mapping = g_new0(
24724933
JG
4410 struct enumeration_mapping, 1);
4411
4412 if (!copy_mapping) {
4e8304f7 4413 BT_LOGE_STR("Failed to allocate one enumeration mapping.");
24724933
JG
4414 goto error;
4415 }
4416
4417 *copy_mapping = *mapping;
4418 g_ptr_array_add(copy_enumeration->entries, copy_mapping);
4419 }
4420
4e8304f7
PP
4421 BT_LOGD("Copied enumeration field type: original-ft-addr=%p, copy-ft-addr=%p",
4422 type, copy);
4423
24724933 4424end:
83509119 4425 bt_put(copy_container);
24724933
JG
4426 return copy;
4427error:
83509119
JG
4428 bt_put(copy_container);
4429 BT_PUT(copy);
4430 return copy;
24724933
JG
4431}
4432
4433static
50842bdc
PP
4434struct bt_field_type *bt_field_type_floating_point_copy(
4435 struct bt_field_type *type)
24724933 4436{
50842bdc
PP
4437 struct bt_field_type *copy;
4438 struct bt_field_type_floating_point *floating_point, *copy_float;
24724933 4439
4e8304f7 4440 BT_LOGD("Copying floating point number field type's: addr=%p", type);
24724933 4441 floating_point = container_of(type,
50842bdc
PP
4442 struct bt_field_type_floating_point, parent);
4443 copy = bt_field_type_floating_point_create();
24724933 4444 if (!copy) {
4e8304f7 4445 BT_LOGE_STR("Cannot create floating point number field type.");
24724933
JG
4446 goto end;
4447 }
4448
4449 copy_float = container_of(copy,
50842bdc 4450 struct bt_field_type_floating_point, parent);
445c3471 4451 copy_float->user_byte_order = floating_point->user_byte_order;
dc3fffef
PP
4452 copy_float->exp_dig = floating_point->exp_dig;
4453 copy_float->mant_dig = floating_point->mant_dig;
4e8304f7
PP
4454 BT_LOGD("Copied floating point number field type: original-ft-addr=%p, copy-ft-addr=%p",
4455 type, copy);
24724933
JG
4456end:
4457 return copy;
4458}
4459
4460static
50842bdc
PP
4461struct bt_field_type *bt_field_type_structure_copy(
4462 struct bt_field_type *type)
24724933 4463{
4e8304f7 4464 int64_t i;
24724933
JG
4465 GHashTableIter iter;
4466 gpointer key, value;
50842bdc
PP
4467 struct bt_field_type *copy;
4468 struct bt_field_type_structure *structure, *copy_structure;
24724933 4469
4e8304f7 4470 BT_LOGD("Copying structure field type's: addr=%p", type);
50842bdc 4471 structure = container_of(type, struct bt_field_type_structure,
24724933 4472 parent);
50842bdc 4473 copy = bt_field_type_structure_create();
24724933 4474 if (!copy) {
4e8304f7 4475 BT_LOGE_STR("Cannot create structure field type.");
24724933
JG
4476 goto end;
4477 }
4478
4479 copy_structure = container_of(copy,
50842bdc 4480 struct bt_field_type_structure, parent);
24724933
JG
4481
4482 /* Copy field_name_to_index */
4483 g_hash_table_iter_init(&iter, structure->field_name_to_index);
4484 while (g_hash_table_iter_next (&iter, &key, &value)) {
4485 g_hash_table_insert(copy_structure->field_name_to_index,
4486 key, value);
4487 }
4488
4489 for (i = 0; i < structure->fields->len; i++) {
4490 struct structure_field *entry, *copy_entry;
50842bdc 4491 struct bt_field_type *copy_field;
24724933 4492
dfc1504d 4493 entry = g_ptr_array_index(structure->fields, i);
ec159b1e 4494 BT_LOGD("Copying structure field type's field: "
dfc1504d
PP
4495 "index=%" PRId64 ", "
4496 "field-ft-addr=%p, field-name=\"%s\"",
4497 i, entry, g_quark_to_string(entry->name));
24724933
JG
4498 copy_entry = g_new0(struct structure_field, 1);
4499 if (!copy_entry) {
4e8304f7 4500 BT_LOGE_STR("Failed to allocate one structure field type field.");
24724933
JG
4501 goto error;
4502 }
4503
50842bdc 4504 copy_field = bt_field_type_copy(entry->type);
24724933 4505 if (!copy_field) {
4e8304f7
PP
4506 BT_LOGE("Cannot copy structure field type's field: "
4507 "index=%" PRId64 ", "
4508 "field-ft-addr=%p, field-name=\"%s\"",
4509 i, entry, g_quark_to_string(entry->name));
24724933
JG
4510 g_free(copy_entry);
4511 goto error;
4512 }
4513
4514 copy_entry->name = entry->name;
4515 copy_entry->type = copy_field;
4516 g_ptr_array_add(copy_structure->fields, copy_entry);
4517 }
4518
4e8304f7
PP
4519 BT_LOGD("Copied structure field type: original-ft-addr=%p, copy-ft-addr=%p",
4520 type, copy);
4521
24724933
JG
4522end:
4523 return copy;
4524error:
83509119
JG
4525 BT_PUT(copy);
4526 return copy;
24724933
JG
4527}
4528
4529static
50842bdc
PP
4530struct bt_field_type *bt_field_type_variant_copy(
4531 struct bt_field_type *type)
24724933 4532{
4e8304f7 4533 int64_t i;
24724933
JG
4534 GHashTableIter iter;
4535 gpointer key, value;
50842bdc
PP
4536 struct bt_field_type *copy = NULL, *copy_tag = NULL;
4537 struct bt_field_type_variant *variant, *copy_variant;
24724933 4538
4e8304f7 4539 BT_LOGD("Copying variant field type's: addr=%p", type);
50842bdc 4540 variant = container_of(type, struct bt_field_type_variant,
24724933
JG
4541 parent);
4542 if (variant->tag) {
ec159b1e 4543 BT_LOGD_STR("Copying variant field type's tag field type.");
50842bdc 4544 copy_tag = bt_field_type_copy(&variant->tag->parent);
24724933 4545 if (!copy_tag) {
4e8304f7 4546 BT_LOGE_STR("Cannot copy variant field type's tag field type.");
24724933
JG
4547 goto end;
4548 }
4549 }
4550
50842bdc 4551 copy = bt_field_type_variant_create(copy_tag,
24724933
JG
4552 variant->tag_name->len ? variant->tag_name->str : NULL);
4553 if (!copy) {
4e8304f7 4554 BT_LOGE_STR("Cannot create variant field type.");
24724933
JG
4555 goto end;
4556 }
4557
50842bdc 4558 copy_variant = container_of(copy, struct bt_field_type_variant,
24724933
JG
4559 parent);
4560
4561 /* Copy field_name_to_index */
4562 g_hash_table_iter_init(&iter, variant->field_name_to_index);
4563 while (g_hash_table_iter_next (&iter, &key, &value)) {
4564 g_hash_table_insert(copy_variant->field_name_to_index,
4565 key, value);
4566 }
4567
4568 for (i = 0; i < variant->fields->len; i++) {
4569 struct structure_field *entry, *copy_entry;
50842bdc 4570 struct bt_field_type *copy_field;
24724933 4571
dfc1504d 4572 entry = g_ptr_array_index(variant->fields, i);
ec159b1e 4573 BT_LOGD("Copying variant field type's field: "
dfc1504d
PP
4574 "index=%" PRId64 ", "
4575 "field-ft-addr=%p, field-name=\"%s\"",
4576 i, entry, g_quark_to_string(entry->name));
24724933
JG
4577 copy_entry = g_new0(struct structure_field, 1);
4578 if (!copy_entry) {
4e8304f7 4579 BT_LOGE_STR("Failed to allocate one variant field type field.");
24724933
JG
4580 goto error;
4581 }
4582
50842bdc 4583 copy_field = bt_field_type_copy(entry->type);
24724933 4584 if (!copy_field) {
4e8304f7
PP
4585 BT_LOGE("Cannot copy variant field type's field: "
4586 "index=%" PRId64 ", "
4587 "field-ft-addr=%p, field-name=\"%s\"",
4588 i, entry, g_quark_to_string(entry->name));
24724933
JG
4589 g_free(copy_entry);
4590 goto error;
4591 }
4592
4593 copy_entry->name = entry->name;
4594 copy_entry->type = copy_field;
4595 g_ptr_array_add(copy_variant->fields, copy_entry);
4596 }
4597
b011f6b0 4598 if (variant->tag_field_path) {
ec159b1e 4599 BT_LOGD_STR("Copying variant field type's tag field path.");
50842bdc 4600 copy_variant->tag_field_path = bt_field_path_copy(
b011f6b0
PP
4601 variant->tag_field_path);
4602 if (!copy_variant->tag_field_path) {
4e8304f7 4603 BT_LOGE_STR("Cannot copy variant field type's tag field path.");
4a1e8671
JG
4604 goto error;
4605 }
4606 }
4e8304f7
PP
4607
4608 BT_LOGD("Copied variant field type: original-ft-addr=%p, copy-ft-addr=%p",
4609 type, copy);
4610
24724933 4611end:
83509119 4612 bt_put(copy_tag);
24724933
JG
4613 return copy;
4614error:
83509119
JG
4615 bt_put(copy_tag);
4616 BT_PUT(copy);
4617 return copy;
24724933
JG
4618}
4619
4620static
50842bdc
PP
4621struct bt_field_type *bt_field_type_array_copy(
4622 struct bt_field_type *type)
24724933 4623{
50842bdc
PP
4624 struct bt_field_type *copy = NULL, *copy_element;
4625 struct bt_field_type_array *array;
24724933 4626
4e8304f7 4627 BT_LOGD("Copying array field type's: addr=%p", type);
50842bdc 4628 array = container_of(type, struct bt_field_type_array,
24724933 4629 parent);
ec159b1e 4630 BT_LOGD_STR("Copying array field type's element field type.");
50842bdc 4631 copy_element = bt_field_type_copy(array->element_type);
24724933 4632 if (!copy_element) {
4e8304f7 4633 BT_LOGE_STR("Cannot copy array field type's element field type.");
24724933
JG
4634 goto end;
4635 }
4636
50842bdc 4637 copy = bt_field_type_array_create(copy_element, array->length);
24724933 4638 if (!copy) {
4e8304f7 4639 BT_LOGE_STR("Cannot create array field type.");
24724933
JG
4640 goto end;
4641 }
4e8304f7
PP
4642
4643 BT_LOGD("Copied array field type: original-ft-addr=%p, copy-ft-addr=%p",
4644 type, copy);
4645
24724933 4646end:
83509119 4647 bt_put(copy_element);
24724933
JG
4648 return copy;
4649}
4650
4651static
50842bdc
PP
4652struct bt_field_type *bt_field_type_sequence_copy(
4653 struct bt_field_type *type)
24724933 4654{
50842bdc
PP
4655 struct bt_field_type *copy = NULL, *copy_element;
4656 struct bt_field_type_sequence *sequence, *copy_sequence;
24724933 4657
4e8304f7 4658 BT_LOGD("Copying sequence field type's: addr=%p", type);
50842bdc 4659 sequence = container_of(type, struct bt_field_type_sequence,
24724933 4660 parent);
ec159b1e 4661 BT_LOGD_STR("Copying sequence field type's element field type.");
50842bdc 4662 copy_element = bt_field_type_copy(sequence->element_type);
24724933 4663 if (!copy_element) {
4e8304f7 4664 BT_LOGE_STR("Cannot copy sequence field type's element field type.");
24724933
JG
4665 goto end;
4666 }
4667
50842bdc 4668 copy = bt_field_type_sequence_create(copy_element,
24724933
JG
4669 sequence->length_field_name->len ?
4670 sequence->length_field_name->str : NULL);
4671 if (!copy) {
4e8304f7 4672 BT_LOGE_STR("Cannot create sequence field type.");
24724933
JG
4673 goto end;
4674 }
4675
50842bdc 4676 copy_sequence = container_of(copy, struct bt_field_type_sequence,
24724933 4677 parent);
aa4e271c 4678 if (sequence->length_field_path) {
ec159b1e 4679 BT_LOGD_STR("Copying sequence field type's length field path.");
50842bdc 4680 copy_sequence->length_field_path = bt_field_path_copy(
aa4e271c
JG
4681 sequence->length_field_path);
4682 if (!copy_sequence->length_field_path) {
4e8304f7 4683 BT_LOGE_STR("Cannot copy sequence field type's length field path.");
aa4e271c
JG
4684 goto error;
4685 }
4686 }
4e8304f7
PP
4687
4688 BT_LOGD("Copied sequence field type: original-ft-addr=%p, copy-ft-addr=%p",
4689 type, copy);
4690
24724933 4691end:
83509119 4692 bt_put(copy_element);
24724933 4693 return copy;
aa4e271c 4694error:
83509119 4695 BT_PUT(copy);
aa4e271c 4696 goto end;
24724933
JG
4697}
4698
4699static
50842bdc
PP
4700struct bt_field_type *bt_field_type_string_copy(
4701 struct bt_field_type *type)
24724933 4702{
50842bdc 4703 struct bt_field_type *copy;
24724933 4704
4e8304f7 4705 BT_LOGD("Copying string field type's: addr=%p", type);
50842bdc 4706 copy = bt_field_type_string_create();
24724933 4707 if (!copy) {
4e8304f7 4708 BT_LOGE_STR("Cannot create string field type.");
24724933
JG
4709 goto end;
4710 }
4711
4e8304f7
PP
4712 BT_LOGD("Copied string field type: original-ft-addr=%p, copy-ft-addr=%p",
4713 type, copy);
24724933
JG
4714end:
4715 return copy;
4716}
265e809c
PP
4717
4718static
50842bdc
PP
4719int bt_field_type_integer_compare(struct bt_field_type *type_a,
4720 struct bt_field_type *type_b)
265e809c
PP
4721{
4722 int ret = 1;
50842bdc
PP
4723 struct bt_field_type_integer *int_type_a;
4724 struct bt_field_type_integer *int_type_b;
265e809c 4725
50842bdc 4726 int_type_a = container_of(type_a, struct bt_field_type_integer,
265e809c 4727 parent);
50842bdc 4728 int_type_b = container_of(type_b, struct bt_field_type_integer,
265e809c 4729 parent);
265e809c
PP
4730
4731 /* Length */
dc3fffef 4732 if (int_type_a->size != int_type_b->size) {
4e8304f7
PP
4733 BT_LOGV("Integer field types differ: different sizes: "
4734 "ft-a-size=%u, ft-b-size=%u",
4735 int_type_a->size, int_type_b->size);
265e809c
PP
4736 goto end;
4737 }
4738
dc3fffef
PP
4739 /* Byte order */
4740 if (int_type_a->user_byte_order != int_type_b->user_byte_order) {
4e8304f7
PP
4741 BT_LOGV("Integer field types differ: different byte orders: "
4742 "ft-a-bo=%s, ft-b-bo=%s",
50842bdc
PP
4743 bt_byte_order_string(int_type_a->user_byte_order),
4744 bt_byte_order_string(int_type_b->user_byte_order));
265e809c
PP
4745 goto end;
4746 }
4747
4748 /* Signedness */
dc3fffef 4749 if (int_type_a->is_signed != int_type_b->is_signed) {
4e8304f7
PP
4750 BT_LOGV("Integer field types differ: different signedness: "
4751 "ft-a-is-signed=%d, ft-b-is-signed=%d",
4752 int_type_a->is_signed,
4753 int_type_b->is_signed);
265e809c
PP
4754 goto end;
4755 }
4756
4757 /* Base */
dc3fffef 4758 if (int_type_a->base != int_type_b->base) {
4e8304f7
PP
4759 BT_LOGV("Integer field types differ: different bases: "
4760 "ft-a-base=%s, ft-b-base=%s",
50842bdc
PP
4761 bt_integer_base_string(int_type_a->base),
4762 bt_integer_base_string(int_type_b->base));
265e809c
PP
4763 goto end;
4764 }
4765
4766 /* Encoding */
dc3fffef 4767 if (int_type_a->encoding != int_type_b->encoding) {
4e8304f7
PP
4768 BT_LOGV("Integer field types differ: different encodings: "
4769 "ft-a-encoding=%s, ft-b-encoding=%s",
50842bdc
PP
4770 bt_string_encoding_string(int_type_a->encoding),
4771 bt_string_encoding_string(int_type_b->encoding));
265e809c
PP
4772 goto end;
4773 }
4774
93dda901
PP
4775 /* Mapped clock class */
4776 if (int_type_a->mapped_clock) {
4777 if (!int_type_b->mapped_clock) {
4778 BT_LOGV_STR("Integer field types differ: field type A "
4779 "has a mapped clock class, but field type B "
4780 "does not.");
4781 goto end;
4782 }
4783
4784 if (bt_clock_class_compare(int_type_a->mapped_clock,
4785 int_type_b->mapped_clock) != 0) {
4786 BT_LOGV_STR("Integer field types differ: different "
4787 "mapped clock classes.");
4788 }
4789 } else {
4790 if (int_type_b->mapped_clock) {
4791 BT_LOGV_STR("Integer field types differ: field type A "
4792 "has no description, but field type B has one.");
4793 goto end;
4794 }
265e809c
PP
4795 }
4796
4797 /* Equal */
4798 ret = 0;
4799
4800end:
4801 return ret;
4802}
4803
4804static
50842bdc
PP
4805int bt_field_type_floating_point_compare(struct bt_field_type *type_a,
4806 struct bt_field_type *type_b)
265e809c
PP
4807{
4808 int ret = 1;
50842bdc
PP
4809 struct bt_field_type_floating_point *float_a;
4810 struct bt_field_type_floating_point *float_b;
265e809c
PP
4811
4812 float_a = container_of(type_a,
50842bdc 4813 struct bt_field_type_floating_point, parent);
265e809c 4814 float_b = container_of(type_b,
50842bdc 4815 struct bt_field_type_floating_point, parent);
265e809c 4816
dc3fffef
PP
4817 /* Byte order */
4818 if (float_a->user_byte_order != float_b->user_byte_order) {
4e8304f7
PP
4819 BT_LOGV("Floating point number field types differ: different byte orders: "
4820 "ft-a-bo=%s, ft-b-bo=%s",
50842bdc
PP
4821 bt_byte_order_string(float_a->user_byte_order),
4822 bt_byte_order_string(float_b->user_byte_order));
265e809c
PP
4823 goto end;
4824 }
4825
4826 /* Exponent length */
dc3fffef 4827 if (float_a->exp_dig != float_b->exp_dig) {
4e8304f7 4828 BT_LOGV("Floating point number field types differ: different exponent sizes: "
32e87ceb 4829 "ft-a-exp-size=%u, ft-b-exp-size=%u",
4e8304f7 4830 float_a->exp_dig, float_b->exp_dig);
265e809c
PP
4831 goto end;
4832 }
4833
4834 /* Mantissa length */
dc3fffef 4835 if (float_a->mant_dig != float_b->mant_dig) {
4e8304f7 4836 BT_LOGV("Floating point number field types differ: different mantissa sizes: "
32e87ceb 4837 "ft-a-mant-size=%u, ft-b-mant-size=%u",
4e8304f7 4838 float_a->mant_dig, float_b->mant_dig);
265e809c
PP
4839 goto end;
4840 }
4841
4842 /* Equal */
4843 ret = 0;
4844
4845end:
4846 return ret;
4847}
4848
4849static
4850int compare_enumeration_mappings(struct enumeration_mapping *mapping_a,
4851 struct enumeration_mapping *mapping_b)
4852{
4853 int ret = 1;
4854
4855 /* Label */
4856 if (mapping_a->string != mapping_b->string) {
4e8304f7
PP
4857 BT_LOGV("Enumeration field type mappings differ: different names: "
4858 "mapping-a-name=\"%s\", mapping-b-name=\"%s\"",
4859 g_quark_to_string(mapping_a->string),
4860 g_quark_to_string(mapping_b->string));
265e809c
PP
4861 goto end;
4862 }
4863
4864 /* Range start */
4865 if (mapping_a->range_start._unsigned !=
4866 mapping_b->range_start._unsigned) {
4e8304f7
PP
4867 BT_LOGV("Enumeration field type mappings differ: different starts of range: "
4868 "mapping-a-range-start-unsigned=%" PRIu64 ", "
4869 "mapping-b-range-start-unsigned=%" PRIu64,
4870 mapping_a->range_start._unsigned,
4871 mapping_b->range_start._unsigned);
265e809c
PP
4872 goto end;
4873 }
4874
4875 /* Range end */
4876 if (mapping_a->range_end._unsigned !=
4877 mapping_b->range_end._unsigned) {
4e8304f7
PP
4878 BT_LOGV("Enumeration field type mappings differ: different ends of range: "
4879 "mapping-a-range-end-unsigned=%" PRIu64 ", "
4880 "mapping-b-range-end-unsigned=%" PRIu64,
4881 mapping_a->range_end._unsigned,
4882 mapping_b->range_end._unsigned);
265e809c
PP
4883 goto end;
4884 }
4885
4886 /* Equal */
4887 ret = 0;
4888
4889end:
4890 return ret;
4891}
4892
4893static
50842bdc
PP
4894int bt_field_type_enumeration_compare(struct bt_field_type *type_a,
4895 struct bt_field_type *type_b)
265e809c
PP
4896{
4897 int ret = 1;
4898 int i;
50842bdc
PP
4899 struct bt_field_type_enumeration *enum_a;
4900 struct bt_field_type_enumeration *enum_b;
265e809c
PP
4901
4902 enum_a = container_of(type_a,
50842bdc 4903 struct bt_field_type_enumeration, parent);
265e809c 4904 enum_b = container_of(type_b,
50842bdc 4905 struct bt_field_type_enumeration, parent);
265e809c
PP
4906
4907 /* Container field type */
50842bdc 4908 ret = bt_field_type_compare(enum_a->container, enum_b->container);
265e809c 4909 if (ret) {
4e8304f7
PP
4910 BT_LOGV("Enumeration field types differ: different container field types: "
4911 "ft-a-container-ft-addr=%p, ft-b-container-ft-addr=%p",
4912 enum_a->container, enum_b->container);
265e809c
PP
4913 goto end;
4914 }
4915
4916 ret = 1;
4917
4918 /* Entries */
4919 if (enum_a->entries->len != enum_b->entries->len) {
4920 goto end;
4921 }
4922
4923 for (i = 0; i < enum_a->entries->len; ++i) {
4924 struct enumeration_mapping *mapping_a =
4925 g_ptr_array_index(enum_a->entries, i);
4926 struct enumeration_mapping *mapping_b =
4927 g_ptr_array_index(enum_b->entries, i);
4928
4929 if (compare_enumeration_mappings(mapping_a, mapping_b)) {
4e8304f7
PP
4930 BT_LOGV("Enumeration field types differ: different mappings: "
4931 "ft-a-mapping-addr=%p, ft-b-mapping-addr=%p, "
4932 "ft-a-mapping-name=\"%s\", ft-b-mapping-name=\"%s\"",
4933 mapping_a, mapping_b,
4934 g_quark_to_string(mapping_a->string),
4935 g_quark_to_string(mapping_b->string));
265e809c
PP
4936 goto end;
4937 }
4938 }
4939
4940 /* Equal */
4941 ret = 0;
4942
4943end:
4944 return ret;
4945}
4946
4947static
50842bdc
PP
4948int bt_field_type_string_compare(struct bt_field_type *type_a,
4949 struct bt_field_type *type_b)
265e809c
PP
4950{
4951 int ret = 1;
50842bdc
PP
4952 struct bt_field_type_string *string_a;
4953 struct bt_field_type_string *string_b;
265e809c
PP
4954
4955 string_a = container_of(type_a,
50842bdc 4956 struct bt_field_type_string, parent);
265e809c 4957 string_b = container_of(type_b,
50842bdc 4958 struct bt_field_type_string, parent);
265e809c
PP
4959
4960 /* Encoding */
dc3fffef 4961 if (string_a->encoding != string_b->encoding) {
4e8304f7
PP
4962 BT_LOGV("String field types differ: different encodings: "
4963 "ft-a-encoding=%s, ft-b-encoding=%s",
50842bdc
PP
4964 bt_string_encoding_string(string_a->encoding),
4965 bt_string_encoding_string(string_b->encoding));
265e809c
PP
4966 goto end;
4967 }
4968
4969 /* Equal */
4970 ret = 0;
4971
4972end:
4973 return ret;
4974}
4975
4976static
4977int compare_structure_fields(struct structure_field *field_a,
4978 struct structure_field *field_b)
4979{
4980 int ret = 1;
4981
4982 /* Label */
4983 if (field_a->name != field_b->name) {
4e8304f7
PP
4984 BT_LOGV("Structure/variant field type fields differ: different names: "
4985 "field-a-name=%s, field-b-name=%s",
4986 g_quark_to_string(field_a->name),
4987 g_quark_to_string(field_b->name));
265e809c
PP
4988 goto end;
4989 }
4990
4991 /* Type */
50842bdc 4992 ret = bt_field_type_compare(field_a->type, field_b->type);
4e8304f7
PP
4993 if (ret == 1) {
4994 BT_LOGV("Structure/variant field type fields differ: different field types: "
32e87ceb 4995 "field-name=\"%s\", field-a-ft-addr=%p, field-b-ft-addr=%p",
4e8304f7
PP
4996 g_quark_to_string(field_a->name),
4997 field_a->type, field_b->type);
4998 }
265e809c
PP
4999
5000end:
5001 return ret;
5002}
5003
5004static
50842bdc
PP
5005int bt_field_type_structure_compare(struct bt_field_type *type_a,
5006 struct bt_field_type *type_b)
265e809c
PP
5007{
5008 int ret = 1;
5009 int i;
50842bdc
PP
5010 struct bt_field_type_structure *struct_a;
5011 struct bt_field_type_structure *struct_b;
265e809c
PP
5012
5013 struct_a = container_of(type_a,
50842bdc 5014 struct bt_field_type_structure, parent);
265e809c 5015 struct_b = container_of(type_b,
50842bdc 5016 struct bt_field_type_structure, parent);
265e809c
PP
5017
5018 /* Alignment */
50842bdc
PP
5019 if (bt_field_type_get_alignment(type_a) !=
5020 bt_field_type_get_alignment(type_b)) {
4e8304f7
PP
5021 BT_LOGV("Structure field types differ: different alignments: "
5022 "ft-a-align=%u, ft-b-align=%u",
50842bdc
PP
5023 bt_field_type_get_alignment(type_a),
5024 bt_field_type_get_alignment(type_b));
265e809c
PP
5025 goto end;
5026 }
5027
5028 /* Fields */
5029 if (struct_a->fields->len != struct_b->fields->len) {
4e8304f7
PP
5030 BT_LOGV("Structure field types differ: different field counts: "
5031 "ft-a-field-count=%u, ft-b-field-count=%u",
5032 struct_a->fields->len, struct_b->fields->len);
265e809c
PP
5033 goto end;
5034 }
5035
5036 for (i = 0; i < struct_a->fields->len; ++i) {
5037 struct structure_field *field_a =
5038 g_ptr_array_index(struct_a->fields, i);
5039 struct structure_field *field_b =
5040 g_ptr_array_index(struct_b->fields, i);
5041
5042 ret = compare_structure_fields(field_a, field_b);
5043 if (ret) {
4e8304f7
PP
5044 /* compare_structure_fields() logs what differs */
5045 BT_LOGV_STR("Structure field types differ: different fields.");
265e809c
PP
5046 goto end;
5047 }
265e809c
PP
5048 }
5049
5050 /* Equal */
5051 ret = 0;
5052
5053end:
5054 return ret;
5055}
5056
5057static
50842bdc
PP
5058int bt_field_type_variant_compare(struct bt_field_type *type_a,
5059 struct bt_field_type *type_b)
265e809c
PP
5060{
5061 int ret = 1;
5062 int i;
50842bdc
PP
5063 struct bt_field_type_variant *variant_a;
5064 struct bt_field_type_variant *variant_b;
265e809c
PP
5065
5066 variant_a = container_of(type_a,
50842bdc 5067 struct bt_field_type_variant, parent);
265e809c 5068 variant_b = container_of(type_b,
50842bdc 5069 struct bt_field_type_variant, parent);
265e809c
PP
5070
5071 /* Tag name */
5072 if (strcmp(variant_a->tag_name->str, variant_b->tag_name->str)) {
4e8304f7 5073 BT_LOGV("Variant field types differ: different tag field names: "
32e87ceb 5074 "ft-a-tag-field-name=\"%s\", ft-b-tag-field-name=\"%s\"",
4e8304f7 5075 variant_a->tag_name->str, variant_b->tag_name->str);
265e809c
PP
5076 goto end;
5077 }
5078
5079 /* Tag type */
50842bdc
PP
5080 ret = bt_field_type_compare(
5081 (struct bt_field_type *) variant_a->tag,
5082 (struct bt_field_type *) variant_b->tag);
265e809c 5083 if (ret) {
4e8304f7
PP
5084 BT_LOGV("Variant field types differ: different tag field types: "
5085 "ft-a-tag-ft-addr=%p, ft-b-tag-ft-addr=%p",
5086 variant_a->tag, variant_b->tag);
265e809c
PP
5087 goto end;
5088 }
5089
5090 ret = 1;
5091
5092 /* Fields */
5093 if (variant_a->fields->len != variant_b->fields->len) {
4e8304f7
PP
5094 BT_LOGV("Structure field types differ: different field counts: "
5095 "ft-a-field-count=%u, ft-b-field-count=%u",
5096 variant_a->fields->len, variant_b->fields->len);
265e809c
PP
5097 goto end;
5098 }
5099
5100 for (i = 0; i < variant_a->fields->len; ++i) {
5101 struct structure_field *field_a =
5102 g_ptr_array_index(variant_a->fields, i);
5103 struct structure_field *field_b =
5104 g_ptr_array_index(variant_b->fields, i);
5105
5106 ret = compare_structure_fields(field_a, field_b);
5107 if (ret) {
4e8304f7
PP
5108 /* compare_structure_fields() logs what differs */
5109 BT_LOGV_STR("Variant field types differ: different fields.");
265e809c
PP
5110 goto end;
5111 }
265e809c
PP
5112 }
5113
5114 /* Equal */
5115 ret = 0;
5116
5117end:
5118 return ret;
5119}
5120
5121static
50842bdc
PP
5122int bt_field_type_array_compare(struct bt_field_type *type_a,
5123 struct bt_field_type *type_b)
265e809c
PP
5124{
5125 int ret = 1;
50842bdc
PP
5126 struct bt_field_type_array *array_a;
5127 struct bt_field_type_array *array_b;
265e809c
PP
5128
5129 array_a = container_of(type_a,
50842bdc 5130 struct bt_field_type_array, parent);
265e809c 5131 array_b = container_of(type_b,
50842bdc 5132 struct bt_field_type_array, parent);
265e809c
PP
5133
5134 /* Length */
5135 if (array_a->length != array_b->length) {
4e8304f7
PP
5136 BT_LOGV("Structure field types differ: different lengths: "
5137 "ft-a-length=%u, ft-b-length=%u",
5138 array_a->length, array_b->length);
265e809c
PP
5139 goto end;
5140 }
5141
5142 /* Element type */
50842bdc 5143 ret = bt_field_type_compare(array_a->element_type,
265e809c 5144 array_b->element_type);
4e8304f7
PP
5145 if (ret == 1) {
5146 BT_LOGV("Array field types differ: different element field types: "
5147 "ft-a-element-ft-addr=%p, ft-b-element-ft-addr=%p",
5148 array_a->element_type, array_b->element_type);
5149 }
265e809c
PP
5150
5151end:
5152 return ret;
5153}
5154
5155static
50842bdc
PP
5156int bt_field_type_sequence_compare(struct bt_field_type *type_a,
5157 struct bt_field_type *type_b)
265e809c
PP
5158{
5159 int ret = -1;
50842bdc
PP
5160 struct bt_field_type_sequence *sequence_a;
5161 struct bt_field_type_sequence *sequence_b;
265e809c
PP
5162
5163 sequence_a = container_of(type_a,
50842bdc 5164 struct bt_field_type_sequence, parent);
265e809c 5165 sequence_b = container_of(type_b,
50842bdc 5166 struct bt_field_type_sequence, parent);
265e809c
PP
5167
5168 /* Length name */
5169 if (strcmp(sequence_a->length_field_name->str,
5170 sequence_b->length_field_name->str)) {
4e8304f7 5171 BT_LOGV("Sequence field types differ: different length field names: "
32e87ceb
PP
5172 "ft-a-length-field-name=\"%s\", "
5173 "ft-b-length-field-name=\"%s\"",
4e8304f7
PP
5174 sequence_a->length_field_name->str,
5175 sequence_b->length_field_name->str);
265e809c
PP
5176 goto end;
5177 }
5178
5179 /* Element type */
50842bdc 5180 ret = bt_field_type_compare(sequence_a->element_type,
265e809c 5181 sequence_b->element_type);
4e8304f7
PP
5182 if (ret == 1) {
5183 BT_LOGV("Sequence field types differ: different element field types: "
5184 "ft-a-element-ft-addr=%p, ft-b-element-ft-addr=%p",
5185 sequence_a->element_type, sequence_b->element_type);
5186 }
265e809c
PP
5187
5188end:
5189 return ret;
5190}
5191
50842bdc
PP
5192int bt_field_type_compare(struct bt_field_type *type_a,
5193 struct bt_field_type *type_b)
265e809c
PP
5194{
5195 int ret = 1;
5196
5197 if (type_a == type_b) {
5198 /* Same reference: equal (even if both are NULL) */
5199 ret = 0;
5200 goto end;
5201 }
5202
4e8304f7
PP
5203 if (!type_a) {
5204 BT_LOGW_STR("Invalid parameter: field type A is NULL.");
5205 ret = -1;
5206 goto end;
5207 }
5208
5209 if (!type_b) {
5210 BT_LOGW_STR("Invalid parameter: field type B is NULL.");
265e809c
PP
5211 ret = -1;
5212 goto end;
5213 }
5214
dc3fffef 5215 if (type_a->id != type_b->id) {
265e809c 5216 /* Different type IDs */
4e8304f7
PP
5217 BT_LOGV("Field types differ: different IDs: "
5218 "ft-a-addr=%p, ft-b-addr=%p, "
5219 "ft-a-id=%s, ft-b-id=%s",
5220 type_a, type_b,
50842bdc
PP
5221 bt_field_type_id_string(type_a->id),
5222 bt_field_type_id_string(type_b->id));
265e809c
PP
5223 goto end;
5224 }
5225
50842bdc 5226 if (type_a->id == BT_FIELD_TYPE_ID_UNKNOWN) {
265e809c 5227 /* Both have unknown type IDs */
4e8304f7 5228 BT_LOGW_STR("Invalid parameter: field type IDs are unknown.");
265e809c
PP
5229 goto end;
5230 }
5231
dc3fffef 5232 ret = type_compare_funcs[type_a->id](type_a, type_b);
4e8304f7
PP
5233 if (ret == 1) {
5234 BT_LOGV("Field types differ: ft-a-addr=%p, ft-b-addr=%p",
5235 type_a, type_b);
5236 }
265e809c
PP
5237
5238end:
5239 return ret;
5240}
09840de5
PP
5241
5242BT_HIDDEN
50842bdc 5243int64_t bt_field_type_get_field_count(struct bt_field_type *field_type)
09840de5 5244{
544d0515 5245 int64_t field_count = -1;
50842bdc 5246 enum bt_field_type_id type_id = bt_field_type_get_type_id(field_type);
09840de5
PP
5247
5248 switch (type_id) {
5249 case CTF_TYPE_STRUCT:
5250 field_count =
50842bdc 5251 bt_field_type_structure_get_field_count(field_type);
09840de5
PP
5252 break;
5253 case CTF_TYPE_VARIANT:
5254 field_count =
50842bdc 5255 bt_field_type_variant_get_field_count(field_type);
09840de5
PP
5256 break;
5257 case CTF_TYPE_ARRAY:
5258 case CTF_TYPE_SEQUENCE:
5259 /*
5260 * Array and sequence types always contain a single member
5261 * (the element type).
5262 */
5263 field_count = 1;
5264 break;
5265 default:
5266 break;
5267 }
5268
5269 return field_count;
5270}
5271
5272BT_HIDDEN
50842bdc
PP
5273struct bt_field_type *bt_field_type_get_field_at_index(
5274 struct bt_field_type *field_type, int index)
09840de5 5275{
50842bdc
PP
5276 struct bt_field_type *field = NULL;
5277 enum bt_field_type_id type_id = bt_field_type_get_type_id(field_type);
09840de5
PP
5278
5279 switch (type_id) {
5280 case CTF_TYPE_STRUCT:
aa15981c 5281 {
50842bdc 5282 int ret = bt_field_type_structure_get_field_by_index(
aa15981c
MD
5283 field_type, NULL, &field, index);
5284 if (ret) {
5285 field = NULL;
5286 goto end;
5287 }
09840de5 5288 break;
aa15981c 5289 }
09840de5 5290 case CTF_TYPE_VARIANT:
8f3a93d9 5291 {
50842bdc 5292 int ret = bt_field_type_variant_get_field_by_index(
9ac68eb1 5293 field_type, NULL, &field, index);
8f3a93d9
JG
5294 if (ret) {
5295 field = NULL;
5296 goto end;
5297 }
09840de5 5298 break;
8f3a93d9 5299 }
09840de5 5300 case CTF_TYPE_ARRAY:
50842bdc 5301 field = bt_field_type_array_get_element_type(field_type);
09840de5
PP
5302 break;
5303 case CTF_TYPE_SEQUENCE:
50842bdc 5304 field = bt_field_type_sequence_get_element_type(field_type);
09840de5
PP
5305 break;
5306 default:
5307 break;
5308 }
8f3a93d9 5309end:
09840de5
PP
5310 return field;
5311}
5312
5313BT_HIDDEN
50842bdc 5314int bt_field_type_get_field_index(struct bt_field_type *field_type,
09840de5
PP
5315 const char *name)
5316{
5317 int field_index = -1;
50842bdc 5318 enum bt_field_type_id type_id = bt_field_type_get_type_id(field_type);
09840de5
PP
5319
5320 switch (type_id) {
5321 case CTF_TYPE_STRUCT:
50842bdc 5322 field_index = bt_field_type_structure_get_field_name_index(
09840de5
PP
5323 field_type, name);
5324 break;
5325 case CTF_TYPE_VARIANT:
50842bdc 5326 field_index = bt_field_type_variant_get_field_name_index(
09840de5
PP
5327 field_type, name);
5328 break;
5329 default:
5330 break;
5331 }
5332
5333 return field_index;
5334}
b011f6b0 5335
50842bdc
PP
5336struct bt_field_path *bt_field_type_variant_get_tag_field_path(
5337 struct bt_field_type *type)
b011f6b0 5338{
50842bdc
PP
5339 struct bt_field_path *field_path = NULL;
5340 struct bt_field_type_variant *variant;
b011f6b0 5341
4e8304f7
PP
5342 if (!type) {
5343 BT_LOGW_STR("Invalid parameter: field type is NULL.");
5344 goto end;
5345 }
5346
50842bdc 5347 if (!bt_field_type_is_variant(type)) {
4e8304f7
PP
5348 BT_LOGW("Invalid parameter: field type is not a variant field type: "
5349 "addr=%p, ft-id=%s", type,
50842bdc 5350 bt_field_type_id_string(type->id));
b011f6b0
PP
5351 goto end;
5352 }
5353
50842bdc 5354 variant = container_of(type, struct bt_field_type_variant,
b011f6b0
PP
5355 parent);
5356 field_path = bt_get(variant->tag_field_path);
5357end:
5358 return field_path;
5359}
5360
50842bdc
PP
5361struct bt_field_path *bt_field_type_sequence_get_length_field_path(
5362 struct bt_field_type *type)
b011f6b0 5363{
50842bdc
PP
5364 struct bt_field_path *field_path = NULL;
5365 struct bt_field_type_sequence *sequence;
b011f6b0 5366
4e8304f7
PP
5367 if (!type) {
5368 BT_LOGW_STR("Invalid parameter: field type is NULL.");
5369 goto end;
5370 }
5371
50842bdc 5372 if (!bt_field_type_is_sequence(type)) {
4e8304f7
PP
5373 BT_LOGW("Invalid parameter: field type is not a sequence field type: "
5374 "addr=%p, ft-id=%s", type,
50842bdc 5375 bt_field_type_id_string(type->id));
b011f6b0
PP
5376 goto end;
5377 }
5378
50842bdc 5379 sequence = container_of(type, struct bt_field_type_sequence,
b011f6b0
PP
5380 parent);
5381 field_path = bt_get(sequence->length_field_path);
5382end:
5383 return field_path;
5384}
This page took 0.336764 seconds and 4 git commands to generate.