ctf-writer: fix linter defects
[babeltrace.git] / formats / ctf / writer / event-types.c
CommitLineData
273b65be
JG
1/*
2 * event-types.c
3 *
4 * Babeltrace CTF Writer
5 *
6 * Copyright 2013 EfficiOS Inc.
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
29#include <babeltrace/ctf-writer/event-types.h>
30#include <babeltrace/ctf-writer/event-types-internal.h>
31#include <babeltrace/ctf-writer/writer-internal.h>
32#include <babeltrace/compiler.h>
33#include <babeltrace/endian.h>
34#include <float.h>
35#include <inttypes.h>
36
37struct range_overlap_query {
38 int64_t range_start, range_end;
39 int overlaps;
40 GQuark mapping_name;
41};
42
43static
44void bt_ctf_field_type_integer_destroy(struct bt_ctf_ref *);
45static
46void bt_ctf_field_type_enumeration_destroy(struct bt_ctf_ref *);
47static
48void bt_ctf_field_type_floating_point_destroy(struct bt_ctf_ref *);
49static
50void bt_ctf_field_type_structure_destroy(struct bt_ctf_ref *);
51static
52void bt_ctf_field_type_variant_destroy(struct bt_ctf_ref *);
53static
54void bt_ctf_field_type_array_destroy(struct bt_ctf_ref *);
55static
56void bt_ctf_field_type_sequence_destroy(struct bt_ctf_ref *);
57static
58void bt_ctf_field_type_string_destroy(struct bt_ctf_ref *);
59
60static
61void (* const type_destroy_funcs[])(struct bt_ctf_ref *) = {
62 [CTF_TYPE_INTEGER] = bt_ctf_field_type_integer_destroy,
63 [CTF_TYPE_ENUM] =
64 bt_ctf_field_type_enumeration_destroy,
65 [CTF_TYPE_FLOAT] =
66 bt_ctf_field_type_floating_point_destroy,
67 [CTF_TYPE_STRUCT] = bt_ctf_field_type_structure_destroy,
68 [CTF_TYPE_VARIANT] = bt_ctf_field_type_variant_destroy,
69 [CTF_TYPE_ARRAY] = bt_ctf_field_type_array_destroy,
70 [CTF_TYPE_SEQUENCE] = bt_ctf_field_type_sequence_destroy,
71 [CTF_TYPE_STRING] = bt_ctf_field_type_string_destroy,
72};
73
74static
75void generic_field_type_freeze(struct bt_ctf_field_type *);
76static
77void bt_ctf_field_type_enumeration_freeze(struct bt_ctf_field_type *);
78static
79void bt_ctf_field_type_structure_freeze(struct bt_ctf_field_type *);
80static
81void bt_ctf_field_type_variant_freeze(struct bt_ctf_field_type *);
82static
83void bt_ctf_field_type_array_freeze(struct bt_ctf_field_type *);
84static
85void bt_ctf_field_type_sequence_freeze(struct bt_ctf_field_type *);
86
87static
88type_freeze_func const type_freeze_funcs[] = {
89 [CTF_TYPE_INTEGER] = generic_field_type_freeze,
90 [CTF_TYPE_ENUM] = bt_ctf_field_type_enumeration_freeze,
91 [CTF_TYPE_FLOAT] = generic_field_type_freeze,
92 [CTF_TYPE_STRUCT] = bt_ctf_field_type_structure_freeze,
93 [CTF_TYPE_VARIANT] = bt_ctf_field_type_variant_freeze,
94 [CTF_TYPE_ARRAY] = bt_ctf_field_type_array_freeze,
95 [CTF_TYPE_SEQUENCE] = bt_ctf_field_type_sequence_freeze,
96 [CTF_TYPE_STRING] = generic_field_type_freeze,
97};
98
99static
100int bt_ctf_field_type_integer_serialize(struct bt_ctf_field_type *,
101 struct metadata_context *);
102static
103int bt_ctf_field_type_enumeration_serialize(struct bt_ctf_field_type *,
104 struct metadata_context *);
105static
106int bt_ctf_field_type_floating_point_serialize(
107 struct bt_ctf_field_type *, struct metadata_context *);
108static
109int bt_ctf_field_type_structure_serialize(struct bt_ctf_field_type *,
110 struct metadata_context *);
111static
112int bt_ctf_field_type_variant_serialize(struct bt_ctf_field_type *,
113 struct metadata_context *);
114static
115int bt_ctf_field_type_array_serialize(struct bt_ctf_field_type *,
116 struct metadata_context *);
117static
118int bt_ctf_field_type_sequence_serialize(struct bt_ctf_field_type *,
119 struct metadata_context *);
120static
121int bt_ctf_field_type_string_serialize(struct bt_ctf_field_type *,
122 struct metadata_context *);
123
124static
125type_serialize_func const type_serialize_funcs[] = {
126 [CTF_TYPE_INTEGER] = bt_ctf_field_type_integer_serialize,
127 [CTF_TYPE_ENUM] =
128 bt_ctf_field_type_enumeration_serialize,
129 [CTF_TYPE_FLOAT] =
130 bt_ctf_field_type_floating_point_serialize,
131 [CTF_TYPE_STRUCT] =
132 bt_ctf_field_type_structure_serialize,
133 [CTF_TYPE_VARIANT] = bt_ctf_field_type_variant_serialize,
134 [CTF_TYPE_ARRAY] = bt_ctf_field_type_array_serialize,
135 [CTF_TYPE_SEQUENCE] = bt_ctf_field_type_sequence_serialize,
136 [CTF_TYPE_STRING] = bt_ctf_field_type_string_serialize,
137};
138
139static
140void bt_ctf_field_type_integer_set_byte_order(struct bt_ctf_field_type *,
141 int byte_order);
142static
143void bt_ctf_field_type_floating_point_set_byte_order(
144 struct bt_ctf_field_type *, int byte_order);
145
146static
147void (* const set_byte_order_funcs[])(struct bt_ctf_field_type *,
148 int) = {
149 [CTF_TYPE_INTEGER] =
150 bt_ctf_field_type_integer_set_byte_order,
151 [CTF_TYPE_FLOAT] =
152 bt_ctf_field_type_floating_point_set_byte_order,
153 [CTF_TYPE_ENUM ... CTF_TYPE_SEQUENCE] = NULL,
154};
155
156
157static
158void destroy_enumeration_mapping(struct enumeration_mapping *mapping)
159{
160 g_free(mapping);
161}
162
163static
164void destroy_structure_field(struct structure_field *field)
165{
166 if (field->type) {
167 bt_ctf_field_type_put(field->type);
168 }
169
170 g_free(field);
171}
172
173static
174void check_ranges_overlap(gpointer element, gpointer query)
175{
176 struct enumeration_mapping *mapping = element;
177 struct range_overlap_query *overlap_query = query;
178
179 if (mapping->range_start <= overlap_query->range_end
180 && overlap_query->range_start <= mapping->range_end) {
181 overlap_query->overlaps = 1;
182 overlap_query->mapping_name = mapping->string;
183 }
184
185 overlap_query->overlaps |=
186 mapping->string == overlap_query->mapping_name;
187}
188
189static
190void bt_ctf_field_type_init(struct bt_ctf_field_type *type)
191{
192 enum ctf_type_id type_id = type->declaration->id;
c4e511df 193 int ret;
273b65be
JG
194
195 assert(type && (type_id > CTF_TYPE_UNKNOWN) &&
196 (type_id < NR_CTF_TYPES));
197
198 bt_ctf_ref_init(&type->ref_count);
199 type->freeze = type_freeze_funcs[type_id];
200 type->serialize = type_serialize_funcs[type_id];
c4e511df
MD
201 ret = bt_ctf_field_type_set_byte_order(type, BT_CTF_BYTE_ORDER_NATIVE);
202 assert(!ret);
273b65be
JG
203 type->declaration->alignment = 1;
204}
205
206static
207int add_structure_field(GPtrArray *fields,
208 GHashTable *field_name_to_index,
209 struct bt_ctf_field_type *field_type,
210 const char *field_name)
211{
212 int ret = 0;
213 GQuark name_quark = g_quark_from_string(field_name);
214 struct structure_field *field;
215
216 /* Make sure structure does not contain a field of the same name */
217 if (g_hash_table_contains(field_name_to_index,
218 GUINT_TO_POINTER(name_quark))) {
219 ret = -1;
220 goto end;
221 }
222
223 field = g_new0(struct structure_field, 1);
224 if (!field) {
225 ret = -1;
226 goto end;
227 }
228
229 bt_ctf_field_type_get(field_type);
230 field->name = name_quark;
231 field->type = field_type;
232 g_hash_table_insert(field_name_to_index,
233 (gpointer) (unsigned long) name_quark,
234 (gpointer) (unsigned long) fields->len);
235 g_ptr_array_add(fields, field);
236 bt_ctf_field_type_freeze(field_type);
237end:
238 return ret;
239}
240
241struct bt_ctf_field_type *bt_ctf_field_type_integer_create(unsigned int size)
242{
243 struct bt_ctf_field_type_integer *integer =
244 g_new0(struct bt_ctf_field_type_integer, 1);
245
246 if (!integer || size > 64) {
247 return NULL;
248 }
249
250 integer->parent.declaration = &integer->declaration.p;
251 integer->parent.declaration->id = CTF_TYPE_INTEGER;
252 integer->declaration.len = size;
253 integer->declaration.base = BT_CTF_INTEGER_BASE_DECIMAL;
254 integer->declaration.encoding = CTF_STRING_NONE;
255 bt_ctf_field_type_init(&integer->parent);
256 return &integer->parent;
257}
258
259int bt_ctf_field_type_integer_set_signed(struct bt_ctf_field_type *type,
260 int is_signed)
261{
262 int ret = 0;
263 struct bt_ctf_field_type_integer *integer;
264
265 if (!type || type->frozen ||
266 type->declaration->id != CTF_TYPE_INTEGER) {
267 ret = -1;
268 goto end;
269 }
270
271 integer = container_of(type, struct bt_ctf_field_type_integer, parent);
272 if (is_signed && integer->declaration.len <= 1) {
273 ret = -1;
274 goto end;
275 }
276
277 integer->declaration.signedness = !!is_signed;
278end:
279 return ret;
280}
281
282int bt_ctf_field_type_integer_set_base(struct bt_ctf_field_type *type,
283 enum bt_ctf_integer_base base)
284{
285 int ret = 0;
286
287 if (!type || type->frozen ||
288 type->declaration->id != CTF_TYPE_INTEGER) {
289 ret = -1;
290 goto end;
291 }
292
293 switch (base) {
294 case BT_CTF_INTEGER_BASE_BINARY:
295 case BT_CTF_INTEGER_BASE_OCTAL:
296 case BT_CTF_INTEGER_BASE_DECIMAL:
297 case BT_CTF_INTEGER_BASE_HEXADECIMAL:
298 {
299 struct bt_ctf_field_type_integer *integer = container_of(type,
300 struct bt_ctf_field_type_integer, parent);
301 integer->declaration.base = base;
302 break;
303 }
304 default:
305 ret = -1;
306 }
307end:
308 return ret;
309}
310
311int bt_ctf_field_type_integer_set_encoding(struct bt_ctf_field_type *type,
312 enum ctf_string_encoding encoding)
313{
314 int ret = 0;
315 struct bt_ctf_field_type_integer *integer;
316
317 if (!type || type->frozen ||
318 (type->declaration->id != CTF_TYPE_INTEGER) ||
319 (encoding < CTF_STRING_NONE) ||
320 (encoding >= CTF_STRING_UNKNOWN)) {
321 ret = -1;
322 goto end;
323 }
324
325 integer = container_of(type, struct bt_ctf_field_type_integer, parent);
326 integer->declaration.encoding = encoding;
327end:
328 return ret;
329}
330
331struct bt_ctf_field_type *bt_ctf_field_type_enumeration_create(
332 struct bt_ctf_field_type *integer_container_type)
333{
334 struct bt_ctf_field_type_enumeration *enumeration = NULL;
335
336 if (!integer_container_type) {
337 goto error;
338 }
339
340 enumeration = g_new0(struct bt_ctf_field_type_enumeration, 1);
341 if (!enumeration) {
342 goto error;
343 }
344
345 enumeration->parent.declaration = &enumeration->declaration.p;
346 enumeration->parent.declaration->id = CTF_TYPE_ENUM;
347 bt_ctf_field_type_get(integer_container_type);
348 enumeration->container = integer_container_type;
349 enumeration->entries = g_ptr_array_new_with_free_func(
350 (GDestroyNotify)destroy_enumeration_mapping);
351 bt_ctf_field_type_init(&enumeration->parent);
352 return &enumeration->parent;
353error:
354 g_free(enumeration);
355 return NULL;
356}
357
358int bt_ctf_field_type_enumeration_add_mapping(
359 struct bt_ctf_field_type *type, const char *string,
360 int64_t range_start, int64_t range_end)
361{
362 int ret = 0;
363 GQuark mapping_name;
364 struct enumeration_mapping *mapping;
365 struct bt_ctf_field_type_enumeration *enumeration;
366 struct range_overlap_query query;
367
368 if (!type || (type->declaration->id != CTF_TYPE_ENUM) ||
369 type->frozen ||
370 (range_end < range_start)) {
371 ret = -1;
372 goto end;
373 }
374
375 if (validate_identifier(string)) {
376 ret = -1;
377 goto end;
378 }
379
380 mapping_name = g_quark_from_string(string);
381 query = (struct range_overlap_query) { .range_start = range_start,
382 .range_end = range_end,
383 .mapping_name = mapping_name,
384 .overlaps = 0 };
385 enumeration = container_of(type, struct bt_ctf_field_type_enumeration,
386 parent);
387
388 /* Check that the range does not overlap with one already present */
389 g_ptr_array_foreach(enumeration->entries, check_ranges_overlap, &query);
390 if (query.overlaps) {
391 ret = -1;
392 goto end;
393 }
394
395 mapping = g_new(struct enumeration_mapping, 1);
396 if (!mapping) {
397 ret = -1;
398 goto end;
399 }
400
401 *mapping = (struct enumeration_mapping) {.range_start = range_start,
402 .range_end = range_end, .string = mapping_name};
403 g_ptr_array_add(enumeration->entries, mapping);
404end:
405 return ret;
406}
407
408struct bt_ctf_field_type *bt_ctf_field_type_floating_point_create(void)
409{
410 struct bt_ctf_field_type_floating_point *floating_point =
411 g_new0(struct bt_ctf_field_type_floating_point, 1);
412
413 if (!floating_point) {
414 goto end;
415 }
416
417 floating_point->declaration.sign = &floating_point->sign;
418 floating_point->declaration.mantissa = &floating_point->mantissa;
419 floating_point->declaration.exp = &floating_point->exp;
420 floating_point->sign.len = 1;
421 floating_point->parent.declaration = &floating_point->declaration.p;
422 floating_point->parent.declaration->id = CTF_TYPE_FLOAT;
423 floating_point->declaration.exp->len =
424 sizeof(float) * CHAR_BIT - FLT_MANT_DIG;
425 floating_point->declaration.mantissa->len = FLT_MANT_DIG - 1;
426 floating_point->sign.p.alignment = 1;
427 floating_point->mantissa.p.alignment = 1;
428 floating_point->exp.p.alignment = 1;
429
430 bt_ctf_field_type_init(&floating_point->parent);
431end:
432 return floating_point ? &floating_point->parent : NULL;
433}
434
435int bt_ctf_field_type_floating_point_set_exponent_digits(
436 struct bt_ctf_field_type *type,
437 unsigned int exponent_digits)
438{
439 int ret = 0;
440 struct bt_ctf_field_type_floating_point *floating_point;
441
442 if (!type || type->frozen ||
443 (type->declaration->id != CTF_TYPE_FLOAT)) {
444 ret = -1;
445 goto end;
446 }
447
448 floating_point = container_of(type,
449 struct bt_ctf_field_type_floating_point, parent);
450 if ((exponent_digits != sizeof(float) * CHAR_BIT - FLT_MANT_DIG) &&
451 (exponent_digits != sizeof(double) * CHAR_BIT - DBL_MANT_DIG) &&
452 (exponent_digits !=
453 sizeof(long double) * CHAR_BIT - LDBL_MANT_DIG)) {
454 ret = -1;
455 goto end;
456 }
457
458 floating_point->declaration.exp->len = exponent_digits;
459end:
460 return ret;
461}
462
463int bt_ctf_field_type_floating_point_set_mantissa_digits(
464 struct bt_ctf_field_type *type,
465 unsigned int mantissa_digits)
466{
467 int ret = 0;
468 struct bt_ctf_field_type_floating_point *floating_point;
469
470 if (!type || type->frozen ||
471 (type->declaration->id != CTF_TYPE_FLOAT)) {
472 ret = -1;
473 goto end;
474 }
475
476 floating_point = container_of(type,
477 struct bt_ctf_field_type_floating_point, parent);
478
479 if ((mantissa_digits != FLT_MANT_DIG) &&
480 (mantissa_digits != DBL_MANT_DIG) &&
481 (mantissa_digits != LDBL_MANT_DIG)) {
482 ret = -1;
483 goto end;
484 }
485
486 floating_point->declaration.mantissa->len = mantissa_digits - 1;
487end:
488 return ret;
489}
490
491struct bt_ctf_field_type *bt_ctf_field_type_structure_create(void)
492{
493 struct bt_ctf_field_type_structure *structure =
494 g_new0(struct bt_ctf_field_type_structure, 1);
495
496 if (!structure) {
497 goto error;
498 }
499
500 structure->parent.declaration = &structure->declaration.p;
501 structure->parent.declaration->id = CTF_TYPE_STRUCT;
502 bt_ctf_field_type_init(&structure->parent);
503 structure->fields = g_ptr_array_new_with_free_func(
504 (GDestroyNotify)destroy_structure_field);
505 structure->field_name_to_index = g_hash_table_new(NULL, NULL);
506 return &structure->parent;
507error:
508 return NULL;
509}
510
511int bt_ctf_field_type_structure_add_field(struct bt_ctf_field_type *type,
512 struct bt_ctf_field_type *field_type,
513 const char *field_name)
514{
515 int ret = 0;
516 struct bt_ctf_field_type_structure *structure;
517
518 if (!type || !field_type || type->frozen ||
519 validate_identifier(field_name) ||
520 (type->declaration->id != CTF_TYPE_STRUCT)) {
521 goto end;
522 }
523
524 structure = container_of(type,
525 struct bt_ctf_field_type_structure, parent);
526 if (add_structure_field(structure->fields,
527 structure->field_name_to_index, field_type, field_name)) {
528 ret = -1;
529 goto end;
530 }
531
532 if (type->declaration->alignment < field_type->declaration->alignment) {
533 type->declaration->alignment =
534 field_type->declaration->alignment;
535 }
536end:
537 return ret;
538}
539
540struct bt_ctf_field_type *bt_ctf_field_type_variant_create(
541 struct bt_ctf_field_type *enum_tag, const char *tag_name)
542{
543 struct bt_ctf_field_type_variant *variant = NULL;
544
545 if (!enum_tag || validate_identifier(tag_name) ||
546 (enum_tag->declaration->id != CTF_TYPE_ENUM)) {
547 goto error;
548 }
549
550 variant = g_new0(struct bt_ctf_field_type_variant, 1);
551 if (!variant) {
552 goto error;
553 }
554
555 variant->parent.declaration = &variant->declaration.p;
556 variant->parent.declaration->id = CTF_TYPE_VARIANT;
557 variant->tag_name = g_string_new(tag_name);
558 bt_ctf_field_type_init(&variant->parent);
559 variant->field_name_to_index = g_hash_table_new(NULL, NULL);
560 variant->fields = g_ptr_array_new_with_free_func(
561 (GDestroyNotify)destroy_structure_field);
562 bt_ctf_field_type_get(enum_tag);
563 variant->tag = container_of(enum_tag,
564 struct bt_ctf_field_type_enumeration, parent);
565 return &variant->parent;
566error:
567 return NULL;
568}
569
570int bt_ctf_field_type_variant_add_field(struct bt_ctf_field_type *type,
571 struct bt_ctf_field_type *field_type,
572 const char *field_name)
573{
574 size_t i;
575 int ret = 0;
576 int name_found = 0;
577 struct bt_ctf_field_type_variant *variant;
578 GQuark field_name_quark = g_quark_from_string(field_name);
579
580 if (!type || !field_type || type->frozen ||
581 validate_identifier(field_name) ||
582 (type->declaration->id != CTF_TYPE_VARIANT)) {
583 ret = -1;
584 goto end;
585 }
586
587 variant = container_of(type, struct bt_ctf_field_type_variant, parent);
588 /* Make sure this name is present in the enum tag */
589 for (i = 0; i < variant->tag->entries->len; i++) {
590 struct enumeration_mapping *mapping =
591 g_ptr_array_index(variant->tag->entries, i);
592
593 if (mapping->string == field_name_quark) {
594 name_found = 1;
595 break;
596 }
597 }
598
599 if (!name_found || add_structure_field(variant->fields,
600 variant->field_name_to_index, field_type, field_name)) {
601 ret = -1;
602 goto end;
603 }
604end:
605 return ret;
606}
607
608struct bt_ctf_field_type *bt_ctf_field_type_array_create(
609 struct bt_ctf_field_type *element_type,
610 unsigned int length)
611{
612 struct bt_ctf_field_type_array *array = NULL;
613
614 if (!element_type || length == 0) {
615 goto error;
616 }
617
618 array = g_new0(struct bt_ctf_field_type_array, 1);
619 if (!array) {
620 goto error;
621 }
622
623 array->parent.declaration = &array->declaration.p;
624 array->parent.declaration->id = CTF_TYPE_ARRAY;
625 bt_ctf_field_type_init(&array->parent);
626 bt_ctf_field_type_get(element_type);
627 array->element_type = element_type;
628 array->length = length;
629 array->parent.declaration->alignment =
630 element_type->declaration->alignment;
631 return &array->parent;
632error:
633 return NULL;
634}
635
636struct bt_ctf_field_type *bt_ctf_field_type_sequence_create(
637 struct bt_ctf_field_type *element_type,
638 const char *length_field_name)
639{
640 struct bt_ctf_field_type_sequence *sequence = NULL;
641
642 if (!element_type || validate_identifier(length_field_name)) {
643 goto error;
644 }
645
646 sequence = g_new0(struct bt_ctf_field_type_sequence, 1);
647 if (!sequence) {
648 goto error;
649 }
650
651 sequence->parent.declaration = &sequence->declaration.p;
652 sequence->parent.declaration->id = CTF_TYPE_SEQUENCE;
653 bt_ctf_field_type_init(&sequence->parent);
654 bt_ctf_field_type_get(element_type);
655 sequence->element_type = element_type;
656 sequence->length_field_name = g_string_new(length_field_name);
657 sequence->parent.declaration->alignment =
658 element_type->declaration->alignment;
659 return &sequence->parent;
660error:
661 return NULL;
662}
663
664struct bt_ctf_field_type *bt_ctf_field_type_string_create(void)
665{
666 struct bt_ctf_field_type_string *string =
667 g_new0(struct bt_ctf_field_type_string, 1);
668
669 if (!string) {
670 return NULL;
671 }
672
673 string->parent.declaration = &string->declaration.p;
674 string->parent.declaration->id = CTF_TYPE_STRING;
675 bt_ctf_field_type_init(&string->parent);
676 string->declaration.encoding = CTF_STRING_UTF8;
677 string->parent.declaration->alignment = CHAR_BIT;
678 return &string->parent;
679}
680
681int bt_ctf_field_type_string_set_encoding(
682 struct bt_ctf_field_type *type,
683 enum ctf_string_encoding encoding)
684{
685 int ret = 0;
686 struct bt_ctf_field_type_string *string;
687
688 if (!type || type->declaration->id != CTF_TYPE_STRING ||
689 (encoding != CTF_STRING_UTF8 &&
690 encoding != CTF_STRING_ASCII)) {
691 ret = -1;
692 goto end;
693 }
694
695 string = container_of(type, struct bt_ctf_field_type_string, parent);
696 string->declaration.encoding = encoding;
697end:
698 return ret;
699}
700
701int bt_ctf_field_type_set_alignment(struct bt_ctf_field_type *type,
702 unsigned int alignment)
703{
704 int ret = 0;
705
706 /* Alignment must be bit-aligned (1) or byte aligned */
707 if (!type || type->frozen || (alignment != 1 && (alignment & 0x7))) {
708 ret = -1;
709 goto end;
710 }
711
712 if (type->declaration->id == CTF_TYPE_STRING &&
713 alignment != CHAR_BIT) {
714 ret = -1;
715 goto end;
716 }
717
718 type->declaration->alignment = alignment;
719 ret = 0;
720end:
721 return ret;
722}
723
724int bt_ctf_field_type_set_byte_order(struct bt_ctf_field_type *type,
725 enum bt_ctf_byte_order byte_order)
726{
727 int ret = 0;
728 int internal_byte_order;
729 enum ctf_type_id type_id;
730
731 if (!type || type->frozen) {
732 ret = -1;
733 goto end;
734 }
735
736 type_id = type->declaration->id;
737 switch (byte_order) {
738 case BT_CTF_BYTE_ORDER_NATIVE:
739 internal_byte_order = (G_BYTE_ORDER == G_LITTLE_ENDIAN ?
740 LITTLE_ENDIAN : BIG_ENDIAN);
741 break;
742 case BT_CTF_BYTE_ORDER_LITTLE_ENDIAN:
743 internal_byte_order = LITTLE_ENDIAN;
744 break;
745 case BT_CTF_BYTE_ORDER_BIG_ENDIAN:
746 case BT_CTF_BYTE_ORDER_NETWORK:
747 internal_byte_order = BIG_ENDIAN;
748 break;
749 default:
750 ret = -1;
751 goto end;
752 }
753
754 if (set_byte_order_funcs[type_id]) {
755 set_byte_order_funcs[type_id](type, internal_byte_order);
756 }
757end:
758 return ret;
759}
760
761void bt_ctf_field_type_get(struct bt_ctf_field_type *type)
762{
763 if (!type) {
764 return;
765 }
766
767 bt_ctf_ref_get(&type->ref_count);
768}
769
770void bt_ctf_field_type_put(struct bt_ctf_field_type *type)
771{
772 enum ctf_type_id type_id;
773
774 if (!type) {
775 return;
776 }
777
778 type_id = type->declaration->id;
779 assert(type_id > CTF_TYPE_UNKNOWN && type_id < NR_CTF_TYPES);
780 bt_ctf_ref_put(&type->ref_count, type_destroy_funcs[type_id]);
781}
782
783BT_HIDDEN
784void bt_ctf_field_type_freeze(struct bt_ctf_field_type *type)
785{
786 if (!type) {
787 return;
788 }
789
790 type->freeze(type);
791}
792
793BT_HIDDEN
794enum ctf_type_id bt_ctf_field_type_get_type_id(
795 struct bt_ctf_field_type *type)
796{
797 if (!type) {
798 return CTF_TYPE_UNKNOWN;
799 }
800
801 return type->declaration->id;
802}
803
804BT_HIDDEN
805struct bt_ctf_field_type *bt_ctf_field_type_structure_get_type(
806 struct bt_ctf_field_type_structure *structure,
807 const char *name)
808{
809 struct bt_ctf_field_type *type = NULL;
810 struct structure_field *field;
811 GQuark name_quark = g_quark_try_string(name);
812 size_t index;
813
814 if (!name_quark) {
815 goto end;
816 }
817
818 if (!g_hash_table_lookup_extended(structure->field_name_to_index,
819 GUINT_TO_POINTER(name_quark), NULL, (gpointer *)&index)) {
820 goto end;
821 }
822
823 field = structure->fields->pdata[index];
824 type = field->type;
825end:
826 return type;
827}
828
829BT_HIDDEN
830struct bt_ctf_field_type *bt_ctf_field_type_array_get_element_type(
831 struct bt_ctf_field_type_array *array)
832{
833 assert(array);
834 return array->element_type;
835}
836
837BT_HIDDEN
838struct bt_ctf_field_type *bt_ctf_field_type_sequence_get_element_type(
839 struct bt_ctf_field_type_sequence *sequence)
840{
841 assert(sequence);
842 return sequence->element_type;
843}
844
845BT_HIDDEN
846struct bt_ctf_field_type *bt_ctf_field_type_variant_get_field_type(
847 struct bt_ctf_field_type_variant *variant,
848 int64_t tag_value)
849{
850 struct bt_ctf_field_type *type = NULL;
851 GQuark field_name_quark;
852 gpointer index;
853 struct structure_field *field_entry;
854 struct range_overlap_query query = {.range_start = tag_value,
855 .range_end = tag_value, .mapping_name = 0, .overlaps = 0};
856
857 g_ptr_array_foreach(variant->tag->entries, check_ranges_overlap,
858 &query);
859 if (!query.overlaps) {
860 goto end;
861 }
862
863 field_name_quark = query.mapping_name;
864 if (!g_hash_table_lookup_extended(variant->field_name_to_index,
865 GUINT_TO_POINTER(field_name_quark), NULL, &index)) {
866 goto end;
867 }
868
869 field_entry = g_ptr_array_index(variant->fields, (size_t)index);
870 type = field_entry->type;
871end:
872 return type;
873}
874
875BT_HIDDEN
876int bt_ctf_field_type_serialize(struct bt_ctf_field_type *type,
877 struct metadata_context *context)
878{
879 int ret;
880
881 if (!type || !context) {
882 ret = -1;
883 goto end;
884 }
885
886 ret = type->serialize(type, context);
887end:
888 return ret;
889}
890
891static
892void bt_ctf_field_type_integer_destroy(struct bt_ctf_ref *ref)
893{
894 struct bt_ctf_field_type_integer *integer;
895
896 if (!ref) {
897 return;
898 }
899
900 integer = container_of(
901 container_of(ref, struct bt_ctf_field_type, ref_count),
902 struct bt_ctf_field_type_integer, parent);
903 g_free(integer);
904}
905
906static
907void bt_ctf_field_type_enumeration_destroy(struct bt_ctf_ref *ref)
908{
909 struct bt_ctf_field_type_enumeration *enumeration;
910
911 if (!ref) {
912 return;
913 }
914
915 enumeration = container_of(
916 container_of(ref, struct bt_ctf_field_type, ref_count),
917 struct bt_ctf_field_type_enumeration, parent);
918 g_ptr_array_free(enumeration->entries, TRUE);
919 bt_ctf_field_type_put(enumeration->container);
920 g_free(enumeration);
921}
922
923static
924void bt_ctf_field_type_floating_point_destroy(struct bt_ctf_ref *ref)
925{
926 struct bt_ctf_field_type_floating_point *floating_point;
927
928 if (!ref) {
929 return;
930 }
931
932 floating_point = container_of(
933 container_of(ref, struct bt_ctf_field_type, ref_count),
934 struct bt_ctf_field_type_floating_point, parent);
935 g_free(floating_point);
936}
937
938static
939void bt_ctf_field_type_structure_destroy(struct bt_ctf_ref *ref)
940{
941 struct bt_ctf_field_type_structure *structure;
942
943 if (!ref) {
944 return;
945 }
946
947 structure = container_of(
948 container_of(ref, struct bt_ctf_field_type, ref_count),
949 struct bt_ctf_field_type_structure, parent);
950 g_ptr_array_free(structure->fields, TRUE);
951 g_hash_table_destroy(structure->field_name_to_index);
952 g_free(structure);
953}
954
955static
956void bt_ctf_field_type_variant_destroy(struct bt_ctf_ref *ref)
957{
958 struct bt_ctf_field_type_variant *variant;
959
960 if (!ref) {
961 return;
962 }
963
964 variant = container_of(
965 container_of(ref, struct bt_ctf_field_type, ref_count),
966 struct bt_ctf_field_type_variant, parent);
967 g_ptr_array_free(variant->fields, TRUE);
968 g_hash_table_destroy(variant->field_name_to_index);
969 g_string_free(variant->tag_name, TRUE);
970 bt_ctf_field_type_put(&variant->tag->parent);
971 g_free(variant);
972}
973
974static
975void bt_ctf_field_type_array_destroy(struct bt_ctf_ref *ref)
976{
977 struct bt_ctf_field_type_array *array;
978
979 if (!ref) {
980 return;
981 }
982
983 array = container_of(
984 container_of(ref, struct bt_ctf_field_type, ref_count),
985 struct bt_ctf_field_type_array, parent);
986 bt_ctf_field_type_put(array->element_type);
987 g_free(array);
988}
989
990static
991void bt_ctf_field_type_sequence_destroy(struct bt_ctf_ref *ref)
992{
993 struct bt_ctf_field_type_sequence *sequence;
994
995 if (!ref) {
996 return;
997 }
998
999 sequence = container_of(
1000 container_of(ref, struct bt_ctf_field_type, ref_count),
1001 struct bt_ctf_field_type_sequence, parent);
1002 bt_ctf_field_type_put(sequence->element_type);
1003 g_string_free(sequence->length_field_name, TRUE);
1004 g_free(sequence);
1005}
1006
1007static
1008void bt_ctf_field_type_string_destroy(struct bt_ctf_ref *ref)
1009{
1010 struct bt_ctf_field_type_string *string;
1011
1012 if (!ref) {
1013 return;
1014 }
1015
1016 string = container_of(
1017 container_of(ref, struct bt_ctf_field_type, ref_count),
1018 struct bt_ctf_field_type_string, parent);
1019 g_free(string);
1020}
1021
1022static
1023void generic_field_type_freeze(struct bt_ctf_field_type *type)
1024{
1025 type->frozen = 1;
1026}
1027
1028static
1029void bt_ctf_field_type_enumeration_freeze(struct bt_ctf_field_type *type)
1030{
1031 struct bt_ctf_field_type_enumeration *enumeration_type = container_of(
1032 type, struct bt_ctf_field_type_enumeration, parent);
1033
1034 generic_field_type_freeze(type);
1035 bt_ctf_field_type_freeze(enumeration_type->container);
1036}
1037
1038static
1039void freeze_structure_field(struct structure_field *field)
1040{
1041 bt_ctf_field_type_freeze(field->type);
1042}
1043
1044static
1045void bt_ctf_field_type_structure_freeze(struct bt_ctf_field_type *type)
1046{
1047 struct bt_ctf_field_type_structure *structure_type = container_of(
1048 type, struct bt_ctf_field_type_structure, parent);
1049
1050 generic_field_type_freeze(type);
1051 g_ptr_array_foreach(structure_type->fields, (GFunc)freeze_structure_field,
1052 NULL);
1053}
1054
1055static
1056void bt_ctf_field_type_variant_freeze(struct bt_ctf_field_type *type)
1057{
1058 struct bt_ctf_field_type_variant *variant_type = container_of(
1059 type, struct bt_ctf_field_type_variant, parent);
1060
1061 generic_field_type_freeze(type);
1062 g_ptr_array_foreach(variant_type->fields, (GFunc)freeze_structure_field,
1063 NULL);
1064}
1065
1066static
1067void bt_ctf_field_type_array_freeze(struct bt_ctf_field_type *type)
1068{
1069 struct bt_ctf_field_type_array *array_type = container_of(
1070 type, struct bt_ctf_field_type_array, parent);
1071
1072 generic_field_type_freeze(type);
1073 bt_ctf_field_type_freeze(array_type->element_type);
1074}
1075
1076static
1077void bt_ctf_field_type_sequence_freeze(struct bt_ctf_field_type *type)
1078{
1079 struct bt_ctf_field_type_sequence *sequence_type = container_of(
1080 type, struct bt_ctf_field_type_sequence, parent);
1081
1082 generic_field_type_freeze(type);
1083 bt_ctf_field_type_freeze(sequence_type->element_type);
1084}
1085
1086static
1087const char *get_encoding_string(enum ctf_string_encoding encoding)
1088{
1089 const char *encoding_string;
1090
1091 switch (encoding) {
1092 case CTF_STRING_NONE:
1093 encoding_string = "none";
1094 break;
1095 case CTF_STRING_ASCII:
1096 encoding_string = "ASCII";
1097 break;
1098 case CTF_STRING_UTF8:
1099 encoding_string = "UTF8";
1100 break;
1101 default:
1102 encoding_string = "unknown";
1103 break;
1104 }
1105
1106 return encoding_string;
1107}
1108
1109static
1110const char *get_integer_base_string(enum bt_ctf_integer_base base)
1111{
1112 const char *base_string;
1113
1114 switch (base) {
1115 case BT_CTF_INTEGER_BASE_DECIMAL:
1116 base_string = "decimal";
1117 break;
1118 case BT_CTF_INTEGER_BASE_HEXADECIMAL:
1119 base_string = "hexadecimal";
1120 break;
1121 case BT_CTF_INTEGER_BASE_OCTAL:
1122 base_string = "octal";
1123 break;
1124 case BT_CTF_INTEGER_BASE_BINARY:
1125 base_string = "binary";
1126 break;
1127 default:
1128 base_string = "unknown";
1129 break;
1130 }
1131
1132 return base_string;
1133}
1134
1135static
1136int bt_ctf_field_type_integer_serialize(struct bt_ctf_field_type *type,
1137 struct metadata_context *context)
1138{
1139 struct bt_ctf_field_type_integer *integer = container_of(type,
1140 struct bt_ctf_field_type_integer, parent);
1141
1142 g_string_append_printf(context->string,
1143 "integer { size = %zu; align = %zu; signed = %s; encoding = %s; base = %s; byte_order = %s; }",
1144 integer->declaration.len, type->declaration->alignment,
1145 (integer->declaration.signedness ? "true" : "false"),
1146 get_encoding_string(integer->declaration.encoding),
1147 get_integer_base_string(integer->declaration.base),
1148 get_byte_order_string(integer->declaration.byte_order));
1149 return 0;
1150}
1151
1152static
1153int bt_ctf_field_type_enumeration_serialize(struct bt_ctf_field_type *type,
1154 struct metadata_context *context)
1155{
1156 size_t entry;
1157 int ret = 0;
1158 struct bt_ctf_field_type_enumeration *enumeration = container_of(type,
1159 struct bt_ctf_field_type_enumeration, parent);
1160
1161 g_string_append(context->string, "enum : ");
1162 ret = bt_ctf_field_type_serialize(enumeration->container, context);
1163 if (ret) {
1164 goto end;
1165 }
1166
1167 g_string_append(context->string, " { ");
1168 for (entry = 0; entry < enumeration->entries->len; entry++) {
1169 struct enumeration_mapping *mapping =
1170 enumeration->entries->pdata[entry];
1171
1172 if (mapping->range_start == mapping->range_end) {
1173 g_string_append_printf(context->string, "%s = %" PRId64,
1174 g_quark_to_string(mapping->string),
1175 mapping->range_start);
1176 } else {
1177 g_string_append_printf(context->string,
1178 "%s = %" PRId64 " ... %" PRId64,
1179 g_quark_to_string(mapping->string),
1180 mapping->range_start, mapping->range_end);
1181 }
1182
1183 g_string_append(context->string,
1184 ((entry != (enumeration->entries->len - 1)) ?
1185 ", " : " }"));
1186 }
1187
1188 if (context->field_name->len) {
1189 g_string_append_printf(context->string, " %s",
1190 context->field_name->str);
1191 g_string_assign(context->field_name, "");
1192 }
1193end:
1194 return ret;
1195}
1196
1197static
1198int bt_ctf_field_type_floating_point_serialize(struct bt_ctf_field_type *type,
1199 struct metadata_context *context)
1200{
1201 struct bt_ctf_field_type_floating_point *floating_point = container_of(
1202 type, struct bt_ctf_field_type_floating_point, parent);
1203
1204 g_string_append_printf(context->string,
1205 "floating_point { exp_dig = %zu; mant_dig = %zu; byte_order = %s; align = %zu; }",
1206 floating_point->declaration.exp->len,
1207 floating_point->declaration.mantissa->len + 1,
1208 get_byte_order_string(floating_point->declaration.byte_order),
1209 type->declaration->alignment);
1210 return 0;
1211}
1212
1213static
1214int bt_ctf_field_type_structure_serialize(struct bt_ctf_field_type *type,
1215 struct metadata_context *context)
1216{
1217 size_t i;
1218 unsigned int indent;
1219 int ret = 0;
1220 struct bt_ctf_field_type_structure *structure = container_of(type,
1221 struct bt_ctf_field_type_structure, parent);
1222 GString *structure_field_name = context->field_name;
1223
1224 context->field_name = g_string_new("");
1225
1226 context->current_indentation_level++;
1227 g_string_append(context->string, "struct {\n");
1228
1229 for (i = 0; i < structure->fields->len; i++) {
1230 struct structure_field *field;
1231
1232 for (indent = 0; indent < context->current_indentation_level;
1233 indent++) {
1234 g_string_append_c(context->string, '\t');
1235 }
1236
1237 field = structure->fields->pdata[i];
1238 g_string_assign(context->field_name,
1239 g_quark_to_string(field->name));
1240 ret = bt_ctf_field_type_serialize(field->type, context);
1241 if (ret) {
1242 goto end;
1243 }
1244
1245 if (context->field_name->len) {
1246 g_string_append_printf(context->string, " %s",
1247 context->field_name->str);
1248 }
1249 g_string_append(context->string, ";\n");
1250 }
1251
1252 context->current_indentation_level--;
1253 for (indent = 0; indent < context->current_indentation_level;
1254 indent++) {
1255 g_string_append_c(context->string, '\t');
1256 }
1257
1258 g_string_append_printf(context->string, "} align(%zu)",
1259 type->declaration->alignment);
1260end:
1261 g_string_free(context->field_name, TRUE);
1262 context->field_name = structure_field_name;
1263 return ret;
1264}
1265
1266static
1267int bt_ctf_field_type_variant_serialize(struct bt_ctf_field_type *type,
1268 struct metadata_context *context)
1269{
1270 size_t i;
1271 unsigned int indent;
1272 int ret = 0;
1273 struct bt_ctf_field_type_variant *variant = container_of(
1274 type, struct bt_ctf_field_type_variant, parent);
1275 GString *variant_field_name = context->field_name;
1276
1277 context->field_name = g_string_new("");
1278 g_string_append_printf(context->string,
1279 "variant <%s> {\n", variant->tag_name->str);
1280 context->current_indentation_level++;
1281 for (i = 0; i < variant->fields->len; i++) {
1282 struct structure_field *field = variant->fields->pdata[i];
1283
1284 g_string_assign(context->field_name,
1285 g_quark_to_string(field->name));
1286 for (indent = 0; indent < context->current_indentation_level;
1287 indent++) {
1288 g_string_append_c(context->string, '\t');
1289 }
1290
1291 g_string_assign(context->field_name,
1292 g_quark_to_string(field->name));
1293 ret = bt_ctf_field_type_serialize(field->type, context);
1294 if (ret) {
1295 goto end;
1296 }
1297
1298 if (context->field_name->len) {
1299 g_string_append_printf(context->string, " %s;",
1300 context->field_name->str);
1301 }
1302
1303 g_string_append_c(context->string, '\n');
1304 }
1305
1306 context->current_indentation_level--;
1307 for (indent = 0; indent < context->current_indentation_level;
1308 indent++) {
1309 g_string_append_c(context->string, '\t');
1310 }
1311
1312 g_string_append(context->string, "}");
1313end:
1314 g_string_free(context->field_name, TRUE);
1315 context->field_name = variant_field_name;
1316 return ret;
1317}
1318
1319static
1320int bt_ctf_field_type_array_serialize(struct bt_ctf_field_type *type,
1321 struct metadata_context *context)
1322{
1323 int ret = 0;
1324 struct bt_ctf_field_type_array *array = container_of(type,
1325 struct bt_ctf_field_type_array, parent);
1326
1327 ret = bt_ctf_field_type_serialize(array->element_type, context);
1328 if (ret) {
1329 goto end;
1330 }
1331
1332 if (context->field_name->len) {
1333 g_string_append_printf(context->string, " %s[%u]",
1334 context->field_name->str, array->length);
1335 g_string_assign(context->field_name, "");
1336 } else {
1337 g_string_append_printf(context->string, "[%u]", array->length);
1338 }
1339end:
1340 return ret;
1341}
1342
1343static
1344int bt_ctf_field_type_sequence_serialize(struct bt_ctf_field_type *type,
1345 struct metadata_context *context)
1346{
1347 int ret = 0;
1348 struct bt_ctf_field_type_sequence *sequence = container_of(
1349 type, struct bt_ctf_field_type_sequence, parent);
1350
1351 ret = bt_ctf_field_type_serialize(sequence->element_type, context);
1352 if (ret) {
1353 goto end;
1354 }
1355
1356 if (context->field_name->len) {
1357 g_string_append_printf(context->string, " %s[%s]",
1358 context->field_name->str,
1359 sequence->length_field_name->str);
1360 g_string_assign(context->field_name, "");
1361 } else {
1362 g_string_append_printf(context->string, "[%s]",
1363 sequence->length_field_name->str);
1364 }
1365end:
1366 return ret;
1367}
1368
1369static
1370int bt_ctf_field_type_string_serialize(struct bt_ctf_field_type *type,
1371 struct metadata_context *context)
1372{
1373 struct bt_ctf_field_type_string *string = container_of(
1374 type, struct bt_ctf_field_type_string, parent);
1375
1376 g_string_append_printf(context->string,
1377 "string { encoding = %s; }",
1378 get_encoding_string(string->declaration.encoding));
1379 return 0;
1380}
1381
1382static
1383void bt_ctf_field_type_integer_set_byte_order(struct bt_ctf_field_type *type,
1384 int byte_order)
1385{
1386 struct bt_ctf_field_type_integer *integer_type = container_of(type,
1387 struct bt_ctf_field_type_integer, parent);
1388
1389 integer_type->declaration.byte_order = byte_order;
1390}
1391
1392static
1393void bt_ctf_field_type_floating_point_set_byte_order(
1394 struct bt_ctf_field_type *type, int byte_order)
1395{
1396 struct bt_ctf_field_type_floating_point *floating_point_type =
1397 container_of(type, struct bt_ctf_field_type_floating_point,
1398 parent);
1399
1400 floating_point_type->declaration.byte_order = byte_order;
1401 floating_point_type->sign.byte_order = byte_order;
1402 floating_point_type->mantissa.byte_order = byte_order;
1403 floating_point_type->exp.byte_order = byte_order;
1404}
This page took 0.071927 seconds and 4 git commands to generate.