lib: add BLOB field class types
authorSimon Marchi <simon.marchi@efficios.com>
Tue, 22 Feb 2022 00:54:51 +0000 (19:54 -0500)
committerSimon Marchi <simon.marchi@efficios.com>
Wed, 4 Sep 2024 19:05:14 +0000 (15:05 -0400)
Add support for BLOB field classes and fields, with the intent of
supporting CTF2‑SPEC‑2.0's BLOB field class types [1].

A BLOB is a sequence of binary data included as-is in the trace.

A BLOB field class has a media type property, which describes the kind
of content its instances hold.

There are three variations of a BLOB field class, analogous to the array
field classes:

 - static length BLOB
 - dynamic length BLOB without a length field
 - dynamic length BLOB with a length field

Static length BLOBs have a fixed length, set in the field class.

Dynamic length BLOBs have a variable length, set in each field instance
of the field class.

Dynamic length BLOBs with a length field have a length field location,
set in the field class, pointing to a preceding field that holds the
length of the BLOB.

Philippe updated the documentation.

[1] https://diamon.org/ctf/CTF2-SPEC-2.0.html#blob-fc

Change-Id: Ib9d7bd12d598fbc6b7ed5d80d8cdfcf294e4254d
Signed-off-by: Simon Marchi <simon.marchi@efficios.com>
Reviewed-on: https://review.lttng.org/c/babeltrace/+/7350
Tested-by: jenkins <jenkins@lttng.org>
Reviewed-by: Philippe Proulx <eeppeliteloop@gmail.com>
Reviewed-on: https://review.lttng.org/c/babeltrace/+/12687

doc/api/libbabeltrace2/Doxyfile.in
include/babeltrace2/trace-ir/field-class.h
include/babeltrace2/trace-ir/field-location.h
include/babeltrace2/trace-ir/field.h
src/common/common.h
src/lib/assert-cond.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
src/lib/trace-ir/field.h

index 12e11382bc86514758d0654bcd7c2805f96ae4c1..64a4e89be0857d46314f320553ef01afe0af767d 100644 (file)
@@ -63,6 +63,10 @@ ALIASES                += bt_pre_is_enum_fc{1}="@pre \bt_p{\1} is an \link api-t
 ALIASES                += bt_pre_is_uenum_fc{1}="@pre \bt_p{\1} is an unsigned \link api-tir-fc-enum enumeration field class\endlink."
 ALIASES                += bt_pre_is_senum_fc{1}="@pre \bt_p{\1} is a signed \link api-tir-fc-enum enumeration field class\endlink."
 ALIASES                += bt_pre_is_string_fc{1}="@pre \bt_p{\1} is a \link api-tir-fc-string string field class\endlink."
+ALIASES                += bt_pre_is_blob_fc{1}="@pre \bt_p{\1} is a BLOB \link api-tir-fc-blob field class\endlink."
+ALIASES                += bt_pre_is_sblob_fc{1}="@pre \bt_p{\1} is a static \link api-tir-fc-blob BLOB field class\endlink."
+ALIASES                += bt_pre_is_dblob_fc{1}="@pre \bt_p{\1} is a dynamic \link api-tir-fc-blob BLOB field class\endlink."
+ALIASES                += bt_pre_is_dblob_wl_fc{1}="@pre \bt_p{\1} is a dynamic \link api-tir-fc-blob BLOB field class\endlink (instances with a linked length field)."
 ALIASES                += bt_pre_is_struct_fc{1}="@pre \bt_p{\1} is a \link api-tir-fc-struct structure field class\endlink."
 ALIASES                += bt_pre_is_array_fc{1}="@pre \bt_p{\1} is an array \link api-tir-fc-array field class\endlink."
 ALIASES                += bt_pre_is_sarray_fc{1}="@pre \bt_p{\1} is a static \link api-tir-fc-array array field class\endlink."
@@ -90,6 +94,9 @@ ALIASES                += bt_pre_is_enum_field{1}="@pre \bt_p{\1} is an \link ap
 ALIASES                += bt_pre_is_uenum_field{1}="@pre \bt_p{\1} is an unsigned \link api-tir-field-enum enumeration field\endlink."
 ALIASES                += bt_pre_is_senum_field{1}="@pre \bt_p{\1} is a signed \link api-tir-field-enum enumeration field\endlink."
 ALIASES                += bt_pre_is_string_field{1}="@pre \bt_p{\1} is a \link api-tir-field-string string field\endlink."
+ALIASES                += bt_pre_is_blob_field{1}="@pre \bt_p{\1} is a \link api-tir-field-blob BLOB field\endlink."
+ALIASES                += bt_pre_is_sblob_field{1}="@pre \bt_p{\1} is a static \link api-tir-field-blob BLOB field\endlink."
+ALIASES                += bt_pre_is_dblob_field{1}="@pre \bt_p{\1} is a dynamic \link api-tir-field-blob BLOB field\endlink."
 ALIASES                += bt_pre_is_struct_field{1}="@pre \bt_p{\1} is a \link api-tir-field-struct structure field\endlink."
 ALIASES                += bt_pre_is_array_field{1}="@pre \bt_p{\1} is an \link api-tir-field-array array field\endlink."
 ALIASES                += bt_pre_is_sarray_field{1}="@pre \bt_p{\1} is a static \link api-tir-field-array array field\endlink."
@@ -122,6 +129,7 @@ ALIASES                += bt_pre_is_se_msg{1}="@pre \bt_p{\1} is a \link api-msg
 # Aliases: preconditions: MIP version
 ALIASES                += bt_pre_tc_with_mip{2}="@pre \bt_p{\1} was created from a \bt_comp which belongs to a trace processing \bt_graph with the effective \bt_mip version&nbsp;\2."
 ALIASES                += bt_pre_fc_with_mip{2}="@pre \bt_p{\1} 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;\2."
+ALIASES                += bt_pre_field_with_mip{2}="@pre The class of \bt_p{\1} 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;\2."
 ALIASES                += bt_pre_trace_with_mip{2}="@pre The \link api-tir-trace-cls class\endlink of \bt_p{\1} was created from a \bt_comp which belongs to a trace processing \bt_graph with the effective \bt_mip version&nbsp;\2."
 ALIASES                += bt_pre_clock_cls_with_mip{2}="@pre \bt_p{\1} was created from a \bt_comp which belongs to a trace processing \bt_graph with the effective \bt_mip version&nbsp;\2."
 
@@ -137,6 +145,9 @@ ALIASES                += bt_enum_fc="\link api-tir-fc-enum enumeration field cl
 ALIASES                += bt_senum_fc="signed \link api-tir-fc-enum enumeration field class\endlink"
 ALIASES                += bt_uenum_fc="unsigned \link api-tir-fc-enum enumeration field class\endlink"
 ALIASES                += bt_string_fc="\link api-tir-fc-string string field class\endlink"
+ALIASES                += bt_blob_fc="\link api-tir-fc-blob BLOB field class\endlink"
+ALIASES                += bt_sblob_fc="static \link api-tir-fc-blob BLOB field class\endlink"
+ALIASES                += bt_dblob_fc="dynamic \link api-tir-fc-blob BLOB field class\endlink"
 ALIASES                += bt_struct_fc="\link api-tir-fc-struct structure field class\endlink"
 ALIASES                += bt_array_fc="\link api-tir-fc-array array field class\endlink"
 ALIASES                += bt_sarray_fc="static \link api-tir-fc-array array field class\endlink"
@@ -156,6 +167,9 @@ ALIASES                += bt_c_enum_fc="\link api-tir-fc-enum Enumeration field
 ALIASES                += bt_c_senum_fc="Signed \link api-tir-fc-enum enumeration field class\endlink"
 ALIASES                += bt_c_uenum_fc="Unsigned \link api-tir-fc-enum enumeration field class\endlink"
 ALIASES                += bt_c_string_fc="\link api-tir-fc-string String field class\endlink"
