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