From: Simon Marchi Date: Mon, 22 Jan 2024 21:20:58 +0000 (+0000) Subject: lib: add support for bit array flags X-Git-Url: http://drtracing.org/?a=commitdiff_plain;h=e52d2ed9ff78516f9fdb3e7d508b833b1973fdf4;p=babeltrace.git lib: add support for bit array flags Implement support for flags on bit array field classes, in order to be able to add support for the fixed-length bit map field class (as specified by CTF2-SPEC-2.0 [1]) in the CTF component classes. A flag is a mapping between bit positions in a fixed-length bit map field and a textual label. A flag is considered active for a given field if any of the bits in the flag's bit positions is set in the field. Flags may have overlapping bit positions, meaning that a single bit can activate multiple flags. Add the following public functions operating on bit array field classes: 🥑 bt_field_class_bit_array_add_flag 🥑 bt_field_class_bit_array_get_flag_count 🥑 bt_field_class_bit_array_borrow_flag_by_index_const 🥑 bt_field_class_bit_array_borrow_flag_by_label_const 🥑 bt_field_class_bit_array_get_active_flag_labels_for_value_as_integer Add the bt_field_class_bit_array_flag type. Then, add the following public functions operating on it: 🥑 bt_field_class_bit_array_flag_get_label 🥑 bt_field_class_bit_array_flag_borrow_index_ranges_const Add the following public function operating on a bit array field: 🥑 bt_field_bit_array_get_active_flag_labels The `bt_field_class_bit_array_get_active_flag_labels_for_value_as_integer` function returns an array of label through an output parameter of type `bt_field_class_bit_array_flag_label_array`. The storage for it is owned by the field class, so the result is only valid until the next call to the function (or until the field class gets destroyed). This behavior is copied from the enum field class. Philippe updated the documentation. [1]: https://diamon.org/ctf/CTF2-SPEC-2.0.html Change-Id: Ib88f3aecf692ea8b6453c0308fa7735fd40e55a9 Signed-off-by: Simon Marchi Reviewed-on: https://review.lttng.org/c/babeltrace/+/12727 Reviewed-by: Philippe Proulx --- diff --git a/include/babeltrace2/trace-ir/field-class.h b/include/babeltrace2/trace-ir/field-class.h index fa5cc222..86ba837c 100644 --- a/include/babeltrace2/trace-ir/field-class.h +++ b/include/babeltrace2/trace-ir/field-class.h @@ -344,6 +344,85 @@ A bit array field class has the following property: Get a bit array field class's length with bt_field_class_bit_array_get_length(). + +
+ \anchor api-tir-fc-ba-prop-flags + \bt_dt_opt Flags + (only available when the field class was created from a + \bt_trace_cls which was created + from a \bt_comp which belongs to a trace processing \bt_graph + with the effective \bt_mip version 1) +
+
+ Set of flags of the bit array field class. + + A bit array field class flag is a label (string) and an + \bt_uint_rs, a set of bit index ranges. In the value of an + instance (a \bt_ba_field) returned by + bt_field_bit_array_get_value_as_integer(), the least significant + bit's index is 0. + + The integer ranges of a given flag or of multiple flags of + the same bit array field class can overlap. For example, + a bit array field class can have those two flags: + + - GALLERY: [1, 4], [8, 14] + - LUNCH: [3, 6] + + In that case, the bit indexes 2 and 12 correspond to the + label GALLERY, the bit index 5 to the label + LUNCH, and the bit index 3 to the labels + \c GALLERY \em and LUNCH. + + Given some bit flag field value (as an integer), a flag is said to + be active when at least one of + its bit indexes is the index of a set bit of the value. For example, + given the 8-bit bit array field value + + @code{.unparsed} + [true, false, true, true, false, true, false, true] + @endcode + + where the first element is the first bit of the bit array field (the + value as an integer being 0xad): + + - A flag targeting bits 1, 3, and 6 would be active because + bit 3 is set. + + - A flag targeting bits 1 and 4 wouldn't be active because both + bits are cleared. + + Two flags of the same bit array field class cannot have the + same label. + + Add a flag to a bit array field class with + bt_field_class_bit_array_add_flag(). + + Get the number of flags in a bit array field class with + bt_field_class_bit_array_get_flag_count(). + + Borrow a flag from a bit array field class with + bt_field_class_bit_array_borrow_flag_by_index_const() + and + bt_field_class_bit_array_borrow_flag_by_label_const(). + + A bit array field class flag is a + \ref api-fund-unique-object "unique object": it + belongs to the bit array field class which contains it. + + The type of a bit array field class flag is + #bt_field_class_bit_array_flag. + + Get the label of a bit array field class flag with + bt_field_class_bit_array_flag_get_label(). + + Borrow the bit index range set of a bit array field class flag + with bt_field_class_bit_array_flag_borrow_index_ranges_const(). + + Get the labels of all the active flags of a bit array field class + for the set bits of some integral value with + bt_field_class_bit_array_get_active_flag_labels_for_value_as_integer(). +