+ALIASES                += bt_c_blob_fc="\link api-tir-fc-blob BLOB field class\endlink"
+ALIASES                += bt_c_sblob_fc="Static \link api-tir-fc-blob BLOB field class\endlink"
+ALIASES                += bt_c_dblob_fc="Dynamic \link api-tir-fc-blob BLOB field class\endlink"
 ALIASES                += bt_c_struct_fc="\link api-tir-fc-struct Structure field class\endlink"
 ALIASES                += bt_c_array_fc="\link api-tir-fc-array Array field class\endlink"
 ALIASES                += bt_c_sarray_fc="Static \link api-tir-fc-array array field class\endlink"
@@ -175,6 +189,9 @@ ALIASES                += bt_p_enum_fc="\link api-tir-fc-enum enumeration field
 ALIASES                += bt_p_senum_fc="signed \link api-tir-fc-enum enumeration field classes\endlink"
 ALIASES                += bt_p_uenum_fc="unsigned \link api-tir-fc-enum enumeration field classes\endlink"
 ALIASES                += bt_p_string_fc="\link api-tir-fc-string string field classes\endlink"
+ALIASES                += bt_p_blob_fc="\link api-tir-fc-blob BLOB field classes\endlink"
+ALIASES                += bt_p_sblob_fc="static \link api-tir-fc-blob BLOB field classes\endlink"
+ALIASES                += bt_p_dblob_fc="dynamic \link api-tir-fc-blob BLOB field classes\endlink"
 ALIASES                += bt_p_struct_fc="\link api-tir-fc-struct structure field classes\endlink"
 ALIASES                += bt_p_array_fc="\link api-tir-fc-array array field classes\endlink"
 ALIASES                += bt_p_sarray_fc="static \link api-tir-fc-array array field classes\endlink"
@@ -194,6 +211,9 @@ ALIASES                += bt_cp_enum_fc="\link api-tir-fc-enum Enumeration field
 ALIASES                += bt_cp_senum_fc="Signed \link api-tir-fc-enum enumeration field classes\endlink"
 ALIASES                += bt_cp_uenum_fc="Unsigned \link api-tir-fc-enum enumeration field classes\endlink"
 ALIASES                += bt_cp_string_fc="\link api-tir-fc-string String field classes\endlink"
+ALIASES                += bt_cp_blob_fc="\link api-tir-fc-blob BLOB field classes\endlink"
+ALIASES                += bt_cp_sblob_fc="Static \link api-tir-fc-blob BLOB field classes\endlink"
+ALIASES                += bt_cp_dblob_fc="Dynamic \link api-tir-fc-blob BLOB field classes\endlink"
 ALIASES                += bt_cp_struct_fc="\link api-tir-fc-struct Structure field classes\endlink"
 ALIASES                += bt_cp_array_fc="\link api-tir-fc-array Array field classes\endlink"
 ALIASES                += bt_cp_sarray_fc="Static \link api-tir-fc-array array field classes\endlink"
@@ -215,6 +235,9 @@ ALIASES                += bt_enum_field="\link api-tir-field-enum enumeration fi
 ALIASES                += bt_senum_field="signed \link api-tir-field-enum enumeration field\endlink"
 ALIASES                += bt_uenum_field="unsigned \link api-tir-field-enum enumeration field\endlink"
 ALIASES                += bt_string_field="\link api-tir-field-string string field\endlink"
+ALIASES                += bt_blob_field="\link api-tir-field-blob BLOB field\endlink"
+ALIASES                += bt_sblob_field="static \link api-tir-field-blob BLOB field\endlink"
+ALIASES                += bt_dblob_field="dynamic \link api-tir-field-blob BLOB field\endlink"
 ALIASES                += bt_struct_field="\link api-tir-field-struct structure field\endlink"
 ALIASES                += bt_array_field="\link api-tir-field-array array field\endlink"
 ALIASES                += bt_sarray_field="static \link api-tir-field-array array field\endlink"
@@ -236,6 +259,9 @@ ALIASES                += bt_c_enum_field="\link api-tir-field-enum Enumeration
 ALIASES                += bt_c_senum_field="Signed \link api-tir-field-enum enumeration field\endlink"
 ALIASES                += bt_c_uenum_field="Unsigned \link api-tir-field-enum enumeration field\endlink"
 ALIASES                += bt_c_string_field="\link api-tir-field-string String field\endlink"
+ALIASES                += bt_c_blob_field="\link api-tir-field-blob BLOB field\endlink"
+ALIASES                += bt_c_sblob_field="Static \link api-tir-field-blob BLOB field\endlink"
+ALIASES                += bt_c_dblob_field="Dynamic \link api-tir-field-blob BLOB field\endlink"
 ALIASES                += bt_c_struct_field="\link api-tir-field-struct Structure field\endlink"
 ALIASES                += bt_c_array_field="\link api-tir-field-array Array field\endlink"
 ALIASES                += bt_c_sarray_field="Static \link api-tir-field-array array field\endlink"
@@ -257,6 +283,9 @@ ALIASES                += bt_p_enum_field="\link api-tir-field-enum enumeration
 ALIASES                += bt_p_senum_field="signed \link api-tir-field-enum enumeration fields\endlink"
 ALIASES                += bt_p_uenum_field="unsigned \link api-tir-field-enum enumeration fields\endlink"
 ALIASES                += bt_p_string_field="\link api-tir-field-string string fields\endlink"
+ALIASES                += bt_p_blob_field="\link api-tir-field-blob BLOB fields\endlink"
+ALIASES                += bt_p_sblob_field="static \link api-tir-field-blob BLOB fields\endlink"
+ALIASES                += bt_p_dblob_field="dynamic \link api-tir-field-blob BLOB fields\endlink"
 ALIASES                += bt_p_struct_field="\link api-tir-field-struct structure fields\endlink"
 ALIASES                += bt_p_array_field="\link api-tir-field-array array fields\endlink"
 ALIASES                += bt_p_sarray_field="static \link api-tir-field-array array fields\endlink"
@@ -278,6 +307,9 @@ ALIASES                += bt_cp_enum_field="\link api-tir-field-enum Enumeration
 ALIASES                += bt_cp_senum_field="Signed \link api-tir-field-enum enumeration fields\endlink"
 ALIASES                += bt_cp_uenum_field="Unsigned \link api-tir-field-enum enumeration fields\endlink"
 ALIASES                += bt_cp_string_field="\link api-tir-field-string String fields\endlink"
+ALIASES                += bt_cp_blob_field="\link api-tir-field-blob BLOB fields\endlink"
+ALIASES                += bt_cp_sblob_field="Static \link api-tir-field-blob BLOB fields\endlink"
+ALIASES                += bt_cp_dblob_field="Dynamic \link api-tir-field-blob BLOB fields\endlink"
 ALIASES                += bt_cp_struct_field="\link api-tir-field-struct Structure fields\endlink"
 ALIASES                += bt_cp_array_field="\link api-tir-field-array Array fields\endlink"
 ALIASES                += bt_cp_sarray_field="Static \link api-tir-field-array array fields\endlink"
index 5d49edc5ca9ae3406f0d574361b6719bbe72cd46..13533c8bb8df91557a70fa3773f7ec65c21d6d27 100644 (file)
@@ -51,6 +51,7 @@ categories:
     - \ref api-tir-fc-enum "Enumeration" (unsigned and signed)
     - \ref api-tir-fc-real "Real" (single-precision and double-precision)
     - \ref api-tir-fc-string "String"
+    - \ref api-tir-fc-blob "BLOB" (static and dynamic)
   </dd>
 
   <dt>Container</dt>
@@ -147,6 +148,22 @@ functions for each type of \em concrete (non-abstract) field class:
     <td><em>\ref api-tir-fc-string "String"</em>
     <td>#BT_FIELD_CLASS_TYPE_STRING
     <td>bt_field_class_string_create()
+  <tr>
+    <td><em>Static \ref api-tir-fc-blob "BLOB"</em>
+    <td>#BT_FIELD_CLASS_TYPE_STATIC_BLOB
+    <td>bt_field_class_blob_static_create()
+  <tr>
+    <td>
+      <em>Dynamic \ref api-tir-fc-blob "BLOB"
+      (instances without a linked length field)</em>
+    <td>#BT_FIELD_CLASS_TYPE_DYNAMIC_BLOB_WITHOUT_LENGTH_FIELD
+    <td>bt_field_class_blob_dynamic_without_length_field_location_create()
+  <tr>
+    <td>
+      <em>Dynamic \ref api-tir-fc-blob "BLOB"
+      (instances with a linked length field)</em>
+    <td>#BT_FIELD_CLASS_TYPE_DYNAMIC_BLOB_WITH_LENGTH_FIELD
+    <td>bt_field_class_blob_dynamic_with_length_field_location_create()
   <tr>
     <td><em>Static \ref api-tir-fc-array "array"</em>
     <td>#BT_FIELD_CLASS_TYPE_STATIC_ARRAY
