ctf plugin: notif iter: use "borrow" functions for metadata where possible
[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 BT_HIDDEN
139 int64_t bt_field_sequence_get_int_length(struct bt_field *field);
140
141 BT_HIDDEN
142 struct bt_field_common *bt_field_common_copy(struct bt_field_common *field);
143
144 BT_HIDDEN
145 int bt_field_common_structure_initialize(struct bt_field_common *field,
146 struct bt_field_type_common *type,
147 bt_object_release_func release_func,
148 struct bt_field_common_methods *methods,
149 bt_field_common_create_func field_create_func);
150
151 BT_HIDDEN
152 int bt_field_common_array_initialize(struct bt_field_common *field,
153 struct bt_field_type_common *type,
154 bt_object_release_func release_func,
155 struct bt_field_common_methods *methods);
156
157 BT_HIDDEN
158 int bt_field_common_generic_validate(struct bt_field_common *field);
159
160 BT_HIDDEN
161 int bt_field_common_enumeration_validate_recursive(
162 struct bt_field_common *field);
163
164 BT_HIDDEN
165 int bt_field_common_structure_validate_recursive(struct bt_field_common *field);
166
167 BT_HIDDEN
168 int bt_field_common_variant_validate_recursive(struct bt_field_common *field);
169
170 BT_HIDDEN
171 int bt_field_common_array_validate_recursive(struct bt_field_common *field);
172
173 BT_HIDDEN
174 int bt_field_common_sequence_validate_recursive(struct bt_field_common *field);
175
176 BT_HIDDEN
177 void bt_field_common_generic_reset(struct bt_field_common *field);
178
179 BT_HIDDEN
180 void bt_field_common_enumeration_reset_recursive(struct bt_field_common *field);
181
182 BT_HIDDEN
183 void bt_field_common_structure_reset_recursive(struct bt_field_common *field);
184
185 BT_HIDDEN
186 void bt_field_common_variant_reset_recursive(struct bt_field_common *field);
187
188 BT_HIDDEN
189 void bt_field_common_array_reset_recursive(struct bt_field_common *field);
190
191 BT_HIDDEN
192 void bt_field_common_sequence_reset_recursive(struct bt_field_common *field);
193
194 BT_HIDDEN
195 void bt_field_common_string_reset(struct bt_field_common *field);
196
197 BT_HIDDEN
198 void bt_field_common_generic_freeze(struct bt_field_common *field);
199
200 BT_HIDDEN
201 void bt_field_common_enumeration_freeze_recursive(struct bt_field_common *field);
202
203 BT_HIDDEN
204 void bt_field_common_structure_freeze_recursive(struct bt_field_common *field);
205
206 BT_HIDDEN
207 void bt_field_common_variant_freeze_recursive(struct bt_field_common *field);
208
209 BT_HIDDEN
210 void bt_field_common_array_freeze_recursive(struct bt_field_common *field);
211
212 BT_HIDDEN
213 void bt_field_common_sequence_freeze_recursive(struct bt_field_common *field);
214
215 BT_HIDDEN
216 void _bt_field_common_freeze_recursive(struct bt_field_common *field);
217
218 BT_HIDDEN
219 bt_bool bt_field_common_generic_is_set(struct bt_field_common *field);
220
221 BT_HIDDEN
222 bt_bool bt_field_common_enumeration_is_set_recursive(
223 struct bt_field_common *field);
224
225 BT_HIDDEN
226 bt_bool bt_field_common_structure_is_set_recursive(
227 struct bt_field_common *field);
228
229 BT_HIDDEN
230 bt_bool bt_field_common_variant_is_set_recursive(struct bt_field_common *field);
231
232 BT_HIDDEN
233 bt_bool bt_field_common_array_is_set_recursive(struct bt_field_common *field);
234
235 BT_HIDDEN
236 bt_bool bt_field_common_sequence_is_set_recursive(struct bt_field_common *field);
237
238 BT_HIDDEN
239 void bt_field_common_integer_destroy(struct bt_object *obj);
240
241 BT_HIDDEN
242 void bt_field_common_enumeration_destroy_recursive(struct bt_object *obj);
243
244 BT_HIDDEN
245 void bt_field_common_floating_point_destroy(struct bt_object *obj);
246
247 BT_HIDDEN
248 void bt_field_common_structure_destroy_recursive(struct bt_object *obj);
249
250 BT_HIDDEN
251 void bt_field_common_variant_destroy_recursive(struct bt_object *obj);
252
253 BT_HIDDEN
254 void bt_field_common_array_destroy_recursive(struct bt_object *obj);
255
256 BT_HIDDEN
257 void bt_field_common_sequence_destroy_recursive(struct bt_object *obj);
258
259 BT_HIDDEN
260 void bt_field_common_string_destroy(struct bt_object *obj);
261
262 #ifdef BT_DEV_MODE
263 # define bt_field_common_validate_recursive _bt_field_common_validate_recursive
264 # define bt_field_common_freeze_recursive _bt_field_common_freeze_recursive
265 # define bt_field_common_is_set_recursive _bt_field_common_is_set_recursive
266 # define bt_field_common_reset_recursive _bt_field_common_reset_recursive
267 # define bt_field_common_set _bt_field_common_set
268 # define bt_field_validate_recursive _bt_field_validate_recursive
269 # define bt_field_freeze_recursive _bt_field_freeze_recursive
270 # define bt_field_is_set_recursive _bt_field_is_set_recursive
271 # define bt_field_reset_recursive _bt_field_reset_recursive
272 # define bt_field_set _bt_field_set
273 #else
274 # define bt_field_common_validate_recursive(_field) (-1)
275 # define bt_field_common_freeze_recursive(_field)
276 # define bt_field_common_is_set_recursive(_field) (BT_FALSE)
277 # define bt_field_common_reset_recursive(_field) (BT_TRUE)
278 # define bt_field_common_set(_field, _val)
279 # define bt_field_validate_recursive(_field) (-1)
280 # define bt_field_freeze_recursive(_field)
281 # define bt_field_is_set_recursive(_field) (BT_FALSE)
282 # define bt_field_reset_recursive(_field) (BT_TRUE)
283 # define bt_field_set(_field, _val)
284 #endif
285
286 BT_ASSERT_FUNC
287 static inline bool field_type_common_has_known_id(
288 struct bt_field_type_common *ft)
289 {
290 return ft->id > BT_FIELD_TYPE_ID_UNKNOWN ||
291 ft->id < BT_FIELD_TYPE_ID_NR;
292 }
293
294 static inline
295 int _bt_field_common_validate_recursive(struct bt_field_common *field)
296 {
297 int ret = 0;
298
299 if (!field) {
300 BT_ASSERT_PRE_MSG("%s", "Invalid field: field is NULL.");
301 ret = -1;
302 goto end;
303 }
304
305 BT_ASSERT(field_type_common_has_known_id(field->type));
306
307 if (field->methods->validate) {
308 ret = field->methods->validate(field);
309 }
310
311 end:
312 return ret;
313 }
314
315 static inline
316 void _bt_field_common_reset_recursive(struct bt_field_common *field)
317 {
318 BT_ASSERT(field);
319 BT_ASSERT(field->methods->reset);
320 field->methods->reset(field);
321 }
322
323 static inline
324 void _bt_field_common_set(struct bt_field_common *field, bool value)
325 {
326 BT_ASSERT(field);
327 field->payload_set = value;
328 }
329
330 static inline
331 bt_bool _bt_field_common_is_set_recursive(struct bt_field_common *field)
332 {
333 bt_bool is_set = BT_FALSE;
334
335 if (!field) {
336 goto end;
337 }
338
339 BT_ASSERT(field_type_common_has_known_id(field->type));
340 BT_ASSERT(field->methods->is_set);
341 is_set = field->methods->is_set(field);
342
343 end:
344 return is_set;
345 }
346
347 static inline
348 void bt_field_common_initialize(struct bt_field_common *field,
349 struct bt_field_type_common *ft,
350 bt_object_release_func release_func,
351 struct bt_field_common_methods *methods)
352 {
353 BT_ASSERT(field);
354 BT_ASSERT(ft);
355 bt_object_init(field, release_func);
356 field->methods = methods;
357 field->type = bt_get(ft);
358 }
359
360 static inline
361 struct bt_field_type_common *bt_field_common_borrow_type(
362 struct bt_field_common *field)
363 {
364 struct bt_field_type_common *ret = NULL;
365
366 BT_ASSERT_PRE_NON_NULL(field, "Field");
367 ret = field->type;
368 return ret;
369 }
370
371 static inline
372 int64_t bt_field_common_sequence_get_int_length(struct bt_field_common *field)
373 {
374 struct bt_field_common_sequence *sequence = BT_FROM_COMMON(field);
375 int64_t ret;
376
377 BT_ASSERT(field);
378 BT_ASSERT(field->type->id == BT_FIELD_TYPE_ID_SEQUENCE);
379 if (!sequence->length) {
380 ret = -1;
381 goto end;
382 }
383
384 ret = (int64_t) sequence->elements->len;
385
386 end:
387 return ret;
388 }
389
390 static inline
391 struct bt_field_common *bt_field_common_sequence_borrow_length(
392 struct bt_field_common *field)
393 {
394 struct bt_field_common_sequence *sequence = BT_FROM_COMMON(field);
395
396 BT_ASSERT_PRE_NON_NULL(field, "Sequence field");
397 BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_SEQUENCE,
398 "Field");
399 return sequence->length;
400 }
401
402 static inline
403 int bt_field_common_sequence_set_length(struct bt_field_common *field,
404 struct bt_field_common *length_field)
405 {
406 int ret = 0;
407 struct bt_field_common_integer *length = BT_FROM_COMMON(length_field);
408 struct bt_field_common_sequence *sequence = BT_FROM_COMMON(field);
409 uint64_t sequence_length;
410
411 BT_ASSERT_PRE_NON_NULL(field, "Sequence field");
412 BT_ASSERT_PRE_NON_NULL(length_field, "Length field");
413 BT_ASSERT_PRE_FIELD_COMMON_HOT(field, "Sequence field");
414 BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(length_field,
415 BT_FIELD_TYPE_ID_INTEGER, "Length field");
416 BT_ASSERT_PRE(
417 !bt_field_type_common_integer_is_signed(length->common.type),
418 "Length field's type is signed: %!+_f", length_field);
419 BT_ASSERT_PRE_FIELD_COMMON_IS_SET(length_field, "Length field");
420 sequence_length = length->payload.unsignd;
421 if (sequence->elements) {
422 g_ptr_array_free(sequence->elements, TRUE);
423 bt_put(sequence->length);
424 }
425
426 sequence->elements = g_ptr_array_sized_new((size_t) sequence_length);
427 if (!sequence->elements) {
428 BT_LOGE_STR("Failed to allocate a GPtrArray.");
429 ret = -1;
430 goto end;
431 }
432
433 g_ptr_array_set_free_func(sequence->elements,
434 (GDestroyNotify) bt_put);
435 g_ptr_array_set_size(sequence->elements, (size_t) sequence_length);
436 bt_get(length_field);
437 sequence->length = length_field;
438 bt_field_common_freeze_recursive(length_field);
439
440 end:
441 return ret;
442 }
443
444 static inline
445 struct bt_field_common *bt_field_common_structure_borrow_field_by_name(
446 struct bt_field_common *field, const char *name)
447 {
448 struct bt_field_common *ret = NULL;
449 GQuark field_quark;
450 struct bt_field_type_common_structure *structure_ft;
451 struct bt_field_common_structure *structure = BT_FROM_COMMON(field);
452 size_t index;
453 GHashTable *field_name_to_index;
454
455 BT_ASSERT_PRE_NON_NULL(field, "Structure field");
456 BT_ASSERT_PRE_NON_NULL(name, "Field name");
457 BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field,
458 BT_FIELD_TYPE_ID_STRUCT, "Field");
459 structure_ft = BT_FROM_COMMON(field->type);
460 field_name_to_index = structure_ft->field_name_to_index;
461 field_quark = g_quark_from_string(name);
462 if (!g_hash_table_lookup_extended(field_name_to_index,
463 GUINT_TO_POINTER(field_quark),
464 NULL, (gpointer *) &index)) {
465 BT_LOGV("Invalid parameter: no such field in structure field's type: "
466 "struct-field-addr=%p, struct-ft-addr=%p, name=\"%s\"",
467 field, field->type, name);
468 goto error;
469 }
470
471 ret = structure->fields->pdata[index];
472 BT_ASSERT(ret);
473
474 error:
475 return ret;
476 }
477
478 static inline
479 struct bt_field_common *bt_field_common_structure_borrow_field_by_index(
480 struct bt_field_common *field, uint64_t index)
481 {
482 struct bt_field_common_structure *structure = BT_FROM_COMMON(field);
483
484 BT_ASSERT_PRE_NON_NULL(field, "Structure field");
485 BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field,
486 BT_FIELD_TYPE_ID_STRUCT, "Field");
487 BT_ASSERT_PRE(index < structure->fields->len,
488 "Index is out of bound: %![struct-field-]+_f, "
489 "index=%" PRIu64 ", count=%u", field, index,
490 structure->fields->len);
491 return structure->fields->pdata[index];
492 }
493
494 BT_ASSERT_PRE_FUNC
495 static inline bool field_to_set_has_expected_type(
496 struct bt_field_common *struct_field,
497 const char *name, struct bt_field_common *value)
498 {
499 bool ret = true;
500 struct bt_field_type_common *expected_field_type = NULL;
501
502 expected_field_type =
503 bt_field_type_common_structure_borrow_field_type_by_name(
504 struct_field->type, name);
505
506 if (bt_field_type_common_compare(expected_field_type, value->type)) {
507 BT_ASSERT_PRE_MSG("Value field's type is different from the expected field type: "
508 "%![value-ft-]+_F, %![expected-ft-]+_F", value->type,
509 expected_field_type);
510 ret = false;
511 goto end;
512 }
513
514 end:
515 return ret;
516 }
517
518 static inline
519 int bt_field_common_structure_set_field_by_name(struct bt_field_common *field,
520 const char *name, struct bt_field_common *value)
521 {
522 int ret = 0;
523 GQuark field_quark;
524 struct bt_field_common_structure *structure = BT_FROM_COMMON(field);
525 size_t index;
526 GHashTable *field_name_to_index;
527 struct bt_field_type_common_structure *structure_ft;
528
529 BT_ASSERT_PRE_NON_NULL(field, "Structure field");
530 BT_ASSERT_PRE_NON_NULL(name, "Field name");
531 BT_ASSERT_PRE_NON_NULL(value, "Value field");
532 BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_STRUCT,
533 "Parent field");
534 BT_ASSERT_PRE(field_to_set_has_expected_type(field, name, value),
535 "Value field's type is different from the expected field type.");
536 field_quark = g_quark_from_string(name);
537 structure_ft = BT_FROM_COMMON(field->type);
538 field_name_to_index = structure_ft->field_name_to_index;
539 if (!g_hash_table_lookup_extended(field_name_to_index,
540 GUINT_TO_POINTER(field_quark), NULL,
541 (gpointer *) &index)) {
542 BT_LOGV("Invalid parameter: no such field in structure field's type: "
543 "struct-field-addr=%p, struct-ft-addr=%p, "
544 "field-ft-addr=%p, name=\"%s\"",
545 field, field->type, value->type, name);
546 ret = -1;
547 goto end;
548 }
549 bt_get(value);
550 BT_MOVE(structure->fields->pdata[index], value);
551
552 end:
553 return ret;
554 }
555
556 static inline
557 struct bt_field_common *bt_field_common_array_borrow_field(
558 struct bt_field_common *field, uint64_t index,
559 bt_field_common_create_func field_create_func)
560 {
561 struct bt_field_common *new_field = NULL;
562 struct bt_field_type_common *field_type = NULL;
563 struct bt_field_common_array *array = BT_FROM_COMMON(field);
564
565 BT_ASSERT_PRE_NON_NULL(field, "Array field");
566 BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_ARRAY, "Field");
567 BT_ASSERT_PRE(index < array->elements->len,
568 "Index is out of bound: %![array-field-]+_f, "
569 "index=%" PRIu64 ", count=%u", field,
570 index, array->elements->len);
571
572 field_type = bt_field_type_common_array_borrow_element_field_type(
573 field->type);
574 if (array->elements->pdata[(size_t) index]) {
575 new_field = array->elements->pdata[(size_t) index];
576 goto end;
577 }
578
579 /* We don't want to modify this field if it's frozen */
580 BT_ASSERT_PRE_FIELD_COMMON_HOT(field, "Array field");
581 new_field = field_create_func(field_type);
582 array->elements->pdata[(size_t) index] = new_field;
583
584 end:
585 return new_field;
586 }
587
588 static inline
589 struct bt_field_common *bt_field_common_sequence_borrow_field(
590 struct bt_field_common *field, uint64_t index,
591 bt_field_common_create_func field_create_func)
592 {
593 struct bt_field_common *new_field = NULL;
594 struct bt_field_type_common *field_type = NULL;
595 struct bt_field_common_sequence *sequence = BT_FROM_COMMON(field);
596
597 BT_ASSERT_PRE_NON_NULL(field, "Sequence field");
598 BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_SEQUENCE,
599 "Field");
600 BT_ASSERT_PRE_NON_NULL(sequence->elements, "Sequence field's element array");
601 BT_ASSERT_PRE(index < sequence->elements->len,
602 "Index is out of bound: %![seq-field-]+_f, "
603 "index=%" PRIu64 ", count=%u", field, index,
604 sequence->elements->len);
605 field_type = bt_field_type_common_sequence_borrow_element_field_type(
606 field->type);
607 if (sequence->elements->pdata[(size_t) index]) {
608 new_field = sequence->elements->pdata[(size_t) index];
609 goto end;
610 }
611
612 /* We don't want to modify this field if it's frozen */
613 BT_ASSERT_PRE_FIELD_COMMON_HOT(field, "Sequence field");
614 new_field = field_create_func(field_type);
615 sequence->elements->pdata[(size_t) index] = new_field;
616
617 end:
618 return new_field;
619 }
620
621 static inline
622 struct bt_field_common *bt_field_common_enumeration_borrow_container(
623 struct bt_field_common *field,
624 bt_field_common_create_func field_create_func)
625 {
626 struct bt_field_common_enumeration *enumeration = BT_FROM_COMMON(field);
627
628 BT_ASSERT_PRE_NON_NULL(field, "Enumeration field");
629 BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field,
630 BT_FIELD_TYPE_ID_ENUM, "Field");
631
632 if (!enumeration->payload) {
633 struct bt_field_type_common_enumeration *enumeration_type;
634
635 /* We don't want to modify this field if it's frozen */
636 BT_ASSERT_PRE_FIELD_COMMON_HOT(field, "Enumeration field");
637
638 enumeration_type = BT_FROM_COMMON(field->type);
639 enumeration->payload =
640 field_create_func(
641 BT_TO_COMMON(enumeration_type->container_ft));
642 }
643
644 return enumeration->payload;
645 }
646
647 static inline
648 struct bt_field_common *bt_field_common_variant_borrow_field(
649 struct bt_field_common *field,
650 struct bt_field_common *tag_field,
651 bt_field_common_create_func field_create_func)
652 {
653 struct bt_field_common *new_field = NULL;
654 struct bt_field_common_variant *variant = BT_FROM_COMMON(field);
655 struct bt_field_type_common_variant *variant_type;
656 struct bt_field_type_common *field_type;
657 struct bt_field_common *tag_enum = NULL;
658 struct bt_field_common_integer *tag_enum_integer =
659 BT_FROM_COMMON(field);
660 int64_t tag_enum_value;
661
662 BT_ASSERT_PRE_NON_NULL(field, "Variant field");
663 BT_ASSERT_PRE_NON_NULL(tag_field, "Tag field");
664 BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_VARIANT,
665 "Variant field");
666 BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(tag_field, BT_FIELD_TYPE_ID_ENUM,
667 "Tag field");
668 variant_type = BT_FROM_COMMON(field->type);
669 tag_enum = bt_field_common_enumeration_borrow_container(tag_field,
670 field_create_func);
671 BT_ASSERT_PRE_NON_NULL(tag_enum, "Tag field's container");
672 tag_enum_integer = BT_FROM_COMMON(tag_enum);
673 BT_ASSERT_PRE(bt_field_common_validate_recursive(tag_field) == 0,
674 "Tag field is invalid: %!+_f", tag_field);
675 tag_enum_value = tag_enum_integer->payload.signd;
676
677 /*
678 * If the variant currently has a tag and a payload, and if the
679 * requested tag value is the same as the current one, return
680 * the current payload instead of creating a fresh one.
681 */
682 if (variant->tag && variant->payload) {
683 struct bt_field_common *cur_tag_container = NULL;
684 struct bt_field_common_integer *cur_tag_enum_integer;
685 int64_t cur_tag_value;
686
687 cur_tag_container =
688 bt_field_common_enumeration_borrow_container(
689 variant->tag, field_create_func);
690 BT_ASSERT(cur_tag_container);
691 cur_tag_enum_integer = BT_FROM_COMMON(cur_tag_container);
692 cur_tag_value = cur_tag_enum_integer->payload.signd;
693
694 if (cur_tag_value == tag_enum_value) {
695 new_field = variant->payload;
696 goto end;
697 }
698 }
699
700 /* We don't want to modify this field if it's frozen */
701 BT_ASSERT_PRE_FIELD_COMMON_HOT(field, "Variant field");
702 field_type = bt_field_type_common_variant_borrow_field_type_signed(
703 variant_type, tag_enum_value);
704
705 /* It's the caller's job to make sure the tag's value is valid */
706 BT_ASSERT_PRE(field_type,
707 "Variant field's type does not contain a field type for "
708 "this tag value: tag-value-signed=%" PRId64 ", "
709 "%![var-ft-]+_F, %![tag-field-]+_f", tag_enum_value,
710 variant_type, tag_field);
711
712 new_field = field_create_func(field_type);
713 if (!new_field) {
714 BT_LOGW("Cannot create field: "
715 "variant-field-addr=%p, variant-ft-addr=%p, "
716 "field-ft-addr=%p", field, field->type, field_type);
717 goto end;
718 }
719
720 bt_put(variant->tag);
721 bt_put(variant->payload);
722 variant->tag = bt_get(tag_field);
723 variant->payload = new_field;
724
725 end:
726 return new_field;
727 }
728
729 static inline
730 struct bt_field_common *bt_field_common_variant_borrow_current_field(
731 struct bt_field_common *variant_field)
732 {
733 struct bt_field_common_variant *variant = BT_FROM_COMMON(variant_field);
734
735 BT_ASSERT_PRE_NON_NULL(variant_field, "Variant field");
736 BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(variant_field,
737 BT_FIELD_TYPE_ID_VARIANT, "Field");
738 return variant->payload;
739 }
740
741 static inline
742 struct bt_field_common *bt_field_common_variant_borrow_tag(
743 struct bt_field_common *variant_field)
744 {
745 struct bt_field_common_variant *variant = BT_FROM_COMMON(variant_field);
746
747 BT_ASSERT_PRE_NON_NULL(variant_field, "Variant field");
748 BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(variant_field,
749 BT_FIELD_TYPE_ID_VARIANT, "Field");
750 return variant->tag;
751 }
752
753 static inline
754 int bt_field_common_integer_signed_get_value(struct bt_field_common *field,
755 int64_t *value)
756 {
757 struct bt_field_common_integer *integer = BT_FROM_COMMON(field);
758
759 BT_ASSERT_PRE_NON_NULL(field, "Integer field");
760 BT_ASSERT_PRE_NON_NULL(value, "Value");
761 BT_ASSERT_PRE_FIELD_COMMON_IS_SET(field, "Integer field");
762 BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field,
763 BT_FIELD_TYPE_ID_INTEGER, "Field");
764 BT_ASSERT_PRE(bt_field_type_common_integer_is_signed(field->type),
765 "Field's type is unsigned: %!+_f", field);
766 *value = integer->payload.signd;
767 return 0;
768 }
769
770 BT_ASSERT_PRE_FUNC
771 static inline bool value_is_in_range_signed(unsigned int size, int64_t value)
772 {
773 bool ret = true;
774 int64_t min_value, max_value;
775
776 min_value = -(1ULL << (size - 1));
777 max_value = (1ULL << (size - 1)) - 1;
778 if (value < min_value || value > max_value) {
779 BT_LOGF("Value is out of bounds: value=%" PRId64 ", "
780 "min-value=%" PRId64 ", max-value=%" PRId64,
781 value, min_value, max_value);
782 ret = false;
783 }
784
785 return ret;
786 }
787
788 static inline
789 int bt_field_common_integer_signed_set_value(struct bt_field_common *field,
790 int64_t value)
791 {
792 int ret = 0;
793 struct bt_field_common_integer *integer = BT_FROM_COMMON(field);
794 struct bt_field_type_common_integer *integer_type;
795
796 BT_ASSERT_PRE_NON_NULL(field, "Integer field");
797 BT_ASSERT_PRE_FIELD_COMMON_HOT(field, "Integer field");
798 BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field,
799 BT_FIELD_TYPE_ID_INTEGER, "Field");
800 integer_type = BT_FROM_COMMON(field->type);
801 BT_ASSERT_PRE(bt_field_type_common_integer_is_signed(field->type),
802 "Field's type is unsigned: %!+_f", field);
803 BT_ASSERT_PRE(value_is_in_range_signed(integer_type->size, value),
804 "Value is out of bounds: value=%" PRId64 ", %![field-]+_f",
805 value, field);
806 integer->payload.signd = value;
807 bt_field_common_set(field, true);
808 return ret;
809 }
810
811 static inline
812 int bt_field_common_integer_unsigned_get_value(struct bt_field_common *field,
813 uint64_t *value)
814 {
815 struct bt_field_common_integer *integer = BT_FROM_COMMON(field);
816
817 BT_ASSERT_PRE_NON_NULL(field, "Integer field");
818 BT_ASSERT_PRE_NON_NULL(value, "Value");
819 BT_ASSERT_PRE_FIELD_COMMON_IS_SET(field, "Integer field");
820 BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field,
821 BT_FIELD_TYPE_ID_INTEGER, "Field");
822 BT_ASSERT_PRE(!bt_field_type_common_integer_is_signed(field->type),
823 "Field's type is signed: %!+_f", field);
824 *value = integer->payload.unsignd;
825 return 0;
826 }
827
828 BT_ASSERT_PRE_FUNC
829 static inline bool value_is_in_range_unsigned(unsigned int size, uint64_t value)
830 {
831 bool ret = true;
832 int64_t max_value;
833
834 max_value = (size == 64) ? UINT64_MAX : ((uint64_t) 1 << size) - 1;
835 if (value > max_value) {
836 BT_LOGF("Value is out of bounds: value=%" PRIu64 ", "
837 "max-value=%" PRIu64,
838 value, max_value);
839 ret = false;
840 }
841
842 return ret;
843 }
844
845 static inline
846 int bt_field_common_integer_unsigned_set_value(struct bt_field_common *field,
847 uint64_t value)
848 {
849 struct bt_field_common_integer *integer = BT_FROM_COMMON(field);
850 struct bt_field_type_common_integer *integer_type;
851
852 BT_ASSERT_PRE_NON_NULL(field, "Integer field");
853 BT_ASSERT_PRE_FIELD_COMMON_HOT(field, "Integer field");
854 BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field,
855 BT_FIELD_TYPE_ID_INTEGER, "Field");
856 integer_type = BT_FROM_COMMON(field->type);
857 BT_ASSERT_PRE(!bt_field_type_common_integer_is_signed(field->type),
858 "Field's type is signed: %!+_f", field);
859 BT_ASSERT_PRE(value_is_in_range_unsigned(integer_type->size, value),
860 "Value is out of bounds: value=%" PRIu64 ", %![field-]+_f",
861 value, field);
862 integer->payload.unsignd = value;
863 bt_field_common_set(field, true);
864 return 0;
865 }
866
867 static inline
868 struct bt_field_type_enumeration_mapping_iterator *
869 bt_field_common_enumeration_get_mappings(struct bt_field_common *field,
870 bt_field_common_create_func field_create_func)
871 {
872 int ret;
873 struct bt_field_common *container = NULL;
874 struct bt_field_type_common_integer *integer_type = NULL;
875 struct bt_field_type_enumeration_mapping_iterator *iter = NULL;
876
877 BT_ASSERT_PRE_NON_NULL(field, "Enumeration field");
878 BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field,
879 BT_FIELD_TYPE_ID_ENUM, "Field");
880 container = bt_field_common_enumeration_borrow_container(field,
881 field_create_func);
882 BT_ASSERT_PRE(container,
883 "Enumeration field has no container field: %!+_f", field);
884 BT_ASSERT(container->type);
885 integer_type = BT_FROM_COMMON(container->type);
886 BT_ASSERT_PRE_FIELD_COMMON_IS_SET(container,
887 "Enumeration field's payload field");
888
889 if (!integer_type->is_signed) {
890 uint64_t value;
891
892 ret = bt_field_common_integer_unsigned_get_value(container,
893 &value);
894 BT_ASSERT(ret == 0);
895 iter = bt_field_type_common_enumeration_unsigned_find_mappings_by_value(
896 field->type, value);
897 } else {
898 int64_t value;
899
900 ret = bt_field_common_integer_signed_get_value(container, &value);
901 BT_ASSERT(ret == 0);
902 iter = bt_field_type_common_enumeration_signed_find_mappings_by_value(
903 field->type, value);
904 }
905
906 return iter;
907 }
908
909 static inline
910 int bt_field_common_floating_point_get_value(struct bt_field_common *field,
911 double *value)
912 {
913 struct bt_field_common_floating_point *floating_point =
914 BT_FROM_COMMON(field);
915
916 BT_ASSERT_PRE_NON_NULL(field, "Floating point number field");
917 BT_ASSERT_PRE_NON_NULL(value, "Value");
918 BT_ASSERT_PRE_FIELD_COMMON_IS_SET(field, "Floating point number field");
919 BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field,
920 BT_FIELD_TYPE_ID_FLOAT, "Field");
921 *value = floating_point->payload;
922 return 0;
923 }
924
925 static inline
926 int bt_field_common_floating_point_set_value(struct bt_field_common *field,
927 double value)
928 {
929 struct bt_field_common_floating_point *floating_point =
930 BT_FROM_COMMON(field);
931
932 BT_ASSERT_PRE_NON_NULL(field, "Floating point number field");
933 BT_ASSERT_PRE_FIELD_COMMON_HOT(field, "Floating point number field");
934 BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field,
935 BT_FIELD_TYPE_ID_FLOAT, "Field");
936 floating_point->payload = value;
937 bt_field_common_set(field, true);
938 return 0;
939 }
940
941 static inline
942 const char *bt_field_common_string_get_value(struct bt_field_common *field)
943 {
944 struct bt_field_common_string *string = BT_FROM_COMMON(field);
945
946 BT_ASSERT_PRE_NON_NULL(field, "String field");
947 BT_ASSERT_PRE_FIELD_COMMON_IS_SET(field, "String field");
948 BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field,
949 BT_FIELD_TYPE_ID_STRING, "Field");
950 return string->payload->str;
951 }
952
953 static inline
954 int bt_field_common_string_set_value(struct bt_field_common *field,
955 const char *value)
956 {
957 struct bt_field_common_string *string = BT_FROM_COMMON(field);
958
959 BT_ASSERT_PRE_NON_NULL(field, "String field");
960 BT_ASSERT_PRE_NON_NULL(value, "Value");
961 BT_ASSERT_PRE_FIELD_COMMON_HOT(field, "String field");
962 BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field,
963 BT_FIELD_TYPE_ID_STRING, "Field");
964
965 if (string->payload) {
966 g_string_assign(string->payload, value);
967 } else {
968 string->payload = g_string_new(value);
969 }
970
971 bt_field_common_set(field, true);
972 return 0;
973 }
974
975 static inline
976 int bt_field_common_string_append(struct bt_field_common *field,
977 const char *value)
978 {
979 struct bt_field_common_string *string_field = BT_FROM_COMMON(field);
980
981 BT_ASSERT_PRE_NON_NULL(field, "String field");
982 BT_ASSERT_PRE_NON_NULL(value, "Value");
983 BT_ASSERT_PRE_FIELD_COMMON_HOT(field, "String field");
984 BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field,
985 BT_FIELD_TYPE_ID_STRING, "Field");
986
987 if (string_field->payload) {
988 g_string_append(string_field->payload, value);
989 } else {
990 string_field->payload = g_string_new(value);
991 }
992
993 bt_field_common_set(field, true);
994 return 0;
995 }
996
997 static inline
998 int bt_field_common_string_append_len(struct bt_field_common *field,
999 const char *value, unsigned int length)
1000 {
1001 struct bt_field_common_string *string_field = BT_FROM_COMMON(field);
1002
1003 BT_ASSERT_PRE_NON_NULL(field, "String field");
1004 BT_ASSERT_PRE_NON_NULL(value, "Value");
1005 BT_ASSERT_PRE_FIELD_COMMON_HOT(field, "String field");
1006 BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field,
1007 BT_FIELD_TYPE_ID_STRING, "Field");
1008
1009 /* make sure no null bytes are appended */
1010 BT_ASSERT_PRE(memchr(value, '\0', length) == NULL,
1011 "String value to append contains a null character: "
1012 "partial-value=\"%.32s\", length=%u", value, length);
1013
1014 if (string_field->payload) {
1015 g_string_append_len(string_field->payload, value, length);
1016 } else {
1017 string_field->payload = g_string_new_len(value, length);
1018 }
1019
1020 bt_field_common_set(field, true);
1021 return 0;
1022 }
1023
1024 static inline
1025 int _bt_field_validate_recursive(struct bt_field *field)
1026 {
1027 return _bt_field_common_validate_recursive((void *) field);
1028 }
1029
1030 static inline
1031 void _bt_field_freeze_recursive(struct bt_field *field)
1032 {
1033 return _bt_field_common_freeze_recursive((void *) field);
1034 }
1035
1036 static inline
1037 bt_bool _bt_field_is_set_recursive(struct bt_field *field)
1038 {
1039 return _bt_field_common_is_set_recursive((void *) field);
1040 }
1041
1042 static inline
1043 void _bt_field_reset_recursive(struct bt_field *field)
1044 {
1045 _bt_field_common_reset_recursive((void *) field);
1046 }
1047
1048 static inline
1049 void _bt_field_set(struct bt_field *field, bool value)
1050 {
1051 _bt_field_common_set((void *) field, value);
1052 }
1053
1054 #endif /* BABELTRACE_CTF_IR_FIELDS_INTERNAL_H */
This page took 0.091733 seconds and 4 git commands to generate.