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