@@ -550,6 +567,102 @@ Create a string field class with bt_field_class_string_create().
 
 A string field class has no specific properties.
 
+<h1>\anchor api-tir-fc-blob BLOB field classes</h1>
+
+@image html fc-blob.png
+
+<strong><em>BLOB field classes</em></strong> are
+classes of \bt_p_blob_field.
+
+BLOB fields contain zero or more bytes of binary data.
+
+@note
+    BLOB field classes are only available when the \bt_trace_cls from
+    which you create them was created from a \bt_comp which belongs
+    to a trace processing \bt_graph with the effective \bt_mip
+    version&nbsp;1.
+
+A BLOB field class is an \em abstract field class: you cannot create
+one. The concrete BLOB field classes are:
+
+<dl>
+  <dt>Static BLOB field class</dt>
+  <dd>
+    Its instances (static BLOB fields) contain a fixed number of bytes.
+
+    Create with bt_field_class_blob_static_create().
+
+    A static BLOB field class has the following specific property:
+
+    <dl>
+      <dt>
+        \anchor api-tir-fc-sblob-prop-len
+        Length
+      </dt>
+      <dd>
+        Number of bytes contained in the instances (static BLOB
+        fields) of the static BLOB field class.
+
+        You cannot change the length once the static BLOB field class is
+        created.
+
+        Get a static BLOB field class's length with
+        bt_field_class_blob_static_get_length().
+      </dd>
+    </dl>
+  </dd>
+
+  <dt>Dynamic BLOB field class</dt>
+  <dd>
+    Its instances (dynamic BLOB fields) contain a variable number
+    of bytes.
+
+    There are two types of dynamic BLOB field classes: instances
+    without or with a linked length field. See
+    \ref api-tir-fc-link "Fields with links to other fields"
+    to learn more.
+
+    @image html dblob-link.png "A dynamic blob field linked to an unsigned integer length field."
+
+    Create with
+    bt_field_class_blob_dynamic_without_length_field_location_create()
+    or bt_field_class_blob_dynamic_with_length_field_location_create().
+
+    The class of a dynamic BLOB field with a linked length field has
+    the following specific property:
+
+    <dl>
+      <dt>
+        \anchor api-tir-fc-dblob-prop-len-fl
+        Length field location
+      </dt>
+      <dd>
+        \bt_c_field_loc to locate the linked length field of an
+        instance.
+
+        Get a dynamic BLOB field class's length field location with
+        bt_field_class_blob_dynamic_with_length_field_borrow_length_field_location_const().
+      </dd>
+    </dl>
+  </dd>
+</dl>
+
+BLOB field classes have the following common property:
+
+<dl>
+  <dt>
+    \anchor api-tir-fc-blob-prop-media-type
+    Media type
+  </dt>
+  <dd>
+    <a href="https://datatracker.ietf.org/doc/html/rfc2046">IANA media type</a>
+    of instances of the BLOB field class.
+
+    Use bt_field_class_blob_set_media_type() and
+    bt_field_class_blob_get_media_type().
+  </dd>
+</dl>
+
 <h1>\anchor api-tir-fc-array Array field classes</h1>
 
 @image html fc-array.png
@@ -1167,18 +1280,24 @@ Variant field classes have the following common property:
 
 <h1>\anchor api-tir-fc-link Fields with links to other fields</h1>
 
-An instance of a \bt_darray_fc, a \bt_opt_fc, or a \bt_var_fc \em may
-have a link to another, anterior field within the same \bt_pkt or
-\bt_ev.
+An instance of a \bt_dblob_fc, a \bt_darray_fc, a \bt_opt_fc, or a
+\bt_var_fc \em may have a link to another, anterior field within the
+same \bt_pkt or \bt_ev.
 
 This feature exists so that the linked field can contain the value of a
 dynamic property of the "dependent" field. Those properties are:
 
 <dl>
+  <dt>\bt_c_dblob_field</dt>
+  <dd>
+    The linked field, a \bt_uint_field, contains the \b length (number
+    of bytes) of the dynamic BLOB field.
+  </dd>
+
   <dt>\bt_c_darray_field</dt>
   <dd>
-    The linked field, a \bt_uint_field, contains the \b length of the
-    dynamic array field.
+    The linked field, a \bt_uint_field, contains the \b length (number
+    of elements) of the dynamic array field.
   </dd>
 
   <dt>\bt_c_opt_field</dt>
@@ -1249,6 +1368,7 @@ processing \bt_graph:
 
     The functions to borrow the field location of a field class are:
 
+    - bt_field_class_blob_dynamic_with_length_field_borrow_length_field_location_const()
     - bt_field_class_array_dynamic_with_length_field_borrow_length_field_location_const()
     - bt_field_class_option_with_selector_field_borrow_selector_field_location_const()
     - bt_field_class_variant_with_selector_field_borrow_selector_field_location_const()
