Split CTF IR and CTF writer APIs and implementations
[babeltrace.git] / include / babeltrace / ctf-ir / fields-internal.h
1 #ifndef BABELTRACE_CTF_IR_FIELDS_INTERNAL_H
2 #define BABELTRACE_CTF_IR_FIELDS_INTERNAL_H
3
4 /*
5 * Babeltrace - CTF IR: Event Fields internal
6 *
7 * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
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
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>
34 #include <babeltrace/object-internal.h>
35 #include <babeltrace/babeltrace-internal.h>
36 #include <babeltrace/types.h>
37 #include <stdint.h>
38 #include <inttypes.h>
39 #include <stdbool.h>
40 #include <glib.h>
41
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))
47
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
55 struct bt_field;
56 struct bt_field_common;
57
58 typedef void (*bt_field_common_method_freeze)(struct bt_field_common *);
59 typedef int (*bt_field_common_method_validate)(struct bt_field_common *);
60 typedef struct bt_field_common *(*bt_field_common_method_copy)(
61 struct bt_field_common *);
62 typedef bt_bool (*bt_field_common_method_is_set)(struct bt_field_common *);
63 typedef void (*bt_field_common_method_reset)(struct bt_field_common *);
64
65 struct 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
73 struct bt_field_common {
74 struct bt_object base;
75 struct bt_field_type_common *type;
76 struct bt_field_common_methods *methods;
77 bool payload_set;
78 bool frozen;
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;
91 };
92
93 struct bt_field_common_integer {
94 struct bt_field_common common;
95 union {
96 int64_t signd;
97 uint64_t unsignd;
98 } payload;
99 };
100
101 struct bt_field_common_enumeration {
102 struct bt_field_common common;
103 struct bt_field_common *payload;
104 };
105
106 struct bt_field_common_floating_point {
107 struct bt_field_common common;
108 double payload;
109 };
110
111 struct bt_field_common_structure {
112 struct bt_field_common common;
113 GPtrArray *fields; /* Array of pointers to struct bt_field_common */
114 };
115
116 struct bt_field_common_variant {
117 struct bt_field_common common;
118 struct bt_field_common *tag;
119 struct bt_field_common *payload;
120 };
121
122 struct bt_field_common_array {
123 struct bt_field_common common;
124 GPtrArray *elements; /* Array of pointers to struct bt_field_common */
125 };
126
127 struct 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 */
131 };
132
133 struct bt_field_common_string {
134 struct bt_field_common common;
135 GString *payload;
136 };
137
138 static inline
139 struct 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
147 BT_HIDDEN
148 int64_t bt_field_sequence_get_int_length(struct bt_field *field);
149
150 BT_HIDDEN
151 struct bt_field_common *bt_field_common_copy(struct bt_field_common *field);
152
153 BT_HIDDEN
154 int 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
160 BT_HIDDEN
161 int 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
166 BT_HIDDEN
167 int bt_field_common_generic_validate(struct bt_field_common *field);
168
169 BT_HIDDEN
170 int bt_field_common_enumeration_validate_recursive(
171 struct bt_field_common *field);
172
173 BT_HIDDEN
174 int bt_field_common_structure_validate_recursive(struct bt_field_common *field);
175
176 BT_HIDDEN
177 int bt_field_common_variant_validate_recursive(struct bt_field_common *field);
178
179 BT_HIDDEN
180 int bt_field_common_array_validate_recursive(struct bt_field_common *field);
181
182 BT_HIDDEN
183 int bt_field_common_sequence_validate_recursive(struct bt_field_common *field);
184
185 BT_HIDDEN
186 void bt_field_common_generic_reset(struct bt_field_common *field);
187
188 BT_HIDDEN
189 void bt_field_common_enumeration_reset_recursive(struct bt_field_common *field);
190
191 BT_HIDDEN
192 void bt_field_common_structure_reset_recursive(struct bt_field_common *field);
193
194 BT_HIDDEN
195 void bt_field_common_variant_reset_recursive(struct bt_field_common *field);
196
197 BT_HIDDEN
198 void bt_field_common_array_reset_recursive(struct bt_field_common *field);
199
200 BT_HIDDEN
201 void bt_field_common_sequence_reset_recursive(struct bt_field_common *field);
202
203 BT_HIDDEN
204 void bt_field_common_string_reset(struct bt_field_common *field);
205
206 BT_HIDDEN
207 void bt_field_common_generic_freeze(struct bt_field_common *field);
208
209 BT_HIDDEN
210 void bt_field_common_enumeration_freeze_recursive(struct bt_field_common *field);
211
212 BT_HIDDEN
213 void bt_field_common_structure_freeze_recursive(struct bt_field_common *field);
214
215 BT_HIDDEN
216 void bt_field_common_variant_freeze_recursive(struct bt_field_common *field);
217
218 BT_HIDDEN
219 void bt_field_common_array_freeze_recursive(struct bt_field_common *field);
220
221 BT_HIDDEN
222 void bt_field_common_sequence_freeze_recursive(struct bt_field_common *field);
223
224 BT_HIDDEN
225 void _bt_field_common_freeze_recursive(struct bt_field_common *field);
226
227 BT_HIDDEN
228 bt_bool bt_field_common_generic_is_set(struct bt_field_common *field);
229
230 BT_HIDDEN
231 bt_bool bt_field_common_enumeration_is_set_recursive(
232 struct bt_field_common *field);
233
234 BT_HIDDEN
235 bt_bool bt_field_common_structure_is_set_recursive(
236 struct bt_field_common *field);
237
238 BT_HIDDEN
239 bt_bool bt_field_common_variant_is_set_recursive(struct bt_field_common *field);
240
241 BT_HIDDEN
242 bt_bool bt_field_common_array_is_set_recursive(struct bt_field_common *field);
243
244 BT_HIDDEN
245 bt_bool bt_field_common_sequence_is_set_recursive(struct bt_field_common *field);
246
247 BT_HIDDEN
248 void bt_field_common_integer_destroy(struct bt_object *obj);
249
250 BT_HIDDEN
251 void bt_field_common_enumeration_destroy_recursive(struct bt_object *obj);
252
253 BT_HIDDEN
254 void bt_field_common_floating_point_destroy(struct bt_object *obj);
255
256 BT_HIDDEN
257 void bt_field_common_structure_destroy_recursive(struct bt_object *obj);
258
259 BT_HIDDEN
260 void bt_field_common_variant_destroy_recursive(struct bt_object *obj);
261
262 BT_HIDDEN
263 void bt_field_common_array_destroy_recursive(struct bt_object *obj);
264
265 BT_HIDDEN
266 void bt_field_common_sequence_destroy_recursive(struct bt_object *obj);
267
268 BT_HIDDEN
269 void bt_field_common_string_destroy(struct bt_object *obj);
270
271 #ifdef BT_DEV_MODE
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
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
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)
289 # define bt_field_freeze_recursive(_field)
290 # define bt_field_is_set_recursive(_field) (BT_FALSE)
291 # define bt_field_reset_recursive(_field) (BT_TRUE)
292 # define bt_field_set(_field, _val)
293 #endif
294
295 BT_ASSERT_FUNC
296 static 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
303 static inline
304 int _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
320 end:
321 return ret;
322 }
323
324 static inline
325 void _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
332 static inline
333 void _bt_field_common_set(struct bt_field_common *field, bool value)
334 {
335 BT_ASSERT(field);
336 field->payload_set = value;
337 }
338
339 static inline
340 bt_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
352 end:
353 return is_set;
354 }
355
356 static inline
357 void 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
369 static inline
370 struct 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
380 static inline
381 int64_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
395 end:
396 return ret;
397 }
398
399 static inline
400 struct 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
411 static inline
412 int 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
449 end:
450 return ret;
451 }
452
453 static inline
454 struct 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
483 error:
484 return ret;
485 }
486
487 static inline
488 struct 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
503 BT_ASSERT_PRE_FUNC
504 static 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
523 end:
524 bt_put(expected_field_type);
525 return ret;
526 }
527
528 static inline
529 int 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
562 end:
563 return ret;
564 }
565
566 static inline
567 struct 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
594 end:
595 bt_put(field_type);
596 bt_get(new_field);
597 return new_field;
598 }
599
600 static inline
601 struct 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
629 end:
630 bt_put(field_type);
631 bt_get(new_field);
632 return new_field;
633 }
634
635 static inline
636 struct 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
661 static inline
662 struct 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
743 end:
744 bt_put(tag_enum);
745 return new_field;
746 }
747
748 static inline
749 struct 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
760 static inline
761 struct 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
772 static inline
773 int 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
789 BT_ASSERT_PRE_FUNC
790 static 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
807 static inline
808 int 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
830 static inline
831 int 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
847 BT_ASSERT_PRE_FUNC
848 static 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
864 static inline
865 int 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
886 static inline
887 struct bt_field_type_enumeration_mapping_iterator *
888 bt_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
929 static inline
930 int 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
945 static inline
946 int 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
961 static inline
962 const 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
973 static inline
974 int 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
995 static inline
996 int 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
1017 static inline
1018 int 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
1044 static inline
1045 int _bt_field_validate_recursive(struct bt_field *field)
1046 {
1047 return _bt_field_common_validate_recursive((void *) field);
1048 }
1049
1050 static inline
1051 void _bt_field_freeze_recursive(struct bt_field *field)
1052 {
1053 return _bt_field_common_freeze_recursive((void *) field);
1054 }
1055
1056 static inline
1057 bt_bool _bt_field_is_set_recursive(struct bt_field *field)
1058 {
1059 return _bt_field_common_is_set_recursive((void *) field);
1060 }
1061
1062 static inline
1063 void _bt_field_reset_recursive(struct bt_field *field)
1064 {
1065 _bt_field_common_reset_recursive((void *) field);
1066 }
1067
1068 static inline
1069 void _bt_field_set(struct bt_field *field, bool value)
1070 {
1071 _bt_field_common_set((void *) field, value);
1072 }
1073
1074 #endif /* BABELTRACE_CTF_IR_FIELDS_INTERNAL_H */
This page took 0.080866 seconds and 5 git commands to generate.