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