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