\anchor api-tir-fc-int Integer field classes

@@ -473,9 +552,9 @@ Enumeration field classes have the following common property: - CALORIES: [1, 11], [15, 37] - SODIUM: [7, 13] - In that case, the values 2 and 30 correpond to the label - CALORIES, the value 12 to the label - SODIUM, and the value 10 to the labels + In that case, the values 2 and 30 correspond to the label + CALORIES, the value 12 to the label + SODIUM, and the value 10 to the labels \c CALORIES \em and SODIUM. Two mappings of the same enumeration field class cannot have the @@ -2026,6 +2105,11 @@ property values: \ref api-tir-fc-ba-prop-len "Length" \bt_p{length} + + + \bt_mip version 1: + \ref api-tir-fc-ba-prop-flags "flags" + \em None \ref api-tir-fc-prop-user-attrs "User attributes" Empty \bt_map_val @@ -2065,6 +2149,288 @@ See the \ref api-tir-fc-ba-prop-len "length" property. extern uint64_t bt_field_class_bit_array_get_length( const bt_field_class *field_class) __BT_NOEXCEPT; +/*! +@brief + Status codes for bt_field_class_bit_array_add_flag(). +*/ +typedef enum bt_field_class_bit_array_add_flag_status { + /*! + @brief + Success. + */ + BT_FIELD_CLASS_BIT_ARRAY_ADD_FLAG_STATUS_OK = __BT_FUNC_STATUS_OK, + + /*! + @brief + Out of memory. + */ + BT_FIELD_CLASS_BIT_ARRAY_ADD_FLAG_STATUS_MEMORY_ERROR = __BT_FUNC_STATUS_MEMORY_ERROR, + +} bt_field_class_bit_array_add_flag_status; + +/*! +@brief + Adds a flag to the \bt_ba_fc \bt_p{field_class} having the + label \bt_p{label} and the bit index ranges \bt_p{index_ranges}. + +See the \ref api-tir-fc-ba-prop-flags "flags" property. + +@param[in] field_class + Bit array field class to which to add a flag having + the label \bt_p{label} and the bit index ranges \bt_p{index_ranges}. +@param[in] label + Label of the flag to add to \bt_p{field_class} (copied). +@param[in] ranges + Bit index ranges of the flag to add to \bt_p{field_class}. + +@retval #BT_FIELD_CLASS_BIT_ARRAY_ADD_FLAG_STATUS_OK + Success. +@retval #BT_FIELD_CLASS_BIT_ARRAY_ADD_FLAG_STATUS_MEMORY_ERROR + Out of memory. + +@bt_pre_not_null{field_class} +@bt_pre_hot{field_class} +@bt_pre_is_ba_fc{field_class} +@bt_pre_fc_with_mip{field_class, 1} +@bt_pre_not_null{label} +@pre + \bt_p{field_class} has no flag with the label \bt_p{label}. +@bt_pre_not_null{ranges} +@pre + \bt_p{index_ranges} contains one or more unsigned integer ranges. +@pre + No \link bt_integer_range_unsigned_get_upper() upper value\endlink + of any range in \bt_p{index_ranges} is greater than or + equal to the + \link bt_field_class_bit_array_get_length() length\endlink of + \bt_p{field_class}. +*/ +extern bt_field_class_bit_array_add_flag_status +bt_field_class_bit_array_add_flag( + bt_field_class *field_class, const char *label, + const bt_integer_range_set_unsigned *index_ranges) __BT_NOEXCEPT; + +/*! +@brief + Returns the number of flags contained in the \bt_ba_fc + \bt_p{field_class}. + +See the \ref api-tir-fc-ba-prop-flags "flags" property. + +@param[in] field_class + Bit array field class of which to get the number of contained + flags. + +@returns + Number of contained flags in \bt_p{field_class}. + +@bt_pre_not_null{field_class} +@bt_pre_is_ba_fc{field_class} +@bt_pre_fc_with_mip{field_class, 1} +*/ +extern uint64_t bt_field_class_bit_array_get_flag_count( + const bt_field_class *field_class) __BT_NOEXCEPT; + +/*! +@brief + Borrows the flag at index \bt_p{index} from the + \bt_ba_fc \bt_p{field_class}. + +See the \ref api-tir-fc-ba-prop-flags "flags" property. + +@param[in] field_class + Bit array field class from which to borrow the flag at + index \bt_p{index}. +@param[in] index + Index of the flag to borrow from \bt_p{field_class}. + +@returns + @parblock + \em Borrowed reference of the flag of + \bt_p{field_class} at index \bt_p{index}. + + The returned pointer remains valid as long as \bt_p{field_class} + is not modified. + @endparblock + +@bt_pre_not_null{field_class} +@bt_pre_is_ba_fc{field_class} +@bt_pre_fc_with_mip{field_class, 1} +@pre + \bt_p{index} is less than the + \link bt_field_class_bit_array_get_flag_count() number of flags\endlink + in \bt_p{field_class}. + +@sa bt_field_class_bit_array_get_flag_count() — + Returns the number of flags contained in a + bit array field class. +*/ +extern const bt_field_class_bit_array_flag * +bt_field_class_bit_array_borrow_flag_by_index_const( + const bt_field_class *field_class, uint64_t index) __BT_NOEXCEPT; + +/*! +@brief + Borrows the flag having the label \bt_p{label} from the + \bt_ba_fc \bt_p{field_class}. + +See the \ref api-tir-fc-ba-prop-flags "flags" property. + +If there's no flag having the label \bt_p{label} in +\bt_p{field_class}, this function returns \c NULL. + +@param[in] field_class + Bit array field class from which to borrow the flag + having the label \bt_p{label}. +@param[in] label + Label of the flag to borrow from \bt_p{field_class}. + +@returns + @parblock + \em Borrowed reference of the flag of + \bt_p{field_class} having the label \bt_p{label}, or \c NULL + if none. + + The returned pointer remains valid as long as \bt_p{field_class} + is not modified. + @endparblock + +@bt_pre_not_null{field_class} +@bt_pre_is_ba_fc{field_class} +@bt_pre_fc_with_mip{field_class, 1} +@bt_pre_not_null{label} +*/ +extern const bt_field_class_bit_array_flag * +bt_field_class_bit_array_borrow_flag_by_label_const( + const bt_field_class *field_class, const char *label) __BT_NOEXCEPT; + +/*! +@brief + Array of \c const \bt_ba_fc flag labels. + +Returned by bt_field_class_bit_array_get_active_flag_labels_for_value_as_integer(). +*/ +typedef char const * const *bt_field_class_bit_array_flag_label_array; + +/*! +@brief + Status codes for + bt_field_class_bit_array_get_active_flag_labels_for_value_as_integer(). +*/ +typedef enum bt_field_class_bit_array_get_active_flag_labels_for_value_as_integer_status { + /*! + @brief + Success. + */ + BT_FIELD_CLASS_BIT_ARRAY_GET_ACTIVE_FLAG_LABELS_FOR_VALUE_AS_INTEGER_STATUS_OK = __BT_FUNC_STATUS_OK, + + /*! + @brief + Out of memory. + */ + BT_FIELD_CLASS_BIT_ARRAY_GET_ACTIVE_FLAG_LABELS_FOR_VALUE_AS_INTEGER_STATUS_MEMORY_ERROR = __BT_FUNC_STATUS_MEMORY_ERROR, +} bt_field_class_bit_array_get_active_flag_labels_for_value_as_integer_status; + +/*! +@brief + Returns the labels of all the active flags of the + \bt_ba_fc \bt_p{field_class} for the set bits of + \bt_p{value_as_integer} (a bit array field value as an integer). + +See the \ref api-tir-fc-ba-prop-flags "flags" property. + +This function sets \bt_p{*labels} to the resulting array and +\bt_p{*count} to the number of labels in \bt_p{*labels}. + +On success, if there's no active flags for \bt_p{value_as_integer}, +\bt_p{*count} is 0. + +@param[in] field_class + Bit array field class from which to get the labels of the + active flags for \bt_p{value_as_integer}. +@param[in] value_as_integer + @parblock + Bits, as an integer, for which to get the labels of the active flags + of \bt_p{field_class}. + + In this integral value, the index of the least significant bit + is 0. + @endparblock +@param[out] labels + @parblock + On success, \bt_p{*labels} + is an array of labels of the active flags of \bt_p{field_class} + for \bt_p{value}. + + The number of labels in \bt_p{*labels} is \bt_p{*count}. + + The array is owned by \bt_p{field_class} and remains valid as long + as: + + - \bt_p{field_class} is not modified. + - You don't call this function again with \bt_p{field_class}. + @endparblock +@param[out] count + On success, \bt_p{*count} is the number of labels + in \bt_p{*labels} (can be 0). + +@retval #BT_FIELD_CLASS_BIT_ARRAY_GET_ACTIVE_FLAG_LABELS_FOR_VALUE_AS_INTEGER_STATUS_OK + Success. +@retval #BT_FIELD_CLASS_BIT_ARRAY_GET_ACTIVE_FLAG_LABELS_FOR_VALUE_AS_INTEGER_STATUS_MEMORY_ERROR + Out of memory. + +@bt_pre_not_null{field_class} +@bt_pre_is_ba_fc{field_class} +@bt_pre_fc_with_mip{field_class, 1} +@bt_pre_not_null{labels} +@bt_pre_not_null{count} +*/ +extern bt_field_class_bit_array_get_active_flag_labels_for_value_as_integer_status +bt_field_class_bit_array_get_active_flag_labels_for_value_as_integer( + const bt_field_class *field_class, uint64_t value_as_integer, + bt_field_class_bit_array_flag_label_array *labels, + uint64_t *count) __BT_NOEXCEPT; + +/*! +@brief + Returns the label of the \bt_ba_fc flag \bt_p{flag}. + +See the \ref api-tir-fc-ba-prop-flags "flags" property. + +@param[in] flag + Bit array field class flag of which to get the label. + +@returns + @parblock + Label of \bt_p{flag}. + + The returned pointer remains valid as long as \bt_p{flag} exists. + @endparblock + +@bt_pre_not_null{flag} +*/ +extern const char *bt_field_class_bit_array_flag_get_label( + const bt_field_class_bit_array_flag *flag) __BT_NOEXCEPT; + +/*! +@brief + Borrows the bit index ranges from the \bt_ba_fc flag \bt_p{flag}. + +See the \ref api-tir-fc-ba-prop-flags "flags" property. + +@param[in] flag + Bit array field class flag from which to borrow the + bit index ranges. + +@returns + Bit index ranges of \bt_p{flag}. + +@bt_pre_not_null{flag} +*/ +extern const bt_integer_range_set_unsigned * +bt_field_class_bit_array_flag_borrow_index_ranges_const( + const bt_field_class_bit_array_flag *flag) __BT_NOEXCEPT; + /*! @} */ @@ -2387,7 +2753,7 @@ extern bt_field_class *bt_field_class_real_double_precision_create( /*! @brief - Array of \c const \bt_enum_fc labels. + Array of \c const \bt_enum_fc mapping labels. Returned by bt_field_class_enumeration_unsigned_get_mapping_labels_for_value() and bt_field_class_enumeration_signed_get_mapping_labels_for_value(). diff --git a/include/babeltrace2/trace-ir/field.h b/include/babeltrace2/trace-ir/field.h index 8ded1075..6487e3c9 100644 --- a/include/babeltrace2/trace-ir/field.h +++ b/include/babeltrace2/trace-ir/field.h @@ -149,7 +149,7 @@ A bit array field contains a fixed-length array of bits. Its length is \ref api-tir-fc-ba-prop-len "given by its class". The bit array field API interprets the array as an unsigned integer -value: the least significant bit's index is 0. +value: the least significant bit's index is 0. For example, to get whether or not bit 3 of a bit array field is set: @@ -157,7 +157,7 @@ set: @code uint64_t value = bt_field_bit_array_get_value_as_integer(field); -if (value & (UINT64_C(1) << UINT64_C(3))) { +if (value & (UINT64_C(1) << 3)) { // Bit 3 is set } @endcode @@ -168,6 +168,10 @@ bt_field_bit_array_set_value_as_integer(). Get the bits of a bit array field with bt_field_bit_array_get_value_as_integer(). +Get the labels of all the active \ref api-tir-fc-ba-prop-flags "flags" +of the \ref api-tir-fc-ba "class" of a bit array field for the set bits +of its integral value with bt_field_bit_array_get_active_flag_labels(). +

\anchor api-tir-field-int Integer fields

Integer fields are \bt_int_fc instances. @@ -623,6 +627,67 @@ See \bt_c_ba_field to learn more. extern uint64_t bt_field_bit_array_get_value_as_integer( const bt_field *field) __BT_NOEXCEPT; +/*! +@brief + Status codes for + bt_field_bit_array_get_active_flag_labels(). +*/ +typedef enum bt_field_bit_array_get_active_flag_labels_status { + /*! + @brief + Success. + */ + BT_FIELD_BIT_ARRAY_GET_ACTIVE_FLAG_LABELS_STATUS_OK = __BT_FUNC_STATUS_OK, + + /*! + @brief + Out of memory. + */ + BT_FIELD_BIT_ARRAY_GET_ACTIVE_FLAG_LABELS_STATUS_MEMORY_ERROR = __BT_FUNC_STATUS_MEMORY_ERROR, +} bt_field_bit_array_get_active_flag_labels_status; + +/*! +@brief + Returns the labels of all the active flags of the + \ref api-tir-fc-ba "class" of the \bt_ba_field \bt_p{field} + for the set bits of the integral value of \bt_p{field}. + +This function returns + +@code +(bt_field_bit_array_get_active_flag_labels_status) +bt_field_class_bit_array_get_active_flag_labels_for_value_as_integer( + bt_field_borrow_class_const(field), + bt_field_bit_array_get_value_as_integer(field), + labels, count) +@endcode + +@param[in] field + Bit array field having the class from which to get the labels of the + active flags for the integral value of \bt_p{field}. +@param[out] labels + See + bt_field_class_bit_array_get_active_flag_labels_for_value_as_integer(). +@param[out] count + See + bt_field_class_bit_array_get_active_flag_labels_for_value_as_integer(). + +@retval #BT_FIELD_BIT_ARRAY_GET_ACTIVE_FLAG_LABELS_STATUS_OK + Success. +@retval #BT_FIELD_BIT_ARRAY_GET_ACTIVE_FLAG_LABELS_STATUS_MEMORY_ERROR + Out of memory. + +@bt_pre_not_null{field} +@bt_pre_is_ba_field{field} +@bt_pre_field_with_mip{field, 1} +@bt_pre_not_null{labels} +@bt_pre_not_null{count} +*/ +extern bt_field_bit_array_get_active_flag_labels_status +bt_field_bit_array_get_active_flag_labels(const bt_field *field, + bt_field_class_bit_array_flag_label_array *labels, + uint64_t *count) __BT_NOEXCEPT; + /*! @} */ /*! diff --git a/include/babeltrace2/types.h b/include/babeltrace2/types.h index 68ca64dc..d69f86d4 100644 --- a/include/babeltrace2/types.h +++ b/include/babeltrace2/types.h @@ -37,6 +37,7 @@ typedef struct bt_event bt_event; typedef struct bt_event_class bt_event_class; typedef struct bt_field bt_field; typedef struct bt_field_class bt_field_class; +typedef struct bt_field_class_bit_array_flag bt_field_class_bit_array_flag; typedef struct bt_field_class_enumeration_mapping bt_field_class_enumeration_mapping; typedef struct bt_field_class_enumeration_signed_mapping bt_field_class_enumeration_signed_mapping; typedef struct bt_field_class_enumeration_unsigned_mapping bt_field_class_enumeration_unsigned_mapping; diff --git a/src/lib/lib-logging.c b/src/lib/lib-logging.c index fba67714..7ee7839e 100644 --- a/src/lib/lib-logging.c +++ b/src/lib/lib-logging.c @@ -184,7 +184,8 @@ static inline void format_field_class(char **buf_ch, bool extended, const struct bt_field_class_bit_array *ba_fc = (const void *) field_class; - BUF_APPEND(", %slength=%" PRIu64, PRFIELD(ba_fc->length)); + BUF_APPEND(", %slength=%" PRIu64 ", %sflag-count=%u", + PRFIELD(ba_fc->length), PRFIELD(ba_fc->flags->len)); break; } case BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER: diff --git a/src/lib/trace-ir/field-class.c b/src/lib/trace-ir/field-class.c index 3f6f3d2c..1db22766 100644 --- a/src/lib/trace-ir/field-class.c +++ b/src/lib/trace-ir/field-class.c @@ -68,15 +68,53 @@ void finalize_field_class(struct bt_field_class *fc) BT_OBJECT_PUT_REF_AND_RESET(fc->user_attributes); } +#define _BT_ASSERT_PRE_BIT_ARRAY_FC_FLAG_NAME "Bit array field class flag" +#define _BT_ASSERT_PRE_BIT_ARRAY_FC_FLAG_ID "bit-array-field-class-flag" + +#define BT_ASSERT_PRE_DEV_BIT_ARRAY_FC_FLAG_NON_NULL(_flag) \ + BT_ASSERT_PRE_DEV_NON_NULL( \ + _BT_ASSERT_PRE_BIT_ARRAY_FC_FLAG_ID, (_flag), \ + _BT_ASSERT_PRE_BIT_ARRAY_FC_FLAG_NAME) + static void destroy_bit_array_field_class(struct bt_object *obj) { + const struct bt_field_class_bit_array *ba_fc; + BT_ASSERT(obj); BT_LIB_LOGD("Destroying bit array field class object: %!+F", obj); + + ba_fc = (const void *) obj; + + if (ba_fc->flags) { + g_ptr_array_free(ba_fc->flags, TRUE); + } + finalize_field_class((void *) obj); g_free(obj); } +static +void destroy_bit_array_flag(struct bt_field_class_bit_array_flag *flag) +{ + if (!flag) { + goto end; + } + + g_free(flag->label); + bt_object_put_ref(flag->range_set); + g_free(flag); + +end: + return; +} + +static +void destroy_bit_array_flag_void(gpointer ptr) +{ + destroy_bit_array_flag((struct bt_field_class_bit_array_flag *) ptr); +} + BT_EXPORT struct bt_field_class *bt_field_class_bit_array_create( struct bt_trace_class *trace_class, uint64_t length) @@ -102,6 +140,13 @@ struct bt_field_class *bt_field_class_bit_array_create( } ba_fc->length = length; + ba_fc->flags = g_ptr_array_new_with_free_func( + destroy_bit_array_flag_void); + if (!ba_fc->flags) { + BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate a GPtrArray."); + goto error; + } + BT_LIB_LOGD("Created bit array field class object: %!+F", ba_fc); goto end; @@ -123,6 +168,190 @@ uint64_t bt_field_class_bit_array_get_length(const struct bt_field_class *fc) return ba_fc->length; } +BT_EXPORT +uint64_t bt_field_class_bit_array_get_flag_count(const bt_field_class *fc) +{ + const struct bt_field_class_bit_array *ba_fc = (const void *) fc; + + BT_ASSERT_PRE_DEV_FC_NON_NULL(fc); + BT_ASSERT_PRE_DEV_FC_HAS_TYPE("field-class", fc, "bit-array", + BT_FIELD_CLASS_TYPE_BIT_ARRAY, "Field class"); + return ba_fc->flags->len; +} + +BT_EXPORT +bt_field_class_bit_array_add_flag_status bt_field_class_bit_array_add_flag( + struct bt_field_class *fc, const char *label, + const bt_integer_range_set_unsigned *index_ranges) +{ + struct bt_field_class_bit_array *ba_fc = (void *) fc; + struct bt_field_class_bit_array_flag *flag = NULL; + bt_field_class_bit_array_add_flag_status status; + struct bt_integer_range_set *index_ranges_internal = + (bt_integer_range_set *) index_ranges; + guint range_i; + + BT_ASSERT_PRE_NO_ERROR(); + BT_ASSERT_PRE_FC_NON_NULL(fc); + BT_ASSERT_PRE_FC_HAS_TYPE("field-class", fc, "bit-array", + BT_FIELD_CLASS_TYPE_BIT_ARRAY, "Field class"); + BT_ASSERT_PRE_NON_NULL("label", label, "Label"); + BT_ASSERT_PRE("bit-array-field-class-flag-label-is-unique", + !bt_field_class_bit_array_borrow_flag_by_label_const(fc, label), + "Duplicate flag name in bit array field class: " + "%![bit-array-fc-]+F, label=\"%s\"", fc, label); + BT_ASSERT_PRE_INT_RANGE_SET_NON_NULL(index_ranges); + + for (range_i = 0; range_i < index_ranges_internal->ranges->len; ++range_i) { + struct bt_integer_range *range + = BT_INTEGER_RANGE_SET_RANGE_AT_INDEX(index_ranges_internal, + range_i); + + BT_ASSERT_PRE("bit-array-field-class-flag-bit-index-is-less-than-field-class-length", + range->upper.u < ba_fc->length, + "Flag bit index range's upper bound is greater than or " + "equal to bit array field length: %![bit-array-fc-]+F, " + "range-index=%u, upper-bound=%" PRIu64, + ba_fc, range_i, range->upper.u); + } + + flag = g_new0(struct bt_field_class_bit_array_flag, 1); + if (!flag) { + BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate a bit_array_flag."); + status = BT_FIELD_CLASS_BIT_ARRAY_ADD_FLAG_STATUS_MEMORY_ERROR; + goto end; + } + + flag->label = g_strdup(label); + if (!flag->label) { + BT_LIB_LOGE_APPEND_CAUSE( + "Failed to allocate memory for bit array flag label."); + status = BT_FIELD_CLASS_BIT_ARRAY_ADD_FLAG_STATUS_MEMORY_ERROR; + goto end; + } + + flag->range_set = index_ranges; + bt_integer_range_set_unsigned_get_ref(flag->range_set); + + /* Set flag->mask */ + for (range_i = 0; range_i < index_ranges_internal->ranges->len; range_i++) { + const struct bt_integer_range *range = (const void *) + BT_INTEGER_RANGE_SET_RANGE_AT_INDEX(index_ranges_internal, + range_i); + uint64_t bit_index; + + for (bit_index = range->lower.u; bit_index <= range->upper.u; + ++bit_index) { + flag->mask |= UINT64_C(1) << bit_index; + } + } + + g_ptr_array_add(ba_fc->flags, flag); + flag = NULL; + + status = BT_FIELD_CLASS_BIT_ARRAY_ADD_FLAG_STATUS_OK; + goto end; + +end: + destroy_bit_array_flag(flag); + return status; +} + +BT_EXPORT +const bt_field_class_bit_array_flag * +bt_field_class_bit_array_borrow_flag_by_index_const( + const struct bt_field_class *fc, uint64_t index) +{ + struct bt_field_class_bit_array *ba_fc = (void *) fc; + + BT_ASSERT_PRE_DEV_FC_NON_NULL(fc); + BT_ASSERT_PRE_DEV_FC_HAS_TYPE("field-class", fc, "bit-array", + BT_FIELD_CLASS_TYPE_BIT_ARRAY, "Field class"); + BT_ASSERT_PRE_DEV_VALID_INDEX(index, ba_fc->flags->len); + return ba_fc->flags->pdata[index]; +} + +BT_EXPORT +const bt_field_class_bit_array_flag * +bt_field_class_bit_array_borrow_flag_by_label_const( + const struct bt_field_class *fc, const char *label) +{ + struct bt_field_class_bit_array *ba_fc = (void *) fc; + const struct bt_field_class_bit_array_flag *flag = NULL; + uint64_t i; + + BT_ASSERT_PRE_DEV_FC_NON_NULL(fc); + BT_ASSERT_PRE_DEV_FC_HAS_TYPE("field-class", fc, "bit-array", + BT_FIELD_CLASS_TYPE_BIT_ARRAY, "Field class"); + BT_ASSERT_PRE_DEV_NON_NULL("label", label, "Label"); + + for (i = 0; i < ba_fc->flags->len; i++) { + const struct bt_field_class_bit_array_flag *candidate = + ba_fc->flags->pdata[i]; + + if (strcmp(candidate->label, label) == 0) { + flag = candidate; + break; + } + } + + return flag; +} + +BT_EXPORT +bt_field_class_bit_array_get_active_flag_labels_for_value_as_integer_status +bt_field_class_bit_array_get_active_flag_labels_for_value_as_integer( + const struct bt_field_class *fc, uint64_t value_as_integer, + bt_field_class_bit_array_flag_label_array *label_array, + uint64_t *count) +{ + struct bt_field_class_bit_array *ba_fc = (void *) fc; + uint64_t i; + + BT_ASSERT_PRE_DEV_NO_ERROR(); + BT_ASSERT_PRE_DEV_FC_NON_NULL(fc); + BT_ASSERT_PRE_DEV_FC_HAS_TYPE("field-class", fc, "bit-array", + BT_FIELD_CLASS_TYPE_BIT_ARRAY, "Field class"); + BT_ASSERT_PRE_DEV_NON_NULL("label-array-output", label_array, + "Label array (output)"); + BT_ASSERT_PRE_DEV_NON_NULL("count-output", count, "Count (output)"); + + g_ptr_array_set_size(ba_fc->label_buf, 0); + + for (i = 0; i < ba_fc->flags->len; ++i) { + const struct bt_field_class_bit_array_flag *flag = + ba_fc->flags->pdata[i]; + + if (value_as_integer & flag->mask) { + g_ptr_array_add(ba_fc->label_buf, flag->label); + } + } + + *label_array = (void *) ba_fc->label_buf->pdata; + *count = (uint64_t) ba_fc->label_buf->len; + + return BT_FIELD_CLASS_BIT_ARRAY_GET_ACTIVE_FLAG_LABELS_FOR_VALUE_AS_INTEGER_STATUS_OK; +} + +BT_EXPORT +const char *bt_field_class_bit_array_flag_get_label( + const struct bt_field_class_bit_array_flag *flag) +{ + BT_ASSERT_PRE_DEV_BIT_ARRAY_FC_FLAG_NON_NULL(flag); + + return flag->label; +} + +BT_EXPORT +const bt_integer_range_set_unsigned * +bt_field_class_bit_array_flag_borrow_index_ranges_const( + const struct bt_field_class_bit_array_flag *flag) +{ + BT_ASSERT_PRE_DEV_BIT_ARRAY_FC_FLAG_NON_NULL(flag); + + return flag->range_set; +} + static void destroy_bool_field_class(struct bt_object *obj) { diff --git a/src/lib/trace-ir/field-class.h b/src/lib/trace-ir/field-class.h index 98c56970..3feada3e 100644 --- a/src/lib/trace-ir/field-class.h +++ b/src/lib/trace-ir/field-class.h @@ -56,9 +56,35 @@ struct bt_field_class_bool { struct bt_field_class common; }; +struct bt_field_class_bit_array_flag { + /* Owned by this */ + gchar *label; + + /* Strong reference */ + const bt_integer_range_set_unsigned *range_set; + + /* + * Mask to apply to the field's value to determine if this flag is + * active. + */ + uint64_t mask; +}; + struct bt_field_class_bit_array { struct bt_field_class common; uint64_t length; + + /* Array of `bt_field_class_bit_array_flag`, owned by this */ + GPtrArray *flags; + + /* + * This is an array of `const char *` which acts as a temporary + * (potentially growing) buffer for + * bt_field_class_bit_array_get_active_flag_labels_for_value_as_integer(). + * + * The actual strings are owned by the flags above. + */ + GPtrArray *label_buf; }; struct bt_field_class_integer { diff --git a/src/lib/trace-ir/field.c b/src/lib/trace-ir/field.c index 19cb7971..0b1627fa 100644 --- a/src/lib/trace-ir/field.c +++ b/src/lib/trace-ir/field.c @@ -737,6 +737,27 @@ void bt_field_bit_array_set_value_as_integer(struct bt_field *field, bt_field_set_single(field, true); } +BT_EXPORT +bt_field_bit_array_get_active_flag_labels_status +bt_field_bit_array_get_active_flag_labels(const struct bt_field *field, + bt_field_class_bit_array_flag_label_array *label_array, + uint64_t *count) +{ + const struct bt_field_bit_array *ba_field = (const void *) field; + + BT_ASSERT_PRE_DEV_NO_ERROR(); + BT_ASSERT_PRE_DEV_FIELD_NON_NULL(field); + BT_ASSERT_PRE_DEV_FIELD_IS_SET("field", field); + BT_ASSERT_PRE_DEV_FIELD_HAS_CLASS_TYPE("field", field, + "bit-array-field", BT_FIELD_CLASS_TYPE_BIT_ARRAY, "Field"); + BT_ASSERT_PRE_DEV_NON_NULL("label-array-output", label_array, + "Label array (output)"); + BT_ASSERT_PRE_DEV_NON_NULL("count-output", count, "Count (output)"); + return (int) + bt_field_class_bit_array_get_active_flag_labels_for_value_as_integer( + field->class, ba_field->value_as_int, label_array, count); +} + BT_EXPORT int64_t bt_field_integer_signed_get_value(const struct bt_field *field) {