@@ -1487,6 +1607,52 @@ typedef enum bt_field_class_type {
        */
        BT_FIELD_CLASS_TYPE_STRING                                              = 1ULL << 9,
 
+       /*!
+       @brief
+           \bt_c_blob_fc.
+
+       No field class has this type: use it with
+       bt_field_class_type_is().
+       */
+       BT_FIELD_CLASS_TYPE_BLOB                                                = (1ULL << 29),
+
+       /*!
+       @brief
+           \bt_c_sblob_fc.
+
+       This type conceptually inherits #BT_FIELD_CLASS_TYPE_BLOB.
+       */
+       BT_FIELD_CLASS_TYPE_STATIC_BLOB                                         = (1ULL << 30) | BT_FIELD_CLASS_TYPE_BLOB,
+
+       /*!
+       @brief
+           \bt_c_dblob_fc.
+
+       This type conceptually inherits #BT_FIELD_CLASS_TYPE_BLOB.
+
+       No field class has this type: use it with
+       bt_field_class_type_is().
+       */
+       BT_FIELD_CLASS_TYPE_DYNAMIC_BLOB                                        = (1ULL << 31) | BT_FIELD_CLASS_TYPE_BLOB,
+
+       /*!
+       @brief
+           \bt_c_dblob_fc (instances without a linked length field).
+
+       This type conceptually inherits
+       #BT_FIELD_CLASS_TYPE_DYNAMIC_BLOB.
+       */
+       BT_FIELD_CLASS_TYPE_DYNAMIC_BLOB_WITHOUT_LENGTH_FIELD                   = (1ULL << 32) | BT_FIELD_CLASS_TYPE_DYNAMIC_BLOB,
+
+       /*!
+       @brief
+           \bt_c_dblob_fc (instances with a linked length field).
+
+       This type conceptually inherits
+       #BT_FIELD_CLASS_TYPE_DYNAMIC_BLOB.
+       */
+       BT_FIELD_CLASS_TYPE_DYNAMIC_BLOB_WITH_LENGTH_FIELD                      = (1ULL << 33) | BT_FIELD_CLASS_TYPE_DYNAMIC_BLOB,
+
        /*!
        @brief
            \bt_c_struct_fc.
@@ -2893,6 +3059,267 @@ extern bt_field_class *bt_field_class_string_create(
 
 /*! @} */
 
+/*!
+@name BLOB field class
+@{
+*/
+
+/*!
+@brief
+    Creates a \bt_sblob_fc having the length \bt_p{length} from the
+    trace class \bt_p{trace_class}.
+
+On success, the returned static BLOB field class has the following
+property values:
+
+<table>
+  <tr>
+    <th>Property
+    <th>Value
+  <tr>
+    <td>\ref api-tir-fc-sarray-prop-len "Length"
+    <td>\bt_p{length}
+  <tr>
+    <td>\ref api-tir-fc-blob-prop-media-type "Media type"
+    <td><code>application/octet-stream</code>
+  <tr>
+    <td>\ref api-tir-fc-prop-user-attrs "User attributes"
+    <td>Empty \bt_map_val
+</table>
+
+@param[in] trace_class
+    Trace class from which to create a static BLOB field class.
+@param[in] length
+    Length (number of bytes) of the instances of the static BLOB
+    field class to create.
+
+@returns
+    New static BLOB field class reference, or \c NULL on memory error.
+
+@bt_pre_not_null{trace_class}
+@bt_pre_tc_with_mip{trace_class, 1}
+
+@sa bt_field_class_blob_dynamic_without_length_field_location_create() &mdash;
+    Creates a class of dynamic BLOB field without a linked length field.
+@sa bt_field_class_blob_dynamic_with_length_field_location_create() &mdash;
+    Creates a class of dynamic BLOB field with a linked length field.
+*/
+extern bt_field_class *bt_field_class_blob_static_create(
+               bt_trace_class *trace_class, uint64_t length) __BT_NOEXCEPT;
+
+/*!
+@brief
+    Creates a \bt_dblob_fc (instances without a linked length field)
+    from the trace class \bt_p{trace_class}.
+
+On success, the returned dynamic BLOB field class has the following
+property values:
+
+<table>
+  <tr>
+    <th>Property
+    <th>Value
+  <tr>
+    <td>\ref api-tir-fc-dblob-prop-len-fl "Length field location"
+    <td>
+      \em None
+  <tr>
+    <td>\ref api-tir-fc-blob-prop-media-type "Media type"
+    <td><code>application/octet-stream</code>
+  <tr>
+    <td>\ref api-tir-fc-prop-user-attrs "User attributes"
+    <td>Empty \bt_map_val
+</table>
+
+@param[in] trace_class
+    Trace class from which to create a dynamic BLOB field class.
+
+@returns
+    New dynamic BLOB field class reference (without a length field),
+    or \c NULL on memory error.
+
+@bt_pre_not_null{trace_class}
+@bt_pre_tc_with_mip{trace_class, 1}
+
+@sa bt_field_class_blob_dynamic_with_length_field_location_create() &mdash;
+    Creates a class of dynamic BLOB field with a linked length field.
+*/
+extern bt_field_class *
+bt_field_class_blob_dynamic_without_length_field_location_create(
+               bt_trace_class *trace_class) __BT_NOEXCEPT;
+
+/*!
+@brief
+    Creates a \bt_dblob_fc (instances with a linked length field)
+    having the length \bt_field_loc \bt_p{length_field_location} from
+    the trace class \bt_p{trace_class}.
+
+On success, the returned dynamic BLOB field class has the following
+property values:
+
+<table>
+  <tr>
+    <th>Property
+    <th>Value
+  <tr>
+    <td>\ref api-tir-fc-dblob-prop-len-fl "Length field location"
+    <td>
+      \bt_p{length_field_location}.
+
+      See \ref api-tir-fc-link "Fields with links to other fields"
+      to learn more.
+  <tr>
+    <td>\ref api-tir-fc-blob-prop-media-type "Media type"
+    <td><code>application/octet-stream</code>
+  <tr>
+    <td>\ref api-tir-fc-prop-user-attrs "User attributes"
+    <td>Empty \bt_map_val
+</table>
+
+@param[in] trace_class
+    Trace class from which to create a dynamic BLOB field class.
+@param[in] length_field_location
+    Length field location of the dynamic BLOB field class to create.
+
+@returns
+    New dynamic BLOB field class reference (instances with a linked
+    length field), or \c NULL on memory error.
+
+@bt_pre_not_null{trace_class}
+@bt_pre_tc_with_mip{trace_class, 1}
+@bt_pre_not_null{length_field_location}
+
+@sa bt_field_class_blob_dynamic_without_length_field_location_create() &mdash;
+    Creates a class of dynamic BLOB field without a linked
+    length field.
+*/
+extern bt_field_class *
+bt_field_class_blob_dynamic_with_length_field_location_create(
+               bt_trace_class *trace_class,
+               const bt_field_location *length_field_location) __BT_NOEXCEPT;
+
+/*!
+@brief
+    Returns the length of the \bt_sblob_fc \bt_p{field_class}.
+
+See the \ref api-tir-fc-sblob-prop-len "length" property.
+
+@param[in] field_class
+    Static BLOB field class of which to get the length (number of bytes
+    in instances).
+
+@returns
+    Length of \bt_p{field_class}.
+
+@bt_pre_not_null{field_class}
+@bt_pre_is_sblob_fc{field_class}
+@bt_pre_fc_with_mip{field_class, 1}
+*/
+extern uint64_t bt_field_class_blob_static_get_length(
+               const bt_field_class *field_class) __BT_NOEXCEPT;
+
+/*!
+@brief
+    Borrows the length field location from the \bt_dblob_fc (instances
+    with a linked length field) \bt_p{field_class}.
+
+See the \ref api-tir-fc-dblob-prop-len-fl "length field location"
+property.
+
+@param[in] field_class
+    Dynamic BLOB field class from which to borrow the length
+    field location.
+
+@returns
+    Length field location of \bt_p{field_class}.
+
+@bt_pre_not_null{field_class}
+@bt_pre_is_dblob_wl_fc{field_class}
+@bt_pre_fc_with_mip{field_class, 1}
+*/
+extern const bt_field_location *
+bt_field_class_blob_dynamic_with_length_field_borrow_length_field_location_const(
+               const bt_field_class *field_class) __BT_NOEXCEPT;
+
+/*!
+@brief
+    Status codes for bt_field_class_blob_set_media_type().
+*/
+typedef enum bt_field_class_blob_set_media_type_status {
+       /*!
+       @brief
+           Success.
+       */
+       BT_FIELD_CLASS_BLOB_SET_MEDIA_TYPE_STATUS_OK            = __BT_FUNC_STATUS_OK,
+
+       /*!
+       @brief
+           Out of memory.
+       */
+       BT_FIELD_CLASS_BLOB_SET_MEDIA_TYPE_STATUS_MEMORY_ERROR  = __BT_FUNC_STATUS_MEMORY_ERROR,
+} bt_field_class_blob_set_media_type_status;
+
+/*!
+@brief
+    Sets the IANA media type of the \bt_blob_fc \bt_p{field_class}
+    to a copy of \bt_p{media_type}.
+
+See the \ref api-tir-fc-blob-prop-media-type "media type" property.
+
+@param[in] field_class
+    BLOB field class of which to set the media type to a copy of
+    \bt_p{media_type}.
+@param[in] media_type
+    New media type of \bt_p{field_class} (copied).
+
+@retval #BT_FIELD_CLASS_BLOB_SET_MEDIA_TYPE_STATUS_OK
+    Success.
+@retval #BT_FIELD_CLASS_BLOB_SET_MEDIA_TYPE_STATUS_MEMORY_ERROR
+    Out of memory.
+
+@bt_pre_not_null{field_class}
+@bt_pre_hot{field_class}
+@bt_pre_is_blob_fc{field_class}
+@bt_pre_fc_with_mip{field_class, 1}
+
+@sa bt_field_class_blob_get_media_type() &mdash;
+    Returns the IANA media type of BLOB field class.
+*/
+extern bt_field_class_blob_set_media_type_status
+bt_field_class_blob_set_media_type(bt_field_class *field_class,
+               const char *media_type) __BT_NOEXCEPT;
+
+/*!
+@brief
+    Returns the IANA media type of the \bt_blob_fc \bt_p{field_class}.
+
+See the \ref api-tir-fc-blob-prop-media-type "media type" property.
+
+If \bt_p{field_class} has no media type, this function returns \c NULL.
+
+@param[in] field_class
+    BLOB field class of which to get the media type.
+
+@returns
+    @parblock
+    Media type of \bt_p{field_class}, 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_blob_fc{field_class}
+@bt_pre_fc_with_mip{field_class, 1}
+
+@sa bt_field_class_blob_set_media_type() &mdash;
+    Sets the media type of a BLOB field class.
+*/
+extern const char *bt_field_class_blob_get_media_type(
+               const bt_field_class *field_class) __BT_NOEXCEPT;
+
+/*! @} */
+
 /*!
 @name Array field class
 @{
index 2e5c54f2614d9a873ec9e6c07fba159dbdff588e..0b43c382608843cb73d8a2efc626c2d6ca0f393e 100644 (file)
@@ -43,6 +43,9 @@ given \bt_field from a given <em>root scope</em>.
 
 A field location indicates how to reach:
 
+- The length field of a \bt_dblob_field
+  (instances with a linked length field).
+
 - The length field of a \bt_darray_field
   (instances with a linked length field).
 
index dc3934392e08b980d8ea7c084acf2be4ff8bc4ce..8ded107513666b6a3acacf327fbc67bef37228f1 100644 (file)
@@ -56,6 +56,7 @@ categories:
     - \ref api-tir-field-enum "Enumeration" (unsigned and signed)
     - \ref api-tir-field-real "Real" (single-precision and double-precision)
     - \ref api-tir-field-string "String"
+    - \ref api-tir-field-blob "BLOB" (static and dynamic)
   </dd>
 
   <dt>Container</dt>
@@ -311,6 +312,48 @@ bt_field_string_append() and bt_field_string_append_with_length().
 
 Clear a string field with bt_field_string_clear().
 
+<h1>\anchor api-tir-field-blob BLOB fields</h1>
+
+<strong><em>BLOB fields</em></strong> are \bt_blob_fc instances.
+
+BLOB fields contain zero or more bytes of binary data.
+
+@note
+    BLOB fields are only available when the \bt_trace_cls from
+    which you create their classes was created from a \bt_comp
+    which belongs to a trace processing \bt_graph with the effective
+    \bt_mip version&nbsp;1.
+
+A BLOB field is an \em abstract field. The concrete BLOB fields are:
+
+<dl>
+  <dt>Static BLOB field</dt>
+  <dd>
+    A \bt_sblob_fc instance.
+
+    A static BLOB field contains a fixed number of bytes. Its length
+    is \ref api-tir-fc-sblob-prop-len "given by its class".
+  </dd>
+
+  <dt>Dynamic BLOB field</dt>
+  <dd>
+    A \bt_dblob_fc instance.
+
+    A dynamic BLOB field contains a variable number of bytes, that is,
+    each instance of the same dynamic BLOB field class can contain a
+    different number of bytes.
+
+    Set a dynamic BLOB field's length with
+    bt_field_blob_dynamic_set_length() before you get its data
+    with bt_field_blob_get_data().
+  </dd>
+</dl>
+
+Get a BLOB field's length with bt_field_blob_get_length().
+
+Get the data of a BLOB field with bt_field_blob_get_data()
+or bt_field_blob_get_data_const().
+
 <h1>\anchor api-tir-field-array Array fields</h1>
 
 <strong><em>Array fields</em></strong> are \bt_array_fc instances.
@@ -328,7 +371,7 @@ An array field is an \em abstract field. The concrete array fields are:
     is \ref api-tir-fc-sarray-prop-len "given by its class".
   </dd>
 
-  <dt>Dynamic array field class</dt>
+  <dt>Dynamic array field</dt>
   <dd>
     A \bt_darray_fc instance.
 
@@ -1074,6 +1117,122 @@ extern void bt_field_string_clear(bt_field *field) __BT_NOEXCEPT;
 
 /*! @} */
 
+/*!
+@name BLOB field
+@{
+*/
+
+/*!
+@brief
+    Returns the length (number of bytes) of the \bt_blob_field \bt_p{field}.
+
+@param[in] field
+    BLOB field of which to get the length.
+
+@returns
+    Length of \bt_p{field}.
+
+@bt_pre_not_null{field}
+@bt_pre_is_blob_field{field}
+@bt_pre_field_with_mip{field, 1}
+*/
+extern uint64_t bt_field_blob_get_length(const bt_field *field);
+
+/*!
+@brief
+    Returns the writable data of the \bt_blob_field \bt_p{field}.
+
+@attention
+    If \bt_p{field} is a dynamic BLOB field, then it must have a length
+    (call bt_field_blob_dynamic_set_length()) before you call this
+    function.
+
+@param[in] field
+    BLOB field from which to get the writable data.
+
+@returns
+    @parblock
+    Writable data of \bt_p{field}.
+
+    The returned pointer remains valid until \bt_p{field} is modified.
+    @endparblock
+
+@bt_pre_not_null{field}
+@bt_pre_is_blob_field{field}
+@bt_pre_hot{field}
+@bt_pre_field_with_mip{field, 1}
+
+@sa bt_field_blob_get_data_const() &mdash;
+    Returns the readable data of a BLOB field.
+*/
+extern uint8_t *bt_field_blob_get_data(bt_field *field);
+
+/*!
+@brief
+    Returns the readable data of the \bt_blob_field \bt_p{field}.
+
+@param[in] field
+    BLOB field from which to get the readable data.
+
+@returns
+    @parblock
+    Readable data of \bt_p{field}.
+
+    The returned pointer remains valid until \bt_p{field} is modified.
+    @endparblock
+
+@bt_pre_not_null{field}
+@bt_pre_is_blob_field{field}
+@bt_pre_field_with_mip{field, 1}
+
+@sa bt_field_blob_get_data() &mdash;
+    Returns the writable data of a BLOB field.
+*/
+extern const uint8_t *bt_field_blob_get_data_const(const bt_field *field);
+
+/*!
+@brief
+    Status codes for bt_field_blob_dynamic_set_length().
+*/
+typedef enum bt_field_blob_dynamic_set_length_status {
+       /*!
+       @brief
+           Success.
+       */
+       BT_FIELD_DYNAMIC_BLOB_SET_LENGTH_STATUS_OK              = __BT_FUNC_STATUS_OK,
+
+       /*!
+       @brief
+           Out of memory.
+       */
+       BT_FIELD_DYNAMIC_BLOB_SET_LENGTH_STATUS_MEMORY_ERROR    = __BT_FUNC_STATUS_MEMORY_ERROR,
+} bt_field_blob_dynamic_set_length_status;
+
+/*!
+@brief
+    Sets the length (number of bytes) of the
+    \bt_dblob_field \bt_p{field}.
+
+@param[in] field
+    Dynamic BLOB field of which to set the length (number of bytes).
+@param[in] length
+    New length of \bt_p{field}.
+
+@retval #BT_FIELD_DYNAMIC_BLOB_SET_LENGTH_STATUS_OK
+    Success.
+@retval #BT_FIELD_DYNAMIC_BLOB_SET_LENGTH_STATUS_MEMORY_ERROR
+    Out of memory.
+
+@bt_pre_not_null{field}
+@bt_pre_is_dblob_field{field}
+@bt_pre_hot{field}
+@bt_pre_field_with_mip{field, 1}
+*/
+extern bt_field_blob_dynamic_set_length_status bt_field_blob_dynamic_set_length(
+               bt_field *field, uint64_t length);
+
+/*! @} */
+
 /*!
 @name Array field
 @{
@@ -1100,7 +1259,7 @@ extern uint64_t bt_field_array_get_length(const bt_field *field) __BT_NOEXCEPT;
     \bt_p{field}.
 
 @attention
-    If \bt_p{field} is a dynamic array field, it must have a length
+    If \bt_p{field} is a dynamic array field, then it must have a length
     (call bt_field_array_dynamic_set_length()) before you call this
     function.
 
index 39a4fd77ac5b8a27e164c4d31a757bd4385a5882..4c91dfd649c200d51045f017cf083c5f52c4bb19 100644 (file)
@@ -436,6 +436,16 @@ const char *bt_common_field_class_type_string(enum bt_field_class_type class_typ
                return "VARIANT_WITH_UNSIGNED_INTEGER_SELECTOR_FIELD";
        case BT_FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_INTEGER_SELECTOR_FIELD:
                return "VARIANT_WITH_SIGNED_INTEGER_SELECTOR_FIELD";
+       case BT_FIELD_CLASS_TYPE_BLOB:
+               return "BT_FIELD_CLASS_TYPE_BLOB";
+       case BT_FIELD_CLASS_TYPE_STATIC_BLOB:
+               return "BT_FIELD_CLASS_TYPE_STATIC_BLOB";
+       case BT_FIELD_CLASS_TYPE_DYNAMIC_BLOB:
+               return "BT_FIELD_CLASS_TYPE_DYNAMIC_BLOB";
+       case BT_FIELD_CLASS_TYPE_DYNAMIC_BLOB_WITHOUT_LENGTH_FIELD:
+               return "BT_FIELD_CLASS_TYPE_DYNAMIC_BLOB_WITHOUT_LENGTH_FIELD";
+       case BT_FIELD_CLASS_TYPE_DYNAMIC_BLOB_WITH_LENGTH_FIELD:
+               return "BT_FIELD_CLASS_TYPE_DYNAMIC_BLOB_WITH_LENGTH_FIELD";
        case __BT_FIELD_CLASS_TYPE_BIG_VALUE:
                bt_common_abort ();
        }
index 93072f781c01ba2790644fa9621681b1a097de53..368164dd77d3f82baf260147271b20d96cdd5a75 100644 (file)
 #define _BT_ASSERT_PRE_FC_IS_VARIANT_WITH_SEL_ID(_fc_id)               \
        "is-variant-field-class-with-selector:" _fc_id
 
+#define _BT_ASSERT_PRE_FC_IS_BLOB_ID(_fc_id)                           \
+       "is-blob-field-class:" _fc_id
+
+#define _BT_ASSERT_PRE_FC_IS_BLOB_COND(_fc)                            \
+       bt_field_class_type_is((_fc)->type, BT_FIELD_CLASS_TYPE_BLOB)
+
+#define _BT_ASSERT_PRE_FC_IS_BLOB_FMT(_name)   \
+       _name " is not a BLOB field class: %![fc-]+F"
+
 #define _BT_ASSERT_PRE_FC_HAS_TYPE_COND(_fc, _type)                    \
        (((const struct bt_field_class *) (_fc))->type == (_type))
 
                _BT_ASSERT_PRE_FC_IS_VARIANT_WITH_SEL_COND(_fc),        \
                _BT_ASSERT_PRE_FC_IS_VARIANT_WITH_SEL_FMT(_name), (_fc))
 
+#define BT_ASSERT_PRE_FC_IS_BLOB(_fc_id, _fc, _name)           \
+       BT_ASSERT_PRE(                                          \
+               _BT_ASSERT_PRE_FC_IS_BLOB_ID(_fc_id),           \
+               _BT_ASSERT_PRE_FC_IS_BLOB_COND(_fc),            \
+               _BT_ASSERT_PRE_FC_IS_BLOB_FMT(_name), (_fc))
+
 #define BT_ASSERT_PRE_FC_HAS_TYPE_FROM_FUNC(_func, _fc_id, _fc, _type_id, _type, _name) \
        BT_ASSERT_PRE_FROM_FUNC(_func,                                  \
                _BT_ASSERT_PRE_FC_HAS_TYPE_ID(_fc_id, _type_id),                \
                ((const struct bt_field *) (_field))->class->type == BT_FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_INTEGER_SELECTOR_FIELD, \
                _name " is not a variant field: %![field-]+f", (_field))
 
+#define BT_ASSERT_PRE_DEV_FIELD_IS_BLOB(_field_id, _field, _name)                      \
+       BT_ASSERT_PRE_DEV(                                                              \
+               "is-blob-field:" _field_id,                                             \
+               bt_field_class_type_is(_field->class->type, BT_FIELD_CLASS_TYPE_BLOB),  \
+               _name "is not a BLOB field: %![field-]+f", (_field))
+
+#define BT_ASSERT_PRE_DEV_FIELD_IS_DYNAMIC_BLOB(_field_id, _field, _name)                      \
+       BT_ASSERT_PRE_DEV(                                                                      \
+               "is-dynamic-blob-field:" _field_id,                                             \
+               bt_field_class_type_is(_field->class->type, BT_FIELD_CLASS_TYPE_DYNAMIC_BLOB),  \
+               _name "is not a dynamic BLOB field: %![field-]+f", (_field))
+
 #define BT_ASSERT_PRE_DEV_FIELD_IS_SET(_field_id, _field)              \
        BT_ASSERT_PRE_DEV("is-field-set:" _field_id,                    \
                bt_field_is_set(_field),                                \
index 2a8f500919f530ddf5be2bd5c958eaf163de0e3c..9128645886930554e5d62262ec0a38d29ec12fe9 100644 (file)
@@ -155,6 +155,13 @@ static inline void format_array_field_class(char **buf_ch, const char *prefix,
                PRFIELD(bt_common_field_class_type_string(array_fc->element_fc->type)));
 }
 
+static inline void format_blob_field_class(char **buf_ch, const char *prefix,
+               const struct bt_field_class_blob *field_class)
+{
+       BUF_APPEND(", %smedia-type=\"%s\"",
+               PRFIELD(field_class->media_type->str));
+}
+
 static inline void format_field_class(char **buf_ch, bool extended,
                const char *prefix, const struct bt_field_class *field_class)
 {
@@ -334,6 +341,33 @@ static inline void format_field_class(char **buf_ch, bool extended,
 
                break;
        }
+       case BT_FIELD_CLASS_TYPE_STATIC_BLOB:
+       {
+               const struct bt_field_class_blob_static *blob_fc =
+                       (const void *) field_class;
+
+               format_blob_field_class(buf_ch, prefix, (const void *) blob_fc);
+               BUF_APPEND(", %slength=%" PRIu64, PRFIELD(blob_fc->length));
+               break;
+       }
+       case BT_FIELD_CLASS_TYPE_DYNAMIC_BLOB_WITHOUT_LENGTH_FIELD:
+       case BT_FIELD_CLASS_TYPE_DYNAMIC_BLOB_WITH_LENGTH_FIELD:
+       {
+               const struct bt_field_class_blob_dynamic *blob_fc =
+                       (const void *) field_class;
+
+               format_blob_field_class(buf_ch, prefix, (const void *) blob_fc);
+
+               if (field_class->type == BT_FIELD_CLASS_TYPE_DYNAMIC_BLOB_WITH_LENGTH_FIELD) {
+                       BT_ASSERT(blob_fc->length_fl);
+                       SET_TMP_PREFIX("length-fl-");
+                       format_field_location(buf_ch, extended, tmp_prefix,
+                               blob_fc->length_fl);
+                       break;
+               }
+
+               break;
+       }
        default:
                break;
        }
index 07e35d9ac52d9e4e84089c78e5bf11392fe07bac..8188906178d919760342c9597c15f5d5cf710c79 100644 (file)
@@ -2854,6 +2854,252 @@ void bt_field_class_variant_option_set_user_attributes(
                user_attributes, __func__);
 }
 
+BT_EXPORT
+bt_field_class_blob_set_media_type_status bt_field_class_blob_set_media_type(
+               struct bt_field_class *fc, const char *media_type)
+{
+       struct bt_field_class_blob *fc_blob = (void *) fc;
+
+       BT_ASSERT_PRE_FC_NON_NULL(fc);
+       BT_ASSERT_PRE_FC_IS_BLOB("field-class", fc, "Field class");
+       BT_ASSERT_PRE_DEV_FC_HOT(fc);
+       BT_ASSERT_PRE_NON_NULL("media-type", media_type, "Media type");
+
+       g_string_assign(fc_blob->media_type, media_type);
+
+       return BT_FIELD_CLASS_BLOB_SET_MEDIA_TYPE_STATUS_OK;
+}
+
+BT_EXPORT
+const char *bt_field_class_blob_get_media_type(
+               const bt_field_class *fc)
+{
+       struct bt_field_class_blob *fc_blob = (void *) fc;
+
+       BT_ASSERT_PRE_FC_NON_NULL(fc);
+       BT_ASSERT_PRE_FC_IS_BLOB("field-class", fc, "Field class");
+
+       return fc_blob->media_type->str;
+}
+
+static
+int init_blob_field_class(struct bt_field_class_blob *fc,
+               enum bt_field_class_type type,
+               bt_object_release_func release_func,
+               bt_trace_class *trace_class)
+{
+       int ret;
+
+       ret = init_field_class((void *) fc, type, release_func,
+               trace_class);
+       if (ret) {
+               goto end;
+       }
+
+       fc->media_type = g_string_new("application/octet-stream");
+
+end:
+       return ret;
+}
+
+static
+void destroy_blob_field_class(struct bt_object *obj)
+{
+       struct bt_field_class_blob *blob = (void *) obj;
+
+       BT_ASSERT(obj);
+       g_string_free(blob->media_type, TRUE);
+       finalize_field_class((void *) obj);
+       g_free(obj);
+}
+
+static
+void destroy_static_blob_field_class(struct bt_object *obj)
+{
+       struct bt_field_class_blob_static *fc = (void *) obj;
+
+       BT_ASSERT(fc);
+       BT_LIB_LOGD("Destroying static BLOB field class object: %!+F", fc);
+
+       destroy_blob_field_class(obj);
+}
+
+BT_EXPORT
+struct bt_field_class *bt_field_class_blob_static_create(
+               struct bt_trace_class *trace_class, uint64_t length)
+{
+       struct bt_field_class_blob_static *blob_fc = NULL;
+       int ret;
+
+       BT_ASSERT_PRE_NO_ERROR();
+       BT_ASSERT_PRE_TC_NON_NULL(trace_class);
+       BT_ASSERT_PRE_TC_MIP_VERSION_GE(trace_class, 1);
+
+       BT_LOGD_STR("Creating default static BLOB field class object.");
+       blob_fc = g_new0(struct bt_field_class_blob_static, 1);
+       if (!blob_fc) {
+               BT_LIB_LOGE_APPEND_CAUSE(
+                       "Failed to allocate one static BLOB field class.");
+               goto error;
+       }
+
+       ret = init_blob_field_class((void *) blob_fc,
+               BT_FIELD_CLASS_TYPE_STATIC_BLOB,
+               destroy_static_blob_field_class,
+               trace_class);
+       if (ret) {
+               goto end;
+       }
+
+       blob_fc->length = length;
+       BT_LIB_LOGD("Created static BLOB field class object: %!+F", blob_fc);
+       goto end;
+
+error:
+       BT_OBJECT_PUT_REF_AND_RESET(blob_fc);
+
+end:
+       return (void *) blob_fc;
+}
+
+BT_EXPORT
+uint64_t bt_field_class_blob_static_get_length(
+               const bt_field_class *fc)
+{
+       const struct bt_field_class_blob_static *blob_fc = (const void *) fc;
+
+       BT_ASSERT_PRE_DEV_FC_NON_NULL(fc);
+       BT_ASSERT_PRE_DEV_FC_HAS_TYPE("field-class", fc,
+               "static-blob-field-class", BT_FIELD_CLASS_TYPE_STATIC_BLOB,
+               "Field class");
+
+       return blob_fc->length;
+}
+
+static
+void destroy_dynamic_blob_field_class(struct bt_object *obj)
+{
+       struct bt_field_class_blob_dynamic *fc = (void *) obj;
+
+       BT_ASSERT(fc);
+       BT_LIB_LOGD("Destroying dynamic BLOB field class object: %!+F", fc);
+
+       bt_object_put_ref(fc->length_fl);
+       fc->length_fl = NULL;
+
+       destroy_blob_field_class(obj);
+}
+
+static
+struct bt_field_class_blob_dynamic *create_dynamic_blob_field_class(
+               struct bt_trace_class *trace_class, enum bt_field_class_type type)
+{
+       struct bt_field_class_blob_dynamic *blob_fc = NULL;
+       int ret;
+
+       BT_LOGD_STR("Creating default dynamic BLOB field class object.");
+       blob_fc = g_new0(struct bt_field_class_blob_dynamic, 1);
+       if (!blob_fc) {
+               BT_LIB_LOGE_APPEND_CAUSE(
+                       "Failed to allocate one dynamic BLOB field class.");
+               goto error;
+       }
+
+       ret = init_blob_field_class((void *) blob_fc, type,
+               destroy_dynamic_blob_field_class, trace_class);
+       if (ret) {
+               goto error;
+       }
+
+       goto end;
+
+error:
+       BT_OBJECT_PUT_REF_AND_RESET(blob_fc);
+
+end:
+       return blob_fc;
+}
+
+BT_EXPORT
+struct bt_field_class *bt_field_class_blob_dynamic_without_length_field_location_create(
+               struct bt_trace_class *trace_class)
+{
+       struct bt_field_class_blob_dynamic *blob_fc = NULL;
+
+       BT_ASSERT_PRE_NO_ERROR();
+       BT_ASSERT_PRE_TC_NON_NULL(trace_class);
+       BT_ASSERT_PRE_TC_MIP_VERSION_GE(trace_class, 1);
+
+       blob_fc = create_dynamic_blob_field_class(trace_class,
+               BT_FIELD_CLASS_TYPE_DYNAMIC_BLOB_WITHOUT_LENGTH_FIELD);
+       if (!blob_fc) {
+               goto error;
+       }
+
+       BT_LIB_LOGD("Created dynamic BLOB field class without field location object: %!+F",
+               blob_fc);
+
+       goto end;
+
+error:
+       BT_OBJECT_PUT_REF_AND_RESET(blob_fc);
+
+end:
+       return (void *) blob_fc;
+}
+
+BT_EXPORT
+struct bt_field_class *bt_field_class_blob_dynamic_with_length_field_location_create(
+               bt_trace_class *trace_class,
+               const bt_field_location *length_field_location)
+{
+       struct bt_field_class_blob_dynamic *blob_fc = NULL;
+
+       BT_ASSERT_PRE_NO_ERROR();
+       BT_ASSERT_PRE_TC_NON_NULL(trace_class);
+       BT_ASSERT_PRE_FL_NON_NULL(length_field_location);
+       BT_ASSERT_PRE_TC_MIP_VERSION_GE(trace_class, 1);
+
+       blob_fc = create_dynamic_blob_field_class(trace_class,
+               BT_FIELD_CLASS_TYPE_DYNAMIC_BLOB_WITH_LENGTH_FIELD);
+       if (!blob_fc) {
+               goto error;
+       }
+
+       blob_fc->length_fl = length_field_location;
+       bt_object_get_ref_no_null_check(length_field_location);
+
+       BT_LIB_LOGD("Created dynamic BLOB field class with field location object: %!+F",
+               blob_fc);
+
+       goto end;
+
+error:
+       BT_OBJECT_PUT_REF_AND_RESET(blob_fc);
+
+end:
+       return (void *) blob_fc;
+}
+
+BT_EXPORT
+const bt_field_location *
+bt_field_class_blob_dynamic_with_length_field_borrow_length_field_location_const(
+               const bt_field_class *fc)
+{
+       const struct bt_field_class_blob_dynamic *blob_fc = (const void *) fc;
+
+       BT_ASSERT_PRE_NO_ERROR();
+       BT_ASSERT_PRE_FC_NON_NULL(fc);
+       BT_ASSERT_PRE_FC_HAS_TYPE("field-class", fc,
+               "dynamic-blob-field-class-with-length-field",
+               BT_FIELD_CLASS_TYPE_DYNAMIC_BLOB_WITH_LENGTH_FIELD,
+               "Field class");
+       BT_ASSERT_PRE_FC_MIP_VERSION_GE(fc, 1);
+       BT_ASSERT(blob_fc->length_fl);
+
+       return blob_fc->length_fl;
+}
+
 BT_EXPORT
 void bt_field_class_get_ref(const struct bt_field_class *field_class)
 {
index a763d6c6b4d3cdc9e356086a607b012225d9dbfc..32209ab98fa81e4a6f11fa9e43cd8d5f0bb11871 100644 (file)
@@ -267,6 +267,22 @@ struct bt_field_class_variant_with_selector_field {
        } selector_field;
 };
 
+struct bt_field_class_blob {
+       struct bt_field_class common;
+
+       GString *media_type;
+};
+
+struct bt_field_class_blob_static {
+       struct bt_field_class_blob common;
+       uint64_t length;
+};
+
+struct bt_field_class_blob_dynamic {
+       struct bt_field_class_blob common;
+       const struct bt_field_location *length_fl;
+};
+
 void _bt_field_class_freeze(const struct bt_field_class *field_class);
 
 #ifdef BT_DEV_MODE
index 8110e58acc80749adfb8352acec7768fd87860a2..19cb7971933abb350012fdecea0356c9beb8326e 100644 (file)
@@ -134,6 +134,13 @@ struct bt_field_methods variant_field_methods = {
        .reset = reset_variant_field,
 };
 
+static
+struct bt_field_methods blob_field_methods = {
+       .set_is_frozen = set_single_field_is_frozen,
+       .is_set = single_field_is_set,
+       .reset = reset_single_field,
+};
+
 static
 struct bt_field *create_bool_field(struct bt_field_class *);
 
@@ -164,6 +171,9 @@ struct bt_field *create_option_field(struct bt_field_class *);
 static
 struct bt_field *create_variant_field(struct bt_field_class *);
 
+static
+struct bt_field *create_blob_field(struct bt_field_class *);
+
 static
 void destroy_bool_field(struct bt_field *field);
 
@@ -191,6 +201,9 @@ void destroy_option_field(struct bt_field *field);
 static
 void destroy_variant_field(struct bt_field *field);
 
+static
+void destroy_blob_field(struct bt_field *field);
+
 BT_EXPORT
 struct bt_field_class *bt_field_borrow_class(struct bt_field *field)
 {
@@ -260,6 +273,11 @@ struct bt_field *bt_field_create(struct bt_field_class *fc)
        case BT_FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_INTEGER_SELECTOR_FIELD:
                field = create_variant_field(fc);
                break;
+       case BT_FIELD_CLASS_TYPE_STATIC_BLOB:
+       case BT_FIELD_CLASS_TYPE_DYNAMIC_BLOB_WITHOUT_LENGTH_FIELD:
+       case BT_FIELD_CLASS_TYPE_DYNAMIC_BLOB_WITH_LENGTH_FIELD:
+               field = create_blob_field(fc);
+               break;
        default:
                bt_common_abort();
        }
@@ -527,6 +545,43 @@ end:
        return (void *) var_field;
 }
 
+static
+struct bt_field *create_blob_field(struct bt_field_class *fc)
+{
+       struct bt_field_blob *blob_field;
+
+       BT_LIB_LOGD("Creating BLOB field object: %![fc-]+F", fc);
+       blob_field = g_new0(struct bt_field_blob, 1);
+       if (!blob_field) {
+               BT_LIB_LOGE_APPEND_CAUSE(
+                       "Failed to allocate one BLOB field.");
+               goto end;
+       }
+
+       init_field((void *) blob_field, fc, &blob_field_methods);
+
+       if (bt_field_class_type_is(fc->type, BT_FIELD_CLASS_TYPE_STATIC_BLOB)) {
+               struct bt_field_class_blob_static *blob_static_fc =
+                       (void *) fc;
+               blob_field->length = blob_static_fc->length;
+               blob_field->data = g_malloc(blob_field->length);
+               if (!blob_field->data) {
+                       BT_LIB_LOGE_APPEND_CAUSE(
+                               "Failed to allocate BLOB field data: %![fc-]+F",
+                               fc);
+                       goto error;
+               }
+       }
+
+       goto end;
+error:
+       bt_field_destroy((void *) blob_field);
+       blob_field = NULL;
+
+end:
+       return (void *) blob_field;
+}
+
 static inline
 int init_array_field_fields(struct bt_field_array *array_field)
 {
@@ -1290,6 +1345,81 @@ uint64_t bt_field_variant_get_selected_option_index(
        return var_field->selected_index;
 }
 
+BT_EXPORT
+uint8_t *bt_field_blob_get_data(struct bt_field *field)
+{
+       const struct bt_field_blob *blob_field = (const void *) field;
+
+       BT_ASSERT_PRE_DEV_FIELD_NON_NULL(field);
+       BT_ASSERT_PRE_DEV_FIELD_IS_BLOB("field", field, "Field");
+       BT_ASSERT_PRE_DEV_FIELD_HOT(field);
+       BT_ASSERT_PRE_DEV("blob-field-length-is-set",
+               blob_field->length > 0,
+               "BLOB field length is not set: %!+f", field);
+
+       /* Assume that the user will fill the bytes. */
+       bt_field_set_single(field, true);
+
+       return blob_field->data;
+}
+
+BT_EXPORT
+const uint8_t *bt_field_blob_get_data_const(const struct bt_field *field)
+{
+       const struct bt_field_blob *blob_field = (const void *) field;
+
+       BT_ASSERT_PRE_DEV_FIELD_NON_NULL(field);
+       BT_ASSERT_PRE_DEV_FIELD_IS_BLOB("field", field, "Field");
+
+       return blob_field->data;
+}
+
+BT_EXPORT
+enum bt_field_blob_dynamic_set_length_status bt_field_blob_dynamic_set_length(
+               struct bt_field *field, uint64_t length)
+{
+       int ret;
+       struct bt_field_blob *blob_field = (void *) field;
+
+       BT_ASSERT_PRE_DEV_NO_ERROR();
+       BT_ASSERT_PRE_DEV_FIELD_NON_NULL(field);
+       BT_ASSERT_PRE_DEV_FIELD_IS_DYNAMIC_BLOB("field", field, "Field");
+       BT_ASSERT_PRE_DEV_FIELD_HOT(field);
+
+       if (G_UNLIKELY(length > blob_field->length)) {
+               /* Make more room */
+               uint8_t *data = g_realloc(blob_field->data, length);
+
+               if (!data) {
+                       BT_LIB_LOGE_APPEND_CAUSE(
+                               "Failed to reallocate BLOB field data: %!+f",
+                               field);
+                       ret = BT_FIELD_DYNAMIC_BLOB_SET_LENGTH_STATUS_MEMORY_ERROR;
+                       goto end;
+               }
+
+               blob_field->data = data;
+       }
+
+       blob_field->length = length;
+       ret = BT_FIELD_DYNAMIC_BLOB_SET_LENGTH_STATUS_OK;
+
+end:
+       return ret;
+}
+
+BT_EXPORT
+uint64_t bt_field_blob_get_length(const struct bt_field *field)
+{
+       const struct bt_field_blob *blob_field = (const void *) field;
+
+       BT_ASSERT_PRE_DEV_FIELD_NON_NULL(field);
+       BT_ASSERT_PRE_DEV_FIELD_IS_BLOB("field", field, "Field");
+
+       return blob_field->length;
+}
+
+
 static inline
 void bt_field_finalize(struct bt_field *field)
 {
@@ -1384,6 +1514,20 @@ void destroy_variant_field(struct bt_field *field)
        g_free(field);
 }
 
