2 * Copyright 2017-2018 Philippe Proulx <pproulx@efficios.com>
3 * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 #define BT_LOG_TAG "FIELD-CLASSES"
25 #include <babeltrace/lib-logging-internal.h>
27 #include <babeltrace/assert-pre-internal.h>
28 #include <babeltrace/trace-ir/field-class.h>
29 #include <babeltrace/trace-ir/field-class-const.h>
30 #include <babeltrace/trace-ir/field-class-internal.h>
31 #include <babeltrace/trace-ir/field-path-internal.h>
32 #include <babeltrace/trace-ir/field-internal.h>
33 #include <babeltrace/trace-ir/field-const.h>
34 #include <babeltrace/trace-ir/field.h>
35 #include <babeltrace/trace-ir/utils-internal.h>
36 #include <babeltrace/object.h>
37 #include <babeltrace/trace-ir/clock-class.h>
38 #include <babeltrace/trace-ir/clock-class-internal.h>
39 #include <babeltrace/object-internal.h>
40 #include <babeltrace/object.h>
41 #include <babeltrace/compiler-internal.h>
42 #include <babeltrace/endian-internal.h>
43 #include <babeltrace/assert-internal.h>
44 #include <babeltrace/compat/glib-internal.h>
49 enum bt_field_class_type
bt_field_class_get_type(
50 const struct bt_field_class
*fc
)
52 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
57 void init_field_class(struct bt_field_class
*fc
, enum bt_field_class_type type
,
58 bt_object_release_func release_func
)
61 BT_ASSERT(bt_field_class_has_known_type(fc
));
62 BT_ASSERT(release_func
);
63 bt_object_init_shared(&fc
->base
, release_func
);
68 void init_integer_field_class(struct bt_field_class_integer
*fc
,
69 enum bt_field_class_type type
,
70 bt_object_release_func release_func
)
72 init_field_class((void *) fc
, type
, release_func
);
74 fc
->base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
;
78 void destroy_integer_field_class(struct bt_object
*obj
)
81 BT_LIB_LOGD("Destroying integer field class object: %!+F", obj
);
86 struct bt_field_class
*create_integer_field_class(enum bt_field_class_type type
)
88 struct bt_field_class_integer
*int_fc
= NULL
;
90 BT_LOGD("Creating default integer field class object: type=%s",
91 bt_common_field_class_type_string(type
));
92 int_fc
= g_new0(struct bt_field_class_integer
, 1);
94 BT_LOGE_STR("Failed to allocate one integer field class.");
98 init_integer_field_class(int_fc
, type
, destroy_integer_field_class
);
99 BT_LIB_LOGD("Created integer field class object: %!+F", int_fc
);
103 BT_OBJECT_PUT_REF_AND_RESET(int_fc
);
106 return (void *) int_fc
;
109 struct bt_field_class
*
110 bt_field_class_unsigned_integer_create(void)
112 return create_integer_field_class(
113 BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER
);
116 struct bt_field_class
*bt_field_class_signed_integer_create(void)
118 return create_integer_field_class(
119 BT_FIELD_CLASS_TYPE_SIGNED_INTEGER
);
122 uint64_t bt_field_class_integer_get_field_value_range(
123 const struct bt_field_class
*fc
)
125 const struct bt_field_class_integer
*int_fc
= (const void *) fc
;
127 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
128 BT_ASSERT_PRE_FC_IS_INT(fc
, "Field class");
129 return int_fc
->range
;
134 bool size_is_valid_for_enumeration_field_class(struct bt_field_class
*fc
,
141 void bt_field_class_integer_set_field_value_range(
142 struct bt_field_class
*fc
, uint64_t size
)
144 struct bt_field_class_integer
*int_fc
= (void *) fc
;
146 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
147 BT_ASSERT_PRE_FC_IS_INT(fc
, "Field class");
148 BT_ASSERT_PRE_FC_HOT(fc
, "Field class");
149 BT_ASSERT_PRE(size
<= 64,
150 "Unsupported size for integer field class's field value range "
151 "(maximum is 64): size=%" PRIu64
, size
);
153 int_fc
->common
.type
== BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER
||
154 int_fc
->common
.type
== BT_FIELD_CLASS_TYPE_SIGNED_INTEGER
||
155 size_is_valid_for_enumeration_field_class(fc
, size
),
156 "Invalid field value range for enumeration field class: "
157 "at least one of the current mapping ranges contains values "
158 "which are outside this range: %!+F, size=%" PRIu64
, fc
, size
);
159 int_fc
->range
= size
;
160 BT_LIB_LOGV("Set integer field class's field value range: %!+F", fc
);
163 enum bt_field_class_integer_preferred_display_base
164 bt_field_class_integer_get_preferred_display_base(const struct bt_field_class
*fc
)
166 const struct bt_field_class_integer
*int_fc
= (const void *) fc
;
168 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
169 BT_ASSERT_PRE_FC_IS_INT(fc
, "Field class");
173 void bt_field_class_integer_set_preferred_display_base(
174 struct bt_field_class
*fc
,
175 enum bt_field_class_integer_preferred_display_base base
)
177 struct bt_field_class_integer
*int_fc
= (void *) fc
;
179 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
180 BT_ASSERT_PRE_FC_IS_INT(fc
, "Field class");
181 BT_ASSERT_PRE_FC_HOT(fc
, "Field class");
183 BT_LIB_LOGV("Set integer field class's preferred display base: %!+F", fc
);
187 void finalize_enumeration_field_class_mapping(
188 struct bt_field_class_enumeration_mapping
*mapping
)
192 if (mapping
->label
) {
193 g_string_free(mapping
->label
, TRUE
);
196 if (mapping
->ranges
) {
197 g_array_free(mapping
->ranges
, TRUE
);
202 void destroy_enumeration_field_class(struct bt_object
*obj
)
204 struct bt_field_class_enumeration
*fc
= (void *) obj
;
207 BT_LIB_LOGD("Destroying enumeration field class object: %!+F", fc
);
212 for (i
= 0; i
< fc
->mappings
->len
; i
++) {
213 finalize_enumeration_field_class_mapping(
214 BT_FIELD_CLASS_ENUM_MAPPING_AT_INDEX(fc
, i
));
217 g_array_free(fc
->mappings
, TRUE
);
222 g_ptr_array_free(fc
->label_buf
, TRUE
);
223 fc
->label_buf
= NULL
;
230 struct bt_field_class
*create_enumeration_field_class(
231 enum bt_field_class_type type
)
233 struct bt_field_class_enumeration
*enum_fc
= NULL
;
235 BT_LOGD("Creating default enumeration field class object: type=%s",
236 bt_common_field_class_type_string(type
));
237 enum_fc
= g_new0(struct bt_field_class_enumeration
, 1);
239 BT_LOGE_STR("Failed to allocate one enumeration field class.");
243 init_integer_field_class((void *) enum_fc
, type
,
244 destroy_enumeration_field_class
);
245 enum_fc
->mappings
= g_array_new(FALSE
, TRUE
,
246 sizeof(struct bt_field_class_enumeration_mapping
));
247 if (!enum_fc
->mappings
) {
248 BT_LOGE_STR("Failed to allocate a GArray.");
252 enum_fc
->label_buf
= g_ptr_array_new();
253 if (!enum_fc
->label_buf
) {
254 BT_LOGE_STR("Failed to allocate a GArray.");
258 BT_LIB_LOGD("Created enumeration field class object: %!+F", enum_fc
);
262 BT_OBJECT_PUT_REF_AND_RESET(enum_fc
);
265 return (void *) enum_fc
;
268 struct bt_field_class
*bt_field_class_unsigned_enumeration_create(void)
270 return create_enumeration_field_class(
271 BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION
);
274 struct bt_field_class
*bt_field_class_signed_enumeration_create(void)
276 return create_enumeration_field_class(
277 BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION
);
280 uint64_t bt_field_class_enumeration_get_mapping_count(
281 const struct bt_field_class
*fc
)
283 const struct bt_field_class_enumeration
*enum_fc
= (const void *) fc
;
285 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
286 BT_ASSERT_PRE_FC_IS_ENUM(fc
, "Field class");
287 return (uint64_t) enum_fc
->mappings
->len
;
290 void bt_field_class_unsigned_enumeration_borrow_mapping_by_index_const(
291 const struct bt_field_class
*fc
, uint64_t index
,
293 const struct bt_field_class_unsigned_enumeration_mapping_ranges
**ranges
)
295 const struct bt_field_class_enumeration
*enum_fc
= (const void *) fc
;
296 const struct bt_field_class_enumeration_mapping
*mapping
;
298 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
299 BT_ASSERT_PRE_NON_NULL(name
, "Name (output)");
300 BT_ASSERT_PRE_NON_NULL(ranges
, "Ranges (output)");
301 BT_ASSERT_PRE_VALID_INDEX(index
, enum_fc
->mappings
->len
);
302 BT_ASSERT_PRE_FC_HAS_ID(fc
, BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION
,
304 mapping
= BT_FIELD_CLASS_ENUM_MAPPING_AT_INDEX(fc
, index
);
305 *name
= mapping
->label
->str
;
306 *ranges
= (void *) mapping
;
309 void bt_field_class_signed_enumeration_borrow_mapping_by_index_const(
310 const struct bt_field_class
*fc
, uint64_t index
,
312 const struct bt_field_class_signed_enumeration_mapping_ranges
**ranges
)
314 const struct bt_field_class_enumeration
*enum_fc
= (const void *) fc
;
315 const struct bt_field_class_enumeration_mapping
*mapping
;
317 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
318 BT_ASSERT_PRE_NON_NULL(name
, "Name (output)");
319 BT_ASSERT_PRE_NON_NULL(ranges
, "Ranges (output)");
320 BT_ASSERT_PRE_VALID_INDEX(index
, enum_fc
->mappings
->len
);
321 BT_ASSERT_PRE_FC_HAS_ID(fc
, BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION
,
323 mapping
= BT_FIELD_CLASS_ENUM_MAPPING_AT_INDEX(fc
, index
);
324 *name
= mapping
->label
->str
;
325 *ranges
= (void *) mapping
;
329 uint64_t get_enumeration_field_class_mapping_range_count(
330 const struct bt_field_class_enumeration_mapping
*mapping
)
332 BT_ASSERT_PRE_NON_NULL(mapping
, "Ranges");
333 return (uint64_t) mapping
->ranges
->len
;
336 uint64_t bt_field_class_unsigned_enumeration_mapping_ranges_get_range_count(
337 const struct bt_field_class_unsigned_enumeration_mapping_ranges
*ranges
)
339 return get_enumeration_field_class_mapping_range_count(
340 (const void *) ranges
);
343 uint64_t bt_field_class_signed_enumeration_mapping_ranges_get_range_count(
344 const struct bt_field_class_signed_enumeration_mapping_ranges
*ranges
)
346 return get_enumeration_field_class_mapping_range_count(
347 (const void *) ranges
);
351 void get_enumeration_field_class_mapping_range_at_index(
352 const struct bt_field_class_enumeration_mapping
*mapping
,
353 uint64_t index
, uint64_t *lower
, uint64_t *upper
)
355 const struct bt_field_class_enumeration_mapping_range
*range
;
357 BT_ASSERT_PRE_NON_NULL(mapping
, "Ranges");
358 BT_ASSERT_PRE_NON_NULL(lower
, "Range's lower (output)");
359 BT_ASSERT_PRE_NON_NULL(upper
, "Range's upper (output)");
360 BT_ASSERT_PRE_VALID_INDEX(index
, mapping
->ranges
->len
);
361 range
= BT_FIELD_CLASS_ENUM_MAPPING_RANGE_AT_INDEX(mapping
, index
);
362 *lower
= range
->lower
.u
;
363 *upper
= range
->upper
.u
;
366 void bt_field_class_unsigned_enumeration_mapping_ranges_get_range_by_index(
367 const struct bt_field_class_unsigned_enumeration_mapping_ranges
*ranges
,
368 uint64_t index
, uint64_t *lower
, uint64_t *upper
)
370 get_enumeration_field_class_mapping_range_at_index(
371 (const void *) ranges
, index
, lower
, upper
);
374 void bt_field_class_signed_enumeration_mapping_ranges_get_range_by_index(
375 const struct bt_field_class_unsigned_enumeration_mapping_ranges
*ranges
,
376 uint64_t index
, int64_t *lower
, int64_t *upper
)
378 get_enumeration_field_class_mapping_range_at_index(
379 (const void *) ranges
, index
,
380 (uint64_t *) lower
, (uint64_t *) upper
);
385 int bt_field_class_unsigned_enumeration_get_mapping_labels_by_value(
386 const struct bt_field_class
*fc
, uint64_t value
,
387 bt_field_class_enumeration_mapping_label_array
*label_array
,
390 const struct bt_field_class_enumeration
*enum_fc
= (const void *) fc
;
393 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
394 BT_ASSERT_PRE_NON_NULL(label_array
, "Label array (output)");
395 BT_ASSERT_PRE_NON_NULL(count
, "Count (output)");
396 BT_ASSERT_PRE_FC_HAS_ID(fc
, BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION
,
398 g_ptr_array_set_size(enum_fc
->label_buf
, 0);
400 for (i
= 0; i
< enum_fc
->mappings
->len
; i
++) {
402 const struct bt_field_class_enumeration_mapping
*mapping
=
403 BT_FIELD_CLASS_ENUM_MAPPING_AT_INDEX(enum_fc
, i
);
405 for (j
= 0; j
< mapping
->ranges
->len
; j
++) {
406 const struct bt_field_class_enumeration_mapping_range
*range
=
407 BT_FIELD_CLASS_ENUM_MAPPING_RANGE_AT_INDEX(
410 if (value
>= range
->lower
.u
&&
411 value
<= range
->upper
.u
) {
412 g_ptr_array_add(enum_fc
->label_buf
,
413 mapping
->label
->str
);
419 *label_array
= (void *) enum_fc
->label_buf
->pdata
;
420 *count
= (uint64_t) enum_fc
->label_buf
->len
;
424 int bt_field_class_signed_enumeration_get_mapping_labels_by_value(
425 const struct bt_field_class
*fc
, int64_t value
,
426 bt_field_class_enumeration_mapping_label_array
*label_array
,
429 const struct bt_field_class_enumeration
*enum_fc
= (const void *) fc
;
432 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
433 BT_ASSERT_PRE_NON_NULL(label_array
, "Label array (output)");
434 BT_ASSERT_PRE_NON_NULL(count
, "Count (output)");
435 BT_ASSERT_PRE_FC_HAS_ID(fc
, BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION
,
437 g_ptr_array_set_size(enum_fc
->label_buf
, 0);
439 for (i
= 0; i
< enum_fc
->mappings
->len
; i
++) {
441 const struct bt_field_class_enumeration_mapping
*mapping
=
442 BT_FIELD_CLASS_ENUM_MAPPING_AT_INDEX(enum_fc
, i
);
444 for (j
= 0; j
< mapping
->ranges
->len
; j
++) {
445 const struct bt_field_class_enumeration_mapping_range
*range
=
446 BT_FIELD_CLASS_ENUM_MAPPING_RANGE_AT_INDEX(
449 if (value
>= range
->lower
.i
&&
450 value
<= range
->upper
.i
) {
451 g_ptr_array_add(enum_fc
->label_buf
,
452 mapping
->label
->str
);
458 *label_array
= (void *) enum_fc
->label_buf
->pdata
;
459 *count
= (uint64_t) enum_fc
->label_buf
->len
;
464 int add_mapping_to_enumeration_field_class(struct bt_field_class
*fc
,
465 const char *label
, uint64_t lower
, uint64_t upper
)
469 struct bt_field_class_enumeration
*enum_fc
= (void *) fc
;
470 struct bt_field_class_enumeration_mapping
*mapping
= NULL
;
471 struct bt_field_class_enumeration_mapping_range
*range
;
474 BT_ASSERT_PRE_NON_NULL(label
, "Label");
476 /* Find existing mapping identified by this label */
477 for (i
= 0; i
< enum_fc
->mappings
->len
; i
++) {
478 struct bt_field_class_enumeration_mapping
*mapping_candidate
=
479 BT_FIELD_CLASS_ENUM_MAPPING_AT_INDEX(enum_fc
, i
);
481 if (strcmp(mapping_candidate
->label
->str
, label
) == 0) {
482 mapping
= mapping_candidate
;
488 /* Create new mapping for this label */
489 g_array_set_size(enum_fc
->mappings
, enum_fc
->mappings
->len
+ 1);
490 mapping
= BT_FIELD_CLASS_ENUM_MAPPING_AT_INDEX(enum_fc
,
491 enum_fc
->mappings
->len
- 1);
492 mapping
->ranges
= g_array_new(FALSE
, TRUE
,
493 sizeof(struct bt_field_class_enumeration_mapping_range
));
494 if (!mapping
->ranges
) {
495 finalize_enumeration_field_class_mapping(mapping
);
496 g_array_set_size(enum_fc
->mappings
,
497 enum_fc
->mappings
->len
- 1);
502 mapping
->label
= g_string_new(label
);
503 if (!mapping
->label
) {
504 finalize_enumeration_field_class_mapping(mapping
);
505 g_array_set_size(enum_fc
->mappings
,
506 enum_fc
->mappings
->len
- 1);
514 g_array_set_size(mapping
->ranges
, mapping
->ranges
->len
+ 1);
515 range
= BT_FIELD_CLASS_ENUM_MAPPING_RANGE_AT_INDEX(mapping
,
516 mapping
->ranges
->len
- 1);
517 range
->lower
.u
= lower
;
518 range
->upper
.u
= upper
;
519 BT_LIB_LOGV("Added mapping to enumeration field class: "
520 "%![fc-]+F, label=\"%s\", lower-unsigned=%" PRIu64
", "
521 "upper-unsigned=%" PRIu64
, fc
, label
, lower
, upper
);
527 int bt_field_class_unsigned_enumeration_map_range(
528 struct bt_field_class
*fc
, const char *label
,
529 uint64_t range_lower
, uint64_t range_upper
)
531 struct bt_field_class_enumeration
*enum_fc
= (void *) fc
;
533 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
534 BT_ASSERT_PRE_FC_HAS_ID(fc
, BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION
,
536 BT_ASSERT_PRE(range_lower
<= range_upper
,
537 "Range's upper bound is less than lower bound: "
538 "upper=%" PRIu64
", lower=%" PRIu64
,
539 range_lower
, range_upper
);
540 BT_ASSERT_PRE(bt_util_value_is_in_range_unsigned(enum_fc
->common
.range
,
542 "Range's lower bound is outside the enumeration field class's value range: "
543 "%![fc-]+F, lower=%" PRIu64
, fc
, range_lower
);
544 BT_ASSERT_PRE(bt_util_value_is_in_range_unsigned(enum_fc
->common
.range
,
546 "Range's upper bound is outside the enumeration field class's value range: "
547 "%![fc-]+F, upper=%" PRIu64
, fc
, range_upper
);
548 return add_mapping_to_enumeration_field_class(fc
, label
, range_lower
,
552 int bt_field_class_signed_enumeration_map_range(
553 struct bt_field_class
*fc
, const char *label
,
554 int64_t range_lower
, int64_t range_upper
)
556 struct bt_field_class_enumeration
*enum_fc
= (void *) fc
;
558 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
559 BT_ASSERT_PRE_FC_HAS_ID(fc
, BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION
,
561 BT_ASSERT_PRE(range_lower
<= range_upper
,
562 "Range's upper bound is less than lower bound: "
563 "upper=%" PRId64
", lower=%" PRId64
,
564 range_lower
, range_upper
);
565 BT_ASSERT_PRE(bt_util_value_is_in_range_signed(enum_fc
->common
.range
,
567 "Range's lower bound is outside the enumeration field class's value range: "
568 "%![fc-]+F, lower=%" PRId64
, fc
, range_lower
);
569 BT_ASSERT_PRE(bt_util_value_is_in_range_signed(enum_fc
->common
.range
,
571 "Range's upper bound is outside the enumeration field class's value range: "
572 "%![fc-]+F, upper=%" PRId64
, fc
, range_upper
);
573 return add_mapping_to_enumeration_field_class(fc
, label
, range_lower
,
578 void destroy_real_field_class(struct bt_object
*obj
)
581 BT_LIB_LOGD("Destroying real field class object: %!+F", obj
);
585 struct bt_field_class
*bt_field_class_real_create(void)
587 struct bt_field_class_real
*real_fc
= NULL
;
589 BT_LOGD_STR("Creating default real field class object.");
590 real_fc
= g_new0(struct bt_field_class_real
, 1);
592 BT_LOGE_STR("Failed to allocate one real field class.");
596 init_field_class((void *) real_fc
, BT_FIELD_CLASS_TYPE_REAL
,
597 destroy_real_field_class
);
598 BT_LIB_LOGD("Created real field class object: %!+F", real_fc
);
602 BT_OBJECT_PUT_REF_AND_RESET(real_fc
);
605 return (void *) real_fc
;
608 bt_bool
bt_field_class_real_is_single_precision(const struct bt_field_class
*fc
)
610 const struct bt_field_class_real
*real_fc
= (const void *) fc
;
612 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
613 BT_ASSERT_PRE_FC_HAS_ID(fc
, BT_FIELD_CLASS_TYPE_REAL
, "Field class");
614 return real_fc
->is_single_precision
;
617 void bt_field_class_real_set_is_single_precision(struct bt_field_class
*fc
,
618 bt_bool is_single_precision
)
620 struct bt_field_class_real
*real_fc
= (void *) fc
;
622 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
623 BT_ASSERT_PRE_FC_HAS_ID(fc
, BT_FIELD_CLASS_TYPE_REAL
, "Field class");
624 BT_ASSERT_PRE_FC_HOT(fc
, "Field class");
625 real_fc
->is_single_precision
= (bool) is_single_precision
;
626 BT_LIB_LOGV("Set real field class's \"is single precision\" property: "
631 int init_named_field_classes_container(
632 struct bt_field_class_named_field_class_container
*fc
,
633 enum bt_field_class_type type
,
634 bt_object_release_func release_func
)
638 init_field_class((void *) fc
, type
, release_func
);
639 fc
->named_fcs
= g_array_new(FALSE
, TRUE
,
640 sizeof(struct bt_named_field_class
));
641 if (!fc
->named_fcs
) {
642 BT_LOGE_STR("Failed to allocate a GArray.");
647 fc
->name_to_index
= g_hash_table_new(g_str_hash
, g_str_equal
);
648 if (!fc
->name_to_index
) {
649 BT_LOGE_STR("Failed to allocate a GHashTable.");
659 void finalize_named_field_class(struct bt_named_field_class
*named_fc
)
662 BT_LIB_LOGD("Finalizing named field class: "
663 "addr=%p, name=\"%s\", %![fc-]+F",
664 named_fc
, named_fc
->name
? named_fc
->name
->str
: NULL
,
667 if (named_fc
->name
) {
668 g_string_free(named_fc
->name
, TRUE
);
671 BT_LOGD_STR("Putting named field class's field class.");
672 BT_OBJECT_PUT_REF_AND_RESET(named_fc
->fc
);
676 void finalize_named_field_classes_container(
677 struct bt_field_class_named_field_class_container
*fc
)
684 for (i
= 0; i
< fc
->named_fcs
->len
; i
++) {
685 finalize_named_field_class(
686 &g_array_index(fc
->named_fcs
,
687 struct bt_named_field_class
, i
));
690 g_array_free(fc
->named_fcs
, TRUE
);
693 if (fc
->name_to_index
) {
694 g_hash_table_destroy(fc
->name_to_index
);
699 void destroy_structure_field_class(struct bt_object
*obj
)
702 BT_LIB_LOGD("Destroying string field class object: %!+F", obj
);
703 finalize_named_field_classes_container((void *) obj
);
707 struct bt_field_class
*bt_field_class_structure_create(void)
710 struct bt_field_class_structure
*struct_fc
= NULL
;
712 BT_LOGD_STR("Creating default structure field class object.");
713 struct_fc
= g_new0(struct bt_field_class_structure
, 1);
715 BT_LOGE_STR("Failed to allocate one structure field class.");
719 ret
= init_named_field_classes_container((void *) struct_fc
,
720 BT_FIELD_CLASS_TYPE_STRUCTURE
, destroy_structure_field_class
);
725 BT_LIB_LOGD("Created structure field class object: %!+F", struct_fc
);
729 BT_OBJECT_PUT_REF_AND_RESET(struct_fc
);
732 return (void *) struct_fc
;
736 int append_named_field_class_to_container_field_class(
737 struct bt_field_class_named_field_class_container
*container_fc
,
738 const char *name
, struct bt_field_class
*fc
)
741 struct bt_named_field_class
*named_fc
;
744 BT_ASSERT(container_fc
);
745 BT_ASSERT_PRE_FC_HOT(container_fc
, "Field class");
746 BT_ASSERT_PRE_NON_NULL(name
, "Name");
747 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
748 BT_ASSERT_PRE(!bt_g_hash_table_contains(container_fc
->name_to_index
,
750 "Duplicate member/option name in structure/variant field class: "
751 "%![container-fc-]+F, name=\"%s\"", container_fc
, name
);
752 name_str
= g_string_new(name
);
754 BT_LOGE_STR("Failed to allocate a GString.");
759 g_array_set_size(container_fc
->named_fcs
,
760 container_fc
->named_fcs
->len
+ 1);
761 named_fc
= &g_array_index(container_fc
->named_fcs
,
762 struct bt_named_field_class
, container_fc
->named_fcs
->len
- 1);
763 named_fc
->name
= name_str
;
765 bt_object_get_no_null_check(fc
);
766 g_hash_table_insert(container_fc
->name_to_index
, named_fc
->name
->str
,
767 GUINT_TO_POINTER(container_fc
->named_fcs
->len
- 1));
768 bt_field_class_freeze(fc
);
774 int bt_field_class_structure_append_member(struct bt_field_class
*fc
,
775 const char *name
, struct bt_field_class
*member_fc
)
778 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
779 BT_ASSERT_PRE_FC_HAS_ID(fc
, BT_FIELD_CLASS_TYPE_STRUCTURE
, "Field class");
780 return append_named_field_class_to_container_field_class((void *) fc
,
784 uint64_t bt_field_class_structure_get_member_count(
785 const struct bt_field_class
*fc
)
787 struct bt_field_class_structure
*struct_fc
= (void *) fc
;
789 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
790 BT_ASSERT_PRE_FC_HAS_ID(fc
, BT_FIELD_CLASS_TYPE_STRUCTURE
, "Field class");
791 return (uint64_t) struct_fc
->common
.named_fcs
->len
;
795 void borrow_named_field_class_from_container_field_class_at_index_const(
796 const struct bt_field_class_named_field_class_container
*fc
,
797 uint64_t index
, const char **name
,
798 const struct bt_field_class
**out_fc
)
800 const struct bt_named_field_class
*named_fc
;
803 BT_ASSERT_PRE_NON_NULL(name
, "Name");
804 BT_ASSERT_PRE_NON_NULL(out_fc
, "Field class (output)");
805 BT_ASSERT_PRE_VALID_INDEX(index
, fc
->named_fcs
->len
);
806 named_fc
= BT_FIELD_CLASS_NAMED_FC_AT_INDEX(fc
, index
);
807 *name
= named_fc
->name
->str
;
808 *out_fc
= named_fc
->fc
;
811 void bt_field_class_structure_borrow_member_by_index_const(
812 const struct bt_field_class
*fc
, uint64_t index
,
813 const char **name
, const struct bt_field_class
**out_fc
)
815 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
816 BT_ASSERT_PRE_FC_HAS_ID(fc
, BT_FIELD_CLASS_TYPE_STRUCTURE
, "Field class");
817 borrow_named_field_class_from_container_field_class_at_index_const(
818 (void *) fc
, index
, name
, out_fc
);
822 const struct bt_field_class
*
823 borrow_field_class_from_container_field_class_by_name_const(
824 const struct bt_field_class_named_field_class_container
*fc
,
827 const struct bt_field_class
*ret_fc
= NULL
;
828 const struct bt_named_field_class
*named_fc
;
833 BT_ASSERT_PRE_NON_NULL(name
, "Name");
834 if (!g_hash_table_lookup_extended(fc
->name_to_index
, name
, &orig_key
,
839 named_fc
= BT_FIELD_CLASS_NAMED_FC_AT_INDEX(fc
,
840 GPOINTER_TO_UINT(value
));
841 ret_fc
= named_fc
->fc
;
847 const struct bt_field_class
*
848 bt_field_class_structure_borrow_member_field_class_by_name(
849 const struct bt_field_class
*fc
, const char *name
)
851 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
852 BT_ASSERT_PRE_FC_HAS_ID(fc
, BT_FIELD_CLASS_TYPE_STRUCTURE
, "Field class");
853 return borrow_field_class_from_container_field_class_by_name_const(
858 void destroy_variant_field_class(struct bt_object
*obj
)
860 struct bt_field_class_variant
*fc
= (void *) obj
;
863 BT_LIB_LOGD("Destroying variant field class object: %!+F", fc
);
864 finalize_named_field_classes_container((void *) fc
);
865 BT_LOGD_STR("Putting selector field path.");
866 BT_OBJECT_PUT_REF_AND_RESET(fc
->selector_field_path
);
867 BT_LOGD_STR("Putting selector field class.");
868 BT_OBJECT_PUT_REF_AND_RESET(fc
->selector_fc
);
872 struct bt_field_class
*bt_field_class_variant_create(void)
875 struct bt_field_class_variant
*var_fc
= NULL
;
877 BT_LOGD_STR("Creating default variant field class object.");
878 var_fc
= g_new0(struct bt_field_class_variant
, 1);
880 BT_LOGE_STR("Failed to allocate one variant field class.");
884 ret
= init_named_field_classes_container((void *) var_fc
,
885 BT_FIELD_CLASS_TYPE_VARIANT
, destroy_variant_field_class
);
890 BT_LIB_LOGD("Created variant field class object: %!+F", var_fc
);
894 BT_OBJECT_PUT_REF_AND_RESET(var_fc
);
897 return (void *) var_fc
;
900 int bt_field_class_variant_set_selector_field_class(
901 struct bt_field_class
*fc
,
902 struct bt_field_class
*selector_fc
)
904 struct bt_field_class_variant
*var_fc
= (void *) fc
;
906 BT_ASSERT_PRE_NON_NULL(fc
, "Variant field class");
907 BT_ASSERT_PRE_NON_NULL(selector_fc
, "Selector field class");
908 BT_ASSERT_PRE_FC_HAS_ID(fc
, BT_FIELD_CLASS_TYPE_VARIANT
, "Field class");
909 BT_ASSERT_PRE_FC_IS_ENUM(selector_fc
, "Selector field class");
910 BT_ASSERT_PRE_FC_HOT(fc
, "Variant field class");
911 var_fc
->selector_fc
= selector_fc
;
912 bt_object_get_no_null_check(selector_fc
);
913 bt_field_class_freeze(selector_fc
);
917 int bt_field_class_variant_append_option(
918 struct bt_field_class
*fc
,
919 const char *name
, struct bt_field_class
*option_fc
)
922 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
923 BT_ASSERT_PRE_FC_HAS_ID(fc
, BT_FIELD_CLASS_TYPE_VARIANT
, "Field class");
924 return append_named_field_class_to_container_field_class((void *) fc
,
928 const struct bt_field_class
*
929 bt_field_class_variant_borrow_option_field_class_by_name_const(
930 const struct bt_field_class
*fc
, const char *name
)
932 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
933 BT_ASSERT_PRE_FC_HAS_ID(fc
, BT_FIELD_CLASS_TYPE_VARIANT
, "Field class");
934 return borrow_field_class_from_container_field_class_by_name_const(
938 uint64_t bt_field_class_variant_get_option_count(const struct bt_field_class
*fc
)
940 const struct bt_field_class_variant
*var_fc
= (const void *) fc
;
942 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
943 BT_ASSERT_PRE_FC_HAS_ID(fc
, BT_FIELD_CLASS_TYPE_VARIANT
, "Field class");
944 return (uint64_t) var_fc
->common
.named_fcs
->len
;
947 void bt_field_class_variant_borrow_option_by_index_const(
948 const struct bt_field_class
*fc
, uint64_t index
,
949 const char **name
, const struct bt_field_class
**out_fc
)
951 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
952 BT_ASSERT_PRE_FC_HAS_ID(fc
, BT_FIELD_CLASS_TYPE_VARIANT
, "Field class");
953 borrow_named_field_class_from_container_field_class_at_index_const(
954 (void *) fc
, index
, name
, out_fc
);
957 const struct bt_field_path
*
958 bt_field_class_variant_borrow_selector_field_path_const(
959 const struct bt_field_class
*fc
)
961 const struct bt_field_class_variant
*var_fc
= (const void *) fc
;
963 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
964 BT_ASSERT_PRE_FC_HAS_ID(fc
, BT_FIELD_CLASS_TYPE_VARIANT
,
966 return var_fc
->selector_field_path
;
970 void init_array_field_class(struct bt_field_class_array
*fc
,
971 enum bt_field_class_type type
, bt_object_release_func release_func
,
972 struct bt_field_class
*element_fc
)
974 BT_ASSERT(element_fc
);
975 init_field_class((void *) fc
, type
, release_func
);
976 fc
->element_fc
= element_fc
;
977 bt_object_get_no_null_check(element_fc
);
978 bt_field_class_freeze(element_fc
);
982 void finalize_array_field_class(struct bt_field_class_array
*array_fc
)
985 BT_LOGD_STR("Putting element field class.");
986 BT_OBJECT_PUT_REF_AND_RESET(array_fc
->element_fc
);
990 void destroy_static_array_field_class(struct bt_object
*obj
)
993 BT_LIB_LOGD("Destroying static array field class object: %!+F", obj
);
994 finalize_array_field_class((void *) obj
);
998 struct bt_field_class
*
999 bt_field_class_static_array_create(struct bt_field_class
*element_fc
,
1002 struct bt_field_class_static_array
*array_fc
= NULL
;
1004 BT_ASSERT_PRE_NON_NULL(element_fc
, "Element field class");
1005 BT_LOGD_STR("Creating default static array field class object.");
1006 array_fc
= g_new0(struct bt_field_class_static_array
, 1);
1008 BT_LOGE_STR("Failed to allocate one static array field class.");
1012 init_array_field_class((void *) array_fc
, BT_FIELD_CLASS_TYPE_STATIC_ARRAY
,
1013 destroy_static_array_field_class
, element_fc
);
1014 array_fc
->length
= length
;
1015 BT_LIB_LOGD("Created static array field class object: %!+F", array_fc
);
1019 BT_OBJECT_PUT_REF_AND_RESET(array_fc
);
1022 return (void *) array_fc
;
1025 const struct bt_field_class
*
1026 bt_field_class_array_borrow_element_field_class_const(
1027 const struct bt_field_class
*fc
)
1029 const struct bt_field_class_array
*array_fc
= (const void *) fc
;
1031 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
1032 BT_ASSERT_PRE_FC_IS_ARRAY(fc
, "Field class");
1033 return array_fc
->element_fc
;
1036 uint64_t bt_field_class_static_array_get_length(const struct bt_field_class
*fc
)
1038 const struct bt_field_class_static_array
*array_fc
= (const void *) fc
;
1040 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
1041 BT_ASSERT_PRE_FC_HAS_ID(fc
, BT_FIELD_CLASS_TYPE_STATIC_ARRAY
,
1043 return (uint64_t) array_fc
->length
;
1047 void destroy_dynamic_array_field_class(struct bt_object
*obj
)
1049 struct bt_field_class_dynamic_array
*fc
= (void *) obj
;
1052 BT_LIB_LOGD("Destroying dynamic array field class object: %!+F", fc
);
1053 finalize_array_field_class((void *) fc
);
1054 BT_LOGD_STR("Putting length field path.");
1055 BT_OBJECT_PUT_REF_AND_RESET(fc
->length_field_path
);
1056 BT_LOGD_STR("Putting length field class.");
1057 BT_OBJECT_PUT_REF_AND_RESET(fc
->length_fc
);
1061 struct bt_field_class
*bt_field_class_dynamic_array_create(
1062 struct bt_field_class
*element_fc
)
1064 struct bt_field_class_dynamic_array
*array_fc
= NULL
;
1066 BT_ASSERT_PRE_NON_NULL(element_fc
, "Element field class");
1067 BT_LOGD_STR("Creating default dynamic array field class object.");
1068 array_fc
= g_new0(struct bt_field_class_dynamic_array
, 1);
1070 BT_LOGE_STR("Failed to allocate one dynamic array field class.");
1074 init_array_field_class((void *) array_fc
,
1075 BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY
,
1076 destroy_dynamic_array_field_class
, element_fc
);
1077 BT_LIB_LOGD("Created dynamic array field class object: %!+F", array_fc
);
1081 BT_OBJECT_PUT_REF_AND_RESET(array_fc
);
1084 return (void *) array_fc
;
1087 int bt_field_class_dynamic_array_set_length_field_class(
1088 struct bt_field_class
*fc
,
1089 struct bt_field_class
*length_fc
)
1091 struct bt_field_class_dynamic_array
*array_fc
= (void *) fc
;
1093 BT_ASSERT_PRE_NON_NULL(fc
, "Dynamic array field class");
1094 BT_ASSERT_PRE_NON_NULL(length_fc
, "Length field class");
1095 BT_ASSERT_PRE_FC_HAS_ID(fc
, BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY
,
1097 BT_ASSERT_PRE_FC_IS_UNSIGNED_INT(length_fc
, "Length field class");
1098 BT_ASSERT_PRE_FC_HOT(fc
, "Dynamic array field class");
1099 array_fc
->length_fc
= length_fc
;
1100 bt_object_get_no_null_check(length_fc
);
1101 bt_field_class_freeze(length_fc
);
1105 const struct bt_field_path
*
1106 bt_field_class_dynamic_array_borrow_length_field_path_const(
1107 const struct bt_field_class
*fc
)
1109 const struct bt_field_class_dynamic_array
*seq_fc
= (const void *) fc
;
1111 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
1112 BT_ASSERT_PRE_FC_HAS_ID(fc
, BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY
,
1114 return seq_fc
->length_field_path
;
1118 void destroy_string_field_class(struct bt_object
*obj
)
1121 BT_LIB_LOGD("Destroying string field class object: %!+F", obj
);
1125 struct bt_field_class
*bt_field_class_string_create(void)
1127 struct bt_field_class_string
*string_fc
= NULL
;
1129 BT_LOGD_STR("Creating default string field class object.");
1130 string_fc
= g_new0(struct bt_field_class_string
, 1);
1132 BT_LOGE_STR("Failed to allocate one string field class.");
1136 init_field_class((void *) string_fc
, BT_FIELD_CLASS_TYPE_STRING
,
1137 destroy_string_field_class
);
1138 BT_LIB_LOGD("Created string field class object: %!+F", string_fc
);
1142 BT_OBJECT_PUT_REF_AND_RESET(string_fc
);
1145 return (void *) string_fc
;
1149 void _bt_field_class_freeze(const struct bt_field_class
*fc
)
1152 * Element/member/option field classes are frozen when added to
1156 ((struct bt_field_class
*) fc
)->frozen
= true;
1160 void _bt_field_class_make_part_of_trace_class(const struct bt_field_class
*c_fc
)
1162 struct bt_field_class
*fc
= (void *) c_fc
;
1165 BT_ASSERT_PRE(!fc
->part_of_trace_class
,
1166 "Field class is already part of a trace: %!+F", fc
);
1167 fc
->part_of_trace_class
= true;
1170 case BT_FIELD_CLASS_TYPE_STRUCTURE
:
1171 case BT_FIELD_CLASS_TYPE_VARIANT
:
1173 struct bt_field_class_named_field_class_container
*container_fc
=
1177 for (i
= 0; i
< container_fc
->named_fcs
->len
; i
++) {
1178 struct bt_named_field_class
*named_fc
=
1179 BT_FIELD_CLASS_NAMED_FC_AT_INDEX(
1182 bt_field_class_make_part_of_trace_class(named_fc
->fc
);
1187 case BT_FIELD_CLASS_TYPE_STATIC_ARRAY
:
1188 case BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY
:
1190 struct bt_field_class_array
*array_fc
= (void *) fc
;
1192 bt_field_class_make_part_of_trace_class(array_fc
->element_fc
);