2 * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
4 * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 #define BT_LOG_TAG "FIELD-CLASSES"
26 #include <babeltrace/lib-logging-internal.h>
28 #include <babeltrace/assert-pre-internal.h>
29 #include <babeltrace/trace-ir/field-class.h>
30 #include <babeltrace/trace-ir/field-class-const.h>
31 #include <babeltrace/trace-ir/field-class-internal.h>
32 #include <babeltrace/trace-ir/field-path-internal.h>
33 #include <babeltrace/trace-ir/field-internal.h>
34 #include <babeltrace/trace-ir/field-const.h>
35 #include <babeltrace/trace-ir/field.h>
36 #include <babeltrace/trace-ir/utils-internal.h>
37 #include <babeltrace/object.h>
38 #include <babeltrace/trace-ir/clock-class.h>
39 #include <babeltrace/trace-ir/clock-class-internal.h>
40 #include <babeltrace/object-internal.h>
41 #include <babeltrace/object.h>
42 #include <babeltrace/compiler-internal.h>
43 #include <babeltrace/endian-internal.h>
44 #include <babeltrace/assert-internal.h>
45 #include <babeltrace/compat/glib-internal.h>
50 enum bt_field_class_type
bt_field_class_get_type(
51 const struct bt_field_class
*fc
)
53 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
58 void init_field_class(struct bt_field_class
*fc
, enum bt_field_class_type type
,
59 bt_object_release_func release_func
)
62 BT_ASSERT(bt_field_class_has_known_type(fc
));
63 BT_ASSERT(release_func
);
64 bt_object_init_shared(&fc
->base
, release_func
);
69 void init_integer_field_class(struct bt_field_class_integer
*fc
,
70 enum bt_field_class_type type
,
71 bt_object_release_func release_func
)
73 init_field_class((void *) fc
, type
, release_func
);
75 fc
->base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
;
79 void destroy_integer_field_class(struct bt_object
*obj
)
82 BT_LIB_LOGD("Destroying integer field class object: %!+F", obj
);
87 struct bt_field_class
*create_integer_field_class(enum bt_field_class_type type
)
89 struct bt_field_class_integer
*int_fc
= NULL
;
91 BT_LOGD("Creating default integer field class object: type=%s",
92 bt_common_field_class_type_string(type
));
93 int_fc
= g_new0(struct bt_field_class_integer
, 1);
95 BT_LOGE_STR("Failed to allocate one integer field class.");
99 init_integer_field_class(int_fc
, type
, destroy_integer_field_class
);
100 BT_LIB_LOGD("Created integer field class object: %!+F", int_fc
);
104 BT_OBJECT_PUT_REF_AND_RESET(int_fc
);
107 return (void *) int_fc
;
110 struct bt_field_class
*
111 bt_field_class_unsigned_integer_create(void)
113 return create_integer_field_class(
114 BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER
);
117 struct bt_field_class
*bt_field_class_signed_integer_create(void)
119 return create_integer_field_class(
120 BT_FIELD_CLASS_TYPE_SIGNED_INTEGER
);
123 uint64_t bt_field_class_integer_get_field_value_range(
124 const struct bt_field_class
*fc
)
126 const struct bt_field_class_integer
*int_fc
= (const void *) fc
;
128 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
129 BT_ASSERT_PRE_FC_IS_INT(fc
, "Field class");
130 return int_fc
->range
;
135 bool size_is_valid_for_enumeration_field_class(struct bt_field_class
*fc
,
142 void bt_field_class_integer_set_field_value_range(
143 struct bt_field_class
*fc
, uint64_t size
)
145 struct bt_field_class_integer
*int_fc
= (void *) fc
;
147 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
148 BT_ASSERT_PRE_FC_IS_INT(fc
, "Field class");
149 BT_ASSERT_PRE_FC_HOT(fc
, "Field class");
150 BT_ASSERT_PRE(size
<= 64,
151 "Unsupported size for integer field class's field value range "
152 "(maximum is 64): size=%" PRIu64
, size
);
154 int_fc
->common
.type
== BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER
||
155 int_fc
->common
.type
== BT_FIELD_CLASS_TYPE_SIGNED_INTEGER
||
156 size_is_valid_for_enumeration_field_class(fc
, size
),
157 "Invalid field value range for enumeration field class: "
158 "at least one of the current mapping ranges contains values "
159 "which are outside this range: %!+F, size=%" PRIu64
, fc
, size
);
160 int_fc
->range
= size
;
161 BT_LIB_LOGV("Set integer field class's field value range: %!+F", fc
);
164 enum bt_field_class_integer_preferred_display_base
165 bt_field_class_integer_get_preferred_display_base(const struct bt_field_class
*fc
)
167 const struct bt_field_class_integer
*int_fc
= (const void *) fc
;
169 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
170 BT_ASSERT_PRE_FC_IS_INT(fc
, "Field class");
174 void bt_field_class_integer_set_preferred_display_base(
175 struct bt_field_class
*fc
,
176 enum bt_field_class_integer_preferred_display_base base
)
178 struct bt_field_class_integer
*int_fc
= (void *) fc
;
180 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
181 BT_ASSERT_PRE_FC_IS_INT(fc
, "Field class");
182 BT_ASSERT_PRE_FC_HOT(fc
, "Field class");
184 BT_LIB_LOGV("Set integer field class's preferred display base: %!+F", fc
);
188 void finalize_enumeration_field_class_mapping(
189 struct bt_field_class_enumeration_mapping
*mapping
)
193 if (mapping
->label
) {
194 g_string_free(mapping
->label
, TRUE
);
197 if (mapping
->ranges
) {
198 g_array_free(mapping
->ranges
, TRUE
);
203 void destroy_enumeration_field_class(struct bt_object
*obj
)
205 struct bt_field_class_enumeration
*fc
= (void *) obj
;
208 BT_LIB_LOGD("Destroying enumeration field class object: %!+F", fc
);
213 for (i
= 0; i
< fc
->mappings
->len
; i
++) {
214 finalize_enumeration_field_class_mapping(
215 BT_FIELD_CLASS_ENUM_MAPPING_AT_INDEX(fc
, i
));
218 g_array_free(fc
->mappings
, TRUE
);
223 g_ptr_array_free(fc
->label_buf
, TRUE
);
224 fc
->label_buf
= NULL
;
231 struct bt_field_class
*create_enumeration_field_class(
232 enum bt_field_class_type type
)
234 struct bt_field_class_enumeration
*enum_fc
= NULL
;
236 BT_LOGD("Creating default enumeration field class object: type=%s",
237 bt_common_field_class_type_string(type
));
238 enum_fc
= g_new0(struct bt_field_class_enumeration
, 1);
240 BT_LOGE_STR("Failed to allocate one enumeration field class.");
244 init_integer_field_class((void *) enum_fc
, type
,
245 destroy_enumeration_field_class
);
246 enum_fc
->mappings
= g_array_new(FALSE
, TRUE
,
247 sizeof(struct bt_field_class_enumeration_mapping
));
248 if (!enum_fc
->mappings
) {
249 BT_LOGE_STR("Failed to allocate a GArray.");
253 enum_fc
->label_buf
= g_ptr_array_new();
254 if (!enum_fc
->label_buf
) {
255 BT_LOGE_STR("Failed to allocate a GArray.");
259 BT_LIB_LOGD("Created enumeration field class object: %!+F", enum_fc
);
263 BT_OBJECT_PUT_REF_AND_RESET(enum_fc
);
266 return (void *) enum_fc
;
269 struct bt_field_class
*bt_field_class_unsigned_enumeration_create(void)
271 return create_enumeration_field_class(
272 BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION
);
275 struct bt_field_class
*bt_field_class_signed_enumeration_create(void)
277 return create_enumeration_field_class(
278 BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION
);
281 uint64_t bt_field_class_enumeration_get_mapping_count(
282 const struct bt_field_class
*fc
)
284 const struct bt_field_class_enumeration
*enum_fc
= (const void *) fc
;
286 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
287 BT_ASSERT_PRE_FC_IS_ENUM(fc
, "Field class");
288 return (uint64_t) enum_fc
->mappings
->len
;
291 void bt_field_class_unsigned_enumeration_borrow_mapping_by_index_const(
292 const struct bt_field_class
*fc
, uint64_t index
,
294 const struct bt_field_class_unsigned_enumeration_mapping_ranges
**ranges
)
296 const struct bt_field_class_enumeration
*enum_fc
= (const void *) fc
;
297 const struct bt_field_class_enumeration_mapping
*mapping
;
299 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
300 BT_ASSERT_PRE_NON_NULL(name
, "Name (output)");
301 BT_ASSERT_PRE_NON_NULL(ranges
, "Ranges (output)");
302 BT_ASSERT_PRE_VALID_INDEX(index
, enum_fc
->mappings
->len
);
303 BT_ASSERT_PRE_FC_HAS_ID(fc
, BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION
,
305 mapping
= BT_FIELD_CLASS_ENUM_MAPPING_AT_INDEX(fc
, index
);
306 *name
= mapping
->label
->str
;
307 *ranges
= (void *) mapping
;
310 void bt_field_class_signed_enumeration_borrow_mapping_by_index_const(
311 const struct bt_field_class
*fc
, uint64_t index
,
313 const struct bt_field_class_signed_enumeration_mapping_ranges
**ranges
)
315 const struct bt_field_class_enumeration
*enum_fc
= (const void *) fc
;
316 const struct bt_field_class_enumeration_mapping
*mapping
;
318 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
319 BT_ASSERT_PRE_NON_NULL(name
, "Name (output)");
320 BT_ASSERT_PRE_NON_NULL(ranges
, "Ranges (output)");
321 BT_ASSERT_PRE_VALID_INDEX(index
, enum_fc
->mappings
->len
);
322 BT_ASSERT_PRE_FC_HAS_ID(fc
, BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION
,
324 mapping
= BT_FIELD_CLASS_ENUM_MAPPING_AT_INDEX(fc
, index
);
325 *name
= mapping
->label
->str
;
326 *ranges
= (void *) mapping
;
330 uint64_t get_enumeration_field_class_mapping_range_count(
331 const struct bt_field_class_enumeration_mapping
*mapping
)
333 BT_ASSERT_PRE_NON_NULL(mapping
, "Ranges");
334 return (uint64_t) mapping
->ranges
->len
;
337 uint64_t bt_field_class_unsigned_enumeration_mapping_ranges_get_range_count(
338 const struct bt_field_class_unsigned_enumeration_mapping_ranges
*ranges
)
340 return get_enumeration_field_class_mapping_range_count(
341 (const void *) ranges
);
344 uint64_t bt_field_class_signed_enumeration_mapping_ranges_get_range_count(
345 const struct bt_field_class_signed_enumeration_mapping_ranges
*ranges
)
347 return get_enumeration_field_class_mapping_range_count(
348 (const void *) ranges
);
352 void get_enumeration_field_class_mapping_range_at_index(
353 const struct bt_field_class_enumeration_mapping
*mapping
,
354 uint64_t index
, uint64_t *lower
, uint64_t *upper
)
356 const struct bt_field_class_enumeration_mapping_range
*range
;
358 BT_ASSERT_PRE_NON_NULL(mapping
, "Ranges");
359 BT_ASSERT_PRE_NON_NULL(lower
, "Range's lower (output)");
360 BT_ASSERT_PRE_NON_NULL(upper
, "Range's upper (output)");
361 BT_ASSERT_PRE_VALID_INDEX(index
, mapping
->ranges
->len
);
362 range
= BT_FIELD_CLASS_ENUM_MAPPING_RANGE_AT_INDEX(mapping
, index
);
363 *lower
= range
->lower
.u
;
364 *upper
= range
->upper
.u
;
367 void bt_field_class_unsigned_enumeration_mapping_ranges_get_range_by_index(
368 const struct bt_field_class_unsigned_enumeration_mapping_ranges
*ranges
,
369 uint64_t index
, uint64_t *lower
, uint64_t *upper
)
371 get_enumeration_field_class_mapping_range_at_index(
372 (const void *) ranges
, index
, lower
, upper
);
375 void bt_field_class_signed_enumeration_mapping_ranges_get_range_by_index(
376 const struct bt_field_class_unsigned_enumeration_mapping_ranges
*ranges
,
377 uint64_t index
, int64_t *lower
, int64_t *upper
)
379 get_enumeration_field_class_mapping_range_at_index(
380 (const void *) ranges
, index
,
381 (uint64_t *) lower
, (uint64_t *) upper
);
386 int bt_field_class_unsigned_enumeration_get_mapping_labels_by_value(
387 const struct bt_field_class
*fc
, uint64_t value
,
388 bt_field_class_enumeration_mapping_label_array
*label_array
,
391 const struct bt_field_class_enumeration
*enum_fc
= (const void *) fc
;
394 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
395 BT_ASSERT_PRE_NON_NULL(label_array
, "Label array (output)");
396 BT_ASSERT_PRE_NON_NULL(count
, "Count (output)");
397 BT_ASSERT_PRE_FC_HAS_ID(fc
, BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION
,
399 g_ptr_array_set_size(enum_fc
->label_buf
, 0);
401 for (i
= 0; i
< enum_fc
->mappings
->len
; i
++) {
403 const struct bt_field_class_enumeration_mapping
*mapping
=
404 BT_FIELD_CLASS_ENUM_MAPPING_AT_INDEX(enum_fc
, i
);
406 for (j
= 0; j
< mapping
->ranges
->len
; j
++) {
407 const struct bt_field_class_enumeration_mapping_range
*range
=
408 BT_FIELD_CLASS_ENUM_MAPPING_RANGE_AT_INDEX(
411 if (value
>= range
->lower
.u
&&
412 value
<= range
->upper
.u
) {
413 g_ptr_array_add(enum_fc
->label_buf
,
414 mapping
->label
->str
);
420 *label_array
= (void *) enum_fc
->label_buf
->pdata
;
421 *count
= (uint64_t) enum_fc
->label_buf
->len
;
425 int bt_field_class_signed_enumeration_get_mapping_labels_by_value(
426 const struct bt_field_class
*fc
, int64_t value
,
427 bt_field_class_enumeration_mapping_label_array
*label_array
,
430 const struct bt_field_class_enumeration
*enum_fc
= (const void *) fc
;
433 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
434 BT_ASSERT_PRE_NON_NULL(label_array
, "Label array (output)");
435 BT_ASSERT_PRE_NON_NULL(count
, "Count (output)");
436 BT_ASSERT_PRE_FC_HAS_ID(fc
, BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION
,
438 g_ptr_array_set_size(enum_fc
->label_buf
, 0);
440 for (i
= 0; i
< enum_fc
->mappings
->len
; i
++) {
442 const struct bt_field_class_enumeration_mapping
*mapping
=
443 BT_FIELD_CLASS_ENUM_MAPPING_AT_INDEX(enum_fc
, i
);
445 for (j
= 0; j
< mapping
->ranges
->len
; j
++) {
446 const struct bt_field_class_enumeration_mapping_range
*range
=
447 BT_FIELD_CLASS_ENUM_MAPPING_RANGE_AT_INDEX(
450 if (value
>= range
->lower
.i
&&
451 value
<= range
->upper
.i
) {
452 g_ptr_array_add(enum_fc
->label_buf
,
453 mapping
->label
->str
);
459 *label_array
= (void *) enum_fc
->label_buf
->pdata
;
460 *count
= (uint64_t) enum_fc
->label_buf
->len
;
465 int add_mapping_to_enumeration_field_class(struct bt_field_class
*fc
,
466 const char *label
, uint64_t lower
, uint64_t upper
)
470 struct bt_field_class_enumeration
*enum_fc
= (void *) fc
;
471 struct bt_field_class_enumeration_mapping
*mapping
= NULL
;
472 struct bt_field_class_enumeration_mapping_range
*range
;
475 BT_ASSERT_PRE_NON_NULL(label
, "Label");
477 /* Find existing mapping identified by this label */
478 for (i
= 0; i
< enum_fc
->mappings
->len
; i
++) {
479 struct bt_field_class_enumeration_mapping
*mapping_candidate
=
480 BT_FIELD_CLASS_ENUM_MAPPING_AT_INDEX(enum_fc
, i
);
482 if (strcmp(mapping_candidate
->label
->str
, label
) == 0) {
483 mapping
= mapping_candidate
;
489 /* Create new mapping for this label */
490 g_array_set_size(enum_fc
->mappings
, enum_fc
->mappings
->len
+ 1);
491 mapping
= BT_FIELD_CLASS_ENUM_MAPPING_AT_INDEX(enum_fc
,
492 enum_fc
->mappings
->len
- 1);
493 mapping
->ranges
= g_array_new(FALSE
, TRUE
,
494 sizeof(struct bt_field_class_enumeration_mapping_range
));
495 if (!mapping
->ranges
) {
496 finalize_enumeration_field_class_mapping(mapping
);
497 g_array_set_size(enum_fc
->mappings
,
498 enum_fc
->mappings
->len
- 1);
503 mapping
->label
= g_string_new(label
);
504 if (!mapping
->label
) {
505 finalize_enumeration_field_class_mapping(mapping
);
506 g_array_set_size(enum_fc
->mappings
,
507 enum_fc
->mappings
->len
- 1);
515 g_array_set_size(mapping
->ranges
, mapping
->ranges
->len
+ 1);
516 range
= BT_FIELD_CLASS_ENUM_MAPPING_RANGE_AT_INDEX(mapping
,
517 mapping
->ranges
->len
- 1);
518 range
->lower
.u
= lower
;
519 range
->upper
.u
= upper
;
520 BT_LIB_LOGV("Added mapping to enumeration field class: "
521 "%![fc-]+F, label=\"%s\", lower-unsigned=%" PRIu64
", "
522 "upper-unsigned=%" PRIu64
, fc
, label
, lower
, upper
);
528 int bt_field_class_unsigned_enumeration_map_range(
529 struct bt_field_class
*fc
, const char *label
,
530 uint64_t range_lower
, uint64_t range_upper
)
532 struct bt_field_class_enumeration
*enum_fc
= (void *) fc
;
534 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
535 BT_ASSERT_PRE_FC_HAS_ID(fc
, BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION
,
537 BT_ASSERT_PRE(range_lower
<= range_upper
,
538 "Range's upper bound is less than lower bound: "
539 "upper=%" PRIu64
", lower=%" PRIu64
,
540 range_lower
, range_upper
);
541 BT_ASSERT_PRE(bt_util_value_is_in_range_unsigned(enum_fc
->common
.range
,
543 "Range's lower bound is outside the enumeration field class's value range: "
544 "%![fc-]+F, lower=%" PRIu64
, fc
, range_lower
);
545 BT_ASSERT_PRE(bt_util_value_is_in_range_unsigned(enum_fc
->common
.range
,
547 "Range's upper bound is outside the enumeration field class's value range: "
548 "%![fc-]+F, upper=%" PRIu64
, fc
, range_upper
);
549 return add_mapping_to_enumeration_field_class(fc
, label
, range_lower
,
553 int bt_field_class_signed_enumeration_map_range(
554 struct bt_field_class
*fc
, const char *label
,
555 int64_t range_lower
, int64_t range_upper
)
557 struct bt_field_class_enumeration
*enum_fc
= (void *) fc
;
559 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
560 BT_ASSERT_PRE_FC_HAS_ID(fc
, BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION
,
562 BT_ASSERT_PRE(range_lower
<= range_upper
,
563 "Range's upper bound is less than lower bound: "
564 "upper=%" PRId64
", lower=%" PRId64
,
565 range_lower
, range_upper
);
566 BT_ASSERT_PRE(bt_util_value_is_in_range_signed(enum_fc
->common
.range
,
568 "Range's lower bound is outside the enumeration field class's value range: "
569 "%![fc-]+F, lower=%" PRId64
, fc
, range_lower
);
570 BT_ASSERT_PRE(bt_util_value_is_in_range_signed(enum_fc
->common
.range
,
572 "Range's upper bound is outside the enumeration field class's value range: "
573 "%![fc-]+F, upper=%" PRId64
, fc
, range_upper
);
574 return add_mapping_to_enumeration_field_class(fc
, label
, range_lower
,
579 void destroy_real_field_class(struct bt_object
*obj
)
582 BT_LIB_LOGD("Destroying real field class object: %!+F", obj
);
586 struct bt_field_class
*bt_field_class_real_create(void)
588 struct bt_field_class_real
*real_fc
= NULL
;
590 BT_LOGD_STR("Creating default real field class object.");
591 real_fc
= g_new0(struct bt_field_class_real
, 1);
593 BT_LOGE_STR("Failed to allocate one real field class.");
597 init_field_class((void *) real_fc
, BT_FIELD_CLASS_TYPE_REAL
,
598 destroy_real_field_class
);
599 BT_LIB_LOGD("Created real field class object: %!+F", real_fc
);
603 BT_OBJECT_PUT_REF_AND_RESET(real_fc
);
606 return (void *) real_fc
;
609 bt_bool
bt_field_class_real_is_single_precision(const struct bt_field_class
*fc
)
611 const struct bt_field_class_real
*real_fc
= (const void *) fc
;
613 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
614 BT_ASSERT_PRE_FC_HAS_ID(fc
, BT_FIELD_CLASS_TYPE_REAL
, "Field class");
615 return real_fc
->is_single_precision
;
618 void bt_field_class_real_set_is_single_precision(struct bt_field_class
*fc
,
619 bt_bool is_single_precision
)
621 struct bt_field_class_real
*real_fc
= (void *) fc
;
623 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
624 BT_ASSERT_PRE_FC_HAS_ID(fc
, BT_FIELD_CLASS_TYPE_REAL
, "Field class");
625 BT_ASSERT_PRE_FC_HOT(fc
, "Field class");
626 real_fc
->is_single_precision
= (bool) is_single_precision
;
627 BT_LIB_LOGV("Set real field class's \"is single precision\" property: "
632 int init_named_field_classes_container(
633 struct bt_field_class_named_field_class_container
*fc
,
634 enum bt_field_class_type type
,
635 bt_object_release_func release_func
)
639 init_field_class((void *) fc
, type
, release_func
);
640 fc
->named_fcs
= g_array_new(FALSE
, TRUE
,
641 sizeof(struct bt_named_field_class
));
642 if (!fc
->named_fcs
) {
643 BT_LOGE_STR("Failed to allocate a GArray.");
648 fc
->name_to_index
= g_hash_table_new(g_str_hash
, g_str_equal
);
649 if (!fc
->name_to_index
) {
650 BT_LOGE_STR("Failed to allocate a GHashTable.");
660 void finalize_named_field_class(struct bt_named_field_class
*named_fc
)
663 BT_LIB_LOGD("Finalizing named field class: "
664 "addr=%p, name=\"%s\", %![fc-]+F",
665 named_fc
, named_fc
->name
? named_fc
->name
->str
: NULL
,
668 if (named_fc
->name
) {
669 g_string_free(named_fc
->name
, TRUE
);
672 BT_LOGD_STR("Putting named field class's field class.");
673 BT_OBJECT_PUT_REF_AND_RESET(named_fc
->fc
);
677 void finalize_named_field_classes_container(
678 struct bt_field_class_named_field_class_container
*fc
)
685 for (i
= 0; i
< fc
->named_fcs
->len
; i
++) {
686 finalize_named_field_class(
687 &g_array_index(fc
->named_fcs
,
688 struct bt_named_field_class
, i
));
691 g_array_free(fc
->named_fcs
, TRUE
);
694 if (fc
->name_to_index
) {
695 g_hash_table_destroy(fc
->name_to_index
);
700 void destroy_structure_field_class(struct bt_object
*obj
)
703 BT_LIB_LOGD("Destroying string field class object: %!+F", obj
);
704 finalize_named_field_classes_container((void *) obj
);
708 struct bt_field_class
*bt_field_class_structure_create(void)
711 struct bt_field_class_structure
*struct_fc
= NULL
;
713 BT_LOGD_STR("Creating default structure field class object.");
714 struct_fc
= g_new0(struct bt_field_class_structure
, 1);
716 BT_LOGE_STR("Failed to allocate one structure field class.");
720 ret
= init_named_field_classes_container((void *) struct_fc
,
721 BT_FIELD_CLASS_TYPE_STRUCTURE
, destroy_structure_field_class
);
726 BT_LIB_LOGD("Created structure field class object: %!+F", struct_fc
);
730 BT_OBJECT_PUT_REF_AND_RESET(struct_fc
);
733 return (void *) struct_fc
;
737 int append_named_field_class_to_container_field_class(
738 struct bt_field_class_named_field_class_container
*container_fc
,
739 const char *name
, struct bt_field_class
*fc
)
742 struct bt_named_field_class
*named_fc
;
745 BT_ASSERT(container_fc
);
746 BT_ASSERT_PRE_FC_HOT(container_fc
, "Field class");
747 BT_ASSERT_PRE_NON_NULL(name
, "Name");
748 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
749 BT_ASSERT_PRE(!bt_g_hash_table_contains(container_fc
->name_to_index
,
751 "Duplicate member/option name in structure/variant field class: "
752 "%![container-fc-]+F, name=\"%s\"", container_fc
, name
);
753 name_str
= g_string_new(name
);
755 BT_LOGE_STR("Failed to allocate a GString.");
760 g_array_set_size(container_fc
->named_fcs
,
761 container_fc
->named_fcs
->len
+ 1);
762 named_fc
= &g_array_index(container_fc
->named_fcs
,
763 struct bt_named_field_class
, container_fc
->named_fcs
->len
- 1);
764 named_fc
->name
= name_str
;
766 bt_object_get_no_null_check(fc
);
767 g_hash_table_insert(container_fc
->name_to_index
, named_fc
->name
->str
,
768 GUINT_TO_POINTER(container_fc
->named_fcs
->len
- 1));
769 bt_field_class_freeze(fc
);
775 int bt_field_class_structure_append_member(struct bt_field_class
*fc
,
776 const char *name
, struct bt_field_class
*member_fc
)
779 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
780 BT_ASSERT_PRE_FC_HAS_ID(fc
, BT_FIELD_CLASS_TYPE_STRUCTURE
, "Field class");
781 return append_named_field_class_to_container_field_class((void *) fc
,
785 uint64_t bt_field_class_structure_get_member_count(
786 const struct bt_field_class
*fc
)
788 struct bt_field_class_structure
*struct_fc
= (void *) fc
;
790 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
791 BT_ASSERT_PRE_FC_HAS_ID(fc
, BT_FIELD_CLASS_TYPE_STRUCTURE
, "Field class");
792 return (uint64_t) struct_fc
->common
.named_fcs
->len
;
796 void borrow_named_field_class_from_container_field_class_at_index_const(
797 const struct bt_field_class_named_field_class_container
*fc
,
798 uint64_t index
, const char **name
,
799 const struct bt_field_class
**out_fc
)
801 const struct bt_named_field_class
*named_fc
;
804 BT_ASSERT_PRE_NON_NULL(name
, "Name");
805 BT_ASSERT_PRE_NON_NULL(out_fc
, "Field class (output)");
806 BT_ASSERT_PRE_VALID_INDEX(index
, fc
->named_fcs
->len
);
807 named_fc
= BT_FIELD_CLASS_NAMED_FC_AT_INDEX(fc
, index
);
808 *name
= named_fc
->name
->str
;
809 *out_fc
= named_fc
->fc
;
812 void bt_field_class_structure_borrow_member_by_index_const(
813 const struct bt_field_class
*fc
, uint64_t index
,
814 const char **name
, const struct bt_field_class
**out_fc
)
816 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
817 BT_ASSERT_PRE_FC_HAS_ID(fc
, BT_FIELD_CLASS_TYPE_STRUCTURE
, "Field class");
818 borrow_named_field_class_from_container_field_class_at_index_const(
819 (void *) fc
, index
, name
, out_fc
);
823 const struct bt_field_class
*
824 borrow_field_class_from_container_field_class_by_name_const(
825 const struct bt_field_class_named_field_class_container
*fc
,
828 const struct bt_field_class
*ret_fc
= NULL
;
829 const struct bt_named_field_class
*named_fc
;
834 BT_ASSERT_PRE_NON_NULL(name
, "Name");
835 if (!g_hash_table_lookup_extended(fc
->name_to_index
, name
, &orig_key
,
840 named_fc
= BT_FIELD_CLASS_NAMED_FC_AT_INDEX(fc
,
841 GPOINTER_TO_UINT(value
));
842 ret_fc
= named_fc
->fc
;
848 const struct bt_field_class
*
849 bt_field_class_structure_borrow_member_field_class_by_name(
850 const struct bt_field_class
*fc
, const char *name
)
852 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
853 BT_ASSERT_PRE_FC_HAS_ID(fc
, BT_FIELD_CLASS_TYPE_STRUCTURE
, "Field class");
854 return borrow_field_class_from_container_field_class_by_name_const(
859 void destroy_variant_field_class(struct bt_object
*obj
)
861 struct bt_field_class_variant
*fc
= (void *) obj
;
864 BT_LIB_LOGD("Destroying variant field class object: %!+F", fc
);
865 finalize_named_field_classes_container((void *) fc
);
866 BT_LOGD_STR("Putting selector field path.");
867 BT_OBJECT_PUT_REF_AND_RESET(fc
->selector_field_path
);
868 BT_LOGD_STR("Putting selector field class.");
869 BT_OBJECT_PUT_REF_AND_RESET(fc
->selector_fc
);
873 struct bt_field_class
*bt_field_class_variant_create(void)
876 struct bt_field_class_variant
*var_fc
= NULL
;
878 BT_LOGD_STR("Creating default variant field class object.");
879 var_fc
= g_new0(struct bt_field_class_variant
, 1);
881 BT_LOGE_STR("Failed to allocate one variant field class.");
885 ret
= init_named_field_classes_container((void *) var_fc
,
886 BT_FIELD_CLASS_TYPE_VARIANT
, destroy_variant_field_class
);
891 BT_LIB_LOGD("Created variant field class object: %!+F", var_fc
);
895 BT_OBJECT_PUT_REF_AND_RESET(var_fc
);
898 return (void *) var_fc
;
901 int bt_field_class_variant_set_selector_field_class(
902 struct bt_field_class
*fc
,
903 struct bt_field_class
*selector_fc
)
905 struct bt_field_class_variant
*var_fc
= (void *) fc
;
907 BT_ASSERT_PRE_NON_NULL(fc
, "Variant field class");
908 BT_ASSERT_PRE_NON_NULL(selector_fc
, "Selector field class");
909 BT_ASSERT_PRE_FC_HAS_ID(fc
, BT_FIELD_CLASS_TYPE_VARIANT
, "Field class");
910 BT_ASSERT_PRE_FC_IS_ENUM(selector_fc
, "Selector field class");
911 BT_ASSERT_PRE_FC_HOT(fc
, "Variant field class");
912 var_fc
->selector_fc
= selector_fc
;
913 bt_object_get_no_null_check(selector_fc
);
914 bt_field_class_freeze(selector_fc
);
918 int bt_field_class_variant_append_option(
919 struct bt_field_class
*fc
,
920 const char *name
, struct bt_field_class
*option_fc
)
923 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
924 BT_ASSERT_PRE_FC_HAS_ID(fc
, BT_FIELD_CLASS_TYPE_VARIANT
, "Field class");
925 return append_named_field_class_to_container_field_class((void *) fc
,
929 const struct bt_field_class
*
930 bt_field_class_variant_borrow_option_field_class_by_name_const(
931 const struct bt_field_class
*fc
, const char *name
)
933 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
934 BT_ASSERT_PRE_FC_HAS_ID(fc
, BT_FIELD_CLASS_TYPE_VARIANT
, "Field class");
935 return borrow_field_class_from_container_field_class_by_name_const(
939 uint64_t bt_field_class_variant_get_option_count(const struct bt_field_class
*fc
)
941 const struct bt_field_class_variant
*var_fc
= (const void *) fc
;
943 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
944 BT_ASSERT_PRE_FC_HAS_ID(fc
, BT_FIELD_CLASS_TYPE_VARIANT
, "Field class");
945 return (uint64_t) var_fc
->common
.named_fcs
->len
;
948 void bt_field_class_variant_borrow_option_by_index_const(
949 const struct bt_field_class
*fc
, uint64_t index
,
950 const char **name
, const struct bt_field_class
**out_fc
)
952 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
953 BT_ASSERT_PRE_FC_HAS_ID(fc
, BT_FIELD_CLASS_TYPE_VARIANT
, "Field class");
954 borrow_named_field_class_from_container_field_class_at_index_const(
955 (void *) fc
, index
, name
, out_fc
);
958 const struct bt_field_path
*
959 bt_field_class_variant_borrow_selector_field_path_const(
960 const struct bt_field_class
*fc
)
962 const struct bt_field_class_variant
*var_fc
= (const void *) fc
;
964 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
965 BT_ASSERT_PRE_FC_HAS_ID(fc
, BT_FIELD_CLASS_TYPE_VARIANT
,
967 return var_fc
->selector_field_path
;
971 void init_array_field_class(struct bt_field_class_array
*fc
,
972 enum bt_field_class_type type
, bt_object_release_func release_func
,
973 struct bt_field_class
*element_fc
)
975 BT_ASSERT(element_fc
);
976 init_field_class((void *) fc
, type
, release_func
);
977 fc
->element_fc
= element_fc
;
978 bt_object_get_no_null_check(element_fc
);
979 bt_field_class_freeze(element_fc
);
983 void finalize_array_field_class(struct bt_field_class_array
*array_fc
)
986 BT_LOGD_STR("Putting element field class.");
987 BT_OBJECT_PUT_REF_AND_RESET(array_fc
->element_fc
);
991 void destroy_static_array_field_class(struct bt_object
*obj
)
994 BT_LIB_LOGD("Destroying static array field class object: %!+F", obj
);
995 finalize_array_field_class((void *) obj
);
999 struct bt_field_class
*
1000 bt_field_class_static_array_create(struct bt_field_class
*element_fc
,
1003 struct bt_field_class_static_array
*array_fc
= NULL
;
1005 BT_ASSERT_PRE_NON_NULL(element_fc
, "Element field class");
1006 BT_LOGD_STR("Creating default static array field class object.");
1007 array_fc
= g_new0(struct bt_field_class_static_array
, 1);
1009 BT_LOGE_STR("Failed to allocate one static array field class.");
1013 init_array_field_class((void *) array_fc
, BT_FIELD_CLASS_TYPE_STATIC_ARRAY
,
1014 destroy_static_array_field_class
, element_fc
);
1015 array_fc
->length
= length
;
1016 BT_LIB_LOGD("Created static array field class object: %!+F", array_fc
);
1020 BT_OBJECT_PUT_REF_AND_RESET(array_fc
);
1023 return (void *) array_fc
;
1026 const struct bt_field_class
*
1027 bt_field_class_array_borrow_element_field_class_const(
1028 const struct bt_field_class
*fc
)
1030 const struct bt_field_class_array
*array_fc
= (const void *) fc
;
1032 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
1033 BT_ASSERT_PRE_FC_IS_ARRAY(fc
, "Field class");
1034 return array_fc
->element_fc
;
1037 uint64_t bt_field_class_static_array_get_length(const struct bt_field_class
*fc
)
1039 const struct bt_field_class_static_array
*array_fc
= (const void *) fc
;
1041 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
1042 BT_ASSERT_PRE_FC_HAS_ID(fc
, BT_FIELD_CLASS_TYPE_STATIC_ARRAY
,
1044 return (uint64_t) array_fc
->length
;
1048 void destroy_dynamic_array_field_class(struct bt_object
*obj
)
1050 struct bt_field_class_dynamic_array
*fc
= (void *) obj
;
1053 BT_LIB_LOGD("Destroying dynamic array field class object: %!+F", fc
);
1054 finalize_array_field_class((void *) fc
);
1055 BT_LOGD_STR("Putting length field path.");
1056 BT_OBJECT_PUT_REF_AND_RESET(fc
->length_field_path
);
1057 BT_LOGD_STR("Putting length field class.");
1058 BT_OBJECT_PUT_REF_AND_RESET(fc
->length_fc
);
1062 struct bt_field_class
*bt_field_class_dynamic_array_create(
1063 struct bt_field_class
*element_fc
)
1065 struct bt_field_class_dynamic_array
*array_fc
= NULL
;
1067 BT_ASSERT_PRE_NON_NULL(element_fc
, "Element field class");
1068 BT_LOGD_STR("Creating default dynamic array field class object.");
1069 array_fc
= g_new0(struct bt_field_class_dynamic_array
, 1);
1071 BT_LOGE_STR("Failed to allocate one dynamic array field class.");
1075 init_array_field_class((void *) array_fc
,
1076 BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY
,
1077 destroy_dynamic_array_field_class
, element_fc
);
1078 BT_LIB_LOGD("Created dynamic array field class object: %!+F", array_fc
);
1082 BT_OBJECT_PUT_REF_AND_RESET(array_fc
);
1085 return (void *) array_fc
;
1088 int bt_field_class_dynamic_array_set_length_field_class(
1089 struct bt_field_class
*fc
,
1090 struct bt_field_class
*length_fc
)
1092 struct bt_field_class_dynamic_array
*array_fc
= (void *) fc
;
1094 BT_ASSERT_PRE_NON_NULL(fc
, "Dynamic array field class");
1095 BT_ASSERT_PRE_NON_NULL(length_fc
, "Length field class");
1096 BT_ASSERT_PRE_FC_HAS_ID(fc
, BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY
,
1098 BT_ASSERT_PRE_FC_IS_UNSIGNED_INT(length_fc
, "Length field class");
1099 BT_ASSERT_PRE_FC_HOT(fc
, "Dynamic array field class");
1100 array_fc
->length_fc
= length_fc
;
1101 bt_object_get_no_null_check(length_fc
);
1102 bt_field_class_freeze(length_fc
);
1106 const struct bt_field_path
*
1107 bt_field_class_dynamic_array_borrow_length_field_path_const(
1108 const struct bt_field_class
*fc
)
1110 const struct bt_field_class_dynamic_array
*seq_fc
= (const void *) fc
;
1112 BT_ASSERT_PRE_NON_NULL(fc
, "Field class");
1113 BT_ASSERT_PRE_FC_HAS_ID(fc
, BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY
,
1115 return seq_fc
->length_field_path
;
1119 void destroy_string_field_class(struct bt_object
*obj
)
1122 BT_LIB_LOGD("Destroying string field class object: %!+F", obj
);
1126 struct bt_field_class
*bt_field_class_string_create(void)
1128 struct bt_field_class_string
*string_fc
= NULL
;
1130 BT_LOGD_STR("Creating default string field class object.");
1131 string_fc
= g_new0(struct bt_field_class_string
, 1);
1133 BT_LOGE_STR("Failed to allocate one string field class.");
1137 init_field_class((void *) string_fc
, BT_FIELD_CLASS_TYPE_STRING
,
1138 destroy_string_field_class
);
1139 BT_LIB_LOGD("Created string field class object: %!+F", string_fc
);
1143 BT_OBJECT_PUT_REF_AND_RESET(string_fc
);
1146 return (void *) string_fc
;
1150 void _bt_field_class_freeze(const struct bt_field_class
*fc
)
1153 * Element/member/option field classes are frozen when added to
1157 ((struct bt_field_class
*) fc
)->frozen
= true;
1161 void _bt_field_class_make_part_of_trace_class(const struct bt_field_class
*c_fc
)
1163 struct bt_field_class
*fc
= (void *) c_fc
;
1166 BT_ASSERT_PRE(!fc
->part_of_trace_class
,
1167 "Field class is already part of a trace: %!+F", fc
);
1168 fc
->part_of_trace_class
= true;
1171 case BT_FIELD_CLASS_TYPE_STRUCTURE
:
1172 case BT_FIELD_CLASS_TYPE_VARIANT
:
1174 struct bt_field_class_named_field_class_container
*container_fc
=
1178 for (i
= 0; i
< container_fc
->named_fcs
->len
; i
++) {
1179 struct bt_named_field_class
*named_fc
=
1180 BT_FIELD_CLASS_NAMED_FC_AT_INDEX(
1183 bt_field_class_make_part_of_trace_class(named_fc
->fc
);
1188 case BT_FIELD_CLASS_TYPE_STATIC_ARRAY
:
1189 case BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY
:
1191 struct bt_field_class_array
*array_fc
= (void *) fc
;
1193 bt_field_class_make_part_of_trace_class(array_fc
->element_fc
);