Implement CTF-IR event fields getters
[babeltrace.git] / formats / ctf / ir / event-fields.c
CommitLineData
273b65be
JG
1/*
2 * event-fields.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-fields.h>
adc315b8
JG
30#include <babeltrace/ctf-ir/event-fields-internal.h>
31#include <babeltrace/ctf-ir/event-types-internal.h>
273b65be
JG
32#include <babeltrace/compiler.h>
33
34#define PACKET_LEN_INCREMENT (getpagesize() * 8 * CHAR_BIT)
35
36static
37struct bt_ctf_field *bt_ctf_field_integer_create(struct bt_ctf_field_type *);
38static
39struct bt_ctf_field *bt_ctf_field_enumeration_create(
40 struct bt_ctf_field_type *);
41static
42struct bt_ctf_field *bt_ctf_field_floating_point_create(
43 struct bt_ctf_field_type *);
44static
45struct bt_ctf_field *bt_ctf_field_structure_create(
46 struct bt_ctf_field_type *);
47static
48struct bt_ctf_field *bt_ctf_field_variant_create(
49 struct bt_ctf_field_type *);
50static
51struct bt_ctf_field *bt_ctf_field_array_create(
52 struct bt_ctf_field_type *);
53static
54struct bt_ctf_field *bt_ctf_field_sequence_create(
55 struct bt_ctf_field_type *);
56static
57struct bt_ctf_field *bt_ctf_field_string_create(struct bt_ctf_field_type *);
58
59static
60void bt_ctf_field_destroy(struct bt_ctf_ref *);
61static
62void bt_ctf_field_integer_destroy(struct bt_ctf_field *);
63static
64void bt_ctf_field_enumeration_destroy(struct bt_ctf_field *);
65static
66void bt_ctf_field_floating_point_destroy(struct bt_ctf_field *);
67static
68void bt_ctf_field_structure_destroy(struct bt_ctf_field *);
69static
70void bt_ctf_field_variant_destroy(struct bt_ctf_field *);
71static
72void bt_ctf_field_array_destroy(struct bt_ctf_field *);
73static
74void bt_ctf_field_sequence_destroy(struct bt_ctf_field *);
75static
76void bt_ctf_field_string_destroy(struct bt_ctf_field *);
77
78static
79int bt_ctf_field_generic_validate(struct bt_ctf_field *field);
80static
81int bt_ctf_field_structure_validate(struct bt_ctf_field *field);
82static
83int bt_ctf_field_variant_validate(struct bt_ctf_field *field);
84static
85int bt_ctf_field_enumeration_validate(struct bt_ctf_field *field);
86static
87int bt_ctf_field_array_validate(struct bt_ctf_field *field);
88static
89int bt_ctf_field_sequence_validate(struct bt_ctf_field *field);
90
91static
92int bt_ctf_field_integer_serialize(struct bt_ctf_field *,
93 struct ctf_stream_pos *);
94static
95int bt_ctf_field_enumeration_serialize(struct bt_ctf_field *,
96 struct ctf_stream_pos *);
97static
98int bt_ctf_field_floating_point_serialize(struct bt_ctf_field *,
99 struct ctf_stream_pos *);
100static
101int bt_ctf_field_structure_serialize(struct bt_ctf_field *,
102 struct ctf_stream_pos *);
103static
104int bt_ctf_field_variant_serialize(struct bt_ctf_field *,
105 struct ctf_stream_pos *);
106static
107int bt_ctf_field_array_serialize(struct bt_ctf_field *,
108 struct ctf_stream_pos *);
109static
110int bt_ctf_field_sequence_serialize(struct bt_ctf_field *,
111 struct ctf_stream_pos *);
112static
113int bt_ctf_field_string_serialize(struct bt_ctf_field *,
114 struct ctf_stream_pos *);
115
116static
117int increase_packet_size(struct ctf_stream_pos *pos);
118
119static
120struct bt_ctf_field *(*field_create_funcs[])(
121 struct bt_ctf_field_type *) = {
122 [CTF_TYPE_INTEGER] = bt_ctf_field_integer_create,
123 [CTF_TYPE_ENUM] = bt_ctf_field_enumeration_create,
124 [CTF_TYPE_FLOAT] =
125 bt_ctf_field_floating_point_create,
126 [CTF_TYPE_STRUCT] = bt_ctf_field_structure_create,
127 [CTF_TYPE_VARIANT] = bt_ctf_field_variant_create,
128 [CTF_TYPE_ARRAY] = bt_ctf_field_array_create,
129 [CTF_TYPE_SEQUENCE] = bt_ctf_field_sequence_create,
130 [CTF_TYPE_STRING] = bt_ctf_field_string_create,
131};
132
133static
134void (*field_destroy_funcs[])(struct bt_ctf_field *) = {
135 [CTF_TYPE_INTEGER] = bt_ctf_field_integer_destroy,
136 [CTF_TYPE_ENUM] = bt_ctf_field_enumeration_destroy,
137 [CTF_TYPE_FLOAT] =
138 bt_ctf_field_floating_point_destroy,
139 [CTF_TYPE_STRUCT] = bt_ctf_field_structure_destroy,
140 [CTF_TYPE_VARIANT] = bt_ctf_field_variant_destroy,
141 [CTF_TYPE_ARRAY] = bt_ctf_field_array_destroy,
142 [CTF_TYPE_SEQUENCE] = bt_ctf_field_sequence_destroy,
143 [CTF_TYPE_STRING] = bt_ctf_field_string_destroy,
144};
145
146static
147int (*field_validate_funcs[])(struct bt_ctf_field *) = {
148 [CTF_TYPE_INTEGER] = bt_ctf_field_generic_validate,
149 [CTF_TYPE_ENUM] = bt_ctf_field_enumeration_validate,
150 [CTF_TYPE_FLOAT] = bt_ctf_field_generic_validate,
151 [CTF_TYPE_STRUCT] = bt_ctf_field_structure_validate,
152 [CTF_TYPE_VARIANT] = bt_ctf_field_variant_validate,
153 [CTF_TYPE_ARRAY] = bt_ctf_field_array_validate,
154 [CTF_TYPE_SEQUENCE] = bt_ctf_field_sequence_validate,
155 [CTF_TYPE_STRING] = bt_ctf_field_generic_validate,
156};
157
158static
159int (*field_serialize_funcs[])(struct bt_ctf_field *,
160 struct ctf_stream_pos *) = {
161 [CTF_TYPE_INTEGER] = bt_ctf_field_integer_serialize,
162 [CTF_TYPE_ENUM] = bt_ctf_field_enumeration_serialize,
163 [CTF_TYPE_FLOAT] =
164 bt_ctf_field_floating_point_serialize,
165 [CTF_TYPE_STRUCT] = bt_ctf_field_structure_serialize,
166 [CTF_TYPE_VARIANT] = bt_ctf_field_variant_serialize,
167 [CTF_TYPE_ARRAY] = bt_ctf_field_array_serialize,
168 [CTF_TYPE_SEQUENCE] = bt_ctf_field_sequence_serialize,
169 [CTF_TYPE_STRING] = bt_ctf_field_string_serialize,
170};
171
172struct bt_ctf_field *bt_ctf_field_create(struct bt_ctf_field_type *type)
173{
174 struct bt_ctf_field *field = NULL;
175 enum ctf_type_id type_id;
176
177 if (!type) {
178 goto error;
179 }
180
181 type_id = bt_ctf_field_type_get_type_id(type);
9ce21c30
JG
182 if (type_id <= CTF_TYPE_UNKNOWN || type_id >= NR_CTF_TYPES ||
183 bt_ctf_field_type_validate(type)) {
273b65be
JG
184 goto error;
185 }
186
187 field = field_create_funcs[type_id](type);
188 if (!field) {
189 goto error;
190 }
191
192 /* The type's declaration can't change after this point */
193 bt_ctf_field_type_freeze(type);
194 bt_ctf_field_type_get(type);
195 bt_ctf_ref_init(&field->ref_count);
196 field->type = type;
197error:
198 return field;
199}
200
201void bt_ctf_field_get(struct bt_ctf_field *field)
202{
203 if (field) {
204 bt_ctf_ref_get(&field->ref_count);
205 }
206}
207
208void bt_ctf_field_put(struct bt_ctf_field *field)
209{
210 if (field) {
211 bt_ctf_ref_put(&field->ref_count, bt_ctf_field_destroy);
212 }
213}
214
cd95e351
JG
215struct bt_ctf_field_type *bt_ctf_field_get_type(struct bt_ctf_field *field)
216{
217 struct bt_ctf_field_type *ret = NULL;
218
219 if (!field) {
220 goto end;
221 }
222
223 ret = field->type;
224 bt_ctf_field_type_get(ret);
225end:
226 return ret;
227}
228
229struct bt_ctf_field *bt_ctf_field_sequence_get_length(
230 struct bt_ctf_field *field)
231{
232 struct bt_ctf_field *ret = NULL;
233 struct bt_ctf_field_sequence *sequence;
234
235 if (!field) {
236 goto end;
237 }
238
239 if (bt_ctf_field_type_get_type_id(field->type) !=
240 CTF_TYPE_SEQUENCE) {
241 goto end;
242 }
243
244 sequence = container_of(field, struct bt_ctf_field_sequence, parent);
245 ret = sequence->length;
246 bt_ctf_field_get(ret);
247end:
248 return ret;
249}
250
273b65be
JG
251int bt_ctf_field_sequence_set_length(struct bt_ctf_field *field,
252 struct bt_ctf_field *length_field)
253{
254 int ret = 0;
255 struct bt_ctf_field_type_integer *length_type;
256 struct bt_ctf_field_integer *length;
257 struct bt_ctf_field_sequence *sequence;
258 uint64_t sequence_length;
259
260 if (!field || !length_field) {
261 ret = -1;
262 goto end;
263 }
264 if (bt_ctf_field_type_get_type_id(length_field->type) !=
265 CTF_TYPE_INTEGER) {
266 ret = -1;
267 goto end;
268 }
269
270 length_type = container_of(length_field->type,
271 struct bt_ctf_field_type_integer, parent);
272 if (length_type->declaration.signedness) {
273 ret = -1;
274 goto end;
275 }
276
277 length = container_of(length_field, struct bt_ctf_field_integer,
278 parent);
279 sequence_length = length->definition.value._unsigned;
280 sequence = container_of(field, struct bt_ctf_field_sequence, parent);
281 if (sequence->elements) {
282 g_ptr_array_free(sequence->elements, TRUE);
283 bt_ctf_field_put(sequence->length);
284 }
285
fe0fe95c 286 sequence->elements = g_ptr_array_sized_new((size_t)sequence_length);
273b65be
JG
287 if (!sequence->elements) {
288 ret = -1;
289 goto end;
290 }
291
fe0fe95c
JG
292 g_ptr_array_set_free_func(sequence->elements,
293 (GDestroyNotify)bt_ctf_field_put);
273b65be
JG
294 g_ptr_array_set_size(sequence->elements, (size_t)sequence_length);
295 bt_ctf_field_get(length_field);
296 sequence->length = length_field;
297end:
298 return ret;
299}
300
301struct bt_ctf_field *bt_ctf_field_structure_get_field(
302 struct bt_ctf_field *field, const char *name)
303{
304 struct bt_ctf_field *new_field = NULL;
305 GQuark field_quark;
306 struct bt_ctf_field_structure *structure;
307 struct bt_ctf_field_type_structure *structure_type;
308 struct bt_ctf_field_type *field_type;
309 size_t index;
310
311 if (!field || !name ||
312 bt_ctf_field_type_get_type_id(field->type) !=
313 CTF_TYPE_STRUCT) {
314 goto error;
315 }
316
317 field_quark = g_quark_from_string(name);
318 structure = container_of(field, struct bt_ctf_field_structure, parent);
319 structure_type = container_of(field->type,
320 struct bt_ctf_field_type_structure, parent);
321 field_type = bt_ctf_field_type_structure_get_type(structure_type, name);
322 if (!g_hash_table_lookup_extended(structure->field_name_to_index,
323 GUINT_TO_POINTER(field_quark), NULL, (gpointer *)&index)) {
324 goto error;
325 }
326
327 if (structure->fields->pdata[index]) {
328 new_field = structure->fields->pdata[index];
329 goto end;
330 }
331
332 new_field = bt_ctf_field_create(field_type);
333 if (!new_field) {
334 goto error;
335 }
336
337 structure->fields->pdata[index] = new_field;
338end:
339 bt_ctf_field_get(new_field);
340error:
341 return new_field;
342}
343
cd95e351
JG
344struct bt_ctf_field *bt_ctf_field_structure_get_field_by_index(
345 struct bt_ctf_field *field, size_t index)
346{
347 int ret;
348 const char *field_name;
349 struct bt_ctf_field_structure *structure;
350 struct bt_ctf_field_type *structure_type;
351 struct bt_ctf_field_type *field_type = NULL;
352 struct bt_ctf_field *ret_field = NULL;
353
354 if (!field ||
355 bt_ctf_field_type_get_type_id(field->type) != CTF_TYPE_STRUCT) {
356 goto end;
357 }
358
359 structure = container_of(field, struct bt_ctf_field_structure, parent);
360 if (index >= structure->fields->len) {
361 goto error;
362 }
363
364 ret_field = structure->fields->pdata[index];
365 if (ret_field) {
366 goto end;
367 }
368
369 /* Field has not been instanciated yet, create it */
370 structure_type = bt_ctf_field_get_type(field);
371 if (!structure_type) {
372 goto error;
373 }
374
375 ret = bt_ctf_field_type_structure_get_field(structure_type,
376 &field_name, &field_type, index);
377 bt_ctf_field_type_put(structure_type);
378 if (ret) {
379 goto error;
380 }
381
382 ret_field = bt_ctf_field_create(field_type);
383 if (!ret_field) {
384 goto error;
385 }
386
387 structure->fields->pdata[index] = ret_field;
388end:
389 bt_ctf_field_get(ret_field);
390error:
391 if (field_type) {
392 bt_ctf_field_type_put(field_type);
393 }
394 return ret_field;
395}
396
273b65be
JG
397BT_HIDDEN
398int bt_ctf_field_structure_set_field(struct bt_ctf_field *field,
399 const char *name, struct bt_ctf_field *value)
400{
401 int ret = 0;
402 GQuark field_quark;
403 struct bt_ctf_field_structure *structure;
404 struct bt_ctf_field_type_structure *structure_type;
405 struct bt_ctf_field_type *expected_field_type;
406 size_t index;
407
408 if (!field || !name || !value ||
409 bt_ctf_field_type_get_type_id(field->type) !=
410 CTF_TYPE_STRUCT) {
411 ret = -1;
412 goto end;
413 }
414
415 field_quark = g_quark_from_string(name);
416 structure = container_of(field, struct bt_ctf_field_structure, parent);
417 structure_type = container_of(field->type,
418 struct bt_ctf_field_type_structure, parent);
419 expected_field_type = bt_ctf_field_type_structure_get_type(
420 structure_type, name);
421 if (expected_field_type != value->type) {
422 ret = -1;
423 goto end;
424 }
425
426 if (!g_hash_table_lookup_extended(structure->field_name_to_index,
427 GUINT_TO_POINTER(field_quark), NULL, (gpointer *) &index)) {
428 goto end;
429 }
430
431 if (structure->fields->pdata[index]) {
432 bt_ctf_field_put(structure->fields->pdata[index]);
433 }
434
435 structure->fields->pdata[index] = value;
436 bt_ctf_field_get(value);
437end:
438 return ret;
439}
440
441struct bt_ctf_field *bt_ctf_field_array_get_field(struct bt_ctf_field *field,
442 uint64_t index)
443{
444 struct bt_ctf_field *new_field = NULL;
445 struct bt_ctf_field_array *array;
446 struct bt_ctf_field_type_array *array_type;
447 struct bt_ctf_field_type *field_type;
448
449 if (!field || bt_ctf_field_type_get_type_id(field->type) !=
450 CTF_TYPE_ARRAY) {
451 goto end;
452 }
453
454 array = container_of(field, struct bt_ctf_field_array, parent);
455 if (index >= array->elements->len) {
456 goto end;
457 }
458
459 array_type = container_of(field->type, struct bt_ctf_field_type_array,
460 parent);
461 field_type = bt_ctf_field_type_array_get_element_type(array_type);
462 if (array->elements->pdata[(size_t)index]) {
463 new_field = array->elements->pdata[(size_t)index];
464 goto end;
465 }
466
467 new_field = bt_ctf_field_create(field_type);
468 bt_ctf_field_get(new_field);
469 array->elements->pdata[(size_t)index] = new_field;
470end:
471 return new_field;
472}
473
474struct bt_ctf_field *bt_ctf_field_sequence_get_field(struct bt_ctf_field *field,
475 uint64_t index)
476{
477 struct bt_ctf_field *new_field = NULL;
478 struct bt_ctf_field_sequence *sequence;
479 struct bt_ctf_field_type_sequence *sequence_type;
480 struct bt_ctf_field_type *field_type;
481
482 if (!field || bt_ctf_field_type_get_type_id(field->type) !=
483 CTF_TYPE_SEQUENCE) {
484 goto end;
485 }
486
487 sequence = container_of(field, struct bt_ctf_field_sequence, parent);
488 if (!sequence->elements || sequence->elements->len <= index) {
489 goto end;
490 }
491
492 sequence_type = container_of(field->type,
493 struct bt_ctf_field_type_sequence, parent);
494 field_type = bt_ctf_field_type_sequence_get_element_type(sequence_type);
495 if (sequence->elements->pdata[(size_t)index]) {
496 new_field = sequence->elements->pdata[(size_t)index];
497 goto end;
498 }
499
500 new_field = bt_ctf_field_create(field_type);
501 bt_ctf_field_get(new_field);
502 sequence->elements->pdata[(size_t)index] = new_field;
503end:
504 return new_field;
505}
506
507struct bt_ctf_field *bt_ctf_field_variant_get_field(struct bt_ctf_field *field,
508 struct bt_ctf_field *tag_field)
509{
510 struct bt_ctf_field *new_field = NULL;
511 struct bt_ctf_field_variant *variant;
512 struct bt_ctf_field_type_variant *variant_type;
513 struct bt_ctf_field_type *field_type;
514 struct bt_ctf_field *tag_enum = NULL;
515 struct bt_ctf_field_integer *tag_enum_integer;
516 int64_t tag_enum_value;
517
518 if (!field || !tag_field ||
519 bt_ctf_field_type_get_type_id(field->type) !=
520 CTF_TYPE_VARIANT ||
521 bt_ctf_field_type_get_type_id(tag_field->type) !=
522 CTF_TYPE_ENUM) {
523 goto end;
524 }
525
526 variant = container_of(field, struct bt_ctf_field_variant, parent);
527 variant_type = container_of(field->type,
528 struct bt_ctf_field_type_variant, parent);
529 tag_enum = bt_ctf_field_enumeration_get_container(tag_field);
530 if (!tag_enum) {
531 goto end;
532 }
533
534 tag_enum_integer = container_of(tag_enum, struct bt_ctf_field_integer,
535 parent);
536
537 if (!bt_ctf_field_validate(variant->tag)) {
538 goto end;
539 }
540
541 tag_enum_value = tag_enum_integer->definition.value._signed;
542 field_type = bt_ctf_field_type_variant_get_field_type(variant_type,
543 tag_enum_value);
544 if (!field_type) {
545 goto end;
546 }
547
548 new_field = bt_ctf_field_create(field_type);
549 if (!new_field) {
550 goto end;
551 }
552
553 bt_ctf_field_put(variant->tag);
554 bt_ctf_field_put(variant->payload);
555 bt_ctf_field_get(new_field);
556 bt_ctf_field_get(tag_field);
557 variant->tag = tag_field;
558 variant->payload = new_field;
559end:
560 bt_ctf_field_put(tag_enum);
561 return new_field;
562}
563
564struct bt_ctf_field *bt_ctf_field_enumeration_get_container(
565 struct bt_ctf_field *field)
566{
567 struct bt_ctf_field *container = NULL;
568 struct bt_ctf_field_enumeration *enumeration;
569
570 if (!field) {
571 goto end;
572 }
573
574 enumeration = container_of(field, struct bt_ctf_field_enumeration,
575 parent);
576 if (!enumeration->payload) {
577 struct bt_ctf_field_type_enumeration *enumeration_type =
578 container_of(field->type,
579 struct bt_ctf_field_type_enumeration, parent);
580 enumeration->payload =
581 bt_ctf_field_create(enumeration_type->container);
582 }
583
584 container = enumeration->payload;
585 bt_ctf_field_get(container);
586end:
587 return container;
588}
589
cd95e351
JG
590const char *bt_ctf_field_enumeration_get_mapping_name(
591 struct bt_ctf_field *field)
592{
593 int ret;
594 const char *name = NULL;
595 struct bt_ctf_field *container = NULL;
596 struct bt_ctf_field_type *container_type = NULL;
597 struct bt_ctf_field_type_integer *integer_type = NULL;
598 struct bt_ctf_field_type_enumeration *enumeration_type = NULL;
599
600 container = bt_ctf_field_enumeration_get_container(field);
601 if (!container) {
602 goto end;
603 }
604
605 container_type = bt_ctf_field_get_type(container);
606 if (!container_type) {
607 goto error_put_container;
608 }
609
610 integer_type = container_of(container_type,
611 struct bt_ctf_field_type_integer, parent);
612 enumeration_type = container_of(field->type,
613 struct bt_ctf_field_type_enumeration, parent);
614
615 if (integer_type->declaration.signedness) {
616 uint64_t value;
617 ret = bt_ctf_field_unsigned_integer_get_value(container,
618 &value);
619 if (ret) {
620 goto error_put_container_type;
621 }
622
623 name = bt_ctf_field_type_enumeration_get_mapping_name_unsigned(
624 enumeration_type, value);
625 } else {
626 int64_t value;
627 ret = bt_ctf_field_signed_integer_get_value(container,
628 &value);
629 if (ret) {
630 goto error_put_container_type;
631 }
632
633 name = bt_ctf_field_type_enumeration_get_mapping_name_signed(
634 enumeration_type, value);
635 }
636
637error_put_container_type:
638 bt_ctf_field_type_put(container_type);
639error_put_container:
640 bt_ctf_field_put(container);
641end:
642 return name;
643}
644
645int bt_ctf_field_signed_integer_get_value(struct bt_ctf_field *field,
646 int64_t *value)
647{
648 int ret = 0;
649 struct bt_ctf_field_integer *integer;
650 struct bt_ctf_field_type_integer *integer_type;
651
652 if (!field || !value || !field->payload_set ||
653 bt_ctf_field_type_get_type_id(field->type) !=
654 CTF_TYPE_INTEGER) {
655 ret = -1;
656 goto end;
657 }
658
659 integer_type = container_of(field->type,
660 struct bt_ctf_field_type_integer, parent);
661 if (!integer_type->declaration.signedness) {
662 ret = -1;
663 goto end;
664 }
665
666 integer = container_of(field,
667 struct bt_ctf_field_integer, parent);
668 *value = integer->definition.value._signed;
669end:
670 return ret;
671}
672
273b65be
JG
673int bt_ctf_field_signed_integer_set_value(struct bt_ctf_field *field,
674 int64_t value)
675{
676 int ret = 0;
677 struct bt_ctf_field_integer *integer;
678 struct bt_ctf_field_type_integer *integer_type;
679 unsigned int size;
680 int64_t min_value, max_value;
681
682 if (!field ||
683 bt_ctf_field_type_get_type_id(field->type) !=
684 CTF_TYPE_INTEGER) {
685 ret = -1;
686 goto end;
687 }
688
689 integer = container_of(field, struct bt_ctf_field_integer, parent);
690 integer_type = container_of(field->type,
691 struct bt_ctf_field_type_integer, parent);
692 if (!integer_type->declaration.signedness) {
693 ret = -1;
694 goto end;
695 }
696
697 size = integer_type->declaration.len;
698 min_value = -((int64_t)1 << (size - 1));
699 max_value = ((int64_t)1 << (size - 1)) - 1;
700 if (value < min_value || value > max_value) {
701 ret = -1;
702 goto end;
703 }
704
705 integer->definition.value._signed = value;
706 integer->parent.payload_set = 1;
707end:
708 return ret;
709}
710
cd95e351
JG
711int bt_ctf_field_unsigned_integer_get_value(struct bt_ctf_field *field,
712 uint64_t *value)
713{
714 int ret = 0;
715 struct bt_ctf_field_integer *integer;
716 struct bt_ctf_field_type_integer *integer_type;
717
718 if (!field || !value || !field->payload_set ||
719 bt_ctf_field_type_get_type_id(field->type) !=
720 CTF_TYPE_INTEGER) {
721 ret = -1;
722 goto end;
723 }
724
725 integer_type = container_of(field->type,
726 struct bt_ctf_field_type_integer, parent);
727 if (integer_type->declaration.signedness) {
728 ret = -1;
729 goto end;
730 }
731
732 integer = container_of(field,
733 struct bt_ctf_field_integer, parent);
734 *value = integer->definition.value._unsigned;
735end:
736 return ret;
737}
738
273b65be
JG
739int bt_ctf_field_unsigned_integer_set_value(struct bt_ctf_field *field,
740 uint64_t value)
741{
742 int ret = 0;
743 struct bt_ctf_field_integer *integer;
744 struct bt_ctf_field_type_integer *integer_type;
745 unsigned int size;
746 uint64_t max_value;
747
748 if (!field ||
749 bt_ctf_field_type_get_type_id(field->type) !=
750 CTF_TYPE_INTEGER) {
751 ret = -1;
752 goto end;
753 }
754
755 integer = container_of(field, struct bt_ctf_field_integer, parent);
756 integer_type = container_of(field->type,
757 struct bt_ctf_field_type_integer, parent);
758 if (integer_type->declaration.signedness) {
759 ret = -1;
760 goto end;
761 }
762
763 size = integer_type->declaration.len;
764 max_value = (size == 64) ? UINT64_MAX : ((uint64_t)1 << size) - 1;
765 if (value > max_value) {
766 ret = -1;
767 goto end;
768 }
769
770 integer->definition.value._unsigned = value;
771 integer->parent.payload_set = 1;
772end:
773 return ret;
774}
775
cd95e351
JG
776int bt_ctf_field_floating_point_get_value(struct bt_ctf_field *field,
777 double *value)
778{
779 int ret = 0;
780 struct bt_ctf_field_floating_point *floating_point;
781
782 if (!field || !value || !field->payload_set ||
783 bt_ctf_field_type_get_type_id(field->type) !=
784 CTF_TYPE_FLOAT) {
785 ret = -1;
786 goto end;
787 }
788
789 floating_point = container_of(field,
790 struct bt_ctf_field_floating_point, parent);
791 *value = floating_point->definition.value;
792end:
793 return ret;
794}
795
273b65be
JG
796int bt_ctf_field_floating_point_set_value(struct bt_ctf_field *field,
797 double value)
798{
799 int ret = 0;
800 struct bt_ctf_field_floating_point *floating_point;
801
802 if (!field ||
803 bt_ctf_field_type_get_type_id(field->type) !=
804 CTF_TYPE_FLOAT) {
805 ret = -1;
806 goto end;
807 }
808 floating_point = container_of(field, struct bt_ctf_field_floating_point,
809 parent);
810 floating_point->definition.value = value;
811 floating_point->parent.payload_set = 1;
812end:
813 return ret;
814}
815
cd95e351
JG
816const char *bt_ctf_field_string_get_value(struct bt_ctf_field *field)
817{
818 const char *ret = NULL;
819 struct bt_ctf_field_string *string;
820
821 if (!field || !field->payload_set ||
822 bt_ctf_field_type_get_type_id(field->type) !=
823 CTF_TYPE_STRING) {
824 goto end;
825 }
826
827 string = container_of(field,
828 struct bt_ctf_field_string, parent);
829 ret = string->payload->str;
830end:
831 return ret;
832}
833
273b65be
JG
834int bt_ctf_field_string_set_value(struct bt_ctf_field *field,
835 const char *value)
836{
837 int ret = 0;
838 struct bt_ctf_field_string *string;
839
840 if (!field || !value ||
841 bt_ctf_field_type_get_type_id(field->type) !=
842 CTF_TYPE_STRING) {
843 ret = -1;
844 goto end;
845 }
846
847 string = container_of(field, struct bt_ctf_field_string, parent);
848 if (string->payload) {
849 g_string_free(string->payload, TRUE);
850 }
851
852 string->payload = g_string_new(value);
853 string->parent.payload_set = 1;
854end:
855 return ret;
856}
857
858BT_HIDDEN
859int bt_ctf_field_validate(struct bt_ctf_field *field)
860{
861 int ret = 0;
862 enum ctf_type_id type_id;
863
864 if (!field) {
865 ret = -1;
866 goto end;
867 }
868
869 type_id = bt_ctf_field_type_get_type_id(field->type);
870 if (type_id <= CTF_TYPE_UNKNOWN || type_id >= NR_CTF_TYPES) {
871 ret = -1;
872 goto end;
873 }
874
875 ret = field_validate_funcs[type_id](field);
876end:
877 return ret;
878}
879
880BT_HIDDEN
881int bt_ctf_field_serialize(struct bt_ctf_field *field,
882 struct ctf_stream_pos *pos)
883{
884 int ret = 0;
885 enum ctf_type_id type_id;
886
887 if (!field || !pos) {
888 ret = -1;
889 goto end;
890 }
891
892 type_id = bt_ctf_field_type_get_type_id(field->type);
893 if (type_id <= CTF_TYPE_UNKNOWN || type_id >= NR_CTF_TYPES) {
894 ret = -1;
895 goto end;
896 }
897
898 ret = field_serialize_funcs[type_id](field, pos);
899end:
900 return ret;
901}
902
903static
904struct bt_ctf_field *bt_ctf_field_integer_create(struct bt_ctf_field_type *type)
905{
906 struct bt_ctf_field_type_integer *integer_type = container_of(type,
907 struct bt_ctf_field_type_integer, parent);
908 struct bt_ctf_field_integer *integer = g_new0(
909 struct bt_ctf_field_integer, 1);
910
911 if (integer) {
912 integer->definition.declaration = &integer_type->declaration;
913 }
914
915 return integer ? &integer->parent : NULL;
916}
917
918static
919struct bt_ctf_field *bt_ctf_field_enumeration_create(
920 struct bt_ctf_field_type *type)
921{
922 struct bt_ctf_field_enumeration *enumeration = g_new0(
923 struct bt_ctf_field_enumeration, 1);
924
925 return enumeration ? &enumeration->parent : NULL;
926}
927
928static
929struct bt_ctf_field *bt_ctf_field_floating_point_create(
930 struct bt_ctf_field_type *type)
931{
932 struct bt_ctf_field_floating_point *floating_point;
933 struct bt_ctf_field_type_floating_point *floating_point_type;
934
935 floating_point = g_new0(struct bt_ctf_field_floating_point, 1);
936 if (!floating_point) {
937 goto end;
938 }
939
940 floating_point_type = container_of(type,
941 struct bt_ctf_field_type_floating_point, parent);
942 floating_point->definition.declaration = container_of(
943 type->declaration, struct declaration_float, p);
944
945
946 floating_point->definition.sign = &floating_point->sign;
947 floating_point->sign.declaration = &floating_point_type->sign;
948 floating_point->definition.sign->p.declaration =
949 &floating_point_type->sign.p;
950
951 floating_point->definition.mantissa = &floating_point->mantissa;
952 floating_point->mantissa.declaration = &floating_point_type->mantissa;
953 floating_point->definition.mantissa->p.declaration =
954 &floating_point_type->mantissa.p;
955
956 floating_point->definition.exp = &floating_point->exp;
957 floating_point->exp.declaration = &floating_point_type->exp;
958 floating_point->definition.exp->p.declaration =
959 &floating_point_type->exp.p;
960
961end:
962 return floating_point ? &floating_point->parent : NULL;
963}
964
965static
966struct bt_ctf_field *bt_ctf_field_structure_create(
967 struct bt_ctf_field_type *type)
968{
969 struct bt_ctf_field_type_structure *structure_type = container_of(type,
970 struct bt_ctf_field_type_structure, parent);
971 struct bt_ctf_field_structure *structure = g_new0(
972 struct bt_ctf_field_structure, 1);
973 struct bt_ctf_field *field = NULL;
974
975 if (!structure || !structure_type->fields->len) {
976 goto end;
977 }
978
979 structure->field_name_to_index = structure_type->field_name_to_index;
980 structure->fields = g_ptr_array_new_with_free_func(
981 (GDestroyNotify)bt_ctf_field_put);
982 g_ptr_array_set_size(structure->fields,
983 g_hash_table_size(structure->field_name_to_index));
984 field = &structure->parent;
985end:
986 return field;
987}
988
989static
990struct bt_ctf_field *bt_ctf_field_variant_create(struct bt_ctf_field_type *type)
991{
992 struct bt_ctf_field_variant *variant = g_new0(
993 struct bt_ctf_field_variant, 1);
994 return variant ? &variant->parent : NULL;
995}
996
997static
998struct bt_ctf_field *bt_ctf_field_array_create(struct bt_ctf_field_type *type)
999{
1000 struct bt_ctf_field_array *array = g_new0(struct bt_ctf_field_array, 1);
1001 struct bt_ctf_field_type_array *array_type;
1002 unsigned int array_length;
1003
1004 if (!array || !type) {
1005 goto error;
1006 }
1007
1008 array_type = container_of(type, struct bt_ctf_field_type_array, parent);
1009 array_length = array_type->length;
fe0fe95c 1010 array->elements = g_ptr_array_sized_new(array_length);
273b65be
JG
1011 if (!array->elements) {
1012 goto error;
1013 }
1014
fe0fe95c
JG
1015 g_ptr_array_set_free_func(array->elements,
1016 (GDestroyNotify)bt_ctf_field_put);
273b65be
JG
1017 g_ptr_array_set_size(array->elements, array_length);
1018 return &array->parent;
1019error:
1020 g_free(array);
1021 return NULL;
1022}
1023
1024static
1025struct bt_ctf_field *bt_ctf_field_sequence_create(
1026 struct bt_ctf_field_type *type)
1027{
1028 struct bt_ctf_field_sequence *sequence = g_new0(
1029 struct bt_ctf_field_sequence, 1);
1030 return sequence ? &sequence->parent : NULL;
1031}
1032
1033static
1034struct bt_ctf_field *bt_ctf_field_string_create(struct bt_ctf_field_type *type)
1035{
1036 struct bt_ctf_field_string *string = g_new0(
1037 struct bt_ctf_field_string, 1);
1038 return string ? &string->parent : NULL;
1039}
1040
1041static
1042void bt_ctf_field_destroy(struct bt_ctf_ref *ref)
1043{
1044 struct bt_ctf_field *field;
1045 struct bt_ctf_field_type *type;
1046 enum ctf_type_id type_id;
1047
1048 if (!ref) {
1049 return;
1050 }
1051
1052 field = container_of(ref, struct bt_ctf_field, ref_count);
1053 type = field->type;
1054 type_id = bt_ctf_field_type_get_type_id(type);
1055 if (type_id <= CTF_TYPE_UNKNOWN ||
1056 type_id >= NR_CTF_TYPES) {
1057 return;
1058 }
1059
1060 field_destroy_funcs[type_id](field);
1061 if (type) {
1062 bt_ctf_field_type_put(type);
1063 }
1064}
1065
1066static
1067void bt_ctf_field_integer_destroy(struct bt_ctf_field *field)
1068{
1069 struct bt_ctf_field_integer *integer;
1070
1071 if (!field) {
1072 return;
1073 }
1074
1075 integer = container_of(field, struct bt_ctf_field_integer, parent);
1076 g_free(integer);
1077}
1078
1079static
1080void bt_ctf_field_enumeration_destroy(struct bt_ctf_field *field)
1081{
1082 struct bt_ctf_field_enumeration *enumeration;
1083
1084 if (!field) {
1085 return;
1086 }
1087
1088 enumeration = container_of(field, struct bt_ctf_field_enumeration,
1089 parent);
1090 bt_ctf_field_put(enumeration->payload);
1091 g_free(enumeration);
1092}
1093
1094static
1095void bt_ctf_field_floating_point_destroy(struct bt_ctf_field *field)
1096{
1097 struct bt_ctf_field_floating_point *floating_point;
1098
1099 if (!field) {
1100 return;
1101 }
1102
1103 floating_point = container_of(field, struct bt_ctf_field_floating_point,
1104 parent);
1105 g_free(floating_point);
1106}
1107
1108static
1109void bt_ctf_field_structure_destroy(struct bt_ctf_field *field)
1110{
1111 struct bt_ctf_field_structure *structure;
1112
1113 if (!field) {
1114 return;
1115 }
1116
1117 structure = container_of(field, struct bt_ctf_field_structure, parent);
1118 g_ptr_array_free(structure->fields, TRUE);
1119 g_free(structure);
1120}
1121
1122static
1123void bt_ctf_field_variant_destroy(struct bt_ctf_field *field)
1124{
1125 struct bt_ctf_field_variant *variant;
1126
1127 if (!field) {
1128 return;
1129 }
1130
1131 variant = container_of(field, struct bt_ctf_field_variant, parent);
1132 bt_ctf_field_put(variant->tag);
1133 bt_ctf_field_put(variant->payload);
1134 g_free(variant);
1135}
1136
1137static
1138void bt_ctf_field_array_destroy(struct bt_ctf_field *field)
1139{
1140 struct bt_ctf_field_array *array;
1141
1142 if (!field) {
1143 return;
1144 }
1145
1146 array = container_of(field, struct bt_ctf_field_array, parent);
1147 g_ptr_array_free(array->elements, TRUE);
1148 g_free(array);
1149}
1150
1151static
1152void bt_ctf_field_sequence_destroy(struct bt_ctf_field *field)
1153{
1154 struct bt_ctf_field_sequence *sequence;
1155
1156 if (!field) {
1157 return;
1158 }
1159
1160 sequence = container_of(field, struct bt_ctf_field_sequence, parent);
1161 g_ptr_array_free(sequence->elements, TRUE);
1162 bt_ctf_field_put(sequence->length);
1163 g_free(sequence);
1164}
1165
1166static
1167void bt_ctf_field_string_destroy(struct bt_ctf_field *field)
1168{
1169 struct bt_ctf_field_string *string;
1170 if (!field) {
1171 return;
1172 }
1173
1174 string = container_of(field, struct bt_ctf_field_string, parent);
1175 g_string_free(string->payload, TRUE);
1176 g_free(string);
1177}
1178
1179static
1180int bt_ctf_field_generic_validate(struct bt_ctf_field *field)
1181{
da2f6971 1182 return (field && field->payload_set) ? 0 : -1;
273b65be
JG
1183}
1184
1185static
1186int bt_ctf_field_enumeration_validate(struct bt_ctf_field *field)
1187{
1188 int ret;
1189 struct bt_ctf_field_enumeration *enumeration;
1190
1191 if (!field) {
1192 ret = -1;
1193 goto end;
1194 }
1195
1196 enumeration = container_of(field, struct bt_ctf_field_enumeration,
1197 parent);
1198 if (!enumeration->payload) {
1199 ret = -1;
1200 goto end;
1201 }
1202
1203 ret = bt_ctf_field_validate(enumeration->payload);
1204end:
1205 return ret;
1206}
1207
1208static
1209int bt_ctf_field_structure_validate(struct bt_ctf_field *field)
1210{
1211 size_t i;
1212 int ret = 0;
1213 struct bt_ctf_field_structure *structure;
1214
1215 if (!field) {
1216 ret = -1;
1217 goto end;
1218 }
1219
1220 structure = container_of(field, struct bt_ctf_field_structure, parent);
1221 for (i = 0; i < structure->fields->len; i++) {
1222 ret = bt_ctf_field_validate(structure->fields->pdata[i]);
1223 if (ret) {
1224 goto end;
1225 }
1226 }
1227end:
1228 return ret;
1229}
1230
1231static
1232int bt_ctf_field_variant_validate(struct bt_ctf_field *field)
1233{
1234 int ret = 0;
1235 struct bt_ctf_field_variant *variant;
1236
1237 if (!field) {
1238 ret = -1;
1239 goto end;
1240 }
1241
1242 variant = container_of(field, struct bt_ctf_field_variant, parent);
1243 ret = bt_ctf_field_validate(variant->payload);
1244end:
1245 return ret;
1246}
1247
1248static
1249int bt_ctf_field_array_validate(struct bt_ctf_field *field)
1250{
1251 size_t i;
1252 int ret = 0;
1253 struct bt_ctf_field_array *array;
1254
1255 if (!field) {
1256 ret = -1;
1257 goto end;
1258 }
1259
1260 array = container_of(field, struct bt_ctf_field_array, parent);
1261 for (i = 0; i < array->elements->len; i++) {
1262 ret = bt_ctf_field_validate(array->elements->pdata[i]);
1263 if (ret) {
1264 goto end;
1265 }
1266 }
1267end:
1268 return ret;
1269}
1270
1271static
1272int bt_ctf_field_sequence_validate(struct bt_ctf_field *field)
1273{
1274 size_t i;
1275 int ret = 0;
1276 struct bt_ctf_field_sequence *sequence;
1277
1278 if (!field) {
1279 ret = -1;
1280 goto end;
1281 }
1282
1283 sequence = container_of(field, struct bt_ctf_field_sequence, parent);
1284 for (i = 0; i < sequence->elements->len; i++) {
1285 ret = bt_ctf_field_validate(sequence->elements->pdata[i]);
1286 if (ret) {
1287 goto end;
1288 }
1289 }
1290end:
1291 return ret;
1292}
1293
1294static
1295int bt_ctf_field_integer_serialize(struct bt_ctf_field *field,
1296 struct ctf_stream_pos *pos)
1297{
1298 int ret = 0;
1299 struct bt_ctf_field_integer *integer = container_of(field,
1300 struct bt_ctf_field_integer, parent);
1301
1302retry:
1303 ret = ctf_integer_write(&pos->parent, &integer->definition.p);
1304 if (ret == -EFAULT) {
1305 /*
1306 * The field is too large to fit in the current packet's
1307 * remaining space. Bump the packet size and retry.
1308 */
1309 ret = increase_packet_size(pos);
1310 if (ret) {
1311 goto end;
1312 }
1313 goto retry;
1314 }
1315end:
1316 return ret;
1317}
1318
1319static
1320int bt_ctf_field_enumeration_serialize(struct bt_ctf_field *field,
1321 struct ctf_stream_pos *pos)
1322{
1323 struct bt_ctf_field_enumeration *enumeration = container_of(
1324 field, struct bt_ctf_field_enumeration, parent);
1325
1326 return bt_ctf_field_serialize(enumeration->payload, pos);
1327}
1328
1329static
1330int bt_ctf_field_floating_point_serialize(struct bt_ctf_field *field,
1331 struct ctf_stream_pos *pos)
1332{
1333 int ret = 0;
1334 struct bt_ctf_field_floating_point *floating_point = container_of(field,
1335 struct bt_ctf_field_floating_point, parent);
1336
1337retry:
1338 ret = ctf_float_write(&pos->parent, &floating_point->definition.p);
1339 if (ret == -EFAULT) {
1340 /*
1341 * The field is too large to fit in the current packet's
1342 * remaining space. Bump the packet size and retry.
1343 */
1344 ret = increase_packet_size(pos);
1345 if (ret) {
1346 goto end;
1347 }
1348 goto retry;
1349 }
1350end:
1351 return ret;
1352}
1353
1354static
1355int bt_ctf_field_structure_serialize(struct bt_ctf_field *field,
1356 struct ctf_stream_pos *pos)
1357{
1358 size_t i;
1359 int ret = 0;
1360 struct bt_ctf_field_structure *structure = container_of(
1361 field, struct bt_ctf_field_structure, parent);
1362
1363 while (!ctf_pos_access_ok(pos,
1364 offset_align(pos->offset,
1365 field->type->declaration->alignment))) {
9f56e450
JG
1366 ret = increase_packet_size(pos);
1367 if (ret) {
1368 goto end;
1369 }
273b65be
JG
1370 }
1371
70fd5a51
MD
1372 if (!ctf_align_pos(pos, field->type->declaration->alignment)) {
1373 ret = -1;
1374 goto end;
1375 }
273b65be
JG
1376
1377 for (i = 0; i < structure->fields->len; i++) {
1378 struct bt_ctf_field *field = g_ptr_array_index(
1379 structure->fields, i);
1380
1381 ret = bt_ctf_field_serialize(field, pos);
1382 if (ret) {
1383 break;
1384 }
1385 }
9f56e450 1386end:
273b65be
JG
1387 return ret;
1388}
1389
1390static
1391int bt_ctf_field_variant_serialize(struct bt_ctf_field *field,
1392 struct ctf_stream_pos *pos)
1393{
1394 struct bt_ctf_field_variant *variant = container_of(
1395 field, struct bt_ctf_field_variant, parent);
1396
1397 return bt_ctf_field_serialize(variant->payload, pos);
1398}
1399
1400static
1401int bt_ctf_field_array_serialize(struct bt_ctf_field *field,
1402 struct ctf_stream_pos *pos)
1403{
1404 size_t i;
1405 int ret = 0;
1406 struct bt_ctf_field_array *array = container_of(
1407 field, struct bt_ctf_field_array, parent);
1408
1409 for (i = 0; i < array->elements->len; i++) {
1410 ret = bt_ctf_field_serialize(
1411 g_ptr_array_index(array->elements, i), pos);
1412 if (ret) {
1413 goto end;
1414 }
1415 }
1416end:
1417 return ret;
1418}
1419
1420static
1421int bt_ctf_field_sequence_serialize(struct bt_ctf_field *field,
1422 struct ctf_stream_pos *pos)
1423{
1424 size_t i;
1425 int ret = 0;
1426 struct bt_ctf_field_sequence *sequence = container_of(
1427 field, struct bt_ctf_field_sequence, parent);
1428
1429 for (i = 0; i < sequence->elements->len; i++) {
1430 ret = bt_ctf_field_serialize(
1431 g_ptr_array_index(sequence->elements, i), pos);
1432 if (ret) {
1433 goto end;
1434 }
1435 }
1436end:
1437 return ret;
1438}
1439
1440static
1441int bt_ctf_field_string_serialize(struct bt_ctf_field *field,
1442 struct ctf_stream_pos *pos)
1443{
1444 size_t i;
1445 int ret = 0;
1446 struct bt_ctf_field_string *string = container_of(field,
1447 struct bt_ctf_field_string, parent);
1448 struct bt_ctf_field_type *character_type =
1449 get_field_type(FIELD_TYPE_ALIAS_UINT8_T);
1450 struct bt_ctf_field *character = bt_ctf_field_create(character_type);
1451
1452 for (i = 0; i < string->payload->len + 1; i++) {
1453 ret = bt_ctf_field_unsigned_integer_set_value(character,
1454 (uint64_t) string->payload->str[i]);
1455 if (ret) {
1456 goto end;
1457 }
1458
1459 ret = bt_ctf_field_integer_serialize(character, pos);
1460 if (ret) {
1461 goto end;
1462 }
1463 }
1464end:
1465 bt_ctf_field_put(character);
1466 bt_ctf_field_type_put(character_type);
1467 return ret;
1468}
1469
1470static
1471int increase_packet_size(struct ctf_stream_pos *pos)
1472{
1473 int ret;
1474
1475 assert(pos);
1476 ret = munmap_align(pos->base_mma);
1477 if (ret) {
1478 goto end;
1479 }
1480
1481 pos->packet_size += PACKET_LEN_INCREMENT;
1482 ret = posix_fallocate(pos->fd, pos->mmap_offset,
1483 pos->packet_size / CHAR_BIT);
1484 if (ret) {
1485 goto end;
1486 }
1487
1488 pos->base_mma = mmap_align(pos->packet_size / CHAR_BIT, pos->prot,
1489 pos->flags, pos->fd, pos->mmap_offset);
1490 if (pos->base_mma == MAP_FAILED) {
1491 ret = -1;
1492 }
1493end:
1494 return ret;
1495}
This page took 0.079077 seconds and 4 git commands to generate.