From b38aea749d62a3453343099231e0af48c3fd1460 Mon Sep 17 00:00:00 2001 From: Philippe Proulx Date: Mon, 12 Aug 2019 17:09:38 -0400 Subject: [PATCH] lib: add option field class and field types This patch adds the option field class (FC) and field to the available library types. An option field can contain or not another field. It is very similar to a variant field in that it's a choice between two things. CTF 2 will very likely have such a type, so Babeltrace 2.0 will be ready. Like a variant FC, an option FC can have a selector which must be a reachable boolean FC. When you create an option with bt_field_class_option_create(), you pass the optional FC, which becomes frozen on success. You can borrow the optional FC of an option FC with bt_field_class_option_borrow_field_class_const(). If the option FC has a selector FC, you can borrow the computed selector field path with bt_field_class_option_borrow_selector_field_path_const(). To set whether or not an option field contains a field, call bt_field_option_set_has_field(). You must call this function even if the option field contains no field (with `BT_FALSE`) because field objects are pooled and not reset for each message in production mode (similar to how you must initially call bt_field_string_clear() before you call bt_field_string_append()). Once you have called bt_field_option_set_has_field() with `BT_TRUE`, you can borrow the optional field with bt_field_option_borrow_field() to fill it. On the const side, you can borrow an option field's optional field with bt_field_option_borrow_field_const(). This function returns `NULL` if the option field does not contain a field. This patch also adds the `BT_FIELD_PATH_ITEM_TYPE_CURRENT_OPTION_CONTENT` field path item type. Such a field path item means the current field of an option field. This patch does not adapt existing plugins and the Python bindings to use and wrap the new option FC and field; this work is reserved for subsequent patches. Signed-off-by: Philippe Proulx Change-Id: Ie76312a53affe8343dd058bd4c38cd9a6074c4d7 Reviewed-on: https://review.lttng.org/c/babeltrace/+/1897 Tested-by: jenkins --- .../babeltrace2/trace-ir/field-class-const.h | 9 ++ include/babeltrace2/trace-ir/field-class.h | 5 + include/babeltrace2/trace-ir/field-const.h | 3 + .../babeltrace2/trace-ir/field-path-const.h | 1 + include/babeltrace2/trace-ir/field.h | 4 + src/lib/lib-logging.c | 23 +++ src/lib/trace-ir/field-class.c | 80 ++++++++++ src/lib/trace-ir/field-class.h | 15 +- src/lib/trace-ir/field.c | 145 +++++++++++++++++- src/lib/trace-ir/field.h | 10 ++ src/lib/trace-ir/resolve-field-path.c | 53 +++++++ 11 files changed, 344 insertions(+), 4 deletions(-) diff --git a/include/babeltrace2/trace-ir/field-class-const.h b/include/babeltrace2/trace-ir/field-class-const.h index 688c61d1..2dfade9f 100644 --- a/include/babeltrace2/trace-ir/field-class-const.h +++ b/include/babeltrace2/trace-ir/field-class-const.h @@ -47,6 +47,7 @@ typedef enum bt_field_class_type { BT_FIELD_CLASS_TYPE_STRUCTURE, BT_FIELD_CLASS_TYPE_STATIC_ARRAY, BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY, + BT_FIELD_CLASS_TYPE_OPTION, BT_FIELD_CLASS_TYPE_VARIANT_WITHOUT_SELECTOR, BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_SELECTOR, BT_FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_SELECTOR, @@ -164,6 +165,14 @@ extern const bt_field_path * bt_field_class_array_dynamic_borrow_length_field_path_const( const bt_field_class *field_class); +extern const bt_field_class * +bt_field_class_option_borrow_field_class_const( + const bt_field_class *field_class); + +extern const bt_field_path * +bt_field_class_option_borrow_selector_field_path_const( + const bt_field_class *field_class); + extern uint64_t bt_field_class_variant_get_option_count( const bt_field_class *field_class); diff --git a/include/babeltrace2/trace-ir/field-class.h b/include/babeltrace2/trace-ir/field-class.h index d2f43bec..20477296 100644 --- a/include/babeltrace2/trace-ir/field-class.h +++ b/include/babeltrace2/trace-ir/field-class.h @@ -116,6 +116,11 @@ extern bt_field_class *bt_field_class_array_dynamic_create( extern bt_field_class *bt_field_class_array_borrow_element_field_class( bt_field_class *field_class); +extern bt_field_class *bt_field_class_option_create( + bt_trace_class *trace_class, + bt_field_class *content_field_class, + bt_field_class *selector_field_class); + extern bt_field_class *bt_field_class_variant_create( bt_trace_class *trace_class, bt_field_class *selector_field_class); diff --git a/include/babeltrace2/trace-ir/field-const.h b/include/babeltrace2/trace-ir/field-const.h index f3f1ef8d..01b74239 100644 --- a/include/babeltrace2/trace-ir/field-const.h +++ b/include/babeltrace2/trace-ir/field-const.h @@ -84,6 +84,9 @@ extern const bt_field * bt_field_array_borrow_element_field_by_index_const( const bt_field *field, uint64_t index); +extern const bt_field * +bt_field_option_borrow_field_const(const bt_field *field); + extern uint64_t bt_field_variant_get_selected_option_field_index( const bt_field *field); diff --git a/include/babeltrace2/trace-ir/field-path-const.h b/include/babeltrace2/trace-ir/field-path-const.h index b1bd0154..f1a69352 100644 --- a/include/babeltrace2/trace-ir/field-path-const.h +++ b/include/babeltrace2/trace-ir/field-path-const.h @@ -38,6 +38,7 @@ extern "C" { typedef enum bt_field_path_item_type { BT_FIELD_PATH_ITEM_TYPE_INDEX, BT_FIELD_PATH_ITEM_TYPE_CURRENT_ARRAY_ELEMENT, + BT_FIELD_PATH_ITEM_TYPE_CURRENT_OPTION_CONTENT, } bt_field_path_item_type; typedef enum bt_field_path_scope { diff --git a/include/babeltrace2/trace-ir/field.h b/include/babeltrace2/trace-ir/field.h index 311c53a8..58959be8 100644 --- a/include/babeltrace2/trace-ir/field.h +++ b/include/babeltrace2/trace-ir/field.h @@ -84,6 +84,10 @@ extern bt_field_array_dynamic_set_length_status bt_field_array_dynamic_set_length( bt_field *field, uint64_t length); +extern void bt_field_option_set_has_field(bt_field *field, bt_bool has_field); + +extern bt_field *bt_field_option_borrow_field(bt_field *field); + typedef enum bt_field_variant_select_option_field_by_index_status { BT_FIELD_VARIANT_SELECT_OPTION_FIELD_STATUS_OK = __BT_FUNC_STATUS_OK, } bt_field_variant_select_option_field_by_index_status; diff --git a/src/lib/lib-logging.c b/src/lib/lib-logging.c index 8b878655..c38948d6 100644 --- a/src/lib/lib-logging.c +++ b/src/lib/lib-logging.c @@ -260,6 +260,29 @@ static inline void format_field_class(char **buf_ch, bool extended, break; } + case BT_FIELD_CLASS_TYPE_OPTION: + { + const struct bt_field_class_option *opt_fc = + (const void *) field_class; + + BUF_APPEND(", %scontent-fc-addr=%p, %scontent-fc-type=%s", + PRFIELD(opt_fc->content_fc), + PRFIELD(bt_common_field_class_type_string(opt_fc->content_fc->type))); + + if (opt_fc->selector_fc) { + SET_TMP_PREFIX("selector-fc-"); + format_field_class(buf_ch, extended, tmp_prefix, + opt_fc->selector_fc); + } + + if (opt_fc->selector_field_path) { + SET_TMP_PREFIX("selector-field-path-"); + format_field_path(buf_ch, extended, tmp_prefix, + opt_fc->selector_field_path); + } + + break; + } 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: diff --git a/src/lib/trace-ir/field-class.c b/src/lib/trace-ir/field-class.c index 6afc32b8..d78aefb3 100644 --- a/src/lib/trace-ir/field-class.c +++ b/src/lib/trace-ir/field-class.c @@ -1019,6 +1019,86 @@ bt_field_class_structure_member_borrow_field_class_const( 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); + BT_LOGD_STR("Putting content field class."); + BT_OBJECT_PUT_REF_AND_RESET(fc->content_fc); + BT_LOGD_STR("Putting selector field path."); + BT_OBJECT_PUT_REF_AND_RESET(fc->selector_field_path); + BT_LOGD_STR("Putting selector field class."); + BT_OBJECT_PUT_REF_AND_RESET(fc->selector_fc); + g_free(fc); +} + +struct bt_field_class *bt_field_class_option_create(bt_trace_class *trace_class, + bt_field_class *content_fc, 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: " + "%![content-fc-]+F, %![sel-fc-]+F", content_fc, selector_fc); + 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; + } + + init_field_class((void *) opt_fc, BT_FIELD_CLASS_TYPE_OPTION, + destroy_option_field_class); + opt_fc->content_fc = content_fc; + bt_object_get_no_null_check(opt_fc->content_fc); + bt_field_class_freeze(opt_fc->content_fc); + + if (selector_fc) { + BT_ASSERT_PRE_FC_HAS_ID(selector_fc, BT_FIELD_CLASS_TYPE_BOOL, + "Selector field class"); + opt_fc->selector_fc = selector_fc; + bt_object_get_no_null_check(opt_fc->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; +} + +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_DEV_FC_HAS_ID(fc, BT_FIELD_CLASS_TYPE_OPTION, + "Field class"); + return opt_fc->content_fc; +} + +const struct bt_field_path * +bt_field_class_option_borrow_selector_field_path_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_DEV_FC_HAS_ID(fc, BT_FIELD_CLASS_TYPE_OPTION, + "Field class"); + return opt_fc->selector_field_path; +} + static void finalize_variant_field_class(struct bt_field_class_variant *var_fc) { diff --git a/src/lib/trace-ir/field-class.h b/src/lib/trace-ir/field-class.h index 53041a13..f2be12c3 100644 --- a/src/lib/trace-ir/field-class.h +++ b/src/lib/trace-ir/field-class.h @@ -290,13 +290,26 @@ struct bt_field_class_array_static { struct bt_field_class_array_dynamic { struct bt_field_class_array common; - /* Weak: never dereferenced, only use to find it elsewhere */ + /* Owned by this */ struct bt_field_class *length_fc; /* Owned by this */ struct bt_field_path *length_field_path; }; +struct bt_field_class_option { + struct bt_field_class common; + + /* Owned by this */ + struct bt_field_class *content_fc; + + /* Owned by this */ + struct bt_field_class *selector_fc; + + /* Owned by this */ + struct bt_field_path *selector_field_path; +}; + /* Variant FC (with selector) option: named field class + range set */ struct bt_field_class_variant_with_selector_option { struct bt_named_field_class common; diff --git a/src/lib/trace-ir/field.c b/src/lib/trace-ir/field.c index 95a76e49..664b1ab4 100644 --- a/src/lib/trace-ir/field.c +++ b/src/lib/trace-ir/field.c @@ -47,6 +47,9 @@ void reset_array_field(struct bt_field *field); static void reset_structure_field(struct bt_field *field); +static +void reset_option_field(struct bt_field *field); + static void reset_variant_field(struct bt_field *field); @@ -59,6 +62,9 @@ void set_array_field_is_frozen(struct bt_field *field, bool is_frozen); static void set_structure_field_is_frozen(struct bt_field *field, bool is_frozen); +static +void set_option_field_is_frozen(struct bt_field *field, bool is_frozen); + static void set_variant_field_is_frozen(struct bt_field *field, bool is_frozen); @@ -71,6 +77,9 @@ bool array_field_is_set(const struct bt_field *field); static bool structure_field_is_set(const struct bt_field *field); +static +bool option_field_is_set(const struct bt_field *field); + static bool variant_field_is_set(const struct bt_field *field); @@ -116,6 +125,13 @@ struct bt_field_methods array_field_methods = { .reset = reset_array_field, }; +static +struct bt_field_methods option_field_methods = { + .set_is_frozen = set_option_field_is_frozen, + .is_set = option_field_is_set, + .reset = reset_option_field, +}; + static struct bt_field_methods variant_field_methods = { .set_is_frozen = set_variant_field_is_frozen, @@ -144,6 +160,9 @@ struct bt_field *create_static_array_field(struct bt_field_class *); static struct bt_field *create_dynamic_array_field(struct bt_field_class *); +static +struct bt_field *create_option_field(struct bt_field_class *); + static struct bt_field *create_variant_field(struct bt_field_class *); @@ -159,6 +178,7 @@ struct bt_field *(* const field_create_funcs[])(struct bt_field_class *) = { [BT_FIELD_CLASS_TYPE_STRUCTURE] = create_structure_field, [BT_FIELD_CLASS_TYPE_STATIC_ARRAY] = create_static_array_field, [BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY] = create_dynamic_array_field, + [BT_FIELD_CLASS_TYPE_OPTION] = create_option_field, [BT_FIELD_CLASS_TYPE_VARIANT_WITHOUT_SELECTOR] = create_variant_field, [BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_SELECTOR] = create_variant_field, [BT_FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_SELECTOR] = create_variant_field, @@ -182,6 +202,9 @@ void destroy_structure_field(struct bt_field *field); static void destroy_array_field(struct bt_field *field); +static +void destroy_option_field(struct bt_field *field); + static void destroy_variant_field(struct bt_field *field); @@ -197,6 +220,7 @@ void (* const field_destroy_funcs[])(struct bt_field *) = { [BT_FIELD_CLASS_TYPE_STRUCTURE] = destroy_structure_field, [BT_FIELD_CLASS_TYPE_STATIC_ARRAY] = destroy_array_field, [BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY] = destroy_array_field, + [BT_FIELD_CLASS_TYPE_OPTION] = destroy_option_field, [BT_FIELD_CLASS_TYPE_VARIANT_WITHOUT_SELECTOR] = destroy_variant_field, [BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_SELECTOR] = destroy_variant_field, [BT_FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_SELECTOR] = destroy_variant_field, @@ -406,6 +430,37 @@ end: return (void *) struct_field; } +static +struct bt_field *create_option_field(struct bt_field_class *fc) +{ + struct bt_field_option *opt_field; + struct bt_field_class_option *opt_fc = (void *) fc; + + BT_LIB_LOGD("Creating option field object: %![fc-]+F", fc); + opt_field = g_new0(struct bt_field_option, 1); + if (!opt_field) { + BT_LIB_LOGE_APPEND_CAUSE( + "Failed to allocate one option field."); + goto end; + } + + init_field((void *) opt_field, fc, &option_field_methods); + opt_field->content_field = bt_field_create(opt_fc->content_fc); + if (!opt_field->content_field) { + BT_LIB_LOGE_APPEND_CAUSE( + "Failed to create option field's content field: " + "%![opt-fc-]+F, %![content-fc-]+F", + opt_fc, opt_fc->content_fc); + BT_OBJECT_PUT_REF_AND_RESET(opt_field); + goto end; + } + + BT_LIB_LOGD("Created option field object: %!+f", opt_field); + +end: + return (void *) opt_field; +} + static struct bt_field *create_variant_field(struct bt_field_class *fc) { @@ -907,6 +962,38 @@ const struct bt_field *bt_field_structure_borrow_member_field_by_name_const( (void *) field, name); } +void bt_field_option_set_has_field(struct bt_field *field, bt_bool has_field) +{ + struct bt_field_option *opt_field = (void *) field; + + BT_ASSERT_PRE_DEV_NON_NULL(field, "Field"); + BT_ASSERT_PRE_DEV_FIELD_HAS_CLASS_TYPE(field, + BT_FIELD_CLASS_TYPE_OPTION, "Field"); + BT_ASSERT_PRE_DEV_FIELD_HOT(field, "Field"); + + if (has_field) { + opt_field->selected_field = opt_field->content_field; + } else { + opt_field->selected_field = NULL; + } +} + +struct bt_field *bt_field_option_borrow_field(struct bt_field *field) +{ + struct bt_field_option *opt_field = (void *) field; + + BT_ASSERT_PRE_DEV_NON_NULL(field, "Field"); + BT_ASSERT_PRE_DEV_FIELD_HAS_CLASS_TYPE(field, + BT_FIELD_CLASS_TYPE_OPTION, "Field"); + return opt_field->selected_field; +} + +const struct bt_field *bt_field_option_borrow_field_const( + const struct bt_field *field) +{ + return (const void *) bt_field_option_borrow_field((void *) field); +} + static inline struct bt_field *borrow_variant_field_selected_option_field( struct bt_field *field) @@ -1054,6 +1141,22 @@ void destroy_structure_field(struct bt_field *field) g_free(field); } +static +void destroy_option_field(struct bt_field *field) +{ + struct bt_field_option *opt_field = (void *) field; + + BT_ASSERT(field); + BT_LIB_LOGD("Destroying option field object: %!+f", field); + bt_field_finalize(field); + + if (opt_field->content_field) { + bt_field_destroy(opt_field->content_field); + } + + g_free(field); +} + static void destroy_variant_field(struct bt_field *field) { @@ -1132,6 +1235,16 @@ void reset_structure_field(struct bt_field *field) } } +static +void reset_option_field(struct bt_field *field) +{ + struct bt_field_option *opt_field = (void *) field; + + BT_ASSERT(opt_field); + bt_field_reset(opt_field->content_field); + opt_field->selected_field = NULL; +} + static void reset_variant_field(struct bt_field *field) { @@ -1179,12 +1292,23 @@ void set_structure_field_is_frozen(struct bt_field *field, bool is_frozen) BT_LIB_LOGD("Setting structure field's member field's " "frozen state: %![field-]+f, index=%" PRIu64, member_field, i); - bt_field_set_is_frozen(member_field, is_frozen); + _bt_field_set_is_frozen(member_field, is_frozen); } set_single_field_is_frozen(field, is_frozen); } +static +void set_option_field_is_frozen(struct bt_field *field, bool is_frozen) +{ + struct bt_field_option *opt_field = (void *) field; + + BT_LIB_LOGD("Setting option field's frozen state: " + "%![field-]+f, is-frozen=%d", field, is_frozen); + _bt_field_set_is_frozen(opt_field->content_field, is_frozen); + set_single_field_is_frozen(field, is_frozen); +} + static void set_variant_field_is_frozen(struct bt_field *field, bool is_frozen) { @@ -1200,7 +1324,7 @@ void set_variant_field_is_frozen(struct bt_field *field, bool is_frozen) BT_LIB_LOGD("Setting variant field's option field's " "frozen state: %![field-]+f, index=%" PRIu64, option_field, i); - bt_field_set_is_frozen(option_field, is_frozen); + _bt_field_set_is_frozen(option_field, is_frozen); } set_single_field_is_frozen(field, is_frozen); @@ -1221,7 +1345,7 @@ void set_array_field_is_frozen(struct bt_field *field, bool is_frozen) BT_LIB_LOGD("Setting array field's element field's " "frozen state: %![field-]+f, index=%" PRIu64, elem_field, i); - bt_field_set_is_frozen(elem_field, is_frozen); + _bt_field_set_is_frozen(elem_field, is_frozen); } set_single_field_is_frozen(field, is_frozen); @@ -1265,6 +1389,21 @@ end: return is_set; } +static +bool option_field_is_set(const struct bt_field *field) +{ + const struct bt_field_option *opt_field = (const void *) field; + bool is_set = false; + + BT_ASSERT(field); + + if (opt_field->selected_field) { + is_set = bt_field_is_set(opt_field->selected_field); + } + + return is_set; +} + static bool variant_field_is_set(const struct bt_field *field) { diff --git a/src/lib/trace-ir/field.h b/src/lib/trace-ir/field.h index 352514ef..2882e778 100644 --- a/src/lib/trace-ir/field.h +++ b/src/lib/trace-ir/field.h @@ -131,6 +131,16 @@ struct bt_field_structure { GPtrArray *fields; }; +struct bt_field_option { + struct bt_field common; + + /* Owned by this */ + struct bt_field *content_field; + + /* Weak: equal to `content_field` above or `NULL` */ + struct bt_field *selected_field; +}; + struct bt_field_variant { struct bt_field common; diff --git a/src/lib/trace-ir/resolve-field-path.c b/src/lib/trace-ir/resolve-field-path.c index 8865a2a5..c49b0245 100644 --- a/src/lib/trace-ir/resolve-field-path.c +++ b/src/lib/trace-ir/resolve-field-path.c @@ -47,6 +47,25 @@ bool find_field_class_recursive(struct bt_field_class *fc, } switch (fc->type) { + case BT_FIELD_CLASS_TYPE_OPTION: + { + struct bt_field_class_option *opt_fc = (void *) fc; + + struct bt_field_path_item item = { + .type = BT_FIELD_PATH_ITEM_TYPE_CURRENT_OPTION_CONTENT, + .index = UINT64_C(-1), + }; + + bt_field_path_append_item(field_path, &item); + found = find_field_class_recursive(opt_fc->content_fc, + tgt_fc, field_path); + if (found) { + goto end; + } + + bt_field_path_remove_last_item(field_path); + break; + } case BT_FIELD_CLASS_TYPE_STRUCTURE: case BT_FIELD_CLASS_TYPE_VARIANT_WITHOUT_SELECTOR: case BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_SELECTOR: @@ -241,6 +260,15 @@ struct bt_field_class *borrow_child_field_class( struct bt_field_class *child_fc = NULL; switch (parent_fc->type) { + case BT_FIELD_CLASS_TYPE_OPTION: + { + struct bt_field_class_option *opt_fc = (void *) parent_fc; + + BT_ASSERT(fp_item->type == + BT_FIELD_PATH_ITEM_TYPE_CURRENT_OPTION_CONTENT); + child_fc = opt_fc->content_fc; + break; + } case BT_FIELD_CLASS_TYPE_STRUCTURE: case BT_FIELD_CLASS_TYPE_VARIANT_WITHOUT_SELECTOR: case BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_SELECTOR: @@ -296,6 +324,7 @@ bool target_field_path_in_different_scope_has_struct_fc_only( if (fc->type == BT_FIELD_CLASS_TYPE_STATIC_ARRAY || fc->type == BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY || + fc->type == BT_FIELD_CLASS_TYPE_OPTION || fc->type == BT_FIELD_CLASS_TYPE_VARIANT_WITHOUT_SELECTOR || fc->type == BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_SELECTOR || fc->type == BT_FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_SELECTOR) { @@ -415,6 +444,7 @@ bool lca_to_target_has_struct_fc_only(struct bt_field_path *src_field_path, if (tgt_fc->type == BT_FIELD_CLASS_TYPE_STATIC_ARRAY || tgt_fc->type == BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY || + tgt_fc->type == BT_FIELD_CLASS_TYPE_OPTION || tgt_fc->type == BT_FIELD_CLASS_TYPE_VARIANT_WITHOUT_SELECTOR || tgt_fc->type == BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_SELECTOR || tgt_fc->type == BT_FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_SELECTOR) { @@ -527,6 +557,22 @@ int bt_resolve_field_paths(struct bt_field_class *fc, /* Resolving part for dynamic array and variant field classes */ switch (fc->type) { + case BT_FIELD_CLASS_TYPE_OPTION: + { + struct bt_field_class_option *opt_fc = (void *) fc; + + if (opt_fc->selector_fc) { + BT_ASSERT(!opt_fc->selector_field_path); + opt_fc->selector_field_path = resolve_field_path( + fc, opt_fc->selector_fc, ctx); + if (!opt_fc->selector_field_path) { + ret = -1; + goto end; + } + } + + break; + } case BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY: { struct bt_field_class_array_dynamic *dyn_array_fc = (void *) fc; @@ -566,6 +612,13 @@ int bt_resolve_field_paths(struct bt_field_class *fc, /* Recursive part */ switch (fc->type) { + case BT_FIELD_CLASS_TYPE_OPTION: + { + struct bt_field_class_option *opt_fc = (void *) fc; + + ret = bt_resolve_field_paths(opt_fc->content_fc, ctx); + break; + } case BT_FIELD_CLASS_TYPE_STRUCTURE: case BT_FIELD_CLASS_TYPE_VARIANT_WITHOUT_SELECTOR: case BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_SELECTOR: -- 2.34.1