Split CTF IR and CTF writer APIs and implementations
[babeltrace.git] / include / babeltrace / ctf-ir / fields-internal.h
CommitLineData
2e33ac5a
PP
1#ifndef BABELTRACE_CTF_IR_FIELDS_INTERNAL_H
2#define BABELTRACE_CTF_IR_FIELDS_INTERNAL_H
273b65be
JG
3
4/*
2e33ac5a 5 * Babeltrace - CTF IR: Event Fields internal
273b65be 6 *
de9dd397 7 * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
273b65be
JG
8 *
9 * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
10 *
11 * Permission is hereby granted, free of charge, to any person obtaining a copy
12 * of this software and associated documentation files (the "Software"), to deal
13 * in the Software without restriction, including without limitation the rights
14 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 * copies of the Software, and to permit persons to whom the Software is
16 * furnished to do so, subject to the following conditions:
17 *
18 * The above copyright notice and this permission notice shall be included in
19 * all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 * SOFTWARE.
28 */
29
3dca2276
PP
30#include <babeltrace/assert-pre-internal.h>
31#include <babeltrace/common-internal.h>
32#include <babeltrace/ctf-ir/field-types-internal.h>
33#include <babeltrace/ctf-ir/utils-internal.h>
83509119 34#include <babeltrace/object-internal.h>
273b65be 35#include <babeltrace/babeltrace-internal.h>
c55a9f58 36#include <babeltrace/types.h>
dc3fffef 37#include <stdint.h>
3dca2276 38#include <inttypes.h>
d990a4fb 39#include <stdbool.h>
273b65be
JG
40#include <glib.h>
41
3dca2276
PP
42#define BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(_field, _type_id, _name) \
43 BT_ASSERT_PRE((_field)->type->id == (_type_id), \
44 _name " has the wrong type ID: expected-type-id=%s, " \
45 "%![field-]+_f", bt_common_field_type_id_string(_type_id), \
46 (_field))
dc3fffef 47
3dca2276
PP
48#define BT_ASSERT_PRE_FIELD_COMMON_IS_SET(_field, _name) \
49 BT_ASSERT_PRE(bt_field_common_is_set_recursive(_field), \
50 _name " is not set: %!+_f", (_field))
51
52#define BT_ASSERT_PRE_FIELD_COMMON_HOT(_field, _name) \
53 BT_ASSERT_PRE_HOT((_field), (_name), ": +%!+_f", (_field))
54
55struct bt_field;
56struct bt_field_common;
57
58typedef void (*bt_field_common_method_freeze)(struct bt_field_common *);
59typedef int (*bt_field_common_method_validate)(struct bt_field_common *);
60typedef struct bt_field_common *(*bt_field_common_method_copy)(
61 struct bt_field_common *);
62typedef bt_bool (*bt_field_common_method_is_set)(struct bt_field_common *);
63typedef void (*bt_field_common_method_reset)(struct bt_field_common *);
64
65struct bt_field_common_methods {
66 bt_field_common_method_freeze freeze;
67 bt_field_common_method_validate validate;
68 bt_field_common_method_copy copy;
69 bt_field_common_method_is_set is_set;
70 bt_field_common_method_reset reset;
71};
72
73struct bt_field_common {
83509119 74 struct bt_object base;
3dca2276
PP
75 struct bt_field_type_common *type;
76 struct bt_field_common_methods *methods;
d990a4fb
JG
77 bool payload_set;
78 bool frozen;
3dca2276
PP
79
80 /*
81 * Specialized data for either CTF IR or CTF writer APIs.
82 * See comment in `field-types-internal.h` for more details.
83 */
84 union {
85 struct {
86 } ir;
87 struct {
88 void *serialize_func;
89 } writer;
90 } spec;
273b65be
JG
91};
92
3dca2276
PP
93struct bt_field_common_integer {
94 struct bt_field_common common;
dc3fffef
PP
95 union {
96 int64_t signd;
97 uint64_t unsignd;
98 } payload;
273b65be
JG
99};
100
3dca2276
PP
101struct bt_field_common_enumeration {
102 struct bt_field_common common;
103 struct bt_field_common *payload;
273b65be
JG
104};
105
3dca2276
PP
106struct bt_field_common_floating_point {
107 struct bt_field_common common;
dc3fffef 108 double payload;
273b65be
JG
109};
110
3dca2276
PP
111struct bt_field_common_structure {
112 struct bt_field_common common;
113 GPtrArray *fields; /* Array of pointers to struct bt_field_common */
273b65be
JG
114};
115
3dca2276
PP
116struct bt_field_common_variant {
117 struct bt_field_common common;
118 struct bt_field_common *tag;
119 struct bt_field_common *payload;
273b65be
JG
120};
121
3dca2276
PP
122struct bt_field_common_array {
123 struct bt_field_common common;
124 GPtrArray *elements; /* Array of pointers to struct bt_field_common */
273b65be
JG
125};
126
3dca2276
PP
127struct bt_field_common_sequence {
128 struct bt_field_common common;
129 struct bt_field_common *length;
130 GPtrArray *elements; /* Array of pointers to struct bt_field_common */
273b65be
JG
131};
132
3dca2276
PP
133struct bt_field_common_string {
134 struct bt_field_common common;
273b65be
JG
135 GString *payload;
136};
137
3dca2276
PP
138static inline
139struct bt_field_type *bt_field_borrow_type(struct bt_field *field)
140{
141 struct bt_field_common *field_common = (void *) field;
142
143 BT_ASSERT(field);
144 return (void *) field_common->type;
145}
146
147BT_HIDDEN
148int64_t bt_field_sequence_get_int_length(struct bt_field *field);
149
150BT_HIDDEN
151struct bt_field_common *bt_field_common_copy(struct bt_field_common *field);
152
153BT_HIDDEN
154int bt_field_common_structure_initialize(struct bt_field_common *field,
155 struct bt_field_type_common *type,
156 bt_object_release_func release_func,
157 struct bt_field_common_methods *methods,
158 bt_field_common_create_func field_create_func);
159
160BT_HIDDEN
161int bt_field_common_array_initialize(struct bt_field_common *field,
162 struct bt_field_type_common *type,
163 bt_object_release_func release_func,
164 struct bt_field_common_methods *methods);
165
166BT_HIDDEN
167int bt_field_common_generic_validate(struct bt_field_common *field);
168
169BT_HIDDEN
170int bt_field_common_enumeration_validate_recursive(
171 struct bt_field_common *field);
172
173BT_HIDDEN
174int bt_field_common_structure_validate_recursive(struct bt_field_common *field);
175
176BT_HIDDEN
177int bt_field_common_variant_validate_recursive(struct bt_field_common *field);
178
179BT_HIDDEN
180int bt_field_common_array_validate_recursive(struct bt_field_common *field);
181
182BT_HIDDEN
183int bt_field_common_sequence_validate_recursive(struct bt_field_common *field);
184
185BT_HIDDEN
186void bt_field_common_generic_reset(struct bt_field_common *field);
187
188BT_HIDDEN
189void bt_field_common_enumeration_reset_recursive(struct bt_field_common *field);
190
191BT_HIDDEN
192void bt_field_common_structure_reset_recursive(struct bt_field_common *field);
193
194BT_HIDDEN
195void bt_field_common_variant_reset_recursive(struct bt_field_common *field);
196
197BT_HIDDEN
198void bt_field_common_array_reset_recursive(struct bt_field_common *field);
199
200BT_HIDDEN
201void bt_field_common_sequence_reset_recursive(struct bt_field_common *field);
202
203BT_HIDDEN
204void bt_field_common_string_reset(struct bt_field_common *field);
205
206BT_HIDDEN
207void bt_field_common_generic_freeze(struct bt_field_common *field);
208
f6ccaed9 209BT_HIDDEN
3dca2276 210void bt_field_common_enumeration_freeze_recursive(struct bt_field_common *field);
f6ccaed9 211
273b65be 212BT_HIDDEN
3dca2276 213void bt_field_common_structure_freeze_recursive(struct bt_field_common *field);
273b65be
JG
214
215BT_HIDDEN
3dca2276 216void bt_field_common_variant_freeze_recursive(struct bt_field_common *field);
f6ccaed9
PP
217
218BT_HIDDEN
3dca2276 219void bt_field_common_array_freeze_recursive(struct bt_field_common *field);
f6ccaed9
PP
220
221BT_HIDDEN
3dca2276 222void bt_field_common_sequence_freeze_recursive(struct bt_field_common *field);
273b65be 223
918be005 224BT_HIDDEN
3dca2276
PP
225void _bt_field_common_freeze_recursive(struct bt_field_common *field);
226
227BT_HIDDEN
228bt_bool bt_field_common_generic_is_set(struct bt_field_common *field);
229
230BT_HIDDEN
231bt_bool bt_field_common_enumeration_is_set_recursive(
232 struct bt_field_common *field);
233
234BT_HIDDEN
235bt_bool bt_field_common_structure_is_set_recursive(
236 struct bt_field_common *field);
237
238BT_HIDDEN
239bt_bool bt_field_common_variant_is_set_recursive(struct bt_field_common *field);
240
241BT_HIDDEN
242bt_bool bt_field_common_array_is_set_recursive(struct bt_field_common *field);
243
244BT_HIDDEN
245bt_bool bt_field_common_sequence_is_set_recursive(struct bt_field_common *field);
246
247BT_HIDDEN
248void bt_field_common_integer_destroy(struct bt_object *obj);
249
250BT_HIDDEN
251void bt_field_common_enumeration_destroy_recursive(struct bt_object *obj);
252
253BT_HIDDEN
254void bt_field_common_floating_point_destroy(struct bt_object *obj);
255
256BT_HIDDEN
257void bt_field_common_structure_destroy_recursive(struct bt_object *obj);
258
259BT_HIDDEN
260void bt_field_common_variant_destroy_recursive(struct bt_object *obj);
261
262BT_HIDDEN
263void bt_field_common_array_destroy_recursive(struct bt_object *obj);
264
265BT_HIDDEN
266void bt_field_common_sequence_destroy_recursive(struct bt_object *obj);
267
268BT_HIDDEN
269void bt_field_common_string_destroy(struct bt_object *obj);
f6ccaed9
PP
270
271#ifdef BT_DEV_MODE
3dca2276
PP
272# define bt_field_common_validate_recursive _bt_field_common_validate_recursive
273# define bt_field_common_freeze_recursive _bt_field_common_freeze_recursive
274# define bt_field_common_is_set_recursive _bt_field_common_is_set_recursive
275# define bt_field_common_reset_recursive _bt_field_common_reset_recursive
276# define bt_field_common_set _bt_field_common_set
f6ccaed9
PP
277# define bt_field_validate_recursive _bt_field_validate_recursive
278# define bt_field_freeze_recursive _bt_field_freeze_recursive
279# define bt_field_is_set_recursive _bt_field_is_set_recursive
280# define bt_field_reset_recursive _bt_field_reset_recursive
281# define bt_field_set _bt_field_set
282#else
3dca2276
PP
283# define bt_field_common_validate_recursive(_field) (-1)
284# define bt_field_common_freeze_recursive(_field)
285# define bt_field_common_is_set_recursive(_field) (BT_FALSE)
286# define bt_field_common_reset_recursive(_field) (BT_TRUE)
287# define bt_field_common_set(_field, _val)
288# define bt_field_validate_recursive(_field) (-1)
f6ccaed9 289# define bt_field_freeze_recursive(_field)
3dca2276 290# define bt_field_is_set_recursive(_field) (BT_FALSE)
f6ccaed9
PP
291# define bt_field_reset_recursive(_field) (BT_TRUE)
292# define bt_field_set(_field, _val)
293#endif
918be005 294
3dca2276
PP
295BT_ASSERT_FUNC
296static inline bool field_type_common_has_known_id(
297 struct bt_field_type_common *ft)
298{
299 return ft->id > BT_FIELD_TYPE_ID_UNKNOWN ||
300 ft->id < BT_FIELD_TYPE_ID_NR;
301}
302
303static inline
304int _bt_field_common_validate_recursive(struct bt_field_common *field)
305{
306 int ret = 0;
307
308 if (!field) {
309 BT_ASSERT_PRE_MSG("%s", "Invalid field: field is NULL.");
310 ret = -1;
311 goto end;
312 }
313
314 BT_ASSERT(field_type_common_has_known_id(field->type));
315
316 if (field->methods->validate) {
317 ret = field->methods->validate(field);
318 }
319
320end:
321 return ret;
322}
323
324static inline
325void _bt_field_common_reset_recursive(struct bt_field_common *field)
326{
327 BT_ASSERT(field);
328 BT_ASSERT(field->methods->reset);
329 field->methods->reset(field);
330}
331
332static inline
333void _bt_field_common_set(struct bt_field_common *field, bool value)
334{
335 BT_ASSERT(field);
336 field->payload_set = value;
337}
338
339static inline
340bt_bool _bt_field_common_is_set_recursive(struct bt_field_common *field)
341{
342 bt_bool is_set = BT_FALSE;
343
344 if (!field) {
345 goto end;
346 }
347
348 BT_ASSERT(field_type_common_has_known_id(field->type));
349 BT_ASSERT(field->methods->is_set);
350 is_set = field->methods->is_set(field);
351
352end:
353 return is_set;
354}
355
356static inline
357void bt_field_common_initialize(struct bt_field_common *field,
358 struct bt_field_type_common *ft,
359 bt_object_release_func release_func,
360 struct bt_field_common_methods *methods)
361{
362 BT_ASSERT(field);
363 BT_ASSERT(ft);
364 bt_object_init(field, release_func);
365 field->methods = methods;
366 field->type = bt_get(ft);
367}
368
369static inline
370struct bt_field_type_common *bt_field_common_get_type(
371 struct bt_field_common *field)
372{
373 struct bt_field_type_common *ret = NULL;
374
375 BT_ASSERT_PRE_NON_NULL(field, "Field");
376 ret = bt_get(field->type);
377 return ret;
378}
379
380static inline
381int64_t bt_field_common_sequence_get_int_length(struct bt_field_common *field)
382{
383 struct bt_field_common_sequence *sequence = BT_FROM_COMMON(field);
384 int64_t ret;
385
386 BT_ASSERT(field);
387 BT_ASSERT(field->type->id == BT_FIELD_TYPE_ID_SEQUENCE);
388 if (!sequence->length) {
389 ret = -1;
390 goto end;
391 }
392
393 ret = (int64_t) sequence->elements->len;
394
395end:
396 return ret;
397}
398
399static inline
400struct bt_field_common *bt_field_common_sequence_get_length(
401 struct bt_field_common *field)
402{
403 struct bt_field_common_sequence *sequence = BT_FROM_COMMON(field);
404
405 BT_ASSERT_PRE_NON_NULL(field, "Sequence field");
406 BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_SEQUENCE,
407 "Field");
408 return bt_get(sequence->length);
409}
410
411static inline
412int bt_field_common_sequence_set_length(struct bt_field_common *field,
413 struct bt_field_common *length_field)
414{
415 int ret = 0;
416 struct bt_field_common_integer *length = BT_FROM_COMMON(length_field);
417 struct bt_field_common_sequence *sequence = BT_FROM_COMMON(field);
418 uint64_t sequence_length;
419
420 BT_ASSERT_PRE_NON_NULL(field, "Sequence field");
421 BT_ASSERT_PRE_NON_NULL(length_field, "Length field");
422 BT_ASSERT_PRE_FIELD_COMMON_HOT(field, "Sequence field");
423 BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(length_field,
424 BT_FIELD_TYPE_ID_INTEGER, "Length field");
425 BT_ASSERT_PRE(
426 !bt_field_type_common_integer_is_signed(length->common.type),
427 "Length field's type is signed: %!+_f", length_field);
428 BT_ASSERT_PRE_FIELD_COMMON_IS_SET(length_field, "Length field");
429 sequence_length = length->payload.unsignd;
430 if (sequence->elements) {
431 g_ptr_array_free(sequence->elements, TRUE);
432 bt_put(sequence->length);
433 }
434
435 sequence->elements = g_ptr_array_sized_new((size_t) sequence_length);
436 if (!sequence->elements) {
437 BT_LOGE_STR("Failed to allocate a GPtrArray.");
438 ret = -1;
439 goto end;
440 }
441
442 g_ptr_array_set_free_func(sequence->elements,
443 (GDestroyNotify) bt_put);
444 g_ptr_array_set_size(sequence->elements, (size_t) sequence_length);
445 bt_get(length_field);
446 sequence->length = length_field;
447 bt_field_common_freeze_recursive(length_field);
448
449end:
450 return ret;
451}
452
453static inline
454struct bt_field_common *bt_field_common_structure_get_field_by_name(
455 struct bt_field_common *field, const char *name)
456{
457 struct bt_field_common *ret = NULL;
458 GQuark field_quark;
459 struct bt_field_type_common_structure *structure_ft;
460 struct bt_field_common_structure *structure = BT_FROM_COMMON(field);
461 size_t index;
462 GHashTable *field_name_to_index;
463
464 BT_ASSERT_PRE_NON_NULL(field, "Structure field");
465 BT_ASSERT_PRE_NON_NULL(name, "Field name");
466 BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field,
467 BT_FIELD_TYPE_ID_STRUCT, "Field");
468 structure_ft = BT_FROM_COMMON(field->type);
469 field_name_to_index = structure_ft->field_name_to_index;
470 field_quark = g_quark_from_string(name);
471 if (!g_hash_table_lookup_extended(field_name_to_index,
472 GUINT_TO_POINTER(field_quark),
473 NULL, (gpointer *) &index)) {
474 BT_LOGV("Invalid parameter: no such field in structure field's type: "
475 "struct-field-addr=%p, struct-ft-addr=%p, name=\"%s\"",
476 field, field->type, name);
477 goto error;
478 }
479
480 ret = bt_get(structure->fields->pdata[index]);
481 BT_ASSERT(ret);
482
483error:
484 return ret;
485}
486
487static inline
488struct bt_field_common *bt_field_common_structure_get_field_by_index(
489 struct bt_field_common *field, uint64_t index)
490{
491 struct bt_field_common_structure *structure = BT_FROM_COMMON(field);
492
493 BT_ASSERT_PRE_NON_NULL(field, "Structure field");
494 BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field,
495 BT_FIELD_TYPE_ID_STRUCT, "Field");
496 BT_ASSERT_PRE(index < structure->fields->len,
497 "Index is out of bound: %![struct-field-]+_f, "
498 "index=%" PRIu64 ", count=%u", field, index,
499 structure->fields->len);
500 return bt_get(structure->fields->pdata[index]);
501}
502
503BT_ASSERT_PRE_FUNC
504static inline bool field_to_set_has_expected_type(
505 struct bt_field_common *struct_field,
506 const char *name, struct bt_field_common *value)
507{
508 bool ret = true;
509 struct bt_field_type_common *expected_field_type = NULL;
510
511 expected_field_type =
512 bt_field_type_common_structure_get_field_type_by_name(
513 struct_field->type, name);
514
515 if (bt_field_type_common_compare(expected_field_type, value->type)) {
516 BT_ASSERT_PRE_MSG("Value field's type is different from the expected field type: "
517 "%![value-ft-]+_F, %![expected-ft-]+_F", value->type,
518 expected_field_type);
519 ret = false;
520 goto end;
521 }
522
523end:
524 bt_put(expected_field_type);
525 return ret;
526}
527
528static inline
529int bt_field_common_structure_set_field_by_name(struct bt_field_common *field,
530 const char *name, struct bt_field_common *value)
531{
532 int ret = 0;
533 GQuark field_quark;
534 struct bt_field_common_structure *structure = BT_FROM_COMMON(field);
535 size_t index;
536 GHashTable *field_name_to_index;
537 struct bt_field_type_common_structure *structure_ft;
538
539 BT_ASSERT_PRE_NON_NULL(field, "Structure field");
540 BT_ASSERT_PRE_NON_NULL(name, "Field name");
541 BT_ASSERT_PRE_NON_NULL(value, "Value field");
542 BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_STRUCT,
543 "Parent field");
544 BT_ASSERT_PRE(field_to_set_has_expected_type(field, name, value),
545 "Value field's type is different from the expected field type.");
546 field_quark = g_quark_from_string(name);
547 structure_ft = BT_FROM_COMMON(field->type);
548 field_name_to_index = structure_ft->field_name_to_index;
549 if (!g_hash_table_lookup_extended(field_name_to_index,
550 GUINT_TO_POINTER(field_quark), NULL,
551 (gpointer *) &index)) {
552 BT_LOGV("Invalid parameter: no such field in structure field's type: "
553 "struct-field-addr=%p, struct-ft-addr=%p, "
554 "field-ft-addr=%p, name=\"%s\"",
555 field, field->type, value->type, name);
556 ret = -1;
557 goto end;
558 }
559 bt_get(value);
560 BT_MOVE(structure->fields->pdata[index], value);
561
562end:
563 return ret;
564}
565
566static inline
567struct bt_field_common *bt_field_common_array_get_field(
568 struct bt_field_common *field, uint64_t index,
569 bt_field_common_create_func field_create_func)
570{
571 struct bt_field_common *new_field = NULL;
572 struct bt_field_type_common *field_type = NULL;
573 struct bt_field_common_array *array = BT_FROM_COMMON(field);
574
575 BT_ASSERT_PRE_NON_NULL(field, "Array field");
576 BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_ARRAY, "Field");
577 BT_ASSERT_PRE(index < array->elements->len,
578 "Index is out of bound: %![array-field-]+_f, "
579 "index=%" PRIu64 ", count=%u", field,
580 index, array->elements->len);
581
582 field_type = bt_field_type_common_array_get_element_field_type(
583 field->type);
584 if (array->elements->pdata[(size_t) index]) {
585 new_field = array->elements->pdata[(size_t) index];
586 goto end;
587 }
588
589 /* We don't want to modify this field if it's frozen */
590 BT_ASSERT_PRE_FIELD_COMMON_HOT(field, "Array field");
591 new_field = field_create_func(field_type);
592 array->elements->pdata[(size_t) index] = new_field;
593
594end:
595 bt_put(field_type);
596 bt_get(new_field);
597 return new_field;
598}
599
600static inline
601struct bt_field_common *bt_field_common_sequence_get_field(
602 struct bt_field_common *field, uint64_t index,
603 bt_field_common_create_func field_create_func)
604{
605 struct bt_field_common *new_field = NULL;
606 struct bt_field_type_common *field_type = NULL;
607 struct bt_field_common_sequence *sequence = BT_FROM_COMMON(field);
608
609 BT_ASSERT_PRE_NON_NULL(field, "Sequence field");
610 BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_SEQUENCE,
611 "Field");
612 BT_ASSERT_PRE_NON_NULL(sequence->elements, "Sequence field's element array");
613 BT_ASSERT_PRE(index < sequence->elements->len,
614 "Index is out of bound: %![seq-field-]+_f, "
615 "index=%" PRIu64 ", count=%u", field, index,
616 sequence->elements->len);
617 field_type = bt_field_type_common_sequence_get_element_field_type(
618 field->type);
619 if (sequence->elements->pdata[(size_t) index]) {
620 new_field = sequence->elements->pdata[(size_t) index];
621 goto end;
622 }
623
624 /* We don't want to modify this field if it's frozen */
625 BT_ASSERT_PRE_FIELD_COMMON_HOT(field, "Sequence field");
626 new_field = field_create_func(field_type);
627 sequence->elements->pdata[(size_t) index] = new_field;
628
629end:
630 bt_put(field_type);
631 bt_get(new_field);
632 return new_field;
633}
634
635static inline
636struct bt_field_common *bt_field_common_enumeration_get_container(
637 struct bt_field_common *field,
638 bt_field_common_create_func field_create_func)
639{
640 struct bt_field_common_enumeration *enumeration = BT_FROM_COMMON(field);
641
642 BT_ASSERT_PRE_NON_NULL(field, "Enumeration field");
643 BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field,
644 BT_FIELD_TYPE_ID_ENUM, "Field");
645
646 if (!enumeration->payload) {
647 struct bt_field_type_common_enumeration *enumeration_type;
648
649 /* We don't want to modify this field if it's frozen */
650 BT_ASSERT_PRE_FIELD_COMMON_HOT(field, "Enumeration field");
651
652 enumeration_type = BT_FROM_COMMON(field->type);
653 enumeration->payload =
654 field_create_func(
655 BT_TO_COMMON(enumeration_type->container_ft));
656 }
657
658 return bt_get(enumeration->payload);
659}
660
661static inline
662struct bt_field_common *bt_field_common_variant_get_field(
663 struct bt_field_common *field,
664 struct bt_field_common *tag_field,
665 bt_field_common_create_func field_create_func)
666{
667 struct bt_field_common *new_field = NULL;
668 struct bt_field_common_variant *variant = BT_FROM_COMMON(field);
669 struct bt_field_type_common_variant *variant_type;
670 struct bt_field_type_common *field_type;
671 struct bt_field_common *tag_enum = NULL;
672 struct bt_field_common_integer *tag_enum_integer =
673 BT_FROM_COMMON(field);
674 int64_t tag_enum_value;
675
676 BT_ASSERT_PRE_NON_NULL(field, "Variant field");
677 BT_ASSERT_PRE_NON_NULL(tag_field, "Tag field");
678 BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_VARIANT,
679 "Variant field");
680 BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(tag_field, BT_FIELD_TYPE_ID_ENUM,
681 "Tag field");
682 variant_type = BT_FROM_COMMON(field->type);
683 tag_enum = bt_field_common_enumeration_get_container(tag_field,
684 field_create_func);
685 BT_ASSERT_PRE_NON_NULL(tag_enum, "Tag field's container");
686 tag_enum_integer = BT_FROM_COMMON(tag_enum);
687 BT_ASSERT_PRE(bt_field_common_validate_recursive(tag_field) == 0,
688 "Tag field is invalid: %!+_f", tag_field);
689 tag_enum_value = tag_enum_integer->payload.signd;
690
691 /*
692 * If the variant currently has a tag and a payload, and if the
693 * requested tag value is the same as the current one, return
694 * the current payload instead of creating a fresh one.
695 */
696 if (variant->tag && variant->payload) {
697 struct bt_field_common *cur_tag_container = NULL;
698 struct bt_field_common_integer *cur_tag_enum_integer;
699 int64_t cur_tag_value;
700
701 cur_tag_container =
702 bt_field_common_enumeration_get_container(variant->tag,
703 field_create_func);
704 BT_ASSERT(cur_tag_container);
705 cur_tag_enum_integer = BT_FROM_COMMON(cur_tag_container);
706 bt_put(cur_tag_container);
707 cur_tag_value = cur_tag_enum_integer->payload.signd;
708
709 if (cur_tag_value == tag_enum_value) {
710 new_field = variant->payload;
711 bt_get(new_field);
712 goto end;
713 }
714 }
715
716 /* We don't want to modify this field if it's frozen */
717 BT_ASSERT_PRE_FIELD_COMMON_HOT(field, "Variant field");
718 field_type = bt_field_type_common_variant_get_field_type_signed(
719 variant_type, tag_enum_value);
720
721 /* It's the caller's job to make sure the tag's value is valid */
722 BT_ASSERT_PRE(field_type,
723 "Variant field's type does not contain a field type for "
724 "this tag value: tag-value-signed=%" PRId64 ", "
725 "%![var-ft-]+_F, %![tag-field-]+_f", tag_enum_value,
726 variant_type, tag_field);
727
728 new_field = field_create_func(field_type);
729 if (!new_field) {
730 BT_LOGW("Cannot create field: "
731 "variant-field-addr=%p, variant-ft-addr=%p, "
732 "field-ft-addr=%p", field, field->type, field_type);
733 goto end;
734 }
735
736 bt_put(variant->tag);
737 bt_put(variant->payload);
738 bt_get(new_field);
739 bt_get(tag_field);
740 variant->tag = tag_field;
741 variant->payload = new_field;
742
743end:
744 bt_put(tag_enum);
745 return new_field;
746}
747
748static inline
749struct bt_field_common *bt_field_common_variant_get_current_field(
750 struct bt_field_common *variant_field)
751{
752 struct bt_field_common_variant *variant = BT_FROM_COMMON(variant_field);
753
754 BT_ASSERT_PRE_NON_NULL(variant_field, "Variant field");
755 BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(variant_field,
756 BT_FIELD_TYPE_ID_VARIANT, "Field");
757 return bt_get(variant->payload);
758}
759
760static inline
761struct bt_field_common *bt_field_common_variant_get_tag(
762 struct bt_field_common *variant_field)
763{
764 struct bt_field_common_variant *variant = BT_FROM_COMMON(variant_field);
765
766 BT_ASSERT_PRE_NON_NULL(variant_field, "Variant field");
767 BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(variant_field,
768 BT_FIELD_TYPE_ID_VARIANT, "Field");
769 return bt_get(variant->tag);
770}
771
772static inline
773int bt_field_common_integer_signed_get_value(struct bt_field_common *field,
774 int64_t *value)
775{
776 struct bt_field_common_integer *integer = BT_FROM_COMMON(field);
777
778 BT_ASSERT_PRE_NON_NULL(field, "Integer field");
779 BT_ASSERT_PRE_NON_NULL(value, "Value");
780 BT_ASSERT_PRE_FIELD_COMMON_IS_SET(field, "Integer field");
781 BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field,
782 BT_FIELD_TYPE_ID_INTEGER, "Field");
783 BT_ASSERT_PRE(bt_field_type_common_integer_is_signed(field->type),
784 "Field's type is unsigned: %!+_f", field);
785 *value = integer->payload.signd;
786 return 0;
787}
788
789BT_ASSERT_PRE_FUNC
790static inline bool value_is_in_range_signed(unsigned int size, int64_t value)
791{
792 bool ret = true;
793 int64_t min_value, max_value;
794
795 min_value = -(1ULL << (size - 1));
796 max_value = (1ULL << (size - 1)) - 1;
797 if (value < min_value || value > max_value) {
798 BT_LOGF("Value is out of bounds: value=%" PRId64 ", "
799 "min-value=%" PRId64 ", max-value=%" PRId64,
800 value, min_value, max_value);
801 ret = false;
802 }
803
804 return ret;
805}
806
807static inline
808int bt_field_common_integer_signed_set_value(struct bt_field_common *field,
809 int64_t value)
810{
811 int ret = 0;
812 struct bt_field_common_integer *integer = BT_FROM_COMMON(field);
813 struct bt_field_type_common_integer *integer_type;
814
815 BT_ASSERT_PRE_NON_NULL(field, "Integer field");
816 BT_ASSERT_PRE_FIELD_COMMON_HOT(field, "Integer field");
817 BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field,
818 BT_FIELD_TYPE_ID_INTEGER, "Field");
819 integer_type = BT_FROM_COMMON(field->type);
820 BT_ASSERT_PRE(bt_field_type_common_integer_is_signed(field->type),
821 "Field's type is unsigned: %!+_f", field);
822 BT_ASSERT_PRE(value_is_in_range_signed(integer_type->size, value),
823 "Value is out of bounds: value=%" PRId64 ", %![field-]+_f",
824 value, field);
825 integer->payload.signd = value;
826 bt_field_common_set(field, true);
827 return ret;
828}
829
830static inline
831int bt_field_common_integer_unsigned_get_value(struct bt_field_common *field,
832 uint64_t *value)
833{
834 struct bt_field_common_integer *integer = BT_FROM_COMMON(field);
835
836 BT_ASSERT_PRE_NON_NULL(field, "Integer field");
837 BT_ASSERT_PRE_NON_NULL(value, "Value");
838 BT_ASSERT_PRE_FIELD_COMMON_IS_SET(field, "Integer field");
839 BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field,
840 BT_FIELD_TYPE_ID_INTEGER, "Field");
841 BT_ASSERT_PRE(!bt_field_type_common_integer_is_signed(field->type),
842 "Field's type is signed: %!+_f", field);
843 *value = integer->payload.unsignd;
844 return 0;
845}
846
847BT_ASSERT_PRE_FUNC
848static inline bool value_is_in_range_unsigned(unsigned int size, uint64_t value)
849{
850 bool ret = true;
851 int64_t max_value;
852
853 max_value = (size == 64) ? UINT64_MAX : ((uint64_t) 1 << size) - 1;
854 if (value > max_value) {
855 BT_LOGF("Value is out of bounds: value=%" PRIu64 ", "
856 "max-value=%" PRIu64,
857 value, max_value);
858 ret = false;
859 }
860
861 return ret;
862}
863
864static inline
865int bt_field_common_integer_unsigned_set_value(struct bt_field_common *field,
866 uint64_t value)
867{
868 struct bt_field_common_integer *integer = BT_FROM_COMMON(field);
869 struct bt_field_type_common_integer *integer_type;
870
871 BT_ASSERT_PRE_NON_NULL(field, "Integer field");
872 BT_ASSERT_PRE_FIELD_COMMON_HOT(field, "Integer field");
873 BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field,
874 BT_FIELD_TYPE_ID_INTEGER, "Field");
875 integer_type = BT_FROM_COMMON(field->type);
876 BT_ASSERT_PRE(!bt_field_type_common_integer_is_signed(field->type),
877 "Field's type is signed: %!+_f", field);
878 BT_ASSERT_PRE(value_is_in_range_unsigned(integer_type->size, value),
879 "Value is out of bounds: value=%" PRIu64 ", %![field-]+_f",
880 value, field);
881 integer->payload.unsignd = value;
882 bt_field_common_set(field, true);
883 return 0;
884}
885
886static inline
887struct bt_field_type_enumeration_mapping_iterator *
888bt_field_common_enumeration_get_mappings(struct bt_field_common *field,
889 bt_field_common_create_func field_create_func)
890{
891 int ret;
892 struct bt_field_common *container = NULL;
893 struct bt_field_type_common_integer *integer_type = NULL;
894 struct bt_field_type_enumeration_mapping_iterator *iter = NULL;
895
896 BT_ASSERT_PRE_NON_NULL(field, "Enumeration field");
897 BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field,
898 BT_FIELD_TYPE_ID_ENUM, "Field");
899 container = bt_field_common_enumeration_get_container(field,
900 field_create_func);
901 BT_ASSERT_PRE(container,
902 "Enumeration field has no container field: %!+_f", field);
903 BT_ASSERT(container->type);
904 integer_type = BT_FROM_COMMON(container->type);
905 BT_ASSERT_PRE_FIELD_COMMON_IS_SET(container,
906 "Enumeration field's payload field");
907
908 if (!integer_type->is_signed) {
909 uint64_t value;
910
911 ret = bt_field_common_integer_unsigned_get_value(container,
912 &value);
913 BT_ASSERT(ret == 0);
914 iter = bt_field_type_common_enumeration_unsigned_find_mappings_by_value(
915 field->type, value);
916 } else {
917 int64_t value;
918
919 ret = bt_field_common_integer_signed_get_value(container, &value);
920 BT_ASSERT(ret == 0);
921 iter = bt_field_type_common_enumeration_signed_find_mappings_by_value(
922 field->type, value);
923 }
924
925 bt_put(container);
926 return iter;
927}
928
929static inline
930int bt_field_common_floating_point_get_value(struct bt_field_common *field,
931 double *value)
932{
933 struct bt_field_common_floating_point *floating_point =
934 BT_FROM_COMMON(field);
935
936 BT_ASSERT_PRE_NON_NULL(field, "Floating point number field");
937 BT_ASSERT_PRE_NON_NULL(value, "Value");
938 BT_ASSERT_PRE_FIELD_COMMON_IS_SET(field, "Floating point number field");
939 BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field,
940 BT_FIELD_TYPE_ID_FLOAT, "Field");
941 *value = floating_point->payload;
942 return 0;
943}
944
945static inline
946int bt_field_common_floating_point_set_value(struct bt_field_common *field,
947 double value)
948{
949 struct bt_field_common_floating_point *floating_point =
950 BT_FROM_COMMON(field);
951
952 BT_ASSERT_PRE_NON_NULL(field, "Floating point number field");
953 BT_ASSERT_PRE_FIELD_COMMON_HOT(field, "Floating point number field");
954 BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field,
955 BT_FIELD_TYPE_ID_FLOAT, "Field");
956 floating_point->payload = value;
957 bt_field_common_set(field, true);
958 return 0;
959}
960
961static inline
962const char *bt_field_common_string_get_value(struct bt_field_common *field)
963{
964 struct bt_field_common_string *string = BT_FROM_COMMON(field);
965
966 BT_ASSERT_PRE_NON_NULL(field, "String field");
967 BT_ASSERT_PRE_FIELD_COMMON_IS_SET(field, "String field");
968 BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field,
969 BT_FIELD_TYPE_ID_STRING, "Field");
970 return string->payload->str;
971}
972
973static inline
974int bt_field_common_string_set_value(struct bt_field_common *field,
975 const char *value)
976{
977 struct bt_field_common_string *string = BT_FROM_COMMON(field);
978
979 BT_ASSERT_PRE_NON_NULL(field, "String field");
980 BT_ASSERT_PRE_NON_NULL(value, "Value");
981 BT_ASSERT_PRE_FIELD_COMMON_HOT(field, "String field");
982 BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field,
983 BT_FIELD_TYPE_ID_STRING, "Field");
984
985 if (string->payload) {
986 g_string_assign(string->payload, value);
987 } else {
988 string->payload = g_string_new(value);
989 }
990
991 bt_field_common_set(field, true);
992 return 0;
993}
994
995static inline
996int bt_field_common_string_append(struct bt_field_common *field,
997 const char *value)
998{
999 struct bt_field_common_string *string_field = BT_FROM_COMMON(field);
1000
1001 BT_ASSERT_PRE_NON_NULL(field, "String field");
1002 BT_ASSERT_PRE_NON_NULL(value, "Value");
1003 BT_ASSERT_PRE_FIELD_COMMON_HOT(field, "String field");
1004 BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field,
1005 BT_FIELD_TYPE_ID_STRING, "Field");
1006
1007 if (string_field->payload) {
1008 g_string_append(string_field->payload, value);
1009 } else {
1010 string_field->payload = g_string_new(value);
1011 }
1012
1013 bt_field_common_set(field, true);
1014 return 0;
1015}
1016
1017static inline
1018int bt_field_common_string_append_len(struct bt_field_common *field,
1019 const char *value, unsigned int length)
1020{
1021 struct bt_field_common_string *string_field = BT_FROM_COMMON(field);
1022
1023 BT_ASSERT_PRE_NON_NULL(field, "String field");
1024 BT_ASSERT_PRE_NON_NULL(value, "Value");
1025 BT_ASSERT_PRE_FIELD_COMMON_HOT(field, "String field");
1026 BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field,
1027 BT_FIELD_TYPE_ID_STRING, "Field");
1028
1029 /* make sure no null bytes are appended */
1030 BT_ASSERT_PRE(memchr(value, '\0', length) == NULL,
1031 "String value to append contains a null character: "
1032 "partial-value=\"%.32s\", length=%u", value, length);
1033
1034 if (string_field->payload) {
1035 g_string_append_len(string_field->payload, value, length);
1036 } else {
1037 string_field->payload = g_string_new_len(value, length);
1038 }
1039
1040 bt_field_common_set(field, true);
1041 return 0;
1042}
1043
1044static inline
1045int _bt_field_validate_recursive(struct bt_field *field)
1046{
1047 return _bt_field_common_validate_recursive((void *) field);
1048}
1049
1050static inline
1051void _bt_field_freeze_recursive(struct bt_field *field)
1052{
1053 return _bt_field_common_freeze_recursive((void *) field);
1054}
1055
1056static inline
1057bt_bool _bt_field_is_set_recursive(struct bt_field *field)
1058{
1059 return _bt_field_common_is_set_recursive((void *) field);
1060}
1061
1062static inline
1063void _bt_field_reset_recursive(struct bt_field *field)
1064{
1065 _bt_field_common_reset_recursive((void *) field);
1066}
1067
1068static inline
1069void _bt_field_set(struct bt_field *field, bool value)
1070{
1071 _bt_field_common_set((void *) field, value);
1072}
2e8876d3 1073
2e33ac5a 1074#endif /* BABELTRACE_CTF_IR_FIELDS_INTERNAL_H */
This page took 0.088663 seconds and 4 git commands to generate.