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