+static
+void destroy_blob_field(struct bt_field *field)
+{
+       struct bt_field_blob *blob_field = (void *) field;
+
+       BT_ASSERT(field);
+       BT_LIB_LOGD("Destroying BLOB field object: %!+f", field);
+       bt_field_finalize(field);
+
+       g_free(blob_field->data);
+
+       g_free(field);
+}
+
 static
 void destroy_array_field(struct bt_field *field)
 {
@@ -1461,6 +1605,11 @@ void bt_field_destroy(struct bt_field *field)
        case BT_FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_INTEGER_SELECTOR_FIELD:
                destroy_variant_field(field);
                break;
+       case BT_FIELD_CLASS_TYPE_STATIC_BLOB:
+       case BT_FIELD_CLASS_TYPE_DYNAMIC_BLOB_WITHOUT_LENGTH_FIELD:
+       case BT_FIELD_CLASS_TYPE_DYNAMIC_BLOB_WITH_LENGTH_FIELD:
+               destroy_blob_field(field);
+               break;
        default:
                bt_common_abort();
        }
index bf90380a6b6951def2aee37b773241348bf4c279..c52bc25d60c37bae2ae4183a02968182769292f0 100644 (file)
@@ -96,6 +96,13 @@ struct bt_field_variant {
        GPtrArray *fields;
 };
 
+struct bt_field_blob {
+       struct bt_field common;
+
+       uint64_t length;
+       uint8_t *data;
+};
+
 struct bt_field_array {
        struct bt_field common;
 
This page took 0.040742 seconds and 4 git commands to generate.