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