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