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