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/trace-ir/clock-class.h>
37 #include <babeltrace/trace-ir/clock-class-internal.h>
38 #include <babeltrace/object-internal.h>
39 #include <babeltrace/compiler-internal.h>
40 #include <babeltrace/endian-internal.h>
41 #include <babeltrace/assert-internal.h>
42 #include <babeltrace/compat/glib-internal.h>
47 enum bt_field_class_type
bt_field_class_get_type(
48 const struct bt_field_class
*fc
)
50 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
55 void init_field_class(struct bt_field_class
*fc
, enum bt_field_class_type type
,
56 bt_object_release_func release_func
)
59 BT_ASSERT(bt_field_class_has_known_type(fc
));
60 BT_ASSERT(release_func
);
61 bt_object_init_shared(&fc
->base
, release_func
);
66 void init_integer_field_class(struct bt_field_class_integer
*fc
,
67 enum bt_field_class_type type
,
68 bt_object_release_func release_func
)
70 init_field_class((void *) fc
, type
, release_func
);
72 fc
->base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
;
76 void destroy_integer_field_class(struct bt_object
*obj
)
79 BT_LIB_LOGD("Destroying integer field class object: %!+F", obj
);
84 struct bt_field_class
*create_integer_field_class(enum bt_field_class_type type
)
86 struct bt_field_class_integer
*int_fc
= NULL
;
88 BT_LOGD("Creating default integer field class object: type=%s",
89 bt_common_field_class_type_string(type
));
90 int_fc
= g_new0(struct bt_field_class_integer
, 1);
92 BT_LOGE_STR("Failed to allocate one integer field class.");
96 init_integer_field_class(int_fc
, type
, destroy_integer_field_class
);
97 BT_LIB_LOGD("Created integer field class object: %!+F", int_fc
);
101 BT_OBJECT_PUT_REF_AND_RESET(int_fc
);
104 return (void *) int_fc
;
107 struct bt_field_class
*
108 bt_field_class_unsigned_integer_create(void)
110 return create_integer_field_class(
111 BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER
);
114 struct bt_field_class
*bt_field_class_signed_integer_create(void)
116 return create_integer_field_class(
117 BT_FIELD_CLASS_TYPE_SIGNED_INTEGER
);
120 uint64_t bt_field_class_integer_get_field_value_range(
121 const struct bt_field_class
*fc
)
123 const struct bt_field_class_integer
*int_fc
= (const void *) fc
;
125 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
126 BT_ASSERT_PRE_FC_IS_INT(fc
, "Field class");
127 return int_fc
->range
;
132 bool size_is_valid_for_enumeration_field_class(struct bt_field_class
*fc
,
139 void bt_field_class_integer_set_field_value_range(
140 struct bt_field_class
*fc
, uint64_t size
)
142 struct bt_field_class_integer
*int_fc
= (void *) fc
;
144 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
145 BT_ASSERT_PRE_FC_IS_INT(fc
, "Field class");
146 BT_ASSERT_PRE_FC_HOT(fc
, "Field class");
147 BT_ASSERT_PRE(size
<= 64,
148 "Unsupported size for integer field class's field value range "
149 "(maximum is 64): size=%" PRIu64
, size
);
151 int_fc
->common
.type
== BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER
||
152 int_fc
->common
.type
== BT_FIELD_CLASS_TYPE_SIGNED_INTEGER
||
153 size_is_valid_for_enumeration_field_class(fc
, size
),
154 "Invalid field value range for enumeration field class: "
155 "at least one of the current mapping ranges contains values "
156 "which are outside this range: %!+F, size=%" PRIu64
, fc
, size
);
157 int_fc
->range
= size
;
158 BT_LIB_LOGV("Set integer field class's field value range: %!+F", fc
);
161 enum bt_field_class_integer_preferred_display_base
162 bt_field_class_integer_get_preferred_display_base(const struct bt_field_class
*fc
)
164 const struct bt_field_class_integer
*int_fc
= (const void *) fc
;
166 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
167 BT_ASSERT_PRE_FC_IS_INT(fc
, "Field class");
171 void bt_field_class_integer_set_preferred_display_base(
172 struct bt_field_class
*fc
,
173 enum bt_field_class_integer_preferred_display_base base
)
175 struct bt_field_class_integer
*int_fc
= (void *) fc
;
177 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
178 BT_ASSERT_PRE_FC_IS_INT(fc
, "Field class");
179 BT_ASSERT_PRE_FC_HOT(fc
, "Field class");
181 BT_LIB_LOGV("Set integer field class's preferred display base: %!+F", fc
);
185 void finalize_enumeration_field_class_mapping(
186 struct bt_field_class_enumeration_mapping
*mapping
)
190 if (mapping
->label
) {
191 g_string_free(mapping
->label
, TRUE
);
194 if (mapping
->ranges
) {
195 g_array_free(mapping
->ranges
, TRUE
);
200 void destroy_enumeration_field_class(struct bt_object
*obj
)
202 struct bt_field_class_enumeration
*fc
= (void *) obj
;
205 BT_LIB_LOGD("Destroying enumeration field class object: %!+F", fc
);
210 for (i
= 0; i
< fc
->mappings
->len
; i
++) {
211 finalize_enumeration_field_class_mapping(
212 BT_FIELD_CLASS_ENUM_MAPPING_AT_INDEX(fc
, i
));
215 g_array_free(fc
->mappings
, TRUE
);
220 g_ptr_array_free(fc
->label_buf
, TRUE
);
221 fc
->label_buf
= NULL
;
228 struct bt_field_class
*create_enumeration_field_class(
229 enum bt_field_class_type type
)
231 struct bt_field_class_enumeration
*enum_fc
= NULL
;
233 BT_LOGD("Creating default enumeration field class object: type=%s",
234 bt_common_field_class_type_string(type
));
235 enum_fc
= g_new0(struct bt_field_class_enumeration
, 1);
237 BT_LOGE_STR("Failed to allocate one enumeration field class.");
241 init_integer_field_class((void *) enum_fc
, type
,
242 destroy_enumeration_field_class
);
243 enum_fc
->mappings
= g_array_new(FALSE
, TRUE
,
244 sizeof(struct bt_field_class_enumeration_mapping
));
245 if (!enum_fc
->mappings
) {
246 BT_LOGE_STR("Failed to allocate a GArray.");
250 enum_fc
->label_buf
= g_ptr_array_new();
251 if (!enum_fc
->label_buf
) {
252 BT_LOGE_STR("Failed to allocate a GArray.");
256 BT_LIB_LOGD("Created enumeration field class object: %!+F", enum_fc
);
260 BT_OBJECT_PUT_REF_AND_RESET(enum_fc
);
263 return (void *) enum_fc
;
266 struct bt_field_class
*bt_field_class_unsigned_enumeration_create(void)
268 return create_enumeration_field_class(
269 BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION
);
272 struct bt_field_class
*bt_field_class_signed_enumeration_create(void)
274 return create_enumeration_field_class(
275 BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION
);
278 uint64_t bt_field_class_enumeration_get_mapping_count(
279 const struct bt_field_class
*fc
)
281 const struct bt_field_class_enumeration
*enum_fc
= (const void *) fc
;
283 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
284 BT_ASSERT_PRE_FC_IS_ENUM(fc
, "Field class");
285 return (uint64_t) enum_fc
->mappings
->len
;
288 void bt_field_class_unsigned_enumeration_borrow_mapping_by_index_const(
289 const struct bt_field_class
*fc
, uint64_t index
,
291 const struct bt_field_class_unsigned_enumeration_mapping_ranges
**ranges
)
293 const struct bt_field_class_enumeration
*enum_fc
= (const void *) fc
;
294 const struct bt_field_class_enumeration_mapping
*mapping
;
296 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
297 BT_ASSERT_PRE_NON_NULL(name
, "Name (output)");
298 BT_ASSERT_PRE_NON_NULL(ranges
, "Ranges (output)");
299 BT_ASSERT_PRE_VALID_INDEX(index
, enum_fc
->mappings
->len
);
300 BT_ASSERT_PRE_FC_HAS_ID(fc
, BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION
,
302 mapping
= BT_FIELD_CLASS_ENUM_MAPPING_AT_INDEX(fc
, index
);
303 *name
= mapping
->label
->str
;
304 *ranges
= (void *) mapping
;
307 void bt_field_class_signed_enumeration_borrow_mapping_by_index_const(
308 const struct bt_field_class
*fc
, uint64_t index
,
310 const struct bt_field_class_signed_enumeration_mapping_ranges
**ranges
)
312 const struct bt_field_class_enumeration
*enum_fc
= (const void *) fc
;
313 const struct bt_field_class_enumeration_mapping
*mapping
;
315 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
316 BT_ASSERT_PRE_NON_NULL(name
, "Name (output)");
317 BT_ASSERT_PRE_NON_NULL(ranges
, "Ranges (output)");
318 BT_ASSERT_PRE_VALID_INDEX(index
, enum_fc
->mappings
->len
);
319 BT_ASSERT_PRE_FC_HAS_ID(fc
, BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION
,
321 mapping
= BT_FIELD_CLASS_ENUM_MAPPING_AT_INDEX(fc
, index
);
322 *name
= mapping
->label
->str
;
323 *ranges
= (void *) mapping
;
327 uint64_t get_enumeration_field_class_mapping_range_count(
328 const struct bt_field_class_enumeration_mapping
*mapping
)
330 BT_ASSERT_PRE_NON_NULL(mapping
, "Ranges");
331 return (uint64_t) mapping
->ranges
->len
;
334 uint64_t bt_field_class_unsigned_enumeration_mapping_ranges_get_range_count(
335 const struct bt_field_class_unsigned_enumeration_mapping_ranges
*ranges
)
337 return get_enumeration_field_class_mapping_range_count(
338 (const void *) ranges
);
341 uint64_t bt_field_class_signed_enumeration_mapping_ranges_get_range_count(
342 const struct bt_field_class_signed_enumeration_mapping_ranges
*ranges
)
344 return get_enumeration_field_class_mapping_range_count(
345 (const void *) ranges
);
349 void get_enumeration_field_class_mapping_range_at_index(
350 const struct bt_field_class_enumeration_mapping
*mapping
,
351 uint64_t index
, uint64_t *lower
, uint64_t *upper
)
353 const struct bt_field_class_enumeration_mapping_range
*range
;
355 BT_ASSERT_PRE_NON_NULL(mapping
, "Ranges");
356 BT_ASSERT_PRE_NON_NULL(lower
, "Range's lower (output)");
357 BT_ASSERT_PRE_NON_NULL(upper
, "Range's upper (output)");
358 BT_ASSERT_PRE_VALID_INDEX(index
, mapping
->ranges
->len
);
359 range
= BT_FIELD_CLASS_ENUM_MAPPING_RANGE_AT_INDEX(mapping
, index
);
360 *lower
= range
->lower
.u
;
361 *upper
= range
->upper
.u
;
364 void bt_field_class_unsigned_enumeration_mapping_ranges_get_range_by_index(
365 const struct bt_field_class_unsigned_enumeration_mapping_ranges
*ranges
,
366 uint64_t index
, uint64_t *lower
, uint64_t *upper
)
368 get_enumeration_field_class_mapping_range_at_index(
369 (const void *) ranges
, index
, lower
, upper
);
372 void bt_field_class_signed_enumeration_mapping_ranges_get_range_by_index(
373 const struct bt_field_class_unsigned_enumeration_mapping_ranges
*ranges
,
374 uint64_t index
, int64_t *lower
, int64_t *upper
)
376 get_enumeration_field_class_mapping_range_at_index(
377 (const void *) ranges
, index
,
378 (uint64_t *) lower
, (uint64_t *) upper
);
383 int bt_field_class_unsigned_enumeration_get_mapping_labels_by_value(
384 const struct bt_field_class
*fc
, uint64_t value
,
385 bt_field_class_enumeration_mapping_label_array
*label_array
,
388 const struct bt_field_class_enumeration
*enum_fc
= (const void *) fc
;
391 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
392 BT_ASSERT_PRE_NON_NULL(label_array
, "Label array (output)");
393 BT_ASSERT_PRE_NON_NULL(count
, "Count (output)");
394 BT_ASSERT_PRE_FC_HAS_ID(fc
, BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION
,
396 g_ptr_array_set_size(enum_fc
->label_buf
, 0);
398 for (i
= 0; i
< enum_fc
->mappings
->len
; i
++) {
400 const struct bt_field_class_enumeration_mapping
*mapping
=
401 BT_FIELD_CLASS_ENUM_MAPPING_AT_INDEX(enum_fc
, i
);
403 for (j
= 0; j
< mapping
->ranges
->len
; j
++) {
404 const struct bt_field_class_enumeration_mapping_range
*range
=
405 BT_FIELD_CLASS_ENUM_MAPPING_RANGE_AT_INDEX(
408 if (value
>= range
->lower
.u
&&
409 value
<= range
->upper
.u
) {
410 g_ptr_array_add(enum_fc
->label_buf
,
411 mapping
->label
->str
);
417 *label_array
= (void *) enum_fc
->label_buf
->pdata
;
418 *count
= (uint64_t) enum_fc
->label_buf
->len
;
422 int bt_field_class_signed_enumeration_get_mapping_labels_by_value(
423 const struct bt_field_class
*fc
, int64_t value
,
424 bt_field_class_enumeration_mapping_label_array
*label_array
,
427 const struct bt_field_class_enumeration
*enum_fc
= (const void *) fc
;
430 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
431 BT_ASSERT_PRE_NON_NULL(label_array
, "Label array (output)");
432 BT_ASSERT_PRE_NON_NULL(count
, "Count (output)");
433 BT_ASSERT_PRE_FC_HAS_ID(fc
, BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION
,
435 g_ptr_array_set_size(enum_fc
->label_buf
, 0);
437 for (i
= 0; i
< enum_fc
->mappings
->len
; i
++) {
439 const struct bt_field_class_enumeration_mapping
*mapping
=
440 BT_FIELD_CLASS_ENUM_MAPPING_AT_INDEX(enum_fc
, i
);
442 for (j
= 0; j
< mapping
->ranges
->len
; j
++) {
443 const struct bt_field_class_enumeration_mapping_range
*range
=
444 BT_FIELD_CLASS_ENUM_MAPPING_RANGE_AT_INDEX(
447 if (value
>= range
->lower
.i
&&
448 value
<= range
->upper
.i
) {
449 g_ptr_array_add(enum_fc
->label_buf
,
450 mapping
->label
->str
);
456 *label_array
= (void *) enum_fc
->label_buf
->pdata
;
457 *count
= (uint64_t) enum_fc
->label_buf
->len
;
462 int add_mapping_to_enumeration_field_class(struct bt_field_class
*fc
,
463 const char *label
, uint64_t lower
, uint64_t upper
)
467 struct bt_field_class_enumeration
*enum_fc
= (void *) fc
;
468 struct bt_field_class_enumeration_mapping
*mapping
= NULL
;
469 struct bt_field_class_enumeration_mapping_range
*range
;
472 BT_ASSERT_PRE_NON_NULL(label
, "Label");
474 /* Find existing mapping identified by this label */
475 for (i
= 0; i
< enum_fc
->mappings
->len
; i
++) {
476 struct bt_field_class_enumeration_mapping
*mapping_candidate
=
477 BT_FIELD_CLASS_ENUM_MAPPING_AT_INDEX(enum_fc
, i
);
479 if (strcmp(mapping_candidate
->label
->str
, label
) == 0) {
480 mapping
= mapping_candidate
;
486 /* Create new mapping for this label */
487 g_array_set_size(enum_fc
->mappings
, enum_fc
->mappings
->len
+ 1);
488 mapping
= BT_FIELD_CLASS_ENUM_MAPPING_AT_INDEX(enum_fc
,
489 enum_fc
->mappings
->len
- 1);
490 mapping
->ranges
= g_array_new(FALSE
, TRUE
,
491 sizeof(struct bt_field_class_enumeration_mapping_range
));
492 if (!mapping
->ranges
) {
493 finalize_enumeration_field_class_mapping(mapping
);
494 g_array_set_size(enum_fc
->mappings
,
495 enum_fc
->mappings
->len
- 1);
500 mapping
->label
= g_string_new(label
);
501 if (!mapping
->label
) {
502 finalize_enumeration_field_class_mapping(mapping
);
503 g_array_set_size(enum_fc
->mappings
,
504 enum_fc
->mappings
->len
- 1);
512 g_array_set_size(mapping
->ranges
, mapping
->ranges
->len
+ 1);
513 range
= BT_FIELD_CLASS_ENUM_MAPPING_RANGE_AT_INDEX(mapping
,
514 mapping
->ranges
->len
- 1);
515 range
->lower
.u
= lower
;
516 range
->upper
.u
= upper
;
517 BT_LIB_LOGV("Added mapping to enumeration field class: "
518 "%![fc-]+F, label=\"%s\", lower-unsigned=%" PRIu64
", "
519 "upper-unsigned=%" PRIu64
, fc
, label
, lower
, upper
);
525 int bt_field_class_unsigned_enumeration_map_range(
526 struct bt_field_class
*fc
, const char *label
,
527 uint64_t range_lower
, uint64_t range_upper
)
529 struct bt_field_class_enumeration
*enum_fc
= (void *) fc
;
531 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
532 BT_ASSERT_PRE_FC_HAS_ID(fc
, BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION
,
534 BT_ASSERT_PRE(range_lower
<= range_upper
,
535 "Range's upper bound is less than lower bound: "
536 "upper=%" PRIu64
", lower=%" PRIu64
,
537 range_lower
, range_upper
);
538 BT_ASSERT_PRE(bt_util_value_is_in_range_unsigned(enum_fc
->common
.range
,
540 "Range's lower bound is outside the enumeration field class's value range: "
541 "%![fc-]+F, lower=%" PRIu64
, fc
, range_lower
);
542 BT_ASSERT_PRE(bt_util_value_is_in_range_unsigned(enum_fc
->common
.range
,
544 "Range's upper bound is outside the enumeration field class's value range: "
545 "%![fc-]+F, upper=%" PRIu64
, fc
, range_upper
);
546 return add_mapping_to_enumeration_field_class(fc
, label
, range_lower
,
550 int bt_field_class_signed_enumeration_map_range(
551 struct bt_field_class
*fc
, const char *label
,
552 int64_t range_lower
, int64_t range_upper
)
554 struct bt_field_class_enumeration
*enum_fc
= (void *) fc
;
556 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
557 BT_ASSERT_PRE_FC_HAS_ID(fc
, BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION
,
559 BT_ASSERT_PRE(range_lower
<= range_upper
,
560 "Range's upper bound is less than lower bound: "
561 "upper=%" PRId64
", lower=%" PRId64
,
562 range_lower
, range_upper
);
563 BT_ASSERT_PRE(bt_util_value_is_in_range_signed(enum_fc
->common
.range
,
565 "Range's lower bound is outside the enumeration field class's value range: "
566 "%![fc-]+F, lower=%" PRId64
, fc
, range_lower
);
567 BT_ASSERT_PRE(bt_util_value_is_in_range_signed(enum_fc
->common
.range
,
569 "Range's upper bound is outside the enumeration field class's value range: "
570 "%![fc-]+F, upper=%" PRId64
, fc
, range_upper
);
571 return add_mapping_to_enumeration_field_class(fc
, label
, range_lower
,
576 void destroy_real_field_class(struct bt_object
*obj
)
579 BT_LIB_LOGD("Destroying real field class object: %!+F", obj
);
583 struct bt_field_class
*bt_field_class_real_create(void)
585 struct bt_field_class_real
*real_fc
= NULL
;
587 BT_LOGD_STR("Creating default real field class object.");
588 real_fc
= g_new0(struct bt_field_class_real
, 1);
590 BT_LOGE_STR("Failed to allocate one real field class.");
594 init_field_class((void *) real_fc
, BT_FIELD_CLASS_TYPE_REAL
,
595 destroy_real_field_class
);
596 BT_LIB_LOGD("Created real field class object: %!+F", real_fc
);
600 BT_OBJECT_PUT_REF_AND_RESET(real_fc
);
603 return (void *) real_fc
;
606 bt_bool
bt_field_class_real_is_single_precision(const struct bt_field_class
*fc
)
608 const struct bt_field_class_real
*real_fc
= (const void *) fc
;
610 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
611 BT_ASSERT_PRE_FC_HAS_ID(fc
, BT_FIELD_CLASS_TYPE_REAL
, "Field class");
612 return real_fc
->is_single_precision
;
615 void bt_field_class_real_set_is_single_precision(struct bt_field_class
*fc
,
616 bt_bool is_single_precision
)
618 struct bt_field_class_real
*real_fc
= (void *) fc
;
620 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
621 BT_ASSERT_PRE_FC_HAS_ID(fc
, BT_FIELD_CLASS_TYPE_REAL
, "Field class");
622 BT_ASSERT_PRE_FC_HOT(fc
, "Field class");
623 real_fc
->is_single_precision
= (bool) is_single_precision
;
624 BT_LIB_LOGV("Set real field class's \"is single precision\" property: "
629 int init_named_field_classes_container(
630 struct bt_field_class_named_field_class_container
*fc
,
631 enum bt_field_class_type type
,
632 bt_object_release_func release_func
)
636 init_field_class((void *) fc
, type
, release_func
);
637 fc
->named_fcs
= g_array_new(FALSE
, TRUE
,
638 sizeof(struct bt_named_field_class
));
639 if (!fc
->named_fcs
) {
640 BT_LOGE_STR("Failed to allocate a GArray.");
645 fc
->name_to_index
= g_hash_table_new(g_str_hash
, g_str_equal
);
646 if (!fc
->name_to_index
) {
647 BT_LOGE_STR("Failed to allocate a GHashTable.");
657 void finalize_named_field_class(struct bt_named_field_class
*named_fc
)
660 BT_LIB_LOGD("Finalizing named field class: "
661 "addr=%p, name=\"%s\", %![fc-]+F",
662 named_fc
, named_fc
->name
? named_fc
->name
->str
: NULL
,
665 if (named_fc
->name
) {
666 g_string_free(named_fc
->name
, TRUE
);
669 BT_LOGD_STR("Putting named field class's field class.");
670 BT_OBJECT_PUT_REF_AND_RESET(named_fc
->fc
);
674 void finalize_named_field_classes_container(
675 struct bt_field_class_named_field_class_container
*fc
)
682 for (i
= 0; i
< fc
->named_fcs
->len
; i
++) {
683 finalize_named_field_class(
684 &g_array_index(fc
->named_fcs
,
685 struct bt_named_field_class
, i
));
688 g_array_free(fc
->named_fcs
, TRUE
);
691 if (fc
->name_to_index
) {
692 g_hash_table_destroy(fc
->name_to_index
);
697 void destroy_structure_field_class(struct bt_object
*obj
)
700 BT_LIB_LOGD("Destroying string field class object: %!+F", obj
);
701 finalize_named_field_classes_container((void *) obj
);
705 struct bt_field_class
*bt_field_class_structure_create(void)
708 struct bt_field_class_structure
*struct_fc
= NULL
;
710 BT_LOGD_STR("Creating default structure field class object.");
711 struct_fc
= g_new0(struct bt_field_class_structure
, 1);
713 BT_LOGE_STR("Failed to allocate one structure field class.");
717 ret
= init_named_field_classes_container((void *) struct_fc
,
718 BT_FIELD_CLASS_TYPE_STRUCTURE
, destroy_structure_field_class
);
723 BT_LIB_LOGD("Created structure field class object: %!+F", struct_fc
);
727 BT_OBJECT_PUT_REF_AND_RESET(struct_fc
);
730 return (void *) struct_fc
;
734 int append_named_field_class_to_container_field_class(
735 struct bt_field_class_named_field_class_container
*container_fc
,
736 const char *name
, struct bt_field_class
*fc
)
739 struct bt_named_field_class
*named_fc
;
742 BT_ASSERT(container_fc
);
743 BT_ASSERT_PRE_FC_HOT(container_fc
, "Field class");
744 BT_ASSERT_PRE_NON_NULL(name
, "Name");
745 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
746 BT_ASSERT_PRE(!bt_g_hash_table_contains(container_fc
->name_to_index
,
748 "Duplicate member/option name in structure/variant field class: "
749 "%![container-fc-]+F, name=\"%s\"", container_fc
, name
);
750 name_str
= g_string_new(name
);
752 BT_LOGE_STR("Failed to allocate a GString.");
757 g_array_set_size(container_fc
->named_fcs
,
758 container_fc
->named_fcs
->len
+ 1);
759 named_fc
= &g_array_index(container_fc
->named_fcs
,
760 struct bt_named_field_class
, container_fc
->named_fcs
->len
- 1);
761 named_fc
->name
= name_str
;
763 bt_object_get_no_null_check(fc
);
764 g_hash_table_insert(container_fc
->name_to_index
, named_fc
->name
->str
,
765 GUINT_TO_POINTER(container_fc
->named_fcs
->len
- 1));
766 bt_field_class_freeze(fc
);
772 int bt_field_class_structure_append_member(struct bt_field_class
*fc
,
773 const char *name
, struct bt_field_class
*member_fc
)
776 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
777 BT_ASSERT_PRE_FC_HAS_ID(fc
, BT_FIELD_CLASS_TYPE_STRUCTURE
, "Field class");
778 return append_named_field_class_to_container_field_class((void *) fc
,
782 uint64_t bt_field_class_structure_get_member_count(
783 const struct bt_field_class
*fc
)
785 struct bt_field_class_structure
*struct_fc
= (void *) fc
;
787 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
788 BT_ASSERT_PRE_FC_HAS_ID(fc
, BT_FIELD_CLASS_TYPE_STRUCTURE
, "Field class");
789 return (uint64_t) struct_fc
->common
.named_fcs
->len
;
793 void borrow_named_field_class_from_container_field_class_at_index_const(
794 const struct bt_field_class_named_field_class_container
*fc
,
795 uint64_t index
, const char **name
,
796 const struct bt_field_class
**out_fc
)
798 const struct bt_named_field_class
*named_fc
;
801 BT_ASSERT_PRE_NON_NULL(name
, "Name");
802 BT_ASSERT_PRE_NON_NULL(out_fc
, "Field class (output)");
803 BT_ASSERT_PRE_VALID_INDEX(index
, fc
->named_fcs
->len
);
804 named_fc
= BT_FIELD_CLASS_NAMED_FC_AT_INDEX(fc
, index
);
805 *name
= named_fc
->name
->str
;
806 *out_fc
= named_fc
->fc
;
809 void bt_field_class_structure_borrow_member_by_index_const(
810 const struct bt_field_class
*fc
, uint64_t index
,
811 const char **name
, const struct bt_field_class
**out_fc
)
813 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
814 BT_ASSERT_PRE_FC_HAS_ID(fc
, BT_FIELD_CLASS_TYPE_STRUCTURE
, "Field class");
815 borrow_named_field_class_from_container_field_class_at_index_const(
816 (void *) fc
, index
, name
, out_fc
);
820 const struct bt_field_class
*
821 borrow_field_class_from_container_field_class_by_name_const(
822 const struct bt_field_class_named_field_class_container
*fc
,
825 const struct bt_field_class
*ret_fc
= NULL
;
826 const struct bt_named_field_class
*named_fc
;
831 BT_ASSERT_PRE_NON_NULL(name
, "Name");
832 if (!g_hash_table_lookup_extended(fc
->name_to_index
, name
, &orig_key
,
837 named_fc
= BT_FIELD_CLASS_NAMED_FC_AT_INDEX(fc
,
838 GPOINTER_TO_UINT(value
));
839 ret_fc
= named_fc
->fc
;
845 const struct bt_field_class
*
846 bt_field_class_structure_borrow_member_field_class_by_name(
847 const struct bt_field_class
*fc
, const char *name
)
849 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
850 BT_ASSERT_PRE_FC_HAS_ID(fc
, BT_FIELD_CLASS_TYPE_STRUCTURE
, "Field class");
851 return borrow_field_class_from_container_field_class_by_name_const(
856 void destroy_variant_field_class(struct bt_object
*obj
)
858 struct bt_field_class_variant
*fc
= (void *) obj
;
861 BT_LIB_LOGD("Destroying variant field class object: %!+F", fc
);
862 finalize_named_field_classes_container((void *) fc
);
863 BT_LOGD_STR("Putting selector field path.");
864 BT_OBJECT_PUT_REF_AND_RESET(fc
->selector_field_path
);
865 BT_LOGD_STR("Putting selector field class.");
866 BT_OBJECT_PUT_REF_AND_RESET(fc
->selector_fc
);
870 struct bt_field_class
*bt_field_class_variant_create(void)
873 struct bt_field_class_variant
*var_fc
= NULL
;
875 BT_LOGD_STR("Creating default variant field class object.");
876 var_fc
= g_new0(struct bt_field_class_variant
, 1);
878 BT_LOGE_STR("Failed to allocate one variant field class.");
882 ret
= init_named_field_classes_container((void *) var_fc
,
883 BT_FIELD_CLASS_TYPE_VARIANT
, destroy_variant_field_class
);
888 BT_LIB_LOGD("Created variant field class object: %!+F", var_fc
);
892 BT_OBJECT_PUT_REF_AND_RESET(var_fc
);
895 return (void *) var_fc
;
898 int bt_field_class_variant_set_selector_field_class(
899 struct bt_field_class
*fc
,
900 struct bt_field_class
*selector_fc
)
902 struct bt_field_class_variant
*var_fc
= (void *) fc
;
904 BT_ASSERT_PRE_NON_NULL(fc
, "Variant field class");
905 BT_ASSERT_PRE_NON_NULL(selector_fc
, "Selector field class");
906 BT_ASSERT_PRE_FC_HAS_ID(fc
, BT_FIELD_CLASS_TYPE_VARIANT
, "Field class");
907 BT_ASSERT_PRE_FC_IS_ENUM(selector_fc
, "Selector field class");
908 BT_ASSERT_PRE_FC_HOT(fc
, "Variant field class");
909 var_fc
->selector_fc
= selector_fc
;
910 bt_object_get_no_null_check(selector_fc
);
911 bt_field_class_freeze(selector_fc
);
915 int bt_field_class_variant_append_option(
916 struct bt_field_class
*fc
,
917 const char *name
, struct bt_field_class
*option_fc
)
920 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
921 BT_ASSERT_PRE_FC_HAS_ID(fc
, BT_FIELD_CLASS_TYPE_VARIANT
, "Field class");
922 return append_named_field_class_to_container_field_class((void *) fc
,
926 const struct bt_field_class
*
927 bt_field_class_variant_borrow_option_field_class_by_name_const(
928 const struct bt_field_class
*fc
, const char *name
)
930 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
931 BT_ASSERT_PRE_FC_HAS_ID(fc
, BT_FIELD_CLASS_TYPE_VARIANT
, "Field class");
932 return borrow_field_class_from_container_field_class_by_name_const(
936 uint64_t bt_field_class_variant_get_option_count(const struct bt_field_class
*fc
)
938 const struct bt_field_class_variant
*var_fc
= (const void *) fc
;
940 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
941 BT_ASSERT_PRE_FC_HAS_ID(fc
, BT_FIELD_CLASS_TYPE_VARIANT
, "Field class");
942 return (uint64_t) var_fc
->common
.named_fcs
->len
;
945 void bt_field_class_variant_borrow_option_by_index_const(
946 const struct bt_field_class
*fc
, uint64_t index
,
947 const char **name
, const struct bt_field_class
**out_fc
)
949 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
950 BT_ASSERT_PRE_FC_HAS_ID(fc
, BT_FIELD_CLASS_TYPE_VARIANT
, "Field class");
951 borrow_named_field_class_from_container_field_class_at_index_const(
952 (void *) fc
, index
, name
, out_fc
);
955 const struct bt_field_path
*
956 bt_field_class_variant_borrow_selector_field_path_const(
957 const struct bt_field_class
*fc
)
959 const struct bt_field_class_variant
*var_fc
= (const void *) fc
;
961 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
962 BT_ASSERT_PRE_FC_HAS_ID(fc
, BT_FIELD_CLASS_TYPE_VARIANT
,
964 return var_fc
->selector_field_path
;
968 void init_array_field_class(struct bt_field_class_array
*fc
,
969 enum bt_field_class_type type
, bt_object_release_func release_func
,
970 struct bt_field_class
*element_fc
)
972 BT_ASSERT(element_fc
);
973 init_field_class((void *) fc
, type
, release_func
);
974 fc
->element_fc
= element_fc
;
975 bt_object_get_no_null_check(element_fc
);
976 bt_field_class_freeze(element_fc
);
980 void finalize_array_field_class(struct bt_field_class_array
*array_fc
)
983 BT_LOGD_STR("Putting element field class.");
984 BT_OBJECT_PUT_REF_AND_RESET(array_fc
->element_fc
);
988 void destroy_static_array_field_class(struct bt_object
*obj
)
991 BT_LIB_LOGD("Destroying static array field class object: %!+F", obj
);
992 finalize_array_field_class((void *) obj
);
996 struct bt_field_class
*
997 bt_field_class_static_array_create(struct bt_field_class
*element_fc
,
1000 struct bt_field_class_static_array
*array_fc
= NULL
;
1002 BT_ASSERT_PRE_NON_NULL(element_fc
, "Element field class");
1003 BT_LOGD_STR("Creating default static array field class object.");
1004 array_fc
= g_new0(struct bt_field_class_static_array
, 1);
1006 BT_LOGE_STR("Failed to allocate one static array field class.");
1010 init_array_field_class((void *) array_fc
, BT_FIELD_CLASS_TYPE_STATIC_ARRAY
,
1011 destroy_static_array_field_class
, element_fc
);
1012 array_fc
->length
= length
;
1013 BT_LIB_LOGD("Created static array field class object: %!+F", array_fc
);
1017 BT_OBJECT_PUT_REF_AND_RESET(array_fc
);
1020 return (void *) array_fc
;
1023 const struct bt_field_class
*
1024 bt_field_class_array_borrow_element_field_class_const(
1025 const struct bt_field_class
*fc
)
1027 const struct bt_field_class_array
*array_fc
= (const void *) fc
;
1029 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
1030 BT_ASSERT_PRE_FC_IS_ARRAY(fc
, "Field class");
1031 return array_fc
->element_fc
;
1034 uint64_t bt_field_class_static_array_get_length(const struct bt_field_class
*fc
)
1036 const struct bt_field_class_static_array
*array_fc
= (const void *) fc
;
1038 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
1039 BT_ASSERT_PRE_FC_HAS_ID(fc
, BT_FIELD_CLASS_TYPE_STATIC_ARRAY
,
1041 return (uint64_t) array_fc
->length
;
1045 void destroy_dynamic_array_field_class(struct bt_object
*obj
)
1047 struct bt_field_class_dynamic_array
*fc
= (void *) obj
;
1050 BT_LIB_LOGD("Destroying dynamic array field class object: %!+F", fc
);
1051 finalize_array_field_class((void *) fc
);
1052 BT_LOGD_STR("Putting length field path.");
1053 BT_OBJECT_PUT_REF_AND_RESET(fc
->length_field_path
);
1054 BT_LOGD_STR("Putting length field class.");
1055 BT_OBJECT_PUT_REF_AND_RESET(fc
->length_fc
);
1059 struct bt_field_class
*bt_field_class_dynamic_array_create(
1060 struct bt_field_class
*element_fc
)
1062 struct bt_field_class_dynamic_array
*array_fc
= NULL
;
1064 BT_ASSERT_PRE_NON_NULL(element_fc
, "Element field class");
1065 BT_LOGD_STR("Creating default dynamic array field class object.");
1066 array_fc
= g_new0(struct bt_field_class_dynamic_array
, 1);
1068 BT_LOGE_STR("Failed to allocate one dynamic array field class.");
1072 init_array_field_class((void *) array_fc
,
1073 BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY
,
1074 destroy_dynamic_array_field_class
, element_fc
);
1075 BT_LIB_LOGD("Created dynamic array field class object: %!+F", array_fc
);
1079 BT_OBJECT_PUT_REF_AND_RESET(array_fc
);
1082 return (void *) array_fc
;
1085 int bt_field_class_dynamic_array_set_length_field_class(
1086 struct bt_field_class
*fc
,
1087 struct bt_field_class
*length_fc
)
1089 struct bt_field_class_dynamic_array
*array_fc
= (void *) fc
;
1091 BT_ASSERT_PRE_NON_NULL(fc
, "Dynamic array field class");
1092 BT_ASSERT_PRE_NON_NULL(length_fc
, "Length field class");
1093 BT_ASSERT_PRE_FC_HAS_ID(fc
, BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY
,
1095 BT_ASSERT_PRE_FC_IS_UNSIGNED_INT(length_fc
, "Length field class");
1096 BT_ASSERT_PRE_FC_HOT(fc
, "Dynamic array field class");
1097 array_fc
->length_fc
= length_fc
;
1098 bt_object_get_no_null_check(length_fc
);
1099 bt_field_class_freeze(length_fc
);
1103 const struct bt_field_path
*
1104 bt_field_class_dynamic_array_borrow_length_field_path_const(
1105 const struct bt_field_class
*fc
)
1107 const struct bt_field_class_dynamic_array
*seq_fc
= (const void *) fc
;
1109 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
1110 BT_ASSERT_PRE_FC_HAS_ID(fc
, BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY
,
1112 return seq_fc
->length_field_path
;
1116 void destroy_string_field_class(struct bt_object
*obj
)
1119 BT_LIB_LOGD("Destroying string field class object: %!+F", obj
);
1123 struct bt_field_class
*bt_field_class_string_create(void)
1125 struct bt_field_class_string
*string_fc
= NULL
;
1127 BT_LOGD_STR("Creating default string field class object.");
1128 string_fc
= g_new0(struct bt_field_class_string
, 1);
1130 BT_LOGE_STR("Failed to allocate one string field class.");
1134 init_field_class((void *) string_fc
, BT_FIELD_CLASS_TYPE_STRING
,
1135 destroy_string_field_class
);
1136 BT_LIB_LOGD("Created string field class object: %!+F", string_fc
);
1140 BT_OBJECT_PUT_REF_AND_RESET(string_fc
);
1143 return (void *) string_fc
;
1147 void _bt_field_class_freeze(const struct bt_field_class
*fc
)
1150 * Element/member/option field classes are frozen when added to
1154 ((struct bt_field_class
*) fc
)->frozen
= true;
1158 void _bt_field_class_make_part_of_trace_class(const struct bt_field_class
*c_fc
)
1160 struct bt_field_class
*fc
= (void *) c_fc
;
1163 BT_ASSERT_PRE(!fc
->part_of_trace_class
,
1164 "Field class is already part of a trace: %!+F", fc
);
1165 fc
->part_of_trace_class
= true;
1168 case BT_FIELD_CLASS_TYPE_STRUCTURE
:
1169 case BT_FIELD_CLASS_TYPE_VARIANT
:
1171 struct bt_field_class_named_field_class_container
*container_fc
=
1175 for (i
= 0; i
< container_fc
->named_fcs
->len
; i
++) {
1176 struct bt_named_field_class
*named_fc
=
1177 BT_FIELD_CLASS_NAMED_FC_AT_INDEX(
1180 bt_field_class_make_part_of_trace_class(named_fc
->fc
);
1185 case BT_FIELD_CLASS_TYPE_STATIC_ARRAY
:
1186 case BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY
:
1188 struct bt_field_class_array
*array_fc
= (void *) fc
;
1190 bt_field_class_make_part_of_trace_class(array_fc
->element_fc
);
1198 void bt_field_class_get_ref(const struct bt_field_class
*field_class
)
1200 bt_object_get_ref(field_class
);
1203 void bt_field_class_put_ref(const struct bt_field_class
*field_class
)
1205 bt_object_put_ref(field_class
);