ctf plugin: notif iter: use "borrow" functions for metadata where possible
[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
138BT_HIDDEN
139int64_t bt_field_sequence_get_int_length(struct bt_field *field);
140
141BT_HIDDEN
142struct bt_field_common *bt_field_common_copy(struct bt_field_common *field);
143
144BT_HIDDEN
145int 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
151BT_HIDDEN
152int 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
157BT_HIDDEN
158int bt_field_common_generic_validate(struct bt_field_common *field);
159
160BT_HIDDEN
161int bt_field_common_enumeration_validate_recursive(
162 struct bt_field_common *field);
163
164BT_HIDDEN
165int bt_field_common_structure_validate_recursive(struct bt_field_common *field);
166
167BT_HIDDEN
168int bt_field_common_variant_validate_recursive(struct bt_field_common *field);
169
170BT_HIDDEN
171int bt_field_common_array_validate_recursive(struct bt_field_common *field);
172
173BT_HIDDEN
174int bt_field_common_sequence_validate_recursive(struct bt_field_common *field);
175
176BT_HIDDEN
177void bt_field_common_generic_reset(struct bt_field_common *field);
178
179BT_HIDDEN
180void bt_field_common_enumeration_reset_recursive(struct bt_field_common *field);
181
182BT_HIDDEN
183void bt_field_common_structure_reset_recursive(struct bt_field_common *field);
184
185BT_HIDDEN
186void bt_field_common_variant_reset_recursive(struct bt_field_common *field);
187
188BT_HIDDEN
189void bt_field_common_array_reset_recursive(struct bt_field_common *field);
190
191BT_HIDDEN
192void bt_field_common_sequence_reset_recursive(struct bt_field_common *field);
193
194BT_HIDDEN
195void bt_field_common_string_reset(struct bt_field_common *field);
196
197BT_HIDDEN
198void bt_field_common_generic_freeze(struct bt_field_common *field);
199
f6ccaed9 200BT_HIDDEN
3dca2276 201void bt_field_common_enumeration_freeze_recursive(struct bt_field_common *field);
f6ccaed9 202
273b65be 203BT_HIDDEN
3dca2276 204void bt_field_common_structure_freeze_recursive(struct bt_field_common *field);
273b65be
JG
205
206BT_HIDDEN
3dca2276 207void bt_field_common_variant_freeze_recursive(struct bt_field_common *field);
f6ccaed9
PP
208
209BT_HIDDEN
3dca2276 210void bt_field_common_array_freeze_recursive(struct bt_field_common *field);
f6ccaed9
PP
211
212BT_HIDDEN
3dca2276 213void bt_field_common_sequence_freeze_recursive(struct bt_field_common *field);
273b65be 214
918be005 215BT_HIDDEN
3dca2276
PP
216void _bt_field_common_freeze_recursive(struct bt_field_common *field);
217
218BT_HIDDEN
219bt_bool bt_field_common_generic_is_set(struct bt_field_common *field);
220
221BT_HIDDEN
222bt_bool bt_field_common_enumeration_is_set_recursive(
223 struct bt_field_common *field);
224
225BT_HIDDEN
226bt_bool bt_field_common_structure_is_set_recursive(
227 struct bt_field_common *field);
228
229BT_HIDDEN
230bt_bool bt_field_common_variant_is_set_recursive(struct bt_field_common *field);
231
232BT_HIDDEN
233bt_bool bt_field_common_array_is_set_recursive(struct bt_field_common *field);
234
235BT_HIDDEN
236bt_bool bt_field_common_sequence_is_set_recursive(struct bt_field_common *field);
237
238BT_HIDDEN
239void bt_field_common_integer_destroy(struct bt_object *obj);
240
241BT_HIDDEN
242void bt_field_common_enumeration_destroy_recursive(struct bt_object *obj);
243
244BT_HIDDEN
245void bt_field_common_floating_point_destroy(struct bt_object *obj);
246
247BT_HIDDEN
248void bt_field_common_structure_destroy_recursive(struct bt_object *obj);
249
250BT_HIDDEN
251void bt_field_common_variant_destroy_recursive(struct bt_object *obj);
252
253BT_HIDDEN
254void bt_field_common_array_destroy_recursive(struct bt_object *obj);
255
256BT_HIDDEN
257void bt_field_common_sequence_destroy_recursive(struct bt_object *obj);
258
259BT_HIDDEN
260void bt_field_common_string_destroy(struct bt_object *obj);
f6ccaed9
PP
261
262#ifdef BT_DEV_MODE
3dca2276
PP
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
f6ccaed9
PP
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
3dca2276
PP
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)
f6ccaed9 280# define bt_field_freeze_recursive(_field)
3dca2276 281# define bt_field_is_set_recursive(_field) (BT_FALSE)
f6ccaed9
PP
282# define bt_field_reset_recursive(_field) (BT_TRUE)
283# define bt_field_set(_field, _val)
284#endif
918be005 285
3dca2276
PP
286BT_ASSERT_FUNC
287static 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
294static inline
295int _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
311end:
312 return ret;
313}
314
315static inline
316void _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
323static inline
324void _bt_field_common_set(struct bt_field_common *field, bool value)
325{
326 BT_ASSERT(field);
327 field->payload_set = value;
328}
329
330static inline
331bt_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
343end:
344 return is_set;
345}
346
347static inline
348void 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
360static inline
094ff7c0 361struct bt_field_type_common *bt_field_common_borrow_type(
3dca2276
PP
362 struct bt_field_common *field)
363{
364 struct bt_field_type_common *ret = NULL;
365
366 BT_ASSERT_PRE_NON_NULL(field, "Field");
094ff7c0 367 ret = field->type;
3dca2276
PP
368 return ret;
369}
370
371static inline
372int64_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
386end:
387 return ret;
388}
389
390static inline
094ff7c0 391struct bt_field_common *bt_field_common_sequence_borrow_length(
3dca2276
PP
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");
094ff7c0 399 return sequence->length;
3dca2276
PP
400}
401
402static inline
403int 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
440end:
441 return ret;
442}
443
444static inline
094ff7c0 445struct bt_field_common *bt_field_common_structure_borrow_field_by_name(
3dca2276
PP
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
094ff7c0 471 ret = structure->fields->pdata[index];
3dca2276
PP
472 BT_ASSERT(ret);
473
474error:
475 return ret;
476}
477
478static inline
094ff7c0 479struct bt_field_common *bt_field_common_structure_borrow_field_by_index(
3dca2276
PP
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);
094ff7c0 491 return structure->fields->pdata[index];
3dca2276
PP
492}
493
494BT_ASSERT_PRE_FUNC
495static 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 =
094ff7c0 503 bt_field_type_common_structure_borrow_field_type_by_name(
3dca2276
PP
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
514end:
3dca2276
PP
515 return ret;
516}
517
518static inline
519int 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
552end:
553 return ret;
554}
555
556static inline
094ff7c0 557struct bt_field_common *bt_field_common_array_borrow_field(
3dca2276
PP
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
094ff7c0 572 field_type = bt_field_type_common_array_borrow_element_field_type(
3dca2276
PP
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
584end:
3dca2276
PP
585 return new_field;
586}
587
588static inline
094ff7c0 589struct bt_field_common *bt_field_common_sequence_borrow_field(
3dca2276
PP
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);
094ff7c0 605 field_type = bt_field_type_common_sequence_borrow_element_field_type(
3dca2276
PP
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
617end:
3dca2276
PP
618 return new_field;
619}
620
621static inline
094ff7c0 622struct bt_field_common *bt_field_common_enumeration_borrow_container(
3dca2276
PP
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
094ff7c0 644 return enumeration->payload;
3dca2276
PP
645}
646
647static inline
094ff7c0 648struct bt_field_common *bt_field_common_variant_borrow_field(
3dca2276
PP
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);
094ff7c0 669 tag_enum = bt_field_common_enumeration_borrow_container(tag_field,
3dca2276
PP
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 =
094ff7c0
PP
688 bt_field_common_enumeration_borrow_container(
689 variant->tag, field_create_func);
3dca2276
PP
690 BT_ASSERT(cur_tag_container);
691 cur_tag_enum_integer = BT_FROM_COMMON(cur_tag_container);
3dca2276
PP
692 cur_tag_value = cur_tag_enum_integer->payload.signd;
693
694 if (cur_tag_value == tag_enum_value) {
695 new_field = variant->payload;
3dca2276
PP
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");
094ff7c0 702 field_type = bt_field_type_common_variant_borrow_field_type_signed(
3dca2276
PP
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);
094ff7c0 722 variant->tag = bt_get(tag_field);
3dca2276
PP
723 variant->payload = new_field;
724
725end:
3dca2276
PP
726 return new_field;
727}
728
729static inline
094ff7c0 730struct bt_field_common *bt_field_common_variant_borrow_current_field(
3dca2276
PP
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");
094ff7c0 738 return variant->payload;
3dca2276
PP
739}
740
741static inline
094ff7c0 742struct bt_field_common *bt_field_common_variant_borrow_tag(
3dca2276
PP
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");
094ff7c0 750 return variant->tag;
3dca2276
PP
751}
752
753static inline
754int 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
770BT_ASSERT_PRE_FUNC
771static 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
788static inline
789int 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
811static inline
812int 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
828BT_ASSERT_PRE_FUNC
829static 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
845static inline
846int 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
867static inline
868struct bt_field_type_enumeration_mapping_iterator *
869bt_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");
094ff7c0 880 container = bt_field_common_enumeration_borrow_container(field,
3dca2276
PP
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
3dca2276
PP
906 return iter;
907}
908
909static inline
910int 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
925static inline
926int 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
941static inline
942const 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
953static inline
954int 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
975static inline
976int 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
997static inline
998int 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
1024static inline
1025int _bt_field_validate_recursive(struct bt_field *field)
1026{
1027 return _bt_field_common_validate_recursive((void *) field);
1028}
1029
1030static inline
1031void _bt_field_freeze_recursive(struct bt_field *field)
1032{
1033 return _bt_field_common_freeze_recursive((void *) field);
1034}
1035
1036static inline
1037bt_bool _bt_field_is_set_recursive(struct bt_field *field)
1038{
1039 return _bt_field_common_is_set_recursive((void *) field);
1040}
1041
1042static inline
1043void _bt_field_reset_recursive(struct bt_field *field)
1044{
1045 _bt_field_common_reset_recursive((void *) field);
1046}
1047
1048static inline
1049void _bt_field_set(struct bt_field *field, bool value)
1050{
1051 _bt_field_common_set((void *) field, value);
1052}
2e8876d3 1053
2e33ac5a 1054#endif /* BABELTRACE_CTF_IR_FIELDS_INTERNAL_H */
This page took 0.089088 seconds and 4 git commands to generate.