lib: add support for bit array flags
authorSimon Marchi <simon.marchi@efficios.com>
Mon, 22 Jan 2024 21:20:58 +0000 (21:20 +0000)
committerSimon Marchi <simon.marchi@efficios.com>
Wed, 4 Sep 2024 19:05:14 +0000 (15:05 -0400)
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 <simon.marchi@efficios.com>
Reviewed-on: https://review.lttng.org/c/babeltrace/+/12727
Reviewed-by: Philippe Proulx <eeppeliteloop@gmail.com>
include/babeltrace2/trace-ir/field-class.h
include/babeltrace2/trace-ir/field.h
include/babeltrace2/types.h
src/lib/lib-logging.c
src/lib/trace-ir/field-class.c
src/lib/trace-ir/field-class.h
src/lib/trace-ir/field.c

index fa5cc22286d357d819e94f23389b7571f16fb78c..86ba837cd2e57cef867c04564034e1ff74a3935a 100644 (file)
@@ -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().
   </dd>
+
+  <dt>
+    \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&nbsp;1)
+  </dt>
+  <dd>
+    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&nbsp;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:
+
+    - <code>GALLERY</code>: [1,&nbsp;4], [8,&nbsp;14]
+    - <code>LUNCH</code>: [3,&nbsp;6]
+
+    In that case, the bit indexes&nbsp;2 and&nbsp;12 correspond to the
+    label <code>GALLERY</code>, the bit index&nbsp;5 to the label
+    <code>LUNCH</code>, and the bit index&nbsp;3 to the labels
+    \c GALLERY \em and <code>LUNCH</code>.
+
+    Given some bit flag field value (as an integer), a flag is said to
+    be <strong><em>active</em></strong> when <em>at least one</em> 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&nbsp;6 would be active because
+      bit&nbsp;3 is set.
+
+    - A flag targeting bits 1 and&nbsp;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().
+  </dd>
 </dl>
 
 <h1>\anchor api-tir-fc-int Integer field classes</h1>
@@ -473,9 +552,9 @@ Enumeration field classes have the following common property:
     - <code>CALORIES</code>: [1,&nbsp;11], [15,&nbsp;37]
     - <code>SODIUM</code>: [7,&nbsp;13]
 
-    In that case, the values 2 and 30 correpond to the label
-    <code>CALORIES</code>, the value 12 to the label
-    <code>SODIUM</code>, and the value 10 to the labels
+    In that case, the values&nbsp;2 and&nbsp;30 correspond to the label
+    <code>CALORIES</code>, the value&nbsp;12 to the label
+    <code>SODIUM</code>, and the value&nbsp;10 to the labels
     \c CALORIES \em and <code>SODIUM</code>.
 
     Two mappings of the same enumeration field class cannot have the
@@ -2026,6 +2105,11 @@ property values:
   <tr>
     <td>\ref api-tir-fc-ba-prop-len "Length"
     <td>\bt_p{length}
+  <tr>
+    <td>
+      \bt_mip version&nbsp;1:
+      \ref api-tir-fc-ba-prop-flags "flags"
+    <td>\em None
   <tr>
     <td>\ref api-tir-fc-prop-user-attrs "User attributes"
     <td>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() &mdash;
+    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&nbsp;0.
+    @endparblock
+@param[out] labels
+    @parblock
+    <strong>On success</strong>, \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
+    <strong>On success</strong>, \bt_p{*count} is the number of labels
+    in \bt_p{*labels} (can be&nbsp;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().
index 8ded107513666b6a3acacf327fbc67bef37228f1..6487e3c9241971d11f1541034dbfbcd538cf78cd 100644 (file)
@@ -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&nbsp;0.
 
 For example, to get whether or not bit&nbsp;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().
+
 <h1>\anchor api-tir-field-int Integer fields</h1>
 
 <strong><em>Integer fields</em></strong> 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;
+
 /*! @} */
 
 /*!
index 68ca64dcf08b68981c09cfc509c2dfaa5f19aa6f..d69f86d4ffbc1491913946b310c3fbde9631cd6b 100644 (file)
@@ -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;
index fba6771493f650bef1c2631531738e9f809b2201..7ee7839e5bb9a0155e197a7f43811985ee3741e9 100644 (file)
@@ -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:
index 3f6f3d2ce6003146b19f249a819c2cbfd64082b3..1db22766e5322cf6188d9426539f019d3642b29e 100644 (file)
@@ -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)
 {
index 98c5697003e2a14611f6cdcda2f5b9a523f8a7ca..3feada3eda02c185578126bdae82f31f319f7d46 100644 (file)
@@ -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 {
index 19cb7971933abb350012fdecea0356c9beb8326e..0b1627fa491509b79c65f361907c0f15d15b811f 100644 (file)
@@ -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)
 {
This page took 0.035509 seconds and 4 git commands to generate.