X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=src%2Flib%2Ftrace-ir%2Ffield-class.c;h=97c8523c6972eaafb65ef4a61a62a918b47646c9;hb=d98421f2abfc5adab28ab7ee9b63537a6c7261cc;hp=fb2e99ec75b095556f6035ae543755e72cdef229;hpb=45c51519900e100d9acda4acb9516ef69bc2d045;p=babeltrace.git diff --git a/src/lib/trace-ir/field-class.c b/src/lib/trace-ir/field-class.c index fb2e99ec..97c8523c 100644 --- a/src/lib/trace-ir/field-class.c +++ b/src/lib/trace-ir/field-class.c @@ -1,33 +1,15 @@ /* + * SPDX-License-Identifier: MIT + * * Copyright 2017-2018 Philippe Proulx * Copyright 2013, 2014 Jérémie Galarneau - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. */ #define BT_LOG_TAG "LIB/FIELD-CLASS" #include "lib/logging.h" -#include "lib/assert-pre.h" +#include "lib/assert-cond.h" #include -#include -#include #include #include #include "lib/object.h" @@ -37,6 +19,7 @@ #include "compat/glib.h" #include #include +#include #include #include "clock-class.h" @@ -46,6 +29,7 @@ #include "utils.h" #include "lib/func-status.h" #include "lib/integer-range-set.h" +#include "lib/value.h" enum bt_field_class_type bt_field_class_get_type( const struct bt_field_class *fc) @@ -55,23 +39,142 @@ enum bt_field_class_type bt_field_class_get_type( } static -void init_field_class(struct bt_field_class *fc, enum bt_field_class_type type, +int init_field_class(struct bt_field_class *fc, enum bt_field_class_type type, bt_object_release_func release_func) { + int ret = 0; + BT_ASSERT(fc); BT_ASSERT(release_func); bt_object_init_shared(&fc->base, release_func); fc->type = type; + fc->user_attributes = bt_value_map_create(); + if (!fc->user_attributes) { + BT_LIB_LOGE_APPEND_CAUSE( + "Failed to create a map value object."); + ret = -1; + goto end; + } + +end: + return ret; +} + +static +void finalize_field_class(struct bt_field_class *fc) +{ + BT_OBJECT_PUT_REF_AND_RESET(fc->user_attributes); } static -void init_integer_field_class(struct bt_field_class_integer *fc, +void destroy_bit_array_field_class(struct bt_object *obj) +{ + BT_ASSERT(obj); + BT_LIB_LOGD("Destroying bit array field class object: %!+F", obj); + finalize_field_class((void *) obj); + g_free(obj); +} + +struct bt_field_class *bt_field_class_bit_array_create( + struct bt_trace_class *trace_class, uint64_t length) +{ + struct bt_field_class_bit_array *ba_fc = NULL; + + BT_ASSERT_PRE_NO_ERROR(); + BT_ASSERT_PRE_NON_NULL(trace_class, "Trace class"); + BT_ASSERT_PRE(length > 0 && length <= 64, + "Unsupported length for bit array field class " + "(minimum is 1, maximum is 64): length=%" PRIu64, length); + BT_LOGD("Creating default bit array field class object."); + ba_fc = g_new0(struct bt_field_class_bit_array, 1); + if (!ba_fc) { + BT_LIB_LOGE_APPEND_CAUSE( + "Failed to allocate one bit array field class."); + goto error; + } + + if (init_field_class((void *) ba_fc, BT_FIELD_CLASS_TYPE_BIT_ARRAY, + destroy_bit_array_field_class)) { + goto error; + } + + ba_fc->length = length; + BT_LIB_LOGD("Created bit array field class object: %!+F", ba_fc); + goto end; + +error: + BT_OBJECT_PUT_REF_AND_RESET(ba_fc); + +end: + return (void *) ba_fc; +} + +uint64_t bt_field_class_bit_array_get_length(const struct bt_field_class *fc) +{ + const struct bt_field_class_bit_array *ba_fc = (const void *) fc; + + BT_ASSERT_PRE_DEV_NON_NULL(fc, "Field class"); + BT_ASSERT_PRE_DEV_FC_HAS_ID(fc, BT_FIELD_CLASS_TYPE_BIT_ARRAY, + "Field class"); + return ba_fc->length; +} + +static +void destroy_bool_field_class(struct bt_object *obj) +{ + BT_ASSERT(obj); + BT_LIB_LOGD("Destroying boolean field class object: %!+F", obj); + finalize_field_class((void *) obj); + g_free(obj); +} + +struct bt_field_class *bt_field_class_bool_create( + bt_trace_class *trace_class) +{ + struct bt_field_class_bool *bool_fc = NULL; + + BT_ASSERT_PRE_NO_ERROR(); + BT_ASSERT_PRE_NON_NULL(trace_class, "Trace class"); + BT_LOGD("Creating default boolean field class object."); + bool_fc = g_new0(struct bt_field_class_bool, 1); + if (!bool_fc) { + BT_LIB_LOGE_APPEND_CAUSE( + "Failed to allocate one boolean field class."); + goto error; + } + + if (init_field_class((void *) bool_fc, BT_FIELD_CLASS_TYPE_BOOL, + destroy_bool_field_class)) { + goto error; + } + + BT_LIB_LOGD("Created boolean field class object: %!+F", bool_fc); + goto end; + +error: + BT_OBJECT_PUT_REF_AND_RESET(bool_fc); + +end: + return (void *) bool_fc; +} + +static +int init_integer_field_class(struct bt_field_class_integer *fc, enum bt_field_class_type type, bt_object_release_func release_func) { - init_field_class((void *) fc, type, release_func); + int ret; + + ret = init_field_class((void *) fc, type, release_func); + if (ret) { + goto end; + } + fc->range = 64; fc->base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL; + +end: + return ret; } static @@ -79,6 +182,7 @@ void destroy_integer_field_class(struct bt_object *obj) { BT_ASSERT(obj); BT_LIB_LOGD("Destroying integer field class object: %!+F", obj); + finalize_field_class((void *) obj); g_free(obj); } @@ -98,7 +202,11 @@ struct bt_field_class *create_integer_field_class(bt_trace_class *trace_class, goto error; } - init_integer_field_class(int_fc, type, destroy_integer_field_class); + if (init_integer_field_class(int_fc, type, + destroy_integer_field_class)) { + goto error; + } + BT_LIB_LOGD("Created integer field class object: %!+F", int_fc); goto end; @@ -109,16 +217,20 @@ end: return (void *) int_fc; } -struct bt_field_class *bt_field_class_unsigned_integer_create( +struct bt_field_class *bt_field_class_integer_unsigned_create( bt_trace_class *trace_class) { + BT_ASSERT_PRE_NO_ERROR(); + return create_integer_field_class(trace_class, BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER); } -struct bt_field_class *bt_field_class_signed_integer_create( +struct bt_field_class *bt_field_class_integer_signed_create( bt_trace_class *trace_class) { + BT_ASSERT_PRE_NO_ERROR(); + return create_integer_field_class(trace_class, BT_FIELD_CLASS_TYPE_SIGNED_INTEGER); } @@ -133,7 +245,6 @@ uint64_t bt_field_class_integer_get_field_value_range( return int_fc->range; } -BT_ASSERT_PRE_FUNC static bool size_is_valid_for_enumeration_field_class(struct bt_field_class *fc, uint64_t size) @@ -150,9 +261,9 @@ void bt_field_class_integer_set_field_value_range( BT_ASSERT_PRE_NON_NULL(fc, "Field class"); BT_ASSERT_PRE_FC_IS_INT(fc, "Field class"); BT_ASSERT_PRE_DEV_FC_HOT(fc, "Field class"); - BT_ASSERT_PRE(size <= 64, + BT_ASSERT_PRE(size >= 1 && size <= 64, "Unsupported size for integer field class's field value range " - "(maximum is 64): size=%" PRIu64, size); + "(minimum is 1, maximum is 64): size=%" PRIu64, size); BT_ASSERT_PRE( int_fc->common.type == BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER || int_fc->common.type == BT_FIELD_CLASS_TYPE_SIGNED_INTEGER || @@ -208,6 +319,7 @@ void destroy_enumeration_field_class(struct bt_object *obj) BT_ASSERT(fc); BT_LIB_LOGD("Destroying enumeration field class object: %!+F", fc); + finalize_field_class((void *) obj); if (fc->mappings) { uint64_t i; @@ -245,8 +357,11 @@ struct bt_field_class *create_enumeration_field_class( goto error; } - init_integer_field_class((void *) enum_fc, type, - destroy_enumeration_field_class); + if (init_integer_field_class((void *) enum_fc, type, + destroy_enumeration_field_class)) { + goto error; + } + enum_fc->mappings = g_array_new(FALSE, TRUE, sizeof(struct bt_field_class_enumeration_mapping)); if (!enum_fc->mappings) { @@ -270,16 +385,20 @@ end: return (void *) enum_fc; } -struct bt_field_class *bt_field_class_unsigned_enumeration_create( +struct bt_field_class *bt_field_class_enumeration_unsigned_create( bt_trace_class *trace_class) { + BT_ASSERT_PRE_NO_ERROR(); + return create_enumeration_field_class(trace_class, BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION); } -struct bt_field_class *bt_field_class_signed_enumeration_create( +struct bt_field_class *bt_field_class_enumeration_signed_create( bt_trace_class *trace_class) { + BT_ASSERT_PRE_NO_ERROR(); + return create_enumeration_field_class(trace_class, BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION); } @@ -294,8 +413,8 @@ uint64_t bt_field_class_enumeration_get_mapping_count( return (uint64_t) enum_fc->mappings->len; } -const struct bt_field_class_unsigned_enumeration_mapping * -bt_field_class_unsigned_enumeration_borrow_mapping_by_index_const( +const struct bt_field_class_enumeration_unsigned_mapping * +bt_field_class_enumeration_unsigned_borrow_mapping_by_index_const( const struct bt_field_class *fc, uint64_t index) { const struct bt_field_class_enumeration *enum_fc = (const void *) fc; @@ -307,8 +426,8 @@ bt_field_class_unsigned_enumeration_borrow_mapping_by_index_const( return (const void *) BT_FIELD_CLASS_ENUM_MAPPING_AT_INDEX(fc, index); } -const struct bt_field_class_signed_enumeration_mapping * -bt_field_class_signed_enumeration_borrow_mapping_by_index_const( +const struct bt_field_class_enumeration_signed_mapping * +bt_field_class_enumeration_signed_borrow_mapping_by_index_const( const struct bt_field_class *fc, uint64_t index) { const struct bt_field_class_enumeration *enum_fc = (const void *) fc; @@ -328,7 +447,7 @@ borrow_enumeration_field_class_mapping_by_label( struct bt_field_class_enumeration_mapping *mapping = NULL; uint64_t i; - BT_ASSERT(fc); + BT_ASSERT_DBG(fc); BT_ASSERT_PRE_DEV_NON_NULL(label, "Label"); for (i = 0; i < fc->mappings->len; i++) { @@ -345,8 +464,8 @@ end: return mapping; } -const struct bt_field_class_signed_enumeration_mapping * -bt_field_class_signed_enumeration_borrow_mapping_by_label_const( +const struct bt_field_class_enumeration_signed_mapping * +bt_field_class_enumeration_signed_borrow_mapping_by_label_const( const struct bt_field_class *fc, const char *label) { BT_ASSERT_PRE_DEV_NON_NULL(fc, "Field class"); @@ -356,8 +475,8 @@ bt_field_class_signed_enumeration_borrow_mapping_by_label_const( (const void *) fc, label); } -const struct bt_field_class_unsigned_enumeration_mapping * -bt_field_class_unsigned_enumeration_borrow_mapping_by_label_const( +const struct bt_field_class_enumeration_unsigned_mapping * +bt_field_class_enumeration_unsigned_borrow_mapping_by_label_const( const struct bt_field_class *fc, const char *label) { BT_ASSERT_PRE_DEV_NON_NULL(fc, "Field class"); @@ -375,8 +494,8 @@ const char *bt_field_class_enumeration_mapping_get_label( } const struct bt_integer_range_set_unsigned * -bt_field_class_unsigned_enumeration_mapping_borrow_ranges_const( - const struct bt_field_class_unsigned_enumeration_mapping *u_mapping) +bt_field_class_enumeration_unsigned_mapping_borrow_ranges_const( + const struct bt_field_class_enumeration_unsigned_mapping *u_mapping) { const struct bt_field_class_enumeration_mapping *mapping = (const void *) u_mapping; @@ -386,8 +505,8 @@ bt_field_class_unsigned_enumeration_mapping_borrow_ranges_const( } const struct bt_integer_range_set_signed * -bt_field_class_signed_enumeration_mapping_borrow_ranges_const( - const struct bt_field_class_signed_enumeration_mapping *s_mapping) +bt_field_class_enumeration_signed_mapping_borrow_ranges_const( + const struct bt_field_class_enumeration_signed_mapping *s_mapping) { const struct bt_field_class_enumeration_mapping *mapping = (const void *) s_mapping; @@ -397,7 +516,7 @@ bt_field_class_signed_enumeration_mapping_borrow_ranges_const( } enum bt_field_class_enumeration_get_mapping_labels_for_value_status -bt_field_class_unsigned_enumeration_get_mapping_labels_for_value( +bt_field_class_enumeration_unsigned_get_mapping_labels_for_value( const struct bt_field_class *fc, uint64_t value, bt_field_class_enumeration_mapping_label_array *label_array, uint64_t *count) @@ -405,6 +524,7 @@ bt_field_class_unsigned_enumeration_get_mapping_labels_for_value( const struct bt_field_class_enumeration *enum_fc = (const void *) fc; uint64_t i; + BT_ASSERT_PRE_DEV_NO_ERROR(); BT_ASSERT_PRE_DEV_NON_NULL(fc, "Field class"); BT_ASSERT_PRE_DEV_NON_NULL(label_array, "Label array (output)"); BT_ASSERT_PRE_DEV_NON_NULL(count, "Count (output)"); @@ -437,7 +557,7 @@ bt_field_class_unsigned_enumeration_get_mapping_labels_for_value( } enum bt_field_class_enumeration_get_mapping_labels_for_value_status -bt_field_class_signed_enumeration_get_mapping_labels_for_value( +bt_field_class_enumeration_signed_get_mapping_labels_for_value( const struct bt_field_class *fc, int64_t value, bt_field_class_enumeration_mapping_label_array *label_array, uint64_t *count) @@ -445,6 +565,7 @@ bt_field_class_signed_enumeration_get_mapping_labels_for_value( const struct bt_field_class_enumeration *enum_fc = (const void *) fc; uint64_t i; + BT_ASSERT_PRE_DEV_NO_ERROR(); BT_ASSERT_PRE_DEV_NON_NULL(fc, "Field class"); BT_ASSERT_PRE_DEV_NON_NULL(label_array, "Label array (output)"); BT_ASSERT_PRE_DEV_NON_NULL(count, "Count (output)"); @@ -511,9 +632,10 @@ add_mapping_to_enumeration_field_class(struct bt_field_class *fc, struct bt_field_class_enumeration *enum_fc = (void *) fc; struct bt_field_class_enumeration_mapping mapping = { 0 }; + BT_ASSERT_PRE_NO_ERROR(); BT_ASSERT(fc); BT_ASSERT_PRE_NON_NULL(label, "Label"); - BT_ASSERT_PRE_NON_NULL(range_set, "Range set"); + BT_ASSERT_PRE_NON_NULL(range_set, "Integer range set"); BT_ASSERT_PRE(!enumeration_field_class_has_mapping_with_label( enum_fc, label), "Duplicate mapping name in enumeration field class: " @@ -536,10 +658,11 @@ end: } enum bt_field_class_enumeration_add_mapping_status -bt_field_class_unsigned_enumeration_add_mapping( +bt_field_class_enumeration_unsigned_add_mapping( struct bt_field_class *fc, const char *label, const struct bt_integer_range_set_unsigned *range_set) { + BT_ASSERT_PRE_NO_ERROR(); BT_ASSERT_PRE_NON_NULL(fc, "Field class"); BT_ASSERT_PRE_FC_HAS_ID(fc, BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION, "Field class"); @@ -548,10 +671,11 @@ bt_field_class_unsigned_enumeration_add_mapping( } enum bt_field_class_enumeration_add_mapping_status -bt_field_class_signed_enumeration_add_mapping( +bt_field_class_enumeration_signed_add_mapping( struct bt_field_class *fc, const char *label, const struct bt_integer_range_set_signed *range_set) { + BT_ASSERT_PRE_NO_ERROR(); BT_ASSERT_PRE_NON_NULL(fc, "Field class"); BT_ASSERT_PRE_FC_HAS_ID(fc, BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION, "Field class"); @@ -564,23 +688,29 @@ void destroy_real_field_class(struct bt_object *obj) { BT_ASSERT(obj); BT_LIB_LOGD("Destroying real field class object: %!+F", obj); + finalize_field_class((void *) obj); g_free(obj); } -struct bt_field_class *bt_field_class_real_create(bt_trace_class *trace_class) +static +struct bt_field_class *create_real_field_class(bt_trace_class *trace_class, + enum bt_field_class_type type) { struct bt_field_class_real *real_fc = NULL; BT_ASSERT_PRE_NON_NULL(trace_class, "Trace class"); - BT_LOGD_STR("Creating default real field class object."); + BT_LOGD("Creating default real field class object: type=%s", + bt_common_field_class_type_string(type)); real_fc = g_new0(struct bt_field_class_real, 1); if (!real_fc) { BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate one real field class."); goto error; } - init_field_class((void *) real_fc, BT_FIELD_CLASS_TYPE_REAL, - destroy_real_field_class); + if (init_field_class((void *) real_fc, type, destroy_real_field_class)) { + goto error; + } + BT_LIB_LOGD("Created real field class object: %!+F", real_fc); goto end; @@ -591,26 +721,22 @@ end: return (void *) real_fc; } -bt_bool bt_field_class_real_is_single_precision(const struct bt_field_class *fc) +struct bt_field_class *bt_field_class_real_single_precision_create( + bt_trace_class *trace_class) { - const struct bt_field_class_real *real_fc = (const void *) fc; + BT_ASSERT_PRE_NO_ERROR(); - BT_ASSERT_PRE_DEV_NON_NULL(fc, "Field class"); - BT_ASSERT_PRE_DEV_FC_HAS_ID(fc, BT_FIELD_CLASS_TYPE_REAL, "Field class"); - return real_fc->is_single_precision; + return create_real_field_class(trace_class, + BT_FIELD_CLASS_TYPE_SINGLE_PRECISION_REAL); } -void bt_field_class_real_set_is_single_precision(struct bt_field_class *fc, - bt_bool is_single_precision) +struct bt_field_class *bt_field_class_real_double_precision_create( + bt_trace_class *trace_class) { - struct bt_field_class_real *real_fc = (void *) fc; + BT_ASSERT_PRE_NO_ERROR(); - BT_ASSERT_PRE_NON_NULL(fc, "Field class"); - BT_ASSERT_PRE_FC_HAS_ID(fc, BT_FIELD_CLASS_TYPE_REAL, "Field class"); - BT_ASSERT_PRE_DEV_FC_HOT(fc, "Field class"); - real_fc->is_single_precision = (bool) is_single_precision; - BT_LIB_LOGD("Set real field class's \"is single precision\" property: " - "%!+F", fc); + return create_real_field_class(trace_class, + BT_FIELD_CLASS_TYPE_DOUBLE_PRECISION_REAL); } static @@ -622,7 +748,11 @@ int init_named_field_classes_container( { int ret = 0; - init_field_class((void *) fc, type, fc_release_func); + ret = init_field_class((void *) fc, type, fc_release_func); + if (ret) { + goto end; + } + fc->named_fcs = g_ptr_array_new_with_free_func(named_fc_destroy_func); if (!fc->named_fcs) { BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate a GPtrArray."); @@ -649,6 +779,7 @@ void finalize_named_field_class(struct bt_named_field_class *named_fc) "addr=%p, name=\"%s\", %![fc-]+F", named_fc, named_fc->name ? named_fc->name->str : NULL, named_fc->fc); + BT_OBJECT_PUT_REF_AND_RESET(named_fc->user_attributes); if (named_fc->name) { g_string_free(named_fc->name, TRUE); @@ -662,16 +793,19 @@ void finalize_named_field_class(struct bt_named_field_class *named_fc) static void destroy_named_field_class(gpointer ptr) { + struct bt_named_field_class *named_fc = ptr; + if (ptr) { + BT_OBJECT_PUT_REF_AND_RESET(named_fc->user_attributes); finalize_named_field_class(ptr); g_free(ptr); } } static -void destroy_variant_with_selector_option(gpointer ptr) +void destroy_variant_with_selector_field_option(gpointer ptr) { - struct bt_field_class_variant_with_selector_option *opt = ptr; + struct bt_field_class_variant_with_selector_field_option *opt = ptr; if (ptr) { finalize_named_field_class(&opt->common); @@ -703,6 +837,7 @@ void destroy_structure_field_class(struct bt_object *obj) { BT_ASSERT(obj); BT_LIB_LOGD("Destroying structure field class object: %!+F", obj); + finalize_field_class((void *) obj); finalize_named_field_classes_container((void *) obj); g_free(obj); } @@ -713,6 +848,7 @@ struct bt_field_class *bt_field_class_structure_create( int ret; struct bt_field_class_structure *struct_fc = NULL; + BT_ASSERT_PRE_NO_ERROR(); BT_ASSERT_PRE_NON_NULL(trace_class, "Trace class"); BT_LOGD_STR("Creating default structure field class object."); struct_fc = g_new0(struct bt_field_class_structure, 1); @@ -756,9 +892,16 @@ int init_named_field_class(struct bt_named_field_class *named_fc, goto end; } + named_fc->user_attributes = bt_value_map_create(); + if (!named_fc->user_attributes) { + BT_LIB_LOGE_APPEND_CAUSE( + "Failed to create a map value object."); + status = BT_FUNC_STATUS_MEMORY_ERROR; + goto end; + } + named_fc->fc = fc; - bt_object_get_no_null_check(named_fc->fc); - bt_named_field_class_freeze(named_fc); + bt_object_get_ref_no_null_check(named_fc->fc); end: return status; @@ -793,13 +936,13 @@ end: } static -struct bt_field_class_variant_with_selector_option * -create_variant_with_selector_option( +struct bt_field_class_variant_with_selector_field_option * +create_variant_with_selector_field_option( const char *name, struct bt_field_class *fc, const struct bt_integer_range_set *range_set) { - struct bt_field_class_variant_with_selector_option *opt = g_new0( - struct bt_field_class_variant_with_selector_option, 1); + struct bt_field_class_variant_with_selector_field_option *opt = g_new0( + struct bt_field_class_variant_with_selector_field_option, 1); BT_ASSERT(range_set); @@ -814,12 +957,12 @@ create_variant_with_selector_option( } opt->range_set = range_set; - bt_object_get_no_null_check(opt->range_set); + bt_object_get_ref_no_null_check(opt->range_set); bt_integer_range_set_freeze(range_set); goto end; error: - destroy_variant_with_selector_option(opt); + destroy_variant_with_selector_field_option(opt); opt = NULL; end: @@ -839,6 +982,13 @@ int append_named_field_class_to_container_field_class( "Duplicate member/option name in structure/variant field class: " "%![container-fc-]+F, name=\"%s\"", container_fc, named_fc->name->str); + + /* + * Freeze the contained field class, but not the named field + * class itself, as it's still possible afterwards to modify + * properties of the member/option object. + */ + bt_field_class_freeze(named_fc->fc); g_ptr_array_add(container_fc->named_fcs, named_fc); g_hash_table_insert(container_fc->name_to_index, named_fc->name->str, GUINT_TO_POINTER(container_fc->named_fcs->len - 1)); @@ -853,6 +1003,7 @@ bt_field_class_structure_append_member( enum bt_field_class_structure_append_member_status status; struct bt_named_field_class *named_fc = NULL; + BT_ASSERT_PRE_NO_ERROR(); BT_ASSERT_PRE_NON_NULL(fc, "Field class"); BT_ASSERT_PRE_FC_HAS_ID(fc, BT_FIELD_CLASS_TYPE_STRUCTURE, "Field class"); @@ -891,7 +1042,7 @@ borrow_named_field_class_from_container_field_class_at_index( struct bt_field_class_named_field_class_container *fc, uint64_t index) { - BT_ASSERT(fc); + BT_ASSERT_DBG(fc); BT_ASSERT_PRE_DEV_VALID_INDEX(index, fc->named_fcs->len); return fc->named_fcs->pdata[index]; } @@ -930,7 +1081,7 @@ borrow_named_field_class_from_container_field_class_by_name( gpointer orig_key; gpointer value; - BT_ASSERT(fc); + BT_ASSERT_DBG(fc); BT_ASSERT_PRE_DEV_NON_NULL(name, "Name"); if (!g_hash_table_lookup_extended(fc->name_to_index, name, &orig_key, &value)) { @@ -986,11 +1137,296 @@ bt_field_class_structure_member_borrow_field_class_const( return named_fc->fc; } +struct bt_field_class * +bt_field_class_structure_member_borrow_field_class( + struct bt_field_class_structure_member *member) +{ + struct bt_named_field_class *named_fc = (void *) member; + + BT_ASSERT_PRE_DEV_NON_NULL(member, "Structure field class member"); + return named_fc->fc; +} + +static +void destroy_option_field_class(struct bt_object *obj) +{ + struct bt_field_class_option *fc = (void *) obj; + + BT_ASSERT(fc); + BT_LIB_LOGD("Destroying option field class object: %!+F", fc); + finalize_field_class((void *) obj); + BT_LOGD_STR("Putting content field class."); + BT_OBJECT_PUT_REF_AND_RESET(fc->content_fc); + + if (fc->common.type != BT_FIELD_CLASS_TYPE_OPTION_WITHOUT_SELECTOR_FIELD) { + struct bt_field_class_option_with_selector_field *with_sel_fc = + (void *) obj; + + BT_LOGD_STR("Putting selector field path."); + BT_OBJECT_PUT_REF_AND_RESET(with_sel_fc->selector_field_path); + BT_LOGD_STR("Putting selector field class."); + BT_OBJECT_PUT_REF_AND_RESET(with_sel_fc->selector_fc); + + if (fc->common.type != BT_FIELD_CLASS_TYPE_OPTION_WITH_BOOL_SELECTOR_FIELD) { + struct bt_field_class_option_with_selector_field_integer *with_int_sel_fc = + (void *) obj; + + BT_LOGD_STR("Putting integer range set."); + BT_OBJECT_PUT_REF_AND_RESET(with_int_sel_fc->range_set); + } + } + + g_free(fc); +} + +static +struct bt_field_class *create_option_field_class( + struct bt_trace_class *trace_class, + enum bt_field_class_type fc_type, + struct bt_field_class *content_fc, + struct bt_field_class *selector_fc) +{ + struct bt_field_class_option *opt_fc = NULL; + + BT_ASSERT_PRE_NON_NULL(trace_class, "Trace class"); + BT_ASSERT_PRE_NON_NULL(content_fc, "Content field class"); + BT_LIB_LOGD("Creating option field class: " + "type=%s, %![content-fc-]+F, %![sel-fc-]+F", + bt_common_field_class_type_string(fc_type), + content_fc, selector_fc); + + if (fc_type != BT_FIELD_CLASS_TYPE_OPTION_WITHOUT_SELECTOR_FIELD) { + struct bt_field_class_option_with_selector_field *opt_with_sel_fc = NULL; + + BT_ASSERT_PRE_NON_NULL(selector_fc, "Selector field class"); + + if (fc_type == BT_FIELD_CLASS_TYPE_OPTION_WITH_BOOL_SELECTOR_FIELD) { + BT_ASSERT_PRE_FC_HAS_ID(selector_fc, + BT_FIELD_CLASS_TYPE_BOOL, + "Selector field class"); + opt_with_sel_fc = (void *) g_new0( + struct bt_field_class_option_with_selector_field_bool, 1); + } else { + BT_ASSERT_PRE_FC_IS_INT(selector_fc, + "Selector field class"); + opt_with_sel_fc = (void *) g_new0( + struct bt_field_class_option_with_selector_field_integer, 1); + } + + if (!opt_with_sel_fc) { + BT_LIB_LOGE_APPEND_CAUSE( + "Failed to allocate one option with selector field class."); + goto error; + } + + opt_with_sel_fc->selector_fc = selector_fc; + bt_object_get_ref_no_null_check(opt_with_sel_fc->selector_fc); + opt_fc = (void *) opt_with_sel_fc; + } else { + opt_fc = g_new0(struct bt_field_class_option, 1); + if (!opt_fc) { + BT_LIB_LOGE_APPEND_CAUSE( + "Failed to allocate one option field class."); + goto error; + } + } + + BT_ASSERT(opt_fc); + + if (init_field_class((void *) opt_fc, fc_type, + destroy_option_field_class)) { + goto error; + } + + opt_fc->content_fc = content_fc; + bt_object_get_ref_no_null_check(opt_fc->content_fc); + bt_field_class_freeze(opt_fc->content_fc); + + if (selector_fc) { + bt_field_class_freeze(selector_fc); + } + + BT_LIB_LOGD("Created option field class object: " + "%![opt-fc-]+F, %![sel-fc-]+F", opt_fc, selector_fc); + goto end; + +error: + BT_OBJECT_PUT_REF_AND_RESET(opt_fc); + +end: + return (void *) opt_fc; +} + +struct bt_field_class *bt_field_class_option_without_selector_create( + struct bt_trace_class *trace_class, + struct bt_field_class *content_fc) +{ + BT_ASSERT_PRE_NO_ERROR(); + + return create_option_field_class(trace_class, + BT_FIELD_CLASS_TYPE_OPTION_WITHOUT_SELECTOR_FIELD, + content_fc, NULL); +} + +struct bt_field_class *bt_field_class_option_with_selector_field_bool_create( + struct bt_trace_class *trace_class, + struct bt_field_class *content_fc, + struct bt_field_class *selector_fc) +{ + BT_ASSERT_PRE_NO_ERROR(); + + return create_option_field_class(trace_class, + BT_FIELD_CLASS_TYPE_OPTION_WITH_BOOL_SELECTOR_FIELD, + content_fc, selector_fc); +} + +struct bt_field_class * +bt_field_class_option_with_selector_field_integer_unsigned_create( + struct bt_trace_class *trace_class, + struct bt_field_class *content_fc, + struct bt_field_class *selector_fc, + const struct bt_integer_range_set_unsigned *u_range_set) +{ + struct bt_field_class_option_with_selector_field_integer *fc; + const struct bt_integer_range_set *range_set = + (const void *) u_range_set; + + BT_ASSERT_PRE_NO_ERROR(); + BT_ASSERT_PRE_NON_NULL(range_set, "Integer range set"); + BT_ASSERT_PRE(range_set->ranges->len > 0, + "Integer range set is empty: %!+R", range_set); + fc = (void *) create_option_field_class(trace_class, + BT_FIELD_CLASS_TYPE_OPTION_WITH_UNSIGNED_INTEGER_SELECTOR_FIELD, + content_fc, selector_fc); + + if (!fc) { + goto end; + } + + fc->range_set = range_set; + bt_object_get_ref_no_null_check(fc->range_set); + bt_integer_range_set_freeze(range_set); + +end: + return (void *) fc; +} + +struct bt_field_class * +bt_field_class_option_with_selector_field_integer_signed_create( + struct bt_trace_class *trace_class, + struct bt_field_class *content_fc, + struct bt_field_class *selector_fc, + const struct bt_integer_range_set_signed *i_range_set) +{ + struct bt_field_class_option_with_selector_field_integer *fc; + const struct bt_integer_range_set *range_set = + (const void *) i_range_set; + + BT_ASSERT_PRE_NO_ERROR(); + BT_ASSERT_PRE_NON_NULL(range_set, "Integer range set"); + BT_ASSERT_PRE(range_set->ranges->len > 0, + "Integer range set is empty: %!+R", range_set); + fc = (void *) create_option_field_class(trace_class, + BT_FIELD_CLASS_TYPE_OPTION_WITH_SIGNED_INTEGER_SELECTOR_FIELD, + content_fc, selector_fc); + + if (!fc) { + goto end; + } + + fc->range_set = range_set; + bt_object_get_ref_no_null_check(fc->range_set); + bt_integer_range_set_freeze(range_set); + +end: + return (void *) fc; +} + +const struct bt_field_class *bt_field_class_option_borrow_field_class_const( + const struct bt_field_class *fc) +{ + struct bt_field_class_option *opt_fc = (void *) fc; + + BT_ASSERT_PRE_NON_NULL(fc, "Field class"); + BT_ASSERT_PRE_FC_IS_OPTION(fc, "Field class"); + return opt_fc->content_fc; +} + +struct bt_field_class *bt_field_class_option_borrow_field_class( + struct bt_field_class *fc) +{ + struct bt_field_class_option *opt_fc = (void *) fc; + + BT_ASSERT_PRE_NON_NULL(fc, "Field class"); + BT_ASSERT_PRE_FC_IS_OPTION(fc, "Field class"); + return opt_fc->content_fc; +} + +const struct bt_field_path * +bt_field_class_option_with_selector_field_borrow_selector_field_path_const( + const struct bt_field_class *fc) +{ + const struct bt_field_class_option_with_selector_field *opt_fc = + (const void *) fc; + + BT_ASSERT_PRE_NON_NULL(fc, "Field class"); + BT_ASSERT_PRE_FC_IS_OPTION_WITH_SEL(fc, "Field class"); + return opt_fc->selector_field_path; +} + +void bt_field_class_option_with_selector_field_bool_set_selector_is_reversed( + struct bt_field_class *fc, bt_bool sel_is_reversed) +{ + struct bt_field_class_option_with_selector_field_bool *opt_fc = (void *) fc; + + BT_ASSERT_PRE_NON_NULL(fc, "Field class"); + BT_ASSERT_PRE_FC_HAS_ID(fc, + BT_FIELD_CLASS_TYPE_OPTION_WITH_BOOL_SELECTOR_FIELD, "Field class"); + BT_ASSERT_PRE_DEV_FC_HOT(fc, "Field class"); + opt_fc->sel_is_reversed = sel_is_reversed; +} + +bt_bool bt_field_class_option_with_selector_field_bool_selector_is_reversed( + const struct bt_field_class *fc) +{ + struct bt_field_class_option_with_selector_field_bool *opt_fc = (void *) fc; + + BT_ASSERT_PRE_NON_NULL(fc, "Field class"); + BT_ASSERT_PRE_FC_HAS_ID(fc, + BT_FIELD_CLASS_TYPE_OPTION_WITH_BOOL_SELECTOR_FIELD, "Field class"); + return opt_fc->sel_is_reversed; +} + +const struct bt_integer_range_set_unsigned * +bt_field_class_option_with_selector_field_integer_unsigned_borrow_selector_ranges_const( + const struct bt_field_class *fc) +{ + struct bt_field_class_option_with_selector_field_integer *opt_fc = + (void *) fc; + + BT_ASSERT_PRE_NON_NULL(fc, "Field class"); + BT_ASSERT_PRE_FC_IS_OPTION_WITH_INT_SEL(fc, "Field class"); + return (const void *) opt_fc->range_set; +} + +const struct bt_integer_range_set_signed * +bt_field_class_option_with_selector_field_integer_signed_borrow_selector_ranges_const( + const struct bt_field_class *fc) +{ + struct bt_field_class_option_with_selector_field_integer *opt_fc = + (void *) fc; + + BT_ASSERT_PRE_NON_NULL(fc, "Field class"); + BT_ASSERT_PRE_FC_IS_OPTION_WITH_INT_SEL(fc, "Field class"); + return (const void *) opt_fc->range_set; +} + static void finalize_variant_field_class(struct bt_field_class_variant *var_fc) { BT_ASSERT(var_fc); BT_LIB_LOGD("Finalizing variant field class object: %!+F", var_fc); + finalize_field_class((void *) var_fc); finalize_named_field_classes_container((void *) var_fc); } @@ -1005,9 +1441,9 @@ void destroy_variant_field_class(struct bt_object *obj) } static -void destroy_variant_with_selector_field_class(struct bt_object *obj) +void destroy_variant_with_selector_field_field_class(struct bt_object *obj) { - struct bt_field_class_variant_with_selector *fc = (void *) obj; + struct bt_field_class_variant_with_selector_field *fc = (void *) obj; BT_ASSERT(fc); finalize_variant_field_class(&fc->common); @@ -1023,9 +1459,10 @@ struct bt_field_class *bt_field_class_variant_create( { int ret; struct bt_field_class_variant *var_fc = NULL; - struct bt_field_class_variant_with_selector *var_with_sel_fc = NULL; + struct bt_field_class_variant_with_selector_field *var_with_sel_fc = NULL; enum bt_field_class_type fc_type; + BT_ASSERT_PRE_NO_ERROR(); BT_ASSERT_PRE_NON_NULL(trace_class, "Trace class"); if (selector_fc) { @@ -1037,33 +1474,35 @@ struct bt_field_class *bt_field_class_variant_create( if (selector_fc) { var_with_sel_fc = g_new0( - struct bt_field_class_variant_with_selector, 1); + struct bt_field_class_variant_with_selector_field, 1); if (!var_with_sel_fc) { BT_LIB_LOGE_APPEND_CAUSE( "Failed to allocate one variant field class with selector."); goto error; } - if (selector_fc->type == BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER || - selector_fc->type == BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION) { - fc_type = BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_SELECTOR; + if (bt_field_class_type_is(selector_fc->type, + BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER)) { + fc_type = BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_INTEGER_SELECTOR_FIELD; } else { - fc_type = BT_FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_SELECTOR; + fc_type = BT_FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_INTEGER_SELECTOR_FIELD; } ret = init_named_field_classes_container( (void *) var_with_sel_fc, fc_type, - destroy_variant_with_selector_field_class, - destroy_variant_with_selector_option); + destroy_variant_with_selector_field_field_class, + destroy_variant_with_selector_field_option); if (ret) { /* init_named_field_classes_container() logs errors */ goto error; } var_with_sel_fc->selector_fc = selector_fc; - bt_object_get_no_null_check(var_with_sel_fc->selector_fc); + bt_object_get_ref_no_null_check(var_with_sel_fc->selector_fc); bt_field_class_freeze(selector_fc); var_fc = (void *) var_with_sel_fc; + BT_LIB_LOGD("Created default variant field class with selector object: " + "%![var-fc-]+F, %![sel-fc-]+F", var_fc, selector_fc); } else { var_fc = g_new0(struct bt_field_class_variant, 1); if (!var_fc) { @@ -1073,21 +1512,22 @@ struct bt_field_class *bt_field_class_variant_create( } ret = init_named_field_classes_container((void *) var_fc, - BT_FIELD_CLASS_TYPE_VARIANT_WITHOUT_SELECTOR, + BT_FIELD_CLASS_TYPE_VARIANT_WITHOUT_SELECTOR_FIELD, destroy_variant_field_class, destroy_named_field_class); if (ret) { /* init_named_field_classes_container() logs errors */ goto error; } + BT_LIB_LOGD("Created default variant field class without selector object: " + "%![var-fc-]+F", var_fc); } BT_ASSERT(var_fc); - BT_LIB_LOGD("Created default variant field class with selector object: " - "%![var-fc-]+F, %![sel-fc-]+F", var_fc, selector_fc); goto end; error: BT_OBJECT_PUT_REF_AND_RESET(var_fc); + BT_OBJECT_PUT_REF_AND_RESET(var_with_sel_fc); end: return (void *) var_fc; @@ -1100,11 +1540,12 @@ bt_field_class_variant_without_selector_append_option(struct bt_field_class *fc, enum bt_field_class_variant_without_selector_append_option_status status; struct bt_named_field_class *named_fc = NULL; + BT_ASSERT_PRE_NO_ERROR(); BT_ASSERT_PRE_NON_NULL(fc, "Field class"); BT_ASSERT_PRE_NON_NULL(name, "Name"); BT_ASSERT_PRE_NON_NULL(option_fc, "Option field class"); BT_ASSERT_PRE_FC_HAS_ID(fc, - BT_FIELD_CLASS_TYPE_VARIANT_WITHOUT_SELECTOR, "Field class"); + BT_FIELD_CLASS_TYPE_VARIANT_WITHOUT_SELECTOR_FIELD, "Field class"); named_fc = create_named_field_class(name, option_fc); if (!named_fc) { /* create_named_field_class() logs errors */ @@ -1155,7 +1596,7 @@ int ranges_overlap(GPtrArray *var_fc_opts, const struct bt_integer_range_set *ra /* Add existing option ranges */ for (i = 0; i < var_fc_opts->len; i++) { - struct bt_field_class_variant_with_selector_option *opt = + struct bt_field_class_variant_with_selector_field_option *opt = var_fc_opts->pdata[i]; uint64_t j; @@ -1213,26 +1654,26 @@ end: } static -int append_option_to_variant_with_selector_field_class( +int append_option_to_variant_with_selector_field_field_class( struct bt_field_class *fc, const char *name, struct bt_field_class *option_fc, const struct bt_integer_range_set *range_set, enum bt_field_class_type expected_type) { int status; - struct bt_field_class_variant_with_selector *var_fc = (void *) fc; - struct bt_field_class_variant_with_selector_option *opt = NULL; + struct bt_field_class_variant_with_selector_field *var_fc = (void *) fc; + struct bt_field_class_variant_with_selector_field_option *opt = NULL; bool has_overlap; BT_ASSERT_PRE_NON_NULL(fc, "Field class"); BT_ASSERT_PRE_NON_NULL(name, "Name"); BT_ASSERT_PRE_NON_NULL(option_fc, "Option field class"); - BT_ASSERT_PRE_NON_NULL(range_set, "Range set"); + BT_ASSERT_PRE_NON_NULL(range_set, "Integer range set"); BT_ASSERT_PRE_FC_HAS_ID(fc, expected_type, "Field class"); BT_ASSERT_PRE(range_set->ranges->len > 0, - "Range set is empty: addr=%p", range_set); + "Integer range set is empty: %!+R", range_set); status = ranges_overlap(var_fc->common.common.named_fcs, range_set, - expected_type == BT_FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_SELECTOR, + expected_type == BT_FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_INTEGER_SELECTOR_FIELD, &has_overlap); if (status) { /* ranges_overlap() logs errors */ @@ -1240,11 +1681,11 @@ int append_option_to_variant_with_selector_field_class( } BT_ASSERT_PRE(!has_overlap, - "Range set's ranges and existing ranges have an overlap: " - "addr=%p", range_set); - opt = create_variant_with_selector_option(name, option_fc, range_set); + "Integer range set's ranges and existing ranges have an overlap: " + "%!+R", range_set); + opt = create_variant_with_selector_field_option(name, option_fc, range_set); if (!opt) { - /* create_variant_with_selector_option() logs errors */ + /* create_variant_with_selector_field_option() logs errors */ status = BT_FUNC_STATUS_MEMORY_ERROR; goto end; } @@ -1258,32 +1699,36 @@ int append_option_to_variant_with_selector_field_class( end: if (opt) { - destroy_variant_with_selector_option(opt); + destroy_variant_with_selector_field_option(opt); } return status; } -enum bt_field_class_variant_with_selector_append_option_status -bt_field_class_variant_with_unsigned_selector_append_option( +enum bt_field_class_variant_with_selector_field_integer_append_option_status +bt_field_class_variant_with_selector_field_integer_unsigned_append_option( struct bt_field_class *fc, const char *name, struct bt_field_class *option_fc, const struct bt_integer_range_set_unsigned *range_set) { - return append_option_to_variant_with_selector_field_class(fc, + BT_ASSERT_PRE_NO_ERROR(); + + return append_option_to_variant_with_selector_field_field_class(fc, name, option_fc, (const void *) range_set, - BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_SELECTOR); + BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_INTEGER_SELECTOR_FIELD); } -enum bt_field_class_variant_with_selector_append_option_status -bt_field_class_variant_with_signed_selector_append_option( +enum bt_field_class_variant_with_selector_field_integer_append_option_status +bt_field_class_variant_with_selector_field_integer_signed_append_option( struct bt_field_class *fc, const char *name, struct bt_field_class *option_fc, const struct bt_integer_range_set_signed *range_set) { - return append_option_to_variant_with_selector_field_class(fc, + BT_ASSERT_PRE_NO_ERROR(); + + return append_option_to_variant_with_selector_field_field_class(fc, name, option_fc, (const void *) range_set, - BT_FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_SELECTOR); + BT_FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_INTEGER_SELECTOR_FIELD); } uint64_t bt_field_class_variant_get_option_count(const struct bt_field_class *fc) @@ -1317,52 +1762,74 @@ bt_field_class_variant_borrow_option_by_index_const( (void *) fc, index); } -const struct bt_field_class_variant_with_unsigned_selector_option * -bt_field_class_variant_with_unsigned_selector_borrow_option_by_name_const( +struct bt_field_class_variant_option * +bt_field_class_variant_borrow_option_by_name( + struct bt_field_class *fc, const char *name) +{ + BT_ASSERT_PRE_DEV_NON_NULL(fc, "Field class"); + BT_ASSERT_PRE_DEV_FC_IS_VARIANT(fc, "Field class"); + return (void *) + borrow_named_field_class_from_container_field_class_by_name( + (void *) fc, name); +} + +struct bt_field_class_variant_option * +bt_field_class_variant_borrow_option_by_index( + struct bt_field_class *fc, uint64_t index) +{ + BT_ASSERT_PRE_DEV_NON_NULL(fc, "Field class"); + BT_ASSERT_PRE_DEV_FC_IS_VARIANT(fc, "Field class"); + return (void *) + borrow_named_field_class_from_container_field_class_at_index( + (void *) fc, index); +} + +const struct bt_field_class_variant_with_selector_field_integer_unsigned_option * +bt_field_class_variant_with_selector_field_integer_unsigned_borrow_option_by_name_const( const struct bt_field_class *fc, const char *name) { BT_ASSERT_PRE_DEV_NON_NULL(fc, "Field class"); BT_ASSERT_PRE_DEV_FC_HAS_ID(fc, - BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_SELECTOR, + BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_INTEGER_SELECTOR_FIELD, "Field class"); return (const void *) borrow_named_field_class_from_container_field_class_by_name( (void *) fc, name); } -const struct bt_field_class_variant_with_unsigned_selector_option * -bt_field_class_variant_with_unsigned_selector_borrow_option_by_index_const( +const struct bt_field_class_variant_with_selector_field_integer_unsigned_option * +bt_field_class_variant_with_selector_field_integer_unsigned_borrow_option_by_index_const( const struct bt_field_class *fc, uint64_t index) { BT_ASSERT_PRE_DEV_NON_NULL(fc, "Field class"); BT_ASSERT_PRE_DEV_FC_HAS_ID(fc, - BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_SELECTOR, + BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_INTEGER_SELECTOR_FIELD, "Field class"); return (const void *) borrow_named_field_class_from_container_field_class_at_index( (void *) fc, index); } -const struct bt_field_class_variant_with_signed_selector_option * -bt_field_class_variant_with_signed_selector_borrow_option_by_name_const( +const struct bt_field_class_variant_with_selector_field_integer_signed_option * +bt_field_class_variant_with_selector_field_integer_signed_borrow_option_by_name_const( const struct bt_field_class *fc, const char *name) { BT_ASSERT_PRE_DEV_NON_NULL(fc, "Field class"); BT_ASSERT_PRE_DEV_FC_HAS_ID(fc, - BT_FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_SELECTOR, + BT_FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_INTEGER_SELECTOR_FIELD, "Field class"); return (const void *) borrow_named_field_class_from_container_field_class_by_name( (void *) fc, name); } -const struct bt_field_class_variant_with_signed_selector_option * -bt_field_class_variant_with_signed_selector_borrow_option_by_index_const( +const struct bt_field_class_variant_with_selector_field_integer_signed_option * +bt_field_class_variant_with_selector_field_integer_signed_borrow_option_by_index_const( const struct bt_field_class *fc, uint64_t index) { BT_ASSERT_PRE_DEV_NON_NULL(fc, "Field class"); BT_ASSERT_PRE_DEV_FC_HAS_ID(fc, - BT_FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_SELECTOR, + BT_FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_INTEGER_SELECTOR_FIELD, "Field class"); return (const void *) borrow_named_field_class_from_container_field_class_at_index( @@ -1388,11 +1855,21 @@ bt_field_class_variant_option_borrow_field_class_const( return named_fc->fc; } +struct bt_field_class * +bt_field_class_variant_option_borrow_field_class( + struct bt_field_class_variant_option *option) +{ + struct bt_named_field_class *named_fc = (void *) option; + + BT_ASSERT_PRE_DEV_NON_NULL(option, "Variant field class option"); + return named_fc->fc; +} + const struct bt_integer_range_set_unsigned * -bt_field_class_variant_with_unsigned_selector_option_borrow_ranges_const( - const struct bt_field_class_variant_with_unsigned_selector_option *option) +bt_field_class_variant_with_selector_field_integer_unsigned_option_borrow_ranges_const( + const struct bt_field_class_variant_with_selector_field_integer_unsigned_option *option) { - const struct bt_field_class_variant_with_selector_option *opt = + const struct bt_field_class_variant_with_selector_field_option *opt = (const void *) option; BT_ASSERT_PRE_DEV_NON_NULL(option, "Variant field class option"); @@ -1400,10 +1877,10 @@ bt_field_class_variant_with_unsigned_selector_option_borrow_ranges_const( } const struct bt_integer_range_set_signed * -bt_field_class_variant_with_signed_selector_option_borrow_ranges_const( - const struct bt_field_class_variant_with_signed_selector_option *option) +bt_field_class_variant_with_selector_field_integer_signed_option_borrow_ranges_const( + const struct bt_field_class_variant_with_selector_field_integer_signed_option *option) { - const struct bt_field_class_variant_with_selector_option *opt = + const struct bt_field_class_variant_with_selector_field_option *opt = (const void *) option; BT_ASSERT_PRE_DEV_NON_NULL(option, "Variant field class option"); @@ -1411,10 +1888,10 @@ bt_field_class_variant_with_signed_selector_option_borrow_ranges_const( } const struct bt_field_path * -bt_field_class_variant_with_selector_borrow_selector_field_path_const( +bt_field_class_variant_with_selector_field_borrow_selector_field_path_const( const struct bt_field_class *fc) { - const struct bt_field_class_variant_with_selector *var_fc = + const struct bt_field_class_variant_with_selector_field *var_fc = (const void *) fc; BT_ASSERT_PRE_DEV_NON_NULL(fc, "Field class"); @@ -1423,15 +1900,24 @@ bt_field_class_variant_with_selector_borrow_selector_field_path_const( } static -void init_array_field_class(struct bt_field_class_array *fc, +int init_array_field_class(struct bt_field_class_array *fc, enum bt_field_class_type type, bt_object_release_func release_func, struct bt_field_class *element_fc) { + int ret; + BT_ASSERT(element_fc); - init_field_class((void *) fc, type, release_func); + ret = init_field_class((void *) fc, type, release_func); + if (ret) { + goto end; + } + fc->element_fc = element_fc; - bt_object_get_no_null_check(fc->element_fc); + bt_object_get_ref_no_null_check(fc->element_fc); bt_field_class_freeze(element_fc); + +end: + return ret; } static @@ -1439,6 +1925,7 @@ void finalize_array_field_class(struct bt_field_class_array *array_fc) { BT_ASSERT(array_fc); BT_LOGD_STR("Putting element field class."); + finalize_field_class((void *) array_fc); BT_OBJECT_PUT_REF_AND_RESET(array_fc->element_fc); } @@ -1452,23 +1939,28 @@ void destroy_static_array_field_class(struct bt_object *obj) } struct bt_field_class * -bt_field_class_static_array_create(bt_trace_class *trace_class, +bt_field_class_array_static_create(bt_trace_class *trace_class, struct bt_field_class *element_fc, uint64_t length) { - struct bt_field_class_static_array *array_fc = NULL; + struct bt_field_class_array_static *array_fc = NULL; + BT_ASSERT_PRE_NO_ERROR(); BT_ASSERT_PRE_NON_NULL(trace_class, "Trace class"); BT_ASSERT_PRE_NON_NULL(element_fc, "Element field class"); BT_LOGD_STR("Creating default static array field class object."); - array_fc = g_new0(struct bt_field_class_static_array, 1); + array_fc = g_new0(struct bt_field_class_array_static, 1); if (!array_fc) { BT_LIB_LOGE_APPEND_CAUSE( "Failed to allocate one static array field class."); goto error; } - init_array_field_class((void *) array_fc, BT_FIELD_CLASS_TYPE_STATIC_ARRAY, - destroy_static_array_field_class, element_fc); + if (init_array_field_class((void *) array_fc, + BT_FIELD_CLASS_TYPE_STATIC_ARRAY, + destroy_static_array_field_class, element_fc)) { + goto error; + } + array_fc->length = length; BT_LIB_LOGD("Created static array field class object: %!+F", array_fc); goto end; @@ -1501,9 +1993,9 @@ bt_field_class_array_borrow_element_field_class(struct bt_field_class *fc) return array_fc->element_fc; } -uint64_t bt_field_class_static_array_get_length(const struct bt_field_class *fc) +uint64_t bt_field_class_array_static_get_length(const struct bt_field_class *fc) { - const struct bt_field_class_static_array *array_fc = (const void *) fc; + const struct bt_field_class_array_static *array_fc = (const void *) fc; BT_ASSERT_PRE_DEV_NON_NULL(fc, "Field class"); BT_ASSERT_PRE_DEV_FC_HAS_ID(fc, BT_FIELD_CLASS_TYPE_STATIC_ARRAY, @@ -1514,7 +2006,7 @@ uint64_t bt_field_class_static_array_get_length(const struct bt_field_class *fc) static void destroy_dynamic_array_field_class(struct bt_object *obj) { - struct bt_field_class_dynamic_array *fc = (void *) obj; + struct bt_field_class_array_dynamic *fc = (void *) obj; BT_ASSERT(fc); BT_LIB_LOGD("Destroying dynamic array field class object: %!+F", fc); @@ -1526,25 +2018,40 @@ void destroy_dynamic_array_field_class(struct bt_object *obj) g_free(fc); } -struct bt_field_class *bt_field_class_dynamic_array_create( - bt_trace_class *trace_class, - struct bt_field_class *element_fc) +struct bt_field_class *bt_field_class_array_dynamic_create( + struct bt_trace_class *trace_class, + struct bt_field_class *element_fc, + struct bt_field_class *length_fc) { - struct bt_field_class_dynamic_array *array_fc = NULL; + struct bt_field_class_array_dynamic *array_fc = NULL; + BT_ASSERT_PRE_NO_ERROR(); BT_ASSERT_PRE_NON_NULL(trace_class, "Trace class"); BT_ASSERT_PRE_NON_NULL(element_fc, "Element field class"); BT_LOGD_STR("Creating default dynamic array field class object."); - array_fc = g_new0(struct bt_field_class_dynamic_array, 1); + array_fc = g_new0(struct bt_field_class_array_dynamic, 1); if (!array_fc) { BT_LIB_LOGE_APPEND_CAUSE( "Failed to allocate one dynamic array field class."); goto error; } - init_array_field_class((void *) array_fc, - BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY, - destroy_dynamic_array_field_class, element_fc); + if (init_array_field_class((void *) array_fc, + length_fc ? + BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY_WITH_LENGTH_FIELD : + BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY_WITHOUT_LENGTH_FIELD, + destroy_dynamic_array_field_class, element_fc)) { + goto error; + } + + if (length_fc) { + BT_ASSERT_PRE_FC_IS_UNSIGNED_INT(length_fc, + "Length field class"); + array_fc->length_fc = length_fc; + bt_object_get_ref_no_null_check(array_fc->length_fc); + bt_field_class_freeze(length_fc); + } + BT_LIB_LOGD("Created dynamic array field class object: %!+F", array_fc); goto end; @@ -1555,33 +2062,16 @@ end: return (void *) array_fc; } -enum bt_field_class_dynamic_array_set_length_field_class_status -bt_field_class_dynamic_array_set_length_field_class( - struct bt_field_class *fc, - struct bt_field_class *length_fc) -{ - struct bt_field_class_dynamic_array *array_fc = (void *) fc; - - BT_ASSERT_PRE_NON_NULL(fc, "Dynamic array field class"); - BT_ASSERT_PRE_NON_NULL(length_fc, "Length field class"); - BT_ASSERT_PRE_FC_HAS_ID(fc, BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY, - "Field class"); - BT_ASSERT_PRE_FC_IS_UNSIGNED_INT(length_fc, "Length field class"); - BT_ASSERT_PRE_DEV_FC_HOT(fc, "Dynamic array field class"); - array_fc->length_fc = length_fc; - bt_object_get_no_null_check(array_fc->length_fc); - bt_field_class_freeze(length_fc); - return BT_FUNC_STATUS_OK; -} - const struct bt_field_path * -bt_field_class_dynamic_array_borrow_length_field_path_const( +bt_field_class_array_dynamic_with_length_field_borrow_length_field_path_const( const struct bt_field_class *fc) { - const struct bt_field_class_dynamic_array *seq_fc = (const void *) fc; + const struct bt_field_class_array_dynamic *seq_fc = (const void *) fc; + BT_ASSERT_PRE_NO_ERROR(); BT_ASSERT_PRE_DEV_NON_NULL(fc, "Field class"); - BT_ASSERT_PRE_DEV_FC_HAS_ID(fc, BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY, + BT_ASSERT_PRE_DEV_FC_HAS_ID(fc, + BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY_WITH_LENGTH_FIELD, "Field class"); return seq_fc->length_field_path; } @@ -1591,6 +2081,7 @@ void destroy_string_field_class(struct bt_object *obj) { BT_ASSERT(obj); BT_LIB_LOGD("Destroying string field class object: %!+F", obj); + finalize_field_class((void *) obj); g_free(obj); } @@ -1598,6 +2089,7 @@ struct bt_field_class *bt_field_class_string_create(bt_trace_class *trace_class) { struct bt_field_class_string *string_fc = NULL; + BT_ASSERT_PRE_NO_ERROR(); BT_ASSERT_PRE_NON_NULL(trace_class, "Trace class"); BT_LOGD_STR("Creating default string field class object."); string_fc = g_new0(struct bt_field_class_string, 1); @@ -1607,8 +2099,11 @@ struct bt_field_class *bt_field_class_string_create(bt_trace_class *trace_class) goto error; } - init_field_class((void *) string_fc, BT_FIELD_CLASS_TYPE_STRING, - destroy_string_field_class); + if (init_field_class((void *) string_fc, BT_FIELD_CLASS_TYPE_STRING, + destroy_string_field_class)) { + goto error; + } + BT_LIB_LOGD("Created string field class object: %!+F", string_fc); goto end; @@ -1629,14 +2124,12 @@ void _bt_field_class_freeze(const struct bt_field_class *c_fc) * their owner. */ BT_ASSERT(fc); + bt_value_freeze(fc->user_attributes); fc->frozen = true; - switch (fc->type) { - case BT_FIELD_CLASS_TYPE_STRUCTURE: - case BT_FIELD_CLASS_TYPE_VARIANT_WITHOUT_SELECTOR: - case BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_SELECTOR: - case BT_FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_SELECTOR: - { + if (fc->type == BT_FIELD_CLASS_TYPE_STRUCTURE || + bt_field_class_type_is(fc->type, + BT_FIELD_CLASS_TYPE_VARIANT)) { struct bt_field_class_named_field_class_container *container_fc = (void *) fc; uint64_t i; @@ -1645,11 +2138,6 @@ void _bt_field_class_freeze(const struct bt_field_class *c_fc) bt_named_field_class_freeze( container_fc->named_fcs->pdata[i]); } - - break; - } - default: - break; } } @@ -1657,8 +2145,11 @@ BT_HIDDEN void _bt_named_field_class_freeze(const struct bt_named_field_class *named_fc) { BT_ASSERT(named_fc); + BT_ASSERT(named_fc->fc->frozen); + BT_LIB_LOGD("Freezing named field class's user attributes: %!+v", + named_fc->user_attributes); + bt_value_freeze(named_fc->user_attributes); ((struct bt_named_field_class *) named_fc)->frozen = true; - bt_field_class_freeze(named_fc->fc); } BT_HIDDEN @@ -1671,12 +2162,9 @@ void bt_field_class_make_part_of_trace_class(const struct bt_field_class *c_fc) "Field class is already part of a trace: %!+F", fc); fc->part_of_trace_class = true; - switch (fc->type) { - case BT_FIELD_CLASS_TYPE_STRUCTURE: - case BT_FIELD_CLASS_TYPE_VARIANT_WITHOUT_SELECTOR: - case BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_SELECTOR: - case BT_FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_SELECTOR: - { + if (fc->type == BT_FIELD_CLASS_TYPE_STRUCTURE || + bt_field_class_type_is(fc->type, + BT_FIELD_CLASS_TYPE_VARIANT)) { struct bt_field_class_named_field_class_container *container_fc = (void *) fc; uint64_t i; @@ -1687,22 +2175,118 @@ void bt_field_class_make_part_of_trace_class(const struct bt_field_class *c_fc) bt_field_class_make_part_of_trace_class(named_fc->fc); } - - break; - } - case BT_FIELD_CLASS_TYPE_STATIC_ARRAY: - case BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY: - { + } else if (bt_field_class_type_is(fc->type, + BT_FIELD_CLASS_TYPE_ARRAY)) { struct bt_field_class_array *array_fc = (void *) fc; bt_field_class_make_part_of_trace_class(array_fc->element_fc); - break; - } - default: - break; } } +const struct bt_value *bt_field_class_borrow_user_attributes_const( + const struct bt_field_class *fc) +{ + BT_ASSERT_PRE_DEV_NON_NULL(fc, "Field class"); + return fc->user_attributes; +} + +struct bt_value *bt_field_class_borrow_user_attributes( + struct bt_field_class *field_class) +{ + return (void *) bt_field_class_borrow_user_attributes_const( + (void *) field_class); +} + + +void bt_field_class_set_user_attributes( + struct bt_field_class *fc, + const struct bt_value *user_attributes) +{ + BT_ASSERT_PRE_NON_NULL(fc, "Field class"); + BT_ASSERT_PRE_NON_NULL(user_attributes, "User attributes"); + BT_ASSERT_PRE(user_attributes->type == BT_VALUE_TYPE_MAP, + "User attributes object is not a map value object."); + BT_ASSERT_PRE_DEV_FC_HOT(fc, "Field class"); + bt_object_put_ref_no_null_check(fc->user_attributes); + fc->user_attributes = (void *) user_attributes; + bt_object_get_ref_no_null_check(fc->user_attributes); +} + +static +const struct bt_value *bt_named_field_class_borrow_user_attributes_const( + const struct bt_named_field_class *named_fc) +{ + return named_fc->user_attributes; +} + +static +void bt_named_field_class_set_user_attributes( + struct bt_named_field_class *named_fc, + const struct bt_value *user_attributes) +{ + BT_ASSERT_PRE_NON_NULL(user_attributes, "User attributes"); + BT_ASSERT_PRE(user_attributes->type == BT_VALUE_TYPE_MAP, + "User attributes object is not a map value object."); + BT_ASSERT_PRE_DEV_HOT(named_fc, + "Structure field class member or variant field class option", + "."); + bt_object_put_ref_no_null_check(named_fc->user_attributes); + named_fc->user_attributes = (void *) user_attributes; + bt_object_get_ref_no_null_check(named_fc->user_attributes); +} + +const struct bt_value * +bt_field_class_structure_member_borrow_user_attributes_const( + const struct bt_field_class_structure_member *member) +{ + BT_ASSERT_PRE_NON_NULL(member, "Structure field class member"); + return bt_named_field_class_borrow_user_attributes_const( + (const void *) member); +} + +struct bt_value * +bt_field_class_structure_member_borrow_user_attributes( + struct bt_field_class_structure_member *member) +{ + BT_ASSERT_PRE_NON_NULL(member, "Structure field class member"); + return (void *) bt_named_field_class_borrow_user_attributes_const( + (void *) member); +} + +void bt_field_class_structure_member_set_user_attributes( + struct bt_field_class_structure_member *member, + const struct bt_value *user_attributes) +{ + BT_ASSERT_PRE_NON_NULL(member, "Structure field class member"); + bt_named_field_class_set_user_attributes((void *) member, + user_attributes); +} + +const struct bt_value *bt_field_class_variant_option_borrow_user_attributes_const( + const struct bt_field_class_variant_option *option) +{ + BT_ASSERT_PRE_NON_NULL(option, "Variant field class option"); + return bt_named_field_class_borrow_user_attributes_const( + (const void *) option); +} + +struct bt_value *bt_field_class_variant_option_borrow_user_attributes( + struct bt_field_class_variant_option *option) +{ + BT_ASSERT_PRE_NON_NULL(option, "Variant field class option"); + return (void *) bt_named_field_class_borrow_user_attributes_const( + (void *) option); +} + +void bt_field_class_variant_option_set_user_attributes( + struct bt_field_class_variant_option *option, + const struct bt_value *user_attributes) +{ + BT_ASSERT_PRE_NON_NULL(option, "Variant field class option"); + bt_named_field_class_set_user_attributes((void *) option, + user_attributes); +} + void bt_field_class_get_ref(const struct bt_field_class *field_class) { bt_object_get_ref(field_class);