Split CTF IR and CTF writer APIs and implementations
authorPhilippe Proulx <eeppeliteloop@gmail.com>
Sat, 7 Apr 2018 17:20:16 +0000 (13:20 -0400)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Fri, 3 May 2019 22:19:33 +0000 (18:19 -0400)
This patch splits the CTF IR and CTF writer APIs, previously implemented
at a single place with aliases to make CTF writer functions and types be
synonymous to CTF IR ones, with as much common code as possible for both
APIs.

The goal of this change is to be able to modify one API/implementation
without disturbing the other, optimization being one major use case.

Common API
==========
Most of the CTF IR and CTF writer functions perform the exact same
tasks. Some functions, however, have minor differences. For example,
bt_trace_add_stream_class() tries to automatically map specific integer
field types to the stream class's CTF writer clock's class if the trace
object was created by a CTF writer object.

To keep as much common code as possible, `struct bt_*_common` types and
bt_*_common() functions are introduced. A common structure contains the
common data needed for both CTF IR and CTF writer, while actual
CTF IR/writer structures "inherit" this one. For example:

    struct bt_stream_common {
        struct bt_object base;
        int64_t id;
        struct bt_stream_class_common *stream_class;
        GString *name;
        GArray *destroy_listeners;
    };

    struct bt_stream {
        struct bt_stream_common common;
    };

    struct bt_ctf_stream {
        struct bt_stream_common common;
        struct bt_ctf_field *packet_header;
        struct bt_ctf_field *packet_context;
        GPtrArray *events;
        struct bt_ctf_stream_pos pos;
        unsigned int flushed_packet_count;
        uint64_t discarded_events;
        uint64_t size;
        uint64_t last_ts_end;
    };

All bt_stream_common_*() functions require a pointer to
`struct bt_stream_common`. You can use the BT_TO_COMMON() and
BT_FROM_COMMON() macros of `include/babeltrace/ctf-ir/utils-internal.h`
to statically cast the pointers in each direction. BT_TO_COMMON() needs
the concrete (non-common) structure to have a common structure member
named `common`.

A concrete implementation is responsible for the allocation and
deallocation of its objects, but the common API provides internal
functions to initialize and finalize the common parts. Examples are
bt_event_common_initialize(), bt_event_class_common_finalize(), and
bt_field_type_common_floating_point_initialize(). Those initialization
functions take a `release_func` parameter which is the concrete object
destruction function. The latter is responsible for finalizing the
specific part, calling bt_*_common_finalize() to finalize the common
part, and deallocating the object.

Most of the concrete functions look like this:

    struct bt_field_type *bt_event_class_get_payload_field_type(
            struct bt_event_class *event_class)
    {
        return BT_FROM_COMMON(bt_event_class_common_get_payload_field_type(
            BT_TO_COMMON(event_class)));
    }

Some common functions are more complicated and can be considered
template methods: they take various options and callback functions to be
called at specific places within the procedure.
bt_event_common_initialize() and bt_trace_common_add_stream_class() are
obvious examples.

The cases of field types and fields are special because those structures
already use inheritance: an integer field type structure inherits the
field type structure. In order for all the APIs to be able to statically
cast to the appropriate types, here's how a concrete field type is
arranged:

    +------------------------------------+
    | Common field type                  | <- bt_field_type_common_*()
    +------------------------------------+
    | Concrete common field type (union) | <- bt_(ctf_)field_type_*()
    +------------------------------------+
    | Common specific field type         | <- bt_field_type_common_integer_*()
    +------------------------------------+
    | Specific field type                | <- bt_(ctf_)field_type_integer_*()
    +------------------------------------+

The four parts are at a fixed offset.

Field objects follow the same structure.

As of this patch, `struct bt_field_type`, `struct bt_ctf_field_type`,
`struct bt_field`, and `struct bt_ctf_field` are only forward-declared
and always `(void *)` casted to and from the appropriate common type for
public APIs because they don't add specific data. For example:

    int bt_ctf_field_type_set_alignment(struct bt_ctf_field_type *ft,
            unsigned int alignment)
    {
        return bt_field_type_common_set_alignment((void *) ft, alignment);
    }

Also of interest is `struct bt_ctf_clock_class` which includes
`struct bt_clock_class`: there's no `struct bt_clock_class_common`
because as of this patch we don't expect a CTF IR clock class property
to be absent from a CTF writer clock class.

As of this patch, the common API and implementation are in the same
source and header files as CTF IR. Fast path common functions (most
getters and almost everything related to fields and events) are
implemented in internal header files as `static inline` functions.

Logging
=======
BT_LIB_LOG(), and consequently BT_ASSERT_PRE() and its variants, is
modified with an added prefix character to distinguish a CTF IR object
from a CTF writer object and from a common object. The prefix character
is inserted just before the format specifier: `_` means a common object
(underscore as in low as in base), and `w` means a CTF writer object. No
prefix means a CTF IR or other object (graph objects, value objects,
etc.).

Using `%!+_t` with a CTF IR trace object, for example, is correct
because it inherits the common part, but using `%!+t` with a common
trace object could eventually lead to bad data or to a segmentation
fault.

See the updated description in
`include/babeltrace/lib-logging-internal.h` for more details.

Testing
=======
Some tests in `tests/lib` are modified because they used a mix of CTF IR
and CTF writer APIs. Also there is a new precondition that a CTF IR
event class must be part of a trace before you can create an event from
it (the CTF writer API does not have this restriction for backward
compatibility reasons): this guarantee could make things easier in the
future and it is acceptable for a CTF IR user.

Some CTF writer tests are removed because they were in fact CTF IR
tests. In the future we should create specific CTF IR tests and reuse
the removed tests.

Limitations
===========
This patch does not address, and reserves for future work:

* Python bindings
* Python bindings tests
* `src.ctf.lttng-live`, `sink.ctf.fs`, `flt.utils.trimmer`,
  `flt.lttng-utils.debug-info`, and `src.text.dmesg` component classes

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
99 files changed:
cli/Makefile.am
configure.ac
include/Makefile.am
include/babeltrace/babeltrace.h
include/babeltrace/common-internal.h
include/babeltrace/ctf-ir/clock-class-internal.h
include/babeltrace/ctf-ir/clock-class.h
include/babeltrace/ctf-ir/event-class-internal.h
include/babeltrace/ctf-ir/event-class.h
include/babeltrace/ctf-ir/event-internal.h
include/babeltrace/ctf-ir/event.h
include/babeltrace/ctf-ir/field-path-internal.h
include/babeltrace/ctf-ir/field-types-internal.h
include/babeltrace/ctf-ir/field-types.h
include/babeltrace/ctf-ir/fields-internal.h
include/babeltrace/ctf-ir/fields.h
include/babeltrace/ctf-ir/packet-internal.h
include/babeltrace/ctf-ir/resolve-internal.h
include/babeltrace/ctf-ir/stream-class-internal.h
include/babeltrace/ctf-ir/stream-class.h
include/babeltrace/ctf-ir/stream-internal.h
include/babeltrace/ctf-ir/stream.h
include/babeltrace/ctf-ir/trace-internal.h
include/babeltrace/ctf-ir/trace.h
include/babeltrace/ctf-ir/utils-internal.h
include/babeltrace/ctf-ir/utils.h
include/babeltrace/ctf-ir/validation-internal.h
include/babeltrace/ctf-writer/clock-class.h [new file with mode: 0644]
include/babeltrace/ctf-writer/clock-internal.h
include/babeltrace/ctf-writer/clock.h
include/babeltrace/ctf-writer/event-fields.h
include/babeltrace/ctf-writer/event-internal.h [new file with mode: 0644]
include/babeltrace/ctf-writer/event-types.h
include/babeltrace/ctf-writer/event.h
include/babeltrace/ctf-writer/field-types-internal.h [new file with mode: 0644]
include/babeltrace/ctf-writer/field-types.h [new file with mode: 0644]
include/babeltrace/ctf-writer/fields-internal.h [new file with mode: 0644]
include/babeltrace/ctf-writer/fields.h [new file with mode: 0644]
include/babeltrace/ctf-writer/functor-internal.h
include/babeltrace/ctf-writer/serialize-internal.h
include/babeltrace/ctf-writer/stream-class-internal.h [new file with mode: 0644]
include/babeltrace/ctf-writer/stream-class.h
include/babeltrace/ctf-writer/stream-internal.h [new file with mode: 0644]
include/babeltrace/ctf-writer/stream.h
include/babeltrace/ctf-writer/trace-internal.h [new file with mode: 0644]
include/babeltrace/ctf-writer/trace.h [new file with mode: 0644]
include/babeltrace/ctf-writer/writer-internal.h
include/babeltrace/ctf-writer/writer.h
include/babeltrace/lib-logging-internal.h
lib/ctf-ir/clock-class.c
lib/ctf-ir/event-class.c
lib/ctf-ir/event.c
lib/ctf-ir/field-types.c
lib/ctf-ir/fields.c
lib/ctf-ir/packet.c
lib/ctf-ir/resolve.c
lib/ctf-ir/stream-class.c
lib/ctf-ir/stream.c
lib/ctf-ir/trace.c
lib/ctf-ir/utils.c
lib/ctf-ir/validation.c
lib/ctf-writer/Makefile.am
lib/ctf-writer/clock.c
lib/ctf-writer/event-class.c [new file with mode: 0644]
lib/ctf-writer/event.c [new file with mode: 0644]
lib/ctf-writer/field-types.c [new file with mode: 0644]
lib/ctf-writer/fields.c [new file with mode: 0644]
lib/ctf-writer/functor.c
lib/ctf-writer/serialize.c
lib/ctf-writer/stream-class.c [new file with mode: 0644]
lib/ctf-writer/stream.c [new file with mode: 0644]
lib/ctf-writer/trace.c [new file with mode: 0644]
lib/ctf-writer/writer.c
lib/graph/iterator.c
lib/graph/notification/event.c
lib/graph/notification/packet.c
lib/graph/notification/stream.c
lib/lib-logging.c
plugins/Makefile.am
plugins/ctf/Makefile.am
plugins/ctf/common/btr/btr.c
plugins/ctf/common/metadata/visitor-generate-ir.c
plugins/ctf/common/notif-iter/notif-iter.c
plugins/ctf/common/utils/utils.c
plugins/ctf/fs-src/data-stream-file.c
plugins/ctf/fs-src/fs.c
plugins/ctf/fs-src/fs.h
plugins/ctf/plugin.c
plugins/text/Makefile.am
plugins/text/plugin.c
plugins/text/pretty/print.c
plugins/utils/Makefile.am
plugins/utils/plugin.c
tests/lib/test_bt_ctf_field_type_validation.c
tests/lib/test_bt_notification_iterator.c
tests/lib/test_ctf_ir_ref.c
tests/lib/test_ctf_writer.c
tests/lib/test_ir_visit.c
tests/plugins/test-utils-muxer.c

index ef5a19aacac0ce2c6d69e6c9034aa7823a07356f..8993c2f880a24a6ba095fc90cd0146d126e5e363 100644 (file)
@@ -45,7 +45,6 @@ babeltrace_bin_LDADD = \
        $(top_builddir)/compat/libcompat.la \
        $(top_builddir)/common/libbabeltrace-common.la \
        $(top_builddir)/logging/libbabeltrace-logging.la \
-       $(top_builddir)/plugins/libctfcopytrace/libctfcopytrace.la \
        $(POPT_LIBS)
 
 if ENABLE_BUILT_IN_PLUGINS
index 09092befb357bf4243ca6d5f2370129934bfab32..16d45c81f4cfe2f92c1d4691c64f8eac1e17b8c9 100644 (file)
@@ -68,7 +68,7 @@ m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
 ##                      ##
 
 MINGW32=no
-DEFAULT_ENABLE_DEBUG_INFO=yes
+DEFAULT_ENABLE_DEBUG_INFO=no
 LT_NO_UNDEFINED=""
 AS_CASE([$host_os],
   [solaris*|darwin*],
index a310b37ba30f2b2ea2cec561f500aa820f2ff255..3dd6eb81abf25037cf9da7a994ae37a104696267 100644 (file)
@@ -86,12 +86,16 @@ babeltracectfinclude_HEADERS = \
 # CTF writer API
 babeltracectfwriterincludedir = "$(includedir)/babeltrace/ctf-writer"
 babeltracectfwriterinclude_HEADERS = \
+       babeltrace/ctf-writer/clock-class.h \
        babeltrace/ctf-writer/clock.h \
        babeltrace/ctf-writer/event-fields.h \
-       babeltrace/ctf-writer/event-types.h \
        babeltrace/ctf-writer/event.h \
+       babeltrace/ctf-writer/event-types.h \
+       babeltrace/ctf-writer/fields.h \
+       babeltrace/ctf-writer/field-types.h \
        babeltrace/ctf-writer/stream-class.h \
        babeltrace/ctf-writer/stream.h \
+       babeltrace/ctf-writer/trace.h \
        babeltrace/ctf-writer/writer.h
 
 # CTF IR API
@@ -155,75 +159,82 @@ babeltracegraphinclude_HEADERS = \
        babeltrace/graph/query-executor.h
 
 noinst_HEADERS = \
-       babeltrace/align-internal.h \
-       babeltrace/assert-internal.h \
-       babeltrace/assert-pre-internal.h \
-       babeltrace/babeltrace-internal.h \
-       babeltrace/bitfield-internal.h \
-       babeltrace/common-internal.h \
+       babeltrace/compat/stdlib-internal.h \
        babeltrace/compat/fcntl-internal.h \
        babeltrace/compat/glib-internal.h \
-       babeltrace/compat/limits-internal.h \
-       babeltrace/compat/memstream-internal.h \
-       babeltrace/compat/mman-internal.h \
-       babeltrace/compat/socket-internal.h \
+       babeltrace/compat/uuid-internal.h \
+       babeltrace/compat/unistd-internal.h \
        babeltrace/compat/stdio-internal.h \
-       babeltrace/compat/stdlib-internal.h \
-       babeltrace/compat/string-internal.h \
        babeltrace/compat/time-internal.h \
-       babeltrace/compat/unistd-internal.h \
        babeltrace/compat/utc-internal.h \
-       babeltrace/compat/uuid-internal.h \
-       babeltrace/compiler-internal.h \
-       babeltrace/ctf-ir/attributes-internal.h \
-       babeltrace/ctf-ir/clock-class-internal.h \
-       babeltrace/ctf-ir/clock-value-internal.h \
+       babeltrace/compat/memstream-internal.h \
+       babeltrace/compat/string-internal.h \
+       babeltrace/compat/limits-internal.h \
+       babeltrace/compat/mman-internal.h \
+       babeltrace/compat/socket-internal.h \
+       babeltrace/common-internal.h \
+       babeltrace/bitfield-internal.h \
+       babeltrace/object-internal.h \
+       babeltrace/plugin/plugin-internal.h \
+       babeltrace/plugin/plugin-so-internal.h \
+       babeltrace/plugin/python-plugin-provider-internal.h \
+       babeltrace/assert-internal.h \
+       babeltrace/values-internal.h \
+       babeltrace/ctf-writer/fields-internal.h \
+       babeltrace/ctf-writer/stream-class-internal.h \
+       babeltrace/ctf-writer/event-internal.h \
+       babeltrace/ctf-writer/trace-internal.h \
+       babeltrace/ctf-writer/field-types-internal.h \
+       babeltrace/ctf-writer/serialize-internal.h \
+       babeltrace/ctf-writer/writer-internal.h \
+       babeltrace/ctf-writer/stream-internal.h \
+       babeltrace/ctf-writer/clock-internal.h \
+       babeltrace/ctf-writer/functor-internal.h \
+       babeltrace/mmap-align-internal.h \
+       babeltrace/align-internal.h \
+       babeltrace/logging-internal.h \
+       babeltrace/endian-internal.h \
+       babeltrace/ctf-ir/packet-internal.h \
        babeltrace/ctf-ir/event-class-internal.h \
+       babeltrace/ctf-ir/utils-internal.h \
+       babeltrace/ctf-ir/validation-internal.h \
+       babeltrace/ctf-ir/fields-internal.h \
+       babeltrace/ctf-ir/stream-class-internal.h \
        babeltrace/ctf-ir/event-internal.h \
        babeltrace/ctf-ir/field-path-internal.h \
+       babeltrace/ctf-ir/trace-internal.h \
+       babeltrace/ctf-ir/clock-class-internal.h \
        babeltrace/ctf-ir/field-types-internal.h \
-       babeltrace/ctf-ir/fields-internal.h \
-       babeltrace/ctf-ir/packet-internal.h \
-       babeltrace/ctf-ir/resolve-internal.h \
-       babeltrace/ctf-ir/stream-class-internal.h \
+       babeltrace/ctf-ir/clock-value-internal.h \
+       babeltrace/ctf-ir/attributes-internal.h \
        babeltrace/ctf-ir/stream-internal.h \
-       babeltrace/ctf-ir/trace-internal.h \
-       babeltrace/ctf-ir/validation-internal.h \
+       babeltrace/ctf-ir/resolve-internal.h \
        babeltrace/ctf-ir/visitor-internal.h \
-       babeltrace/ctf-ir/utils-internal.h \
-       babeltrace/ctf-writer/clock-internal.h \
-       babeltrace/ctf-writer/functor-internal.h \
-       babeltrace/ctf-writer/serialize-internal.h \
-       babeltrace/ctf-writer/writer-internal.h \
-       babeltrace/endian-internal.h \
-       babeltrace/graph/clock-class-priority-map-internal.h \
-       babeltrace/graph/component-class-internal.h \
-       babeltrace/graph/component-class-sink-colander-internal.h \
-       babeltrace/graph/component-filter-internal.h \
+       babeltrace/prio-heap-internal.h \
+       babeltrace/lib-logging-internal.h \
+       babeltrace/compiler-internal.h \
+       babeltrace/babeltrace-internal.h \
+       babeltrace/assert-pre-internal.h \
+       babeltrace/ref-internal.h \
        babeltrace/graph/component-internal.h \
-       babeltrace/graph/component-sink-internal.h \
-       babeltrace/graph/component-source-internal.h \
+       babeltrace/graph/notification-stream-internal.h \
        babeltrace/graph/connection-internal.h \
-       babeltrace/graph/graph-internal.h \
-       babeltrace/graph/notification-discarded-elements-internal.h \
        babeltrace/graph/notification-event-internal.h \
-       babeltrace/graph/notification-heap-internal.h \
+       babeltrace/graph/query-executor-internal.h \
+       babeltrace/graph/graph-internal.h \
+       babeltrace/graph/component-class-sink-colander-internal.h \
        babeltrace/graph/notification-inactivity-internal.h \
-       babeltrace/graph/notification-internal.h \
-       babeltrace/graph/notification-iterator-internal.h \
+       babeltrace/graph/notification-heap-internal.h \
+       babeltrace/graph/component-source-internal.h \
+       babeltrace/graph/notification-discarded-elements-internal.h \
        babeltrace/graph/notification-packet-internal.h \
-       babeltrace/graph/notification-stream-internal.h \
+       babeltrace/graph/notification-iterator-internal.h \
+       babeltrace/graph/notification-internal.h \
+       babeltrace/graph/component-filter-internal.h \
+       babeltrace/graph/component-class-internal.h \
+       babeltrace/graph/component-sink-internal.h \
        babeltrace/graph/port-internal.h \
-       babeltrace/graph/query-executor-internal.h \
-       babeltrace/lib-logging-internal.h \
+       babeltrace/graph/clock-class-priority-map-internal.h \
        babeltrace/list-internal.h \
-       babeltrace/logging-internal.h \
-       babeltrace/mmap-align-internal.h \
-       babeltrace/object-internal.h \
-       babeltrace/plugin/plugin-internal.h \
-       babeltrace/plugin/plugin-so-internal.h \
-       babeltrace/prio-heap-internal.h \
-       babeltrace/ref-internal.h \
-       babeltrace/values-internal.h \
        version.h \
        version.i
index f1a798df8de033bd6bf6ac69461e121fe75e0f0d..d59f36a105f23bfd5a520280a8e93f689d131f24 100644 (file)
 #include <babeltrace/ctf/events.h>
 
 /* CTF writer API */
+#include <babeltrace/ctf-writer/clock-class.h>
 #include <babeltrace/ctf-writer/clock.h>
 #include <babeltrace/ctf-writer/event-fields.h>
 #include <babeltrace/ctf-writer/event-types.h>
 #include <babeltrace/ctf-writer/event.h>
+#include <babeltrace/ctf-writer/field-types.h>
+#include <babeltrace/ctf-writer/fields.h>
 #include <babeltrace/ctf-writer/stream-class.h>
 #include <babeltrace/ctf-writer/stream.h>
+#include <babeltrace/ctf-writer/trace.h>
 #include <babeltrace/ctf-writer/writer.h>
 
 /* CTF IR API */
 #include <babeltrace/ctf-ir/clock-class.h>
 #include <babeltrace/ctf-ir/clock-value.h>
+#include <babeltrace/ctf-ir/clock.h>
 #include <babeltrace/ctf-ir/event-class.h>
 #include <babeltrace/ctf-ir/event.h>
 #include <babeltrace/ctf-ir/field-path.h>
index b6981b27a0125508fe79acd29a5ab8e575cedd6d..6428adda4a93d84e979c360e184d4f3b6a8e7a73 100644 (file)
@@ -2,8 +2,13 @@
 #define BABELTRACE_COMMON_INTERNAL_H
 
 #include <stdbool.h>
+#include <babeltrace/assert-internal.h>
 #include <babeltrace/babeltrace-internal.h>
+#include <babeltrace/ctf-ir/field-types.h>
+#include <babeltrace/ctf-ir/field-path.h>
+#include <babeltrace/ctf-ir/event-class.h>
 #include <stdarg.h>
+#include <glib.h>
 
 #define BT_COMMON_COLOR_RESET              "\033[0m"
 #define BT_COMMON_COLOR_BOLD               "\033[1m"
@@ -273,4 +278,186 @@ void bt_common_custom_snprintf(char *buf, size_t buf_size,
 BT_HIDDEN
 size_t bt_common_get_page_size(void);
 
+static inline
+const char *bt_common_field_type_id_string(enum bt_field_type_id type_id)
+{
+       switch (type_id) {
+       case BT_FIELD_TYPE_ID_UNKNOWN:
+               return "BT_FIELD_TYPE_ID_UNKNOWN";
+       case BT_FIELD_TYPE_ID_INTEGER:
+               return "BT_FIELD_TYPE_ID_INTEGER";
+       case BT_FIELD_TYPE_ID_FLOAT:
+               return "BT_FIELD_TYPE_ID_FLOAT";
+       case BT_FIELD_TYPE_ID_ENUM:
+               return "BT_FIELD_TYPE_ID_ENUM";
+       case BT_FIELD_TYPE_ID_STRING:
+               return "BT_FIELD_TYPE_ID_STRING";
+       case BT_FIELD_TYPE_ID_STRUCT:
+               return "BT_FIELD_TYPE_ID_STRUCT";
+       case BT_FIELD_TYPE_ID_ARRAY:
+               return "BT_FIELD_TYPE_ID_ARRAY";
+       case BT_FIELD_TYPE_ID_SEQUENCE:
+               return "BT_FIELD_TYPE_ID_SEQUENCE";
+       case BT_FIELD_TYPE_ID_VARIANT:
+               return "BT_FIELD_TYPE_ID_VARIANT";
+       default:
+               return "(unknown)";
+       }
+};
+
+static inline
+const char *bt_common_byte_order_string(enum bt_byte_order bo)
+{
+       switch (bo) {
+       case BT_BYTE_ORDER_UNKNOWN:
+               return "BT_BYTE_ORDER_UNKNOWN";
+       case BT_BYTE_ORDER_UNSPECIFIED:
+               return "BT_BYTE_ORDER_UNSPECIFIED";
+       case BT_BYTE_ORDER_NATIVE:
+               return "BT_BYTE_ORDER_NATIVE";
+       case BT_BYTE_ORDER_LITTLE_ENDIAN:
+               return "BT_BYTE_ORDER_LITTLE_ENDIAN";
+       case BT_BYTE_ORDER_BIG_ENDIAN:
+               return "BT_BYTE_ORDER_BIG_ENDIAN";
+       case BT_BYTE_ORDER_NETWORK:
+               return "BT_BYTE_ORDER_NETWORK";
+       default:
+               return "(unknown)";
+       }
+};
+
+static inline
+const char *bt_common_string_encoding_string(enum bt_string_encoding encoding)
+{
+       switch (encoding) {
+       case BT_STRING_ENCODING_UNKNOWN:
+               return "BT_STRING_ENCODING_UNKNOWN";
+       case BT_STRING_ENCODING_NONE:
+               return "BT_STRING_ENCODING_NONE";
+       case BT_STRING_ENCODING_UTF8:
+               return "BT_STRING_ENCODING_UTF8";
+       case BT_STRING_ENCODING_ASCII:
+               return "BT_STRING_ENCODING_ASCII";
+       default:
+               return "(unknown)";
+       }
+};
+
+static inline
+const char *bt_common_integer_base_string(enum bt_integer_base base)
+{
+       switch (base) {
+       case BT_INTEGER_BASE_UNKNOWN:
+               return "BT_INTEGER_BASE_UNKNOWN";
+       case BT_INTEGER_BASE_UNSPECIFIED:
+               return "BT_INTEGER_BASE_UNSPECIFIED";
+       case BT_INTEGER_BASE_BINARY:
+               return "BT_INTEGER_BASE_BINARY";
+       case BT_INTEGER_BASE_OCTAL:
+               return "BT_INTEGER_BASE_OCTAL";
+       case BT_INTEGER_BASE_DECIMAL:
+               return "BT_INTEGER_BASE_DECIMAL";
+       case BT_INTEGER_BASE_HEXADECIMAL:
+               return "BT_INTEGER_BASE_HEXADECIMAL";
+       default:
+               return "(unknown)";
+       }
+}
+
+static inline
+const char *bt_common_scope_string(enum bt_scope scope)
+{
+       switch (scope) {
+       case BT_SCOPE_UNKNOWN:
+               return "BT_SCOPE_UNKNOWN";
+       case BT_SCOPE_TRACE_PACKET_HEADER:
+               return "BT_SCOPE_TRACE_PACKET_HEADER";
+       case BT_SCOPE_STREAM_PACKET_CONTEXT:
+               return "BT_SCOPE_STREAM_PACKET_CONTEXT";
+       case BT_SCOPE_STREAM_EVENT_HEADER:
+               return "BT_SCOPE_STREAM_EVENT_HEADER";
+       case BT_SCOPE_STREAM_EVENT_CONTEXT:
+               return "BT_SCOPE_STREAM_EVENT_CONTEXT";
+       case BT_SCOPE_EVENT_CONTEXT:
+               return "BT_SCOPE_EVENT_CONTEXT";
+       case BT_SCOPE_EVENT_PAYLOAD:
+               return "BT_SCOPE_EVENT_PAYLOAD";
+       case BT_SCOPE_ENV:
+               return "BT_SCOPE_ENV";
+       default:
+               return "(unknown)";
+       }
+}
+
+static inline
+const char *bt_common_event_class_log_level_string(
+               enum bt_event_class_log_level level)
+{
+       switch (level) {
+       case BT_EVENT_CLASS_LOG_LEVEL_UNKNOWN:
+               return "BT_EVENT_CLASS_LOG_LEVEL_UNKNOWN";
+       case BT_EVENT_CLASS_LOG_LEVEL_UNSPECIFIED:
+               return "BT_EVENT_CLASS_LOG_LEVEL_UNSPECIFIED";
+       case BT_EVENT_CLASS_LOG_LEVEL_EMERGENCY:
+               return "BT_EVENT_CLASS_LOG_LEVEL_EMERGENCY";
+       case BT_EVENT_CLASS_LOG_LEVEL_ALERT:
+               return "BT_EVENT_CLASS_LOG_LEVEL_ALERT";
+       case BT_EVENT_CLASS_LOG_LEVEL_CRITICAL:
+               return "BT_EVENT_CLASS_LOG_LEVEL_CRITICAL";
+       case BT_EVENT_CLASS_LOG_LEVEL_ERROR:
+               return "BT_EVENT_CLASS_LOG_LEVEL_ERROR";
+       case BT_EVENT_CLASS_LOG_LEVEL_WARNING:
+               return "BT_EVENT_CLASS_LOG_LEVEL_WARNING";
+       case BT_EVENT_CLASS_LOG_LEVEL_NOTICE:
+               return "BT_EVENT_CLASS_LOG_LEVEL_NOTICE";
+       case BT_EVENT_CLASS_LOG_LEVEL_INFO:
+               return "BT_EVENT_CLASS_LOG_LEVEL_INFO";
+       case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_SYSTEM:
+               return "BT_EVENT_CLASS_LOG_LEVEL_DEBUG_SYSTEM";
+       case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROGRAM:
+               return "BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROGRAM";
+       case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROCESS:
+               return "BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROCESS";
+       case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_MODULE:
+               return "BT_EVENT_CLASS_LOG_LEVEL_DEBUG_MODULE";
+       case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_UNIT:
+               return "BT_EVENT_CLASS_LOG_LEVEL_DEBUG_UNIT";
+       case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_FUNCTION:
+               return "BT_EVENT_CLASS_LOG_LEVEL_DEBUG_FUNCTION";
+       case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_LINE:
+               return "BT_EVENT_CLASS_LOG_LEVEL_DEBUG_LINE";
+       case BT_EVENT_CLASS_LOG_LEVEL_DEBUG:
+               return "BT_EVENT_CLASS_LOG_LEVEL_DEBUG";
+       default:
+               return "(unknown)";
+       }
+};
+
+static inline
+GString *bt_field_path_string(struct bt_field_path *path)
+{
+       GString *str = g_string_new(NULL);
+       size_t i;
+
+       BT_ASSERT(path);
+
+       if (!str) {
+               goto end;
+       }
+
+       g_string_append_printf(str, "[%s", bt_common_scope_string(
+               bt_field_path_get_root_scope(path)));
+
+       for (i = 0; i < bt_field_path_get_index_count(path); i++) {
+               int index = bt_field_path_get_index(path, i);
+
+               g_string_append_printf(str, ", %d", index);
+       }
+
+       g_string_append(str, "]");
+
+end:
+       return str;
+}
+
 #endif /* BABELTRACE_COMMON_INTERNAL_H */
index d38f140613523c188f976a030dc2676d5a30761d..cd4c6cb00f2ec80ad470cebc0ffa4052b0bee98a 100644 (file)
@@ -28,7 +28,6 @@
  */
 
 #include <babeltrace/ctf-ir/clock-class.h>
-#include <babeltrace/ctf-ir/trace-internal.h>
 #include <babeltrace/object-internal.h>
 #include <babeltrace/babeltrace-internal.h>
 #include <babeltrace/compat/uuid-internal.h>
@@ -59,10 +58,6 @@ struct bt_clock_class {
 BT_HIDDEN
 void bt_clock_class_freeze(struct bt_clock_class *clock_class);
 
-BT_HIDDEN
-void bt_clock_class_serialize(struct bt_clock_class *clock_class,
-               struct metadata_context *context);
-
 BT_HIDDEN
 bt_bool bt_clock_class_is_valid(struct bt_clock_class *clock_class);
 
index 3dde3d764091610367247e3ead44dd0ed7cd4466..bb68d2b7fc1cbdabf63fffc2ca23315b35aa31b4 100644 (file)
@@ -78,14 +78,6 @@ extern const unsigned char *bt_clock_class_get_uuid(
                struct bt_clock_class *clock_class);
 extern int bt_clock_class_set_uuid(struct bt_clock_class *clock_class,
                const unsigned char *uuid);
-extern struct bt_clock_value *bt_clock_value_create(
-               struct bt_clock_class *clock_class, uint64_t value);
-extern struct bt_clock_class *bt_clock_value_get_class(
-               struct bt_clock_value *clock_value);
-extern int bt_clock_value_get_value(
-               struct bt_clock_value *clock_value, uint64_t *raw_value);
-extern int bt_clock_value_get_value_ns_from_epoch(
-               struct bt_clock_value *clock_value, int64_t *value_ns);
 
 #ifdef __cplusplus
 }
index 81117435e6d2e967a283610d2427e120769c7128..4836ec368292ab27b3d581faf50096e1b1abbc33 100644 (file)
@@ -27,6 +27,7 @@
  * SOFTWARE.
  */
 
+#include <babeltrace/assert-pre-internal.h>
 #include <babeltrace/ctf-ir/field-types.h>
 #include <babeltrace/ctf-ir/fields.h>
 #include <babeltrace/babeltrace-internal.h>
 #include <babeltrace/assert-internal.h>
 #include <glib.h>
 
-struct bt_event_class {
+struct bt_event_class_common {
        struct bt_object base;
-       /* Structure type containing the event's context */
-       struct bt_field_type *context;
-       /* Structure type containing the event's fields */
-       struct bt_field_type *fields;
+       struct bt_field_type_common *context_field_type;
+       struct bt_field_type_common *payload_field_type;
        int frozen;
 
        /*
@@ -58,77 +57,355 @@ struct bt_event_class {
        /* Attributes */
        GString *name;
        int64_t id;
-       enum bt_event_class_log_level log_level;
+       int log_level;
        GString *emf_uri;
 };
 
+struct bt_event_class {
+       struct bt_event_class_common common;
+};
+
 BT_HIDDEN
 void bt_event_class_freeze(struct bt_event_class *event_class);
 
 BT_HIDDEN
-int bt_event_class_serialize(struct bt_event_class *event_class,
-               struct metadata_context *context);
+void bt_event_class_common_freeze(struct bt_event_class_common *event_class);
 
 BT_HIDDEN
-void bt_event_class_set_native_byte_order(
-               struct bt_event_class *event_class,
-               int byte_order);
+void bt_event_class_common_set_native_byte_order(
+               struct bt_event_class_common *event_class, int byte_order);
 
 static inline
-struct bt_stream_class *bt_event_class_borrow_stream_class(
-               struct bt_event_class *event_class)
+struct bt_stream_class_common *bt_event_class_common_borrow_stream_class(
+               struct bt_event_class_common *event_class)
 {
        BT_ASSERT(event_class);
        return (void *) bt_object_borrow_parent(event_class);
 }
 
 static inline
-const char *bt_event_class_log_level_string(
-               enum bt_event_class_log_level level)
+struct bt_stream_class *bt_event_class_borrow_stream_class(
+               struct bt_event_class *event_class)
+{
+       return BT_FROM_COMMON(bt_event_class_common_borrow_stream_class(
+               BT_TO_COMMON(event_class)));
+}
+
+typedef struct bt_field_type_common *(*bt_field_type_structure_create_func)();
+
+BT_HIDDEN
+int bt_event_class_common_initialize(struct bt_event_class_common *event_class,
+               const char *name, bt_object_release_func release_func,
+               bt_field_type_structure_create_func ft_struct_create_func);
+
+BT_HIDDEN
+void bt_event_class_common_finalize(struct bt_object *obj);
+
+BT_HIDDEN
+int bt_event_class_common_validate_single_clock_class(
+               struct bt_event_class_common *event_class,
+               struct bt_clock_class **expected_clock_class);
+
+static inline
+const char *bt_event_class_common_get_name(
+               struct bt_event_class_common *event_class)
+{
+       BT_ASSERT_PRE_NON_NULL(event_class, "Event class");
+       BT_ASSERT(event_class->name);
+       return event_class->name->str;
+}
+
+static inline
+int64_t bt_event_class_common_get_id(
+               struct bt_event_class_common *event_class)
+{
+       BT_ASSERT_PRE_NON_NULL(event_class, "Event class");
+       return event_class->id;
+}
+
+static inline
+int bt_event_class_common_set_id(
+               struct bt_event_class_common *event_class, uint64_t id_param)
 {
-       switch (level) {
-       case BT_EVENT_CLASS_LOG_LEVEL_UNKNOWN:
-               return "BT_EVENT_CLASS_LOG_LEVEL_UNKNOWN";
+       int ret = 0;
+       int64_t id = (int64_t) id_param;
+
+       if (!event_class) {
+               BT_LOGW_STR("Invalid parameter: event class is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       if (event_class->frozen) {
+               BT_LOGW("Invalid parameter: event class is frozen: "
+                       "addr=%p, name=\"%s\", id=%" PRId64,
+                       event_class,
+                       bt_event_class_common_get_name(event_class),
+                       bt_event_class_common_get_id(event_class));
+               ret = -1;
+               goto end;
+       }
+
+       if (id < 0) {
+               BT_LOGW("Invalid parameter: invalid event class's ID: "
+                       "addr=%p, name=\"%s\", id=%" PRIu64,
+                       event_class,
+                       bt_event_class_common_get_name(event_class),
+                       id_param);
+               ret = -1;
+               goto end;
+       }
+
+       event_class->id = id;
+       BT_LOGV("Set event class's ID: "
+               "addr=%p, name=\"%s\", id=%" PRId64,
+               event_class, bt_event_class_common_get_name(event_class), id);
+
+end:
+       return ret;
+}
+
+static inline
+int bt_event_class_common_get_log_level(
+               struct bt_event_class_common *event_class)
+{
+       BT_ASSERT_PRE_NON_NULL(event_class, "Event class");
+       return event_class->log_level;
+}
+
+static inline
+int bt_event_class_common_set_log_level(
+               struct bt_event_class_common *event_class, int log_level)
+{
+       int ret = 0;
+
+       if (!event_class) {
+               BT_LOGW_STR("Invalid parameter: event class is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       if (event_class->frozen) {
+               BT_LOGW("Invalid parameter: event class is frozen: "
+                       "addr=%p, name=\"%s\", id=%" PRId64,
+                       event_class,
+                       bt_event_class_common_get_name(event_class),
+                       bt_event_class_common_get_id(event_class));
+               ret = -1;
+               goto end;
+       }
+
+       switch (log_level) {
        case BT_EVENT_CLASS_LOG_LEVEL_UNSPECIFIED:
-               return "BT_EVENT_CLASS_LOG_LEVEL_UNSPECIFIED";
        case BT_EVENT_CLASS_LOG_LEVEL_EMERGENCY:
-               return "BT_EVENT_CLASS_LOG_LEVEL_EMERGENCY";
        case BT_EVENT_CLASS_LOG_LEVEL_ALERT:
-               return "BT_EVENT_CLASS_LOG_LEVEL_ALERT";
        case BT_EVENT_CLASS_LOG_LEVEL_CRITICAL:
-               return "BT_EVENT_CLASS_LOG_LEVEL_CRITICAL";
        case BT_EVENT_CLASS_LOG_LEVEL_ERROR:
-               return "BT_EVENT_CLASS_LOG_LEVEL_ERROR";
        case BT_EVENT_CLASS_LOG_LEVEL_WARNING:
-               return "BT_EVENT_CLASS_LOG_LEVEL_WARNING";
        case BT_EVENT_CLASS_LOG_LEVEL_NOTICE:
-               return "BT_EVENT_CLASS_LOG_LEVEL_NOTICE";
        case BT_EVENT_CLASS_LOG_LEVEL_INFO:
-               return "BT_EVENT_CLASS_LOG_LEVEL_INFO";
        case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_SYSTEM:
-               return "BT_EVENT_CLASS_LOG_LEVEL_DEBUG_SYSTEM";
        case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROGRAM:
-               return "BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROGRAM";
        case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROCESS:
-               return "BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROCESS";
        case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_MODULE:
-               return "BT_EVENT_CLASS_LOG_LEVEL_DEBUG_MODULE";
        case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_UNIT:
-               return "BT_EVENT_CLASS_LOG_LEVEL_DEBUG_UNIT";
        case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_FUNCTION:
-               return "BT_EVENT_CLASS_LOG_LEVEL_DEBUG_FUNCTION";
        case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_LINE:
-               return "BT_EVENT_CLASS_LOG_LEVEL_DEBUG_LINE";
        case BT_EVENT_CLASS_LOG_LEVEL_DEBUG:
-               return "BT_EVENT_CLASS_LOG_LEVEL_DEBUG";
+               break;
        default:
-               return "(unknown)";
+               BT_LOGW("Invalid parameter: unknown event class log level: "
+                       "addr=%p, name=\"%s\", id=%" PRId64 ", log-level=%d",
+                       event_class, bt_event_class_common_get_name(event_class),
+                       bt_event_class_common_get_id(event_class), log_level);
+               ret = -1;
+               goto end;
        }
-};
 
-BT_HIDDEN
-int bt_event_class_validate_single_clock_class(
-               struct bt_event_class *event_class,
-               struct bt_clock_class **expected_clock_class);
+       event_class->log_level = log_level;
+       BT_LOGV("Set event class's log level: "
+               "addr=%p, name=\"%s\", id=%" PRId64 ", log-level=%s",
+               event_class, bt_event_class_common_get_name(event_class),
+               bt_event_class_common_get_id(event_class),
+               bt_common_event_class_log_level_string(log_level));
+
+end:
+       return ret;
+}
+
+static inline
+const char *bt_event_class_common_get_emf_uri(
+               struct bt_event_class_common *event_class)
+{
+       const char *emf_uri = NULL;
+
+       BT_ASSERT_PRE_NON_NULL(event_class, "Event class");
+
+       if (event_class->emf_uri->len > 0) {
+               emf_uri = event_class->emf_uri->str;
+       }
+
+       return emf_uri;
+}
+
+static inline
+int bt_event_class_common_set_emf_uri(
+               struct bt_event_class_common *event_class,
+               const char *emf_uri)
+{
+       int ret = 0;
+
+       if (!event_class) {
+               BT_LOGW_STR("Invalid parameter: event class is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       if (emf_uri && strlen(emf_uri) == 0) {
+               BT_LOGW_STR("Invalid parameter: EMF URI is empty.");
+               ret = -1;
+               goto end;
+       }
+
+       if (event_class->frozen) {
+               BT_LOGW("Invalid parameter: event class is frozen: "
+                       "addr=%p, name=\"%s\", id=%" PRId64,
+                       event_class, bt_event_class_common_get_name(event_class),
+                       bt_event_class_common_get_id(event_class));
+               ret = -1;
+               goto end;
+       }
+
+       if (emf_uri) {
+               g_string_assign(event_class->emf_uri, emf_uri);
+               BT_LOGV("Set event class's EMF URI: "
+                       "addr=%p, name=\"%s\", id=%" PRId64 ", emf-uri=\"%s\"",
+                       event_class, bt_event_class_common_get_name(event_class),
+                       bt_event_class_common_get_id(event_class), emf_uri);
+       } else {
+               g_string_assign(event_class->emf_uri, "");
+               BT_LOGV("Reset event class's EMF URI: "
+                       "addr=%p, name=\"%s\", id=%" PRId64,
+                       event_class, bt_event_class_common_get_name(event_class),
+                       bt_event_class_common_get_id(event_class));
+       }
+
+end:
+       return ret;
+}
+
+static inline
+struct bt_field_type_common *bt_event_class_common_get_context_field_type(
+               struct bt_event_class_common *event_class)
+{
+       struct bt_field_type_common *context_ft = NULL;
+
+       BT_ASSERT_PRE_NON_NULL(event_class, "Event class");
+
+       if (!event_class->context_field_type) {
+               BT_LOGV("Event class has no context field type: "
+                       "addr=%p, name=\"%s\", id=%" PRId64,
+                       event_class, bt_event_class_common_get_name(event_class),
+                       bt_event_class_common_get_id(event_class));
+               goto end;
+       }
+
+       context_ft = bt_get(event_class->context_field_type);
+
+end:
+       return context_ft;
+}
+
+static inline
+int bt_event_class_common_set_context_field_type(
+               struct bt_event_class_common *event_class,
+               struct bt_field_type_common *context_ft)
+{
+       int ret = 0;
+
+       if (!event_class) {
+               BT_LOGW_STR("Invalid parameter: event class is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       if (event_class->frozen) {
+               BT_LOGW("Invalid parameter: event class is frozen: "
+                       "addr=%p, name=\"%s\", id=%" PRId64,
+                       event_class, bt_event_class_common_get_name(event_class),
+                       bt_event_class_common_get_id(event_class));
+               ret = -1;
+               goto end;
+       }
+
+       if (context_ft && bt_field_type_common_get_type_id(context_ft) !=
+                       BT_FIELD_TYPE_ID_STRUCT) {
+               BT_LOGW("Invalid parameter: event class's context field type must be a structure: "
+                       "addr=%p, name=\"%s\", id=%" PRId64 ", "
+                       "context-ft-id=%s",
+                       event_class, bt_event_class_common_get_name(event_class),
+                       bt_event_class_common_get_id(event_class),
+                       bt_common_field_type_id_string(
+                               bt_field_type_common_get_type_id(context_ft)));
+               ret = -1;
+               goto end;
+       }
+
+       bt_put(event_class->context_field_type);
+       event_class->context_field_type = bt_get(context_ft);
+       BT_LOGV("Set event class's context field type: "
+               "event-class-addr=%p, event-class-name=\"%s\", "
+               "event-class-id=%" PRId64 ", context-ft-addr=%p",
+               event_class, bt_event_class_common_get_name(event_class),
+               bt_event_class_common_get_id(event_class), context_ft);
+
+end:
+       return ret;
+}
+
+static inline
+struct bt_field_type_common *bt_event_class_common_get_payload_field_type(
+               struct bt_event_class_common *event_class)
+{
+       BT_ASSERT_PRE_NON_NULL(event_class, "Event class");
+       return bt_get(event_class->payload_field_type);
+}
+
+static inline
+int bt_event_class_common_set_payload_field_type(
+               struct bt_event_class_common *event_class,
+               struct bt_field_type_common *payload_ft)
+{
+       int ret = 0;
+
+       if (!event_class) {
+               BT_LOGW_STR("Invalid parameter: event class is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       if (payload_ft && bt_field_type_common_get_type_id(payload_ft) !=
+                       BT_FIELD_TYPE_ID_STRUCT) {
+               BT_LOGW("Invalid parameter: event class's payload field type must be a structure: "
+                       "addr=%p, name=\"%s\", id=%" PRId64 ", "
+                       "payload-ft-addr=%p, payload-ft-id=%s",
+                       event_class, bt_event_class_common_get_name(event_class),
+                       bt_event_class_common_get_id(event_class), payload_ft,
+                       bt_common_field_type_id_string(
+                               bt_field_type_common_get_type_id(payload_ft)));
+               ret = -1;
+               goto end;
+       }
+
+       bt_put(event_class->payload_field_type);
+       event_class->payload_field_type = bt_get(payload_ft);
+       BT_LOGV("Set event class's payload field type: "
+               "event-class-addr=%p, event-class-name=\"%s\", "
+               "event-class-id=%" PRId64 ", payload-ft-addr=%p",
+               event_class, bt_event_class_common_get_name(event_class),
+               bt_event_class_common_get_id(event_class), payload_ft);
+end:
+       return ret;
+}
 
 #endif /* BABELTRACE_CTF_IR_EVENT_CLASS_INTERNAL_H */
index 0b0a0581a886c278ca0b685bf803868a1dc3e745..a8a3a673f1c994965bc6da754ad16fa2427b394f 100644 (file)
@@ -183,8 +183,8 @@ enum bt_event_class_log_level {
 On success, the context and payload field types are empty structure
 field types. You can modify those default field types after the
 event class is created with
-bt_event_class_set_context_type() and
-bt_event_class_set_payload_type().
+bt_event_class_set_context_field_type() and
+bt_event_class_set_payload_field_type().
 
 Upon creation, the event class's ID is <em>not set</em>. You
 can set it to a specific value with bt_event_class_set_id(). If it
@@ -405,10 +405,10 @@ extern int bt_event_class_set_emf_uri(
 @post <strong>On success, if the return value is a field type</strong>, its
        reference count is incremented.
 
-@sa bt_event_class_set_context_type(): Sets the context field type of a
+@sa bt_event_class_set_context_field_type(): Sets the context field type of a
        given event class.
 */
-extern struct bt_field_type *bt_event_class_get_context_type(
+extern struct bt_field_type *bt_event_class_get_context_field_type(
                struct bt_event_class *event_class);
 
 /**
@@ -437,10 +437,10 @@ As of Babeltrace \btversion, if \p context_type is not \c NULL,
 @post <strong>On success, if \p context_type is not \c NULL</strong>,
        the reference count of \p context_type is incremented.
 
-@sa bt_event_class_get_context_type(): Returns the context field type of a
+@sa bt_event_class_get_context_field_type(): Returns the context field type of a
        given event class.
 */
-extern int bt_event_class_set_context_type(
+extern int bt_event_class_set_context_field_type(
                struct bt_event_class *event_class,
                struct bt_field_type *context_type);
 
@@ -457,10 +457,10 @@ extern int bt_event_class_set_context_type(
 @post <strong>On success, if the return value is a field type</strong>, its
        reference count is incremented.
 
-@sa bt_event_class_set_payload_type(): Sets the payload field type of a
+@sa bt_event_class_set_payload_field_type(): Sets the payload field type of a
        given event class.
 */
-extern struct bt_field_type *bt_event_class_get_payload_type(
+extern struct bt_field_type *bt_event_class_get_payload_field_type(
                struct bt_event_class *event_class);
 
 /**
@@ -489,141 +489,17 @@ As of Babeltrace \btversion, if \p payload_type is not \c NULL,
 @post <strong>On success, if \p payload_type is not \c NULL</strong>,
        the reference count of \p payload_type is incremented.
 
-@sa bt_event_class_get_payload_type(): Returns the payload field type of a
+@sa bt_event_class_get_payload_field_type(): Returns the payload field type of a
        given event class.
 */
-extern int bt_event_class_set_payload_type(
+extern int bt_event_class_set_payload_field_type(
                struct bt_event_class *event_class,
                struct bt_field_type *payload_type);
 
-/**
-@brief Returns the number of fields contained in the
-       payload field type of the CTF IR event class \p event_class.
-
-@remarks
-Calling this function is the equivalent of getting the payload field
-type of \p event_class with bt_event_class_get_payload_type() and
-getting its field count with
-bt_field_type_structure_get_field_count().
-
-@param[in] event_class Event class of which to get the number
-                       of fields contained in its payload field type.
-@returns               Number of fields in the payload field type
-                       of \p event_class, or a negative value on error.
-
-@prenotnull{event_class}
-@postrefcountsame{event_class}
-*/
-extern int64_t bt_event_class_get_payload_type_field_count(
-               struct bt_event_class *event_class);
-
-/**
-@brief Returns the type and the name of the field at index \p index
-       in the payload field type of the CTF IR event class
-       \p event_class.
-
-On success, the field's type is placed in \p *field_type if
-\p field_type is not \c NULL. The field's name is placed in
-\p *name if \p name is not \c NULL. \p event_class remains the sole
-owner of \p *name.
-
-Both \p name and \p field_type can be \c NULL if the caller is not
-interested in one of them.
-
-@remarks
-Calling this function is the equivalent of getting the payload field
-type of \p event_class with bt_event_class_get_payload_type() and
-getting the type and name of one of its field with
-bt_field_type_structure_get_field().
-
-@param[in] event_class Event class of which to get the type and name
-                       of a field in its payload field type.
-@param[out] field_name Name of the field at the index
-                       \p index in the payload field type of
-                       \p event_class (can be \c NULL).
-@param[out] field_type Type of the field at the index \p index in the
-                       payload field type of \p event_class
-                       (can be \c NULL).
-@param[in] index       Index of the payload field type's field to find.
-@returns               0 on success, or a negative value on error.
-
-@prenotnull{event_class}
-@pre \p index is lesser than the number of fields contained in the
-       payload field type of \p event_class (see
-       bt_event_class_get_payload_type_field_count()).
-@postrefcountsame{event_class}
-@post <strong>On success, if \p field_type is not \c NULL</strong>, the
-       reference count of \p *field_type is incremented.
-*/
-extern int bt_event_class_get_payload_type_field_by_index(
-               struct bt_event_class *event_class,
-               const char **field_name, struct bt_field_type **field_type,
-               uint64_t index);
-
-/**
-@brief  Returns the type of the field named \p name in the payload
-       field type of the CTF IR event class \p event_class.
-
-@remarks
-Calling this function is the equivalent of getting the payload field
-type of \p event_class with bt_event_class_get_payload_type() and
-getting the type of one of its field with
-bt_field_type_structure_get_field_type_by_name().
-
-@param[in] event_class Event class of which to get the type of a
-                       payload field type's field.
-@param[in] name                Name of the payload field type's field to get.
-@returns               Type of the field named \p name in the payload
-                       field type of \p event_class, or \c NULL if
-                       the function cannot find the field or
-                       on error.
-
-@prenotnull{event_class}
-@prenotnull{name}
-@postrefcountsame{event_class}
-@postsuccessrefcountretinc
-*/
-extern struct bt_field_type *
-bt_event_class_get_payload_type_field_type_by_name(
-               struct bt_event_class *event_class, const char *name);
-
-/**
-@brief Adds a field named \p name with the type \p field_type to the
-       payload field type of the CTF IR event class \p event_class.
-
-@remarks
-Calling this function is the equivalent of getting the payload field
-type of \p event_class with bt_event_class_get_payload_type() and
-adding a field to it with bt_field_type_structure_add_field().
-
-@param[in] event_class Event class containing the payload field
-                       type in which to add a field.
-@param[in] field_type  Type of the field to add.
-@param[in] name                Name of the field to add (copied on
-                       success).
-@returns               0 on success, or a negative value on error.
-
-@prenotnull{event_class}
-@prenotnull{type}
-@prenotnull{name}
-@prehot{event_class}
-@postrefcountsame{event_class}
-@postsuccessrefcountinc{field_type}
-*/
-extern int bt_event_class_add_field(struct bt_event_class *event_class,
-               struct bt_field_type *field_type,
-               const char *name);
-
 /** @} */
 
 /** @} */
 
-/* Pre-2.0 CTF writer compatibility */
-#define bt_ctf_event_class bt_event_class
-#define bt_ctf_event_class_create bt_event_class_create
-#define bt_ctf_event_class_get_field_by_name bt_event_class_get_payload_type_field_type_by_name
-#define bt_ctf_event_class_add_field bt_event_class_add_field
-
 #ifdef __cplusplus
 }
 #endif
index 8dab37891000d5c188866f2341a1bba6d0ef2fd0..d9d0fe3e15b46ebfff0ccedd80ecd4681ddf2c1c 100644 (file)
  * SOFTWARE.
  */
 
-#include <babeltrace/ctf-writer/event-types.h>
-#include <babeltrace/ctf-writer/event-fields.h>
+#include <babeltrace/assert-pre-internal.h>
 #include <babeltrace/babeltrace-internal.h>
 #include <babeltrace/values.h>
 #include <babeltrace/ctf-ir/stream-class.h>
 #include <babeltrace/ctf-ir/stream.h>
 #include <babeltrace/ctf-ir/packet.h>
+#include <babeltrace/ctf-ir/fields.h>
+#include <babeltrace/ctf-ir/fields-internal.h>
+#include <babeltrace/ctf-ir/event-class-internal.h>
+#include <babeltrace/ctf-ir/validation-internal.h>
 #include <babeltrace/object-internal.h>
 #include <babeltrace/assert-internal.h>
 #include <glib.h>
 
 struct bt_stream_pos;
 
-struct bt_event {
+struct bt_event_common {
        struct bt_object base;
-       struct bt_event_class *event_class;
-       struct bt_packet *packet;
-       struct bt_field *event_header;
-       struct bt_field *stream_event_context;
-       struct bt_field *context_payload;
-       struct bt_field *fields_payload;
+       struct bt_event_class_common *class;
+       struct bt_field_common *header_field;
+       struct bt_field_common *stream_event_context_field;
+       struct bt_field_common *context_field;
+       struct bt_field_common *payload_field;
+       int frozen;
+};
+
+struct bt_event {
+       struct bt_event_common common;
+
        /* Maps clock classes to bt_clock_value. */
        GHashTable *clock_values;
-       int frozen;
+       struct bt_packet *packet;
 };
 
 BT_HIDDEN
-int bt_event_serialize(struct bt_event *event,
-               struct bt_stream_pos *pos,
-               enum bt_byte_order native_byte_order);
+int _bt_event_common_validate(struct bt_event_common *event);
 
 BT_HIDDEN
-int _bt_event_validate(struct bt_event *event);
+void _bt_event_common_freeze(struct bt_event_common *event);
 
 BT_HIDDEN
 void _bt_event_freeze(struct bt_event *event);
 
 #ifdef BT_DEV_MODE
-# define bt_event_validate             _bt_event_validate
-# define bt_event_freeze               _bt_event_freeze
+# define bt_event_common_validate              _bt_event_common_validate
+# define bt_event_common_freeze                        _bt_event_common_freeze
+# define bt_event_freeze                       _bt_event_freeze
 #else
-# define bt_event_validate(_event)     0
+# define bt_event_common_validate(_event)      0
+# define bt_event_common_freeze(_event)
 # define bt_event_freeze(_event)
 #endif
 
+#define BT_ASSERT_PRE_EVENT_COMMON_HOT(_event, _name)                  \
+       BT_ASSERT_PRE_HOT((_event), (_name), ": +%!+_e", (_event))
+
 static inline struct bt_packet *bt_event_borrow_packet(struct bt_event *event)
 {
        BT_ASSERT(event);
@@ -82,11 +93,288 @@ BT_HIDDEN
 struct bt_stream *bt_event_borrow_stream(struct bt_event *event);
 
 static inline
-struct bt_event_class *bt_event_borrow_event_class(
-               struct bt_event *event)
+struct bt_event_class_common *bt_event_common_borrow_class(
+               struct bt_event_common *event)
 {
        BT_ASSERT(event);
-       return event->event_class;
+       return event->class;
+}
+
+static inline
+struct bt_event_class *bt_event_borrow_class(struct bt_event *event)
+{
+       return BT_FROM_COMMON(bt_event_common_borrow_class(
+               BT_TO_COMMON(event)));
+}
+
+BT_HIDDEN
+int bt_event_common_initialize(struct bt_event_common *event,
+               struct bt_event_class_common *event_class,
+               struct bt_clock_class *init_expected_clock_class,
+               bt_object_release_func release_func,
+               bt_validation_flag_copy_field_type_func field_type_copy_func,
+               bool must_be_in_trace,
+               int (*map_clock_classes_func)(struct bt_stream_class_common *stream_class,
+                       struct bt_field_type_common *packet_context_field_type,
+                       struct bt_field_type_common *event_header_field_type),
+               void *(*create_field_func)(void *));
+
+static inline
+struct bt_field_common *bt_event_common_get_payload(
+               struct bt_event_common *event)
+{
+       struct bt_field_common *payload = NULL;
+
+       BT_ASSERT_PRE_NON_NULL(event, "Event");
+
+       if (!event->payload_field) {
+               BT_LOGV("Event has no current payload field: addr=%p, "
+                       "event-class-name=\"%s\", event-class-id=%" PRId64,
+                       event, bt_event_class_common_get_name(event->class),
+                       bt_event_class_common_get_id(event->class));
+               goto end;
+       }
+
+       payload = event->payload_field;
+       bt_get(payload);
+
+end:
+       return payload;
+}
+
+static inline
+int bt_event_common_set_payload(struct bt_event_common *event,
+               struct bt_field_common *payload)
+{
+       BT_ASSERT_PRE_NON_NULL(event, "Event");
+       BT_ASSERT_PRE_EVENT_COMMON_HOT(event, "Event");
+
+       if (payload) {
+               BT_ASSERT_PRE(bt_field_type_common_compare(payload->type,
+                       event->class->payload_field_type) == 0,
+                       "Payload field's type is different from the "
+                       "expected field type: %![event-]+_e, %![ft-]+_F, "
+                       "%![expected-ft-]+_F",
+                       event, payload->type,
+                       event->class->payload_field_type);
+       } else {
+               BT_ASSERT_PRE(!event->class->payload_field_type,
+                       "Setting no event payload field, "
+                       "but event payload field type is not NULL: ",
+                       "%![event-]+_e, %![payload-ft-]+_F",
+                       event, event->class->payload_field_type);
+       }
+
+       bt_put(event->payload_field);
+       event->payload_field = bt_get(payload);
+       BT_LOGV("Set event's payload field: event-addr=%p, "
+               "event-class-name=\"%s\", event-class-id=%" PRId64 ", "
+               "payload-field-addr=%p",
+               event, bt_event_class_common_get_name(event->class),
+               bt_event_class_common_get_id(event->class), payload);
+       return 0;
+}
+
+static inline
+struct bt_field_common *bt_event_common_get_header(
+               struct bt_event_common *event)
+{
+       struct bt_field_common *header = NULL;
+
+       BT_ASSERT_PRE_NON_NULL(event, "Event");
+
+       if (!event->header_field) {
+               BT_LOGV("Event has no current header field: addr=%p, "
+                       "event-class-name=\"%s\", event-class-id=%" PRId64,
+                       event, bt_event_class_common_get_name(event->class),
+                       bt_event_class_common_get_id(event->class));
+               goto end;
+       }
+
+       header = event->header_field;
+       bt_get(header);
+
+end:
+       return header;
+}
+
+static inline
+int bt_event_common_set_header(struct bt_event_common *event,
+               struct bt_field_common *header)
+{
+       BT_ASSERT_PRE_NON_NULL(event, "Event");
+       BT_ASSERT_PRE_EVENT_COMMON_HOT(event, "Event");
+
+       /*
+        * Ensure the provided header's type matches the one registered to the
+        * stream class.
+        */
+       if (header) {
+               BT_ASSERT_PRE(bt_field_type_common_compare(header->type,
+                       bt_event_class_common_borrow_stream_class(event->class)->event_header_field_type) == 0,
+                       "Header field's type is different from the "
+                       "expected field type: %![event-]+_e, %![ft-]+_F, "
+                       "%![expected-ft-]+_F",
+                       event, header->type,
+                       bt_event_class_common_borrow_stream_class(event->class)->event_header_field_type);
+       } else {
+               BT_ASSERT_PRE(!bt_event_class_common_borrow_stream_class(event->class)->event_header_field_type,
+                       "Setting no event header field, "
+                       "but event header field type is not NULL: ",
+                       "%![event-]+_e, %![header-ft-]+_F",
+                       event,
+                       bt_event_class_common_borrow_stream_class(event->class)->event_header_field_type);
+       }
+
+       bt_put(event->header_field);
+       event->header_field = bt_get(header);
+       BT_LOGV("Set event's header field: event-addr=%p, "
+               "event-class-name=\"%s\", event-class-id=%" PRId64 ", "
+               "header-field-addr=%p",
+               event, bt_event_class_common_get_name(event->class),
+               bt_event_class_common_get_id(event->class), header);
+       return 0;
+}
+
+static inline
+struct bt_field_common *bt_event_common_get_context(
+               struct bt_event_common *event)
+{
+       struct bt_field_common *context = NULL;
+
+       BT_ASSERT_PRE_NON_NULL(event, "Event");
+
+       if (!event->context_field) {
+               BT_LOGV("Event has no current context field: addr=%p, "
+                       "event-class-name=\"%s\", event-class-id=%" PRId64,
+                       event, bt_event_class_common_get_name(event->class),
+                       bt_event_class_common_get_id(event->class));
+               goto end;
+       }
+
+       context = event->context_field;
+       bt_get(context);
+
+end:
+       return context;
+}
+
+static inline
+int bt_event_common_set_context(struct bt_event_common *event,
+               struct bt_field_common *context)
+{
+       BT_ASSERT_PRE_NON_NULL(event, "Event");
+       BT_ASSERT_PRE_EVENT_COMMON_HOT(event, "Event");
+
+       if (context) {
+               BT_ASSERT_PRE(bt_field_type_common_compare(context->type,
+                       event->class->context_field_type) == 0,
+                       "Context field's type is different from the "
+                       "expected field type: %![event-]+_e, %![ft-]+_F, "
+                       "%![expected-ft-]+_F",
+                       event, context->type, event->class->context_field_type);
+       } else {
+               BT_ASSERT_PRE(!event->class->context_field_type,
+                       "Setting no event context field, "
+                       "but event context field type is not NULL: ",
+                       "%![event-]+_e, %![context-ft-]+_F",
+                       event, event->class->context_field_type);
+       }
+
+       bt_put(event->context_field);
+       event->context_field = bt_get(context);
+       BT_LOGV("Set event's context field: event-addr=%p, "
+               "event-class-name=\"%s\", event-class-id=%" PRId64 ", "
+               "context-field-addr=%p",
+               event, bt_event_class_common_get_name(event->class),
+               bt_event_class_common_get_id(event->class), context);
+       return 0;
+}
+
+static inline
+struct bt_field_common *bt_event_common_get_stream_event_context(
+               struct bt_event_common *event)
+{
+       struct bt_field_common *stream_event_context = NULL;
+
+       BT_ASSERT_PRE_NON_NULL(event, "Event");
+
+       if (!event->stream_event_context_field) {
+               BT_LOGV("Event has no current stream event context field: addr=%p, "
+                       "event-class-name=\"%s\", event-class-id=%" PRId64,
+                       event, bt_event_class_common_get_name(event->class),
+                       bt_event_class_common_get_id(event->class));
+               goto end;
+       }
+
+       stream_event_context = event->stream_event_context_field;
+
+end:
+       return bt_get(stream_event_context);
+}
+
+static inline
+int bt_event_common_set_stream_event_context(struct bt_event_common *event,
+               struct bt_field_common *stream_event_context)
+{
+       BT_ASSERT_PRE_NON_NULL(event, "Event");
+       BT_ASSERT_PRE_EVENT_COMMON_HOT(event, "Event");
+
+       if (stream_event_context) {
+               BT_ASSERT_PRE(bt_field_type_common_compare(stream_event_context->type,
+                       bt_event_class_common_borrow_stream_class(event->class)->event_context_field_type) == 0,
+                       "Stream event context field's type is different from the "
+                       "expected field type: %![event-]+_e, %![ft-]+_F, "
+                       "%![expected-ft-]+_F",
+                       event, stream_event_context->type,
+                       bt_event_class_common_borrow_stream_class(event->class)->event_context_field_type);
+       } else {
+               BT_ASSERT_PRE(!bt_event_class_common_borrow_stream_class(event->class)->event_context_field_type,
+                       "Setting no stream event context field, "
+                       "but stream event context field type is not NULL: ",
+                       "%![event-]+_e, %![context-ft-]+_F",
+                       event,
+                       bt_event_class_common_borrow_stream_class(event->class)->event_context_field_type);
+       }
+
+       bt_get(stream_event_context);
+       BT_MOVE(event->stream_event_context_field, stream_event_context);
+       BT_LOGV("Set event's stream event context field: event-addr=%p, "
+               "event-class-name=\"%s\", event-class-id=%" PRId64 ", "
+               "stream-event-context-field-addr=%p",
+               event, bt_event_class_common_get_name(event->class),
+               bt_event_class_common_get_id(event->class),
+               stream_event_context);
+       return 0;
+}
+
+static inline
+void bt_event_common_finalize(struct bt_object *obj)
+{
+       struct bt_event_common *event = (void *) obj;
+
+       BT_LOGD("Destroying event: addr=%p, "
+               "event-class-name=\"%s\", event-class-id=%" PRId64,
+               event, bt_event_class_common_get_name(event->class),
+               bt_event_class_common_get_id(event->class));
+
+       if (!event->base.parent) {
+               /*
+                * Event was keeping a reference to its class since it shared no
+                * common ancestor with it to guarantee they would both have the
+                * same lifetime.
+                */
+               bt_put(event->class);
+       }
+
+       bt_put(event->header_field);
+       BT_LOGD_STR("Putting event's stream event context field.");
+       bt_put(event->stream_event_context_field);
+       BT_LOGD_STR("Putting event's context field.");
+       bt_put(event->context_field);
+       BT_LOGD_STR("Putting event's payload field.");
+       bt_put(event->payload_field);
+       BT_LOGD_STR("Putting event's packet.");
 }
 
 #endif /* BABELTRACE_CTF_IR_EVENT_INTERNAL_H */
index e416627a1fb77340a0b0d419ed94b2645d44960f..3bdee29b0ea4ecb603853d2a6ee0ddc618011fb3 100644 (file)
@@ -141,7 +141,7 @@ struct bt_packet;
 On success, the four fields of the created event object are not set. You
 can set them with bt_event_set_header(),
 bt_event_set_stream_event_context(),
-bt_event_set_event_context(), and bt_event_set_event_payload().
+bt_event_set_context(), and bt_event_set_payload().
 
 This function tries to resolve the needed
 \link ctfirfieldtypes CTF IR field type\endlink of the dynamic field
@@ -162,8 +162,7 @@ with bt_trace_add_stream_class(), then this function fails.
 @pre \p event_class has a parent stream class.
 @postsuccessrefcountret1
 */
-extern struct bt_event *bt_event_create(
-               struct bt_event_class *event_class);
+extern struct bt_event *bt_event_create(struct bt_event_class *event_class);
 
 /**
 @brief Returns the parent CTF IR event class of the CTF IR event
@@ -180,8 +179,7 @@ create the event object in the first place with bt_event_create().
 @postrefcountsame{event}
 @postsuccessrefcountretinc
 */
-extern struct bt_event_class *bt_event_get_class(
-               struct bt_event *event);
+extern struct bt_event_class *bt_event_get_class(struct bt_event *event);
 
 /**
 @brief Returns the CTF IR packet associated to the CTF IR event
@@ -202,8 +200,7 @@ This function returns a reference to the event class which was set to
 @sa bt_event_set_packet(): Associates a given event to a given
        packet.
 */
-extern struct bt_packet *bt_event_get_packet(
-               struct bt_event *event);
+extern struct bt_packet *bt_event_get_packet(struct bt_event *event);
 
 /**
 @brief Associates the CTF IR event \p event to the CTF IR packet
@@ -249,8 +246,7 @@ extern int bt_event_set_packet(struct bt_event *event,
 @postrefcountsame{event}
 @postsuccessrefcountretinc
 */
-extern struct bt_stream *bt_event_get_stream(
-               struct bt_event *event);
+extern struct bt_stream *bt_event_get_stream(struct bt_event *event);
 
 /** @} */
 
@@ -276,8 +272,7 @@ extern struct bt_stream *bt_event_get_stream(
 @sa bt_event_get_header(): Sets the stream event header
        field of a given event.
 */
-extern struct bt_field *bt_event_get_header(
-               struct bt_event *event);
+extern struct bt_field *bt_event_get_header(struct bt_event *event);
 
 /**
 @brief Sets the stream event header field of the CTF IR event
@@ -369,11 +364,10 @@ extern int bt_event_set_stream_event_context(struct bt_event *event,
 @postrefcountsame{event}
 @postsuccessrefcountretinc
 
-@sa bt_event_set_event_context(): Sets the event context field of a given
+@sa bt_event_set_context(): Sets the event context field of a given
        event.
 */
-extern struct bt_field *bt_event_get_event_context(
-               struct bt_event *event);
+extern struct bt_field *bt_event_get_context(struct bt_event *event);
 
 /**
 @brief Sets the event context field of the CTF IR event \p event to \p context,
@@ -398,7 +392,7 @@ bt_event_class_get_context_type() for the parent class of \p event.
 
 @sa bt_event_get_context(): Returns the context field of a given event.
 */
-extern int bt_event_set_event_context(struct bt_event *event,
+extern int bt_event_set_context(struct bt_event *event,
                struct bt_field *context);
 
 /**
@@ -412,11 +406,10 @@ extern int bt_event_set_event_context(struct bt_event *event,
 @postrefcountsame{event}
 @postsuccessrefcountretinc
 
-@sa bt_event_set_event_payload(): Sets the payload field of a given
+@sa bt_event_set_payload(): Sets the payload field of a given
        event.
 */
-extern struct bt_field *bt_event_get_event_payload(
-               struct bt_event *event);
+extern struct bt_field *bt_event_get_payload(struct bt_event *event);
 
 /**
 @brief Sets the payload field of the CTF IR event \p event to \p payload,
@@ -441,74 +434,8 @@ bt_event_class_get_payload_type() for the parent class of \p event.
 
 @sa bt_event_get_payload(): Returns the payload field of a given event.
 */
-extern int bt_event_set_event_payload(struct bt_event *event,
-               struct bt_field *payload);
-
-/** @cond DOCUMENT */
-
-/*
- * TODO: Doxygenize.
- *
- * bt_event_get_payload: get an event's field.
- *
- * Returns the field matching "name". bt_put() must be called on the
- * returned value.
- *
- * @param event Event instance.
- * @param name Event field name, see notes.
- *
- * Returns a field instance on success, NULL on error.
- *
- * Note: Passing a name will cause the function to perform a look-up by
- *     name assuming the event's payload is a structure. This will return
- *     the raw payload instance if name is NULL.
- */
-extern struct bt_field *bt_event_get_payload(struct bt_event *event,
-               const char *name);
-
-/*
- * TODO: Doxygenize.
- *
- * bt_event_get_payload_by_index: Get event's field by index.
- *
- * Returns the field associated with the provided index. bt_put()
- * must be called on the returned value. The indexes to be provided are
- * the same as can be retrieved from the event class.
- *
- * @param event Event.
- * @param index Index of field.
- *
- * Returns the event's field, NULL on error.
- *
- * Note: Will return an error if the payload's type is not a structure.
- */
-extern struct bt_field *bt_event_get_payload_by_index(
-               struct bt_event *event, uint64_t index);
-
-/*
- * TODO: Doxygenize.
- *
- * bt_event_set_payload: set an event's field.
- *
- * Set a manually allocated field as an event's payload. The event will share
- * the field's ownership by using its reference count.
- * bt_put() must be called on the returned value.
- *
- * @param event Event instance.
- * @param name Event field name, see notes.
- * @param value Instance of a field whose type corresponds to the event's field.
- *
- * Returns 0 on success, a negative value on error.
- *
- * Note: The function will return an error if a name is provided and the payload
- *     type is not a structure. If name is NULL, the payload field will be set
- *     directly and must match the event class' payload's type.
- */
 extern int bt_event_set_payload(struct bt_event *event,
-               const char *name,
-               struct bt_field *value);
-
-/** @endcond */
+               struct bt_field *payload);
 
 /** @} */
 
@@ -567,12 +494,6 @@ extern int bt_event_set_clock_value(
 
 /** @} */
 
-/* Pre-2.0 CTF writer compatibility */
-#define bt_ctf_event bt_event
-#define bt_ctf_event_create bt_event_create
-#define bt_ctf_event_get_payload bt_event_get_payload
-#define bt_ctf_event_set_payload bt_event_set_payload
-
 #ifdef __cplusplus
 }
 #endif
index 2f9611c8e8c30e4d9130a5c6e2105c8098332f89..907be9b2dcfe17b43f88df4ca43a324e3f8a6957 100644 (file)
@@ -28,6 +28,7 @@
  * http://www.efficios.com/ctf
  */
 
+#include <babeltrace/common-internal.h>
 #include <babeltrace/object-internal.h>
 #include <babeltrace/assert-internal.h>
 #include <glib.h>
@@ -55,30 +56,4 @@ BT_HIDDEN
 struct bt_field_path *bt_field_path_copy(
                struct bt_field_path *path);
 
-static inline
-GString *bt_field_path_string(struct bt_field_path *path)
-{
-       GString *str = g_string_new(NULL);
-       size_t i;
-
-       BT_ASSERT(path);
-
-       if (!str) {
-               goto end;
-       }
-
-       g_string_append_printf(str, "[%s", bt_scope_string(path->root));
-
-       for (i = 0; i < path->indexes->len; i++) {
-               int index = g_array_index(path->indexes, int, i);
-
-               g_string_append_printf(str, ", %d", index);
-       }
-
-       g_string_append(str, "]");
-
-end:
-       return str;
-}
-
 #endif /* BABELTRACE_CTF_IR_FIELD_PATH_INTERNAL */
index e418b1f3283574178ef8ab79f3b51850a922218f..70a15b0c21fd55a066e36e4936b7e2ea9dd72d75 100644 (file)
  * SOFTWARE.
  */
 
-#include <stdint.h>
-#include <babeltrace/ctf-writer/event-types.h>
-#include <babeltrace/ctf-writer/event-fields.h>
-#include <babeltrace/ctf-writer/writer.h>
-#include <babeltrace/ctf-ir/trace-internal.h>
+#include <babeltrace/assert-pre-internal.h>
 #include <babeltrace/ctf-ir/clock-class.h>
 #include <babeltrace/ctf-ir/field-types.h>
 #include <babeltrace/babeltrace-internal.h>
 #include <babeltrace/object-internal.h>
 #include <babeltrace/types.h>
+#include <stdint.h>
 #include <glib.h>
 
-typedef void (*type_freeze_func)(struct bt_field_type *);
-typedef int (*type_serialize_func)(struct bt_field_type *,
-               struct metadata_context *);
+#define BT_ASSERT_PRE_FT_COMMON_HAS_ID(_ft, _type_id, _name)           \
+       BT_ASSERT_PRE(((struct bt_field_type_common *) (_ft))->id == (_type_id), \
+               _name " has the wrong type ID: expected-type-id=%s, "   \
+               "%![ft-]+_F", bt_common_field_type_id_string(_type_id), (_ft))
+
+#define BT_ASSERT_PRE_FT_HOT(_ft, _name)                               \
+       BT_ASSERT_PRE_HOT((_ft), (_name), ": +%!+_F", (_ft))
+
+struct bt_field_common;
+struct bt_field_type_common;
+struct bt_field_type;
+
+typedef void (*bt_field_type_common_method_freeze)(
+               struct bt_field_type_common *);
+typedef int (*bt_field_type_common_method_validate)(
+               struct bt_field_type_common *);
+typedef void (*bt_field_type_common_method_set_byte_order)(
+               struct bt_field_type_common *, enum bt_byte_order);
+typedef struct bt_field_type_common *(*bt_field_type_common_method_copy)(
+               struct bt_field_type_common *);
+typedef int (*bt_field_type_common_method_compare)(
+               struct bt_field_type_common *,
+               struct bt_field_type_common *);
+
+struct bt_field_type_common_methods {
+       bt_field_type_common_method_freeze freeze;
+       bt_field_type_common_method_validate validate;
+       bt_field_type_common_method_set_byte_order set_byte_order;
+       bt_field_type_common_method_copy copy;
+       bt_field_type_common_method_compare compare;
+};
 
-struct bt_field_type {
+struct bt_field_type_common {
        struct bt_object base;
        enum bt_field_type_id id;
        unsigned int alignment;
-       type_freeze_func freeze;
-       type_serialize_func serialize;
+
+       /* Virtual table */
+       struct bt_field_type_common_methods *methods;
+
        /*
         * A type can't be modified once it is added to an event or after a
         * a field has been instanciated from it.
@@ -61,11 +88,37 @@ struct bt_field_type {
         * a valid field type are also valid (and thus frozen).
         */
        int valid;
+
+       /*
+        * Specialized data for either CTF IR or CTF writer APIs.
+        * Having this here ensures that:
+        *
+        * * The type-specific common data is always found at the same
+        *   offset when the common API has a `struct
+        *   bt_field_type_common *` so that you can cast it to `struct
+        *   bt_field_type_common_integer *` for example and access the
+        *   common integer field type fields.
+        *
+        * * The specific CTF IR and CTF writer APIs can access their
+        *   specific field type fields in this union at an offset known
+        *   at build time. This avoids a pointer to specific data so
+        *   that all the fields, common or specific, of a CTF IR
+        *   integer field type or of a CTF writer integer field type,
+        *   for example, are contained within the same contiguous block
+        *   of memory.
+        */
+       union {
+               struct {
+               } ir;
+               struct {
+                       void *serialize_func;
+               } writer;
+       } spec;
 };
 
-struct bt_field_type_integer {
-       struct bt_field_type parent;
-       struct bt_clock_class *mapped_clock;
+struct bt_field_type_common_integer {
+       struct bt_field_type_common common;
+       struct bt_clock_class *mapped_clock_class;
        enum bt_byte_order user_byte_order;
        bt_bool is_signed;
        unsigned int size;
@@ -86,9 +139,9 @@ struct enumeration_mapping {
        GQuark string;
 };
 
-struct bt_field_type_enumeration {
-       struct bt_field_type parent;
-       struct bt_field_type *container;
+struct bt_field_type_common_enumeration {
+       struct bt_field_type_common common;
+       struct bt_field_type_common_integer *container_ft;
        GPtrArray *entries; /* Array of ptrs to struct enumeration_mapping */
        /* Only set during validation. */
        bt_bool has_overlapping_ranges;
@@ -102,7 +155,7 @@ enum bt_field_type_enumeration_mapping_iterator_type {
 
 struct bt_field_type_enumeration_mapping_iterator {
        struct bt_object base;
-       struct bt_field_type_enumeration *enumeration_type;
+       struct bt_field_type_common_enumeration *enumeration_ft;
        enum bt_field_type_enumeration_mapping_iterator_type type;
        int index;
        union {
@@ -112,233 +165,554 @@ struct bt_field_type_enumeration_mapping_iterator {
        } u;
 };
 
-struct bt_field_type_floating_point {
-       struct bt_field_type parent;
+struct bt_field_type_common_floating_point {
+       struct bt_field_type_common common;
        enum bt_byte_order user_byte_order;
        unsigned int exp_dig;
        unsigned int mant_dig;
 };
 
-struct structure_field {
+struct structure_field_common {
+       struct bt_field_type_common common;
        GQuark name;
-       struct bt_field_type *type;
+       struct bt_field_type_common *type;
 };
 
-struct bt_field_type_structure {
-       struct bt_field_type parent;
+struct bt_field_type_common_structure {
+       struct bt_field_type_common common;
        GHashTable *field_name_to_index;
-       GPtrArray *fields; /* Array of pointers to struct structure_field */
+       GPtrArray *fields; /* Array of pointers to struct structure_field_common */
 };
 
-struct bt_field_type_variant {
-       struct bt_field_type parent;
+struct bt_field_type_common_variant {
+       struct bt_field_type_common common;
        GString *tag_name;
-       struct bt_field_type_enumeration *tag;
+       struct bt_field_type_common_enumeration *tag_ft;
        struct bt_field_path *tag_field_path;
        GHashTable *field_name_to_index;
-       GPtrArray *fields; /* Array of pointers to struct structure_field */
+       GPtrArray *fields; /* Array of pointers to struct structure_field_common */
 };
 
-struct bt_field_type_array {
-       struct bt_field_type parent;
-       struct bt_field_type *element_type;
+struct bt_field_type_common_array {
+       struct bt_field_type_common common;
+       struct bt_field_type_common *element_ft;
        unsigned int length; /* Number of elements */
 };
 
-struct bt_field_type_sequence {
-       struct bt_field_type parent;
-       struct bt_field_type *element_type;
+struct bt_field_type_common_sequence {
+       struct bt_field_type_common common;
+       struct bt_field_type_common *element_ft;
        GString *length_field_name;
        struct bt_field_path *length_field_path;
 };
 
-struct bt_field_type_string {
-       struct bt_field_type parent;
+struct bt_field_type_common_string {
+       struct bt_field_type_common common;
        enum bt_string_encoding encoding;
 };
 
 #ifdef BT_DEV_MODE
-# define bt_field_type_freeze  _bt_field_type_freeze
+# define bt_field_type_freeze          _bt_field_type_freeze
+# define bt_field_type_common_freeze   _bt_field_type_common_freeze
 #else
 # define bt_field_type_freeze(_ft)
+# define bt_field_type_common_freeze(_ft)
 #endif
 
+typedef struct bt_field_common *(* bt_field_common_create_func)(
+               struct bt_field_type_common *);
+
 BT_HIDDEN
-void _bt_field_type_freeze(struct bt_field_type *type);
+void bt_field_type_common_initialize(struct bt_field_type_common *ft,
+               bool init_bo, bt_object_release_func release_func,
+               struct bt_field_type_common_methods *methods);
 
 BT_HIDDEN
-struct bt_field_type *bt_field_type_variant_get_field_type_signed(
-               struct bt_field_type_variant *variant, int64_t tag_value);
+void bt_field_type_common_integer_initialize(
+               struct bt_field_type_common *ft,
+               unsigned int size, bt_object_release_func release_func,
+               struct bt_field_type_common_methods *methods);
 
 BT_HIDDEN
-struct bt_field_type *bt_field_type_variant_get_field_type_unsigned(
-               struct bt_field_type_variant *variant, uint64_t tag_value);
+void bt_field_type_common_floating_point_initialize(
+               struct bt_field_type_common *ft,
+               bt_object_release_func release_func,
+               struct bt_field_type_common_methods *methods);
 
 BT_HIDDEN
-int bt_field_type_serialize(struct bt_field_type *type,
-               struct metadata_context *context);
+void bt_field_type_common_enumeration_initialize(
+               struct bt_field_type_common *ft,
+               struct bt_field_type_common *container_ft,
+               bt_object_release_func release_func,
+               struct bt_field_type_common_methods *methods);
 
 BT_HIDDEN
-int bt_field_type_validate(struct bt_field_type *type);
+void bt_field_type_common_string_initialize(
+               struct bt_field_type_common *ft,
+               bt_object_release_func release_func,
+               struct bt_field_type_common_methods *methods);
 
 BT_HIDDEN
-int bt_field_type_structure_get_field_name_index(
-               struct bt_field_type *structure, const char *name);
+void bt_field_type_common_structure_initialize(
+               struct bt_field_type_common *ft,
+               bt_object_release_func release_func,
+               struct bt_field_type_common_methods *methods);
 
 BT_HIDDEN
-int bt_field_type_structure_replace_field(struct bt_field_type *type,
-               const char *field_name, struct bt_field_type *field_type);
+void bt_field_type_common_array_initialize(
+               struct bt_field_type_common *ft,
+               struct bt_field_type_common *element_ft,
+               unsigned int length, bt_object_release_func release_func,
+               struct bt_field_type_common_methods *methods);
 
 BT_HIDDEN
-int bt_field_type_variant_get_field_name_index(
-               struct bt_field_type *variant, const char *name);
+void bt_field_type_common_sequence_initialize(
+               struct bt_field_type_common *ft,
+               struct bt_field_type_common *element_ft,
+               const char *length_field_name,
+               bt_object_release_func release_func,
+               struct bt_field_type_common_methods *methods);
 
 BT_HIDDEN
-int bt_field_type_sequence_set_length_field_path(
-               struct bt_field_type *type,
-               struct bt_field_path *path);
+void bt_field_type_common_variant_initialize(
+               struct bt_field_type_common *ft,
+               struct bt_field_type_common *tag_ft,
+               const char *tag_name,
+               bt_object_release_func release_func,
+               struct bt_field_type_common_methods *methods);
 
 BT_HIDDEN
-int bt_field_type_variant_set_tag_field_path(struct bt_field_type *type,
-               struct bt_field_path *path);
+void bt_field_type_common_integer_destroy(struct bt_object *obj);
 
 BT_HIDDEN
-int bt_field_type_variant_set_tag_field_type(struct bt_field_type *type,
-               struct bt_field_type *tag_type);
+void bt_field_type_common_floating_point_destroy(struct bt_object *obj);
 
 BT_HIDDEN
-int bt_field_type_array_set_element_type(struct bt_field_type *array,
-               struct bt_field_type *element_type);
+void bt_field_type_common_enumeration_destroy_recursive(struct bt_object *obj);
 
 BT_HIDDEN
-int bt_field_type_sequence_set_element_type(struct bt_field_type *array,
-               struct bt_field_type *element_type);
+void bt_field_type_common_string_destroy(struct bt_object *obj);
 
 BT_HIDDEN
-int64_t bt_field_type_get_field_count(struct bt_field_type *type);
+void bt_field_type_common_structure_destroy_recursive(struct bt_object *obj);
 
 BT_HIDDEN
-struct bt_field_type *bt_field_type_get_field_at_index(
-               struct bt_field_type *type, int index);
+void bt_field_type_common_array_destroy_recursive(struct bt_object *obj);
 
 BT_HIDDEN
-int bt_field_type_get_field_index(struct bt_field_type *type,
-               const char *name);
+void bt_field_type_common_sequence_destroy_recursive(struct bt_object *obj);
+
+BT_HIDDEN
+void bt_field_type_common_variant_destroy_recursive(struct bt_object *obj);
+
+BT_HIDDEN
+int bt_field_type_common_integer_validate(struct bt_field_type_common *ft);
+
+BT_HIDDEN
+int bt_field_type_common_enumeration_validate_recursive(
+               struct bt_field_type_common *ft);
+
+BT_HIDDEN
+int bt_field_type_common_sequence_validate_recursive(
+               struct bt_field_type_common *ft);
+
+BT_HIDDEN
+int bt_field_type_common_array_validate_recursive(
+               struct bt_field_type_common *ft);
+
+BT_HIDDEN
+int bt_field_type_common_structure_validate_recursive(
+               struct bt_field_type_common *ft);
+
+BT_HIDDEN
+int bt_field_type_common_variant_validate_recursive(
+               struct bt_field_type_common *type);
+
+BT_HIDDEN
+int bt_field_type_common_validate(struct bt_field_type_common *ft);
+
+BT_HIDDEN
+int bt_field_type_common_integer_get_size(struct bt_field_type_common *ft);
+
+BT_HIDDEN
+bt_bool bt_field_type_common_integer_is_signed(struct bt_field_type_common *ft);
+
+BT_HIDDEN
+int bt_field_type_common_integer_set_is_signed(struct bt_field_type_common *ft,
+               bt_bool is_signed);
+
+BT_HIDDEN
+int bt_field_type_common_integer_set_size(struct bt_field_type_common *ft,
+               unsigned int size);
+
+BT_HIDDEN
+enum bt_integer_base bt_field_type_common_integer_get_base(
+               struct bt_field_type_common *ft);
 
 BT_HIDDEN
-int bt_field_type_integer_set_mapped_clock_class_no_check(
-               struct bt_field_type *int_field_type,
+int bt_field_type_common_integer_set_base(struct bt_field_type_common *ft,
+               enum bt_integer_base base);
+
+BT_HIDDEN
+enum bt_string_encoding bt_field_type_common_integer_get_encoding(
+               struct bt_field_type_common *ft);
+
+BT_HIDDEN
+int bt_field_type_common_integer_set_encoding(struct bt_field_type_common *ft,
+               enum bt_string_encoding encoding);
+
+BT_HIDDEN
+struct bt_clock_class *bt_field_type_common_integer_get_mapped_clock_class(
+               struct bt_field_type_common *ft);
+
+BT_HIDDEN
+int bt_field_type_common_integer_set_mapped_clock_class_no_check_frozen(
+               struct bt_field_type_common *ft,
                struct bt_clock_class *clock_class);
 
-static inline
-const char *bt_field_type_id_string(enum bt_field_type_id type_id)
-{
-       switch (type_id) {
-       case BT_FIELD_TYPE_ID_UNKNOWN:
-               return "BT_FIELD_TYPE_ID_UNKNOWN";
-       case BT_FIELD_TYPE_ID_INTEGER:
-               return "BT_FIELD_TYPE_ID_INTEGER";
-       case BT_FIELD_TYPE_ID_FLOAT:
-               return "BT_FIELD_TYPE_ID_FLOAT";
-       case BT_FIELD_TYPE_ID_ENUM:
-               return "BT_FIELD_TYPE_ID_ENUM";
-       case BT_FIELD_TYPE_ID_STRING:
-               return "BT_FIELD_TYPE_ID_STRING";
-       case BT_FIELD_TYPE_ID_STRUCT:
-               return "BT_FIELD_TYPE_ID_STRUCT";
-       case BT_FIELD_TYPE_ID_ARRAY:
-               return "BT_FIELD_TYPE_ID_ARRAY";
-       case BT_FIELD_TYPE_ID_SEQUENCE:
-               return "BT_FIELD_TYPE_ID_SEQUENCE";
-       case BT_FIELD_TYPE_ID_VARIANT:
-               return "BT_FIELD_TYPE_ID_VARIANT";
-       default:
-               return "(unknown)";
-       }
-};
+BT_HIDDEN
+int bt_field_type_common_integer_set_mapped_clock_class(
+               struct bt_field_type_common *ft,
+               struct bt_clock_class *clock_class);
 
-static inline
-const char *bt_byte_order_string(enum bt_byte_order bo)
-{
-       switch (bo) {
-       case BT_BYTE_ORDER_UNKNOWN:
-               return "BT_BYTE_ORDER_UNKNOWN";
-       case BT_BYTE_ORDER_UNSPECIFIED:
-               return "BT_BYTE_ORDER_UNSPECIFIED";
-       case BT_BYTE_ORDER_NATIVE:
-               return "BT_BYTE_ORDER_NATIVE";
-       case BT_BYTE_ORDER_LITTLE_ENDIAN:
-               return "BT_BYTE_ORDER_LITTLE_ENDIAN";
-       case BT_BYTE_ORDER_BIG_ENDIAN:
-               return "BT_BYTE_ORDER_BIG_ENDIAN";
-       case BT_BYTE_ORDER_NETWORK:
-               return "BT_BYTE_ORDER_NETWORK";
-       default:
-               return "(unknown)";
-       }
-};
+BT_HIDDEN
+struct bt_field_type_enumeration_mapping_iterator *
+bt_field_type_common_enumeration_find_mappings_by_name(
+               struct bt_field_type_common *ft, const char *name);
 
-static inline
-const char *bt_string_encoding_string(enum bt_string_encoding encoding)
-{
-       switch (encoding) {
-       case BT_STRING_ENCODING_UNKNOWN:
-               return "BT_STRING_ENCODING_UNKNOWN";
-       case BT_STRING_ENCODING_NONE:
-               return "BT_STRING_ENCODING_NONE";
-       case BT_STRING_ENCODING_UTF8:
-               return "BT_STRING_ENCODING_UTF8";
-       case BT_STRING_ENCODING_ASCII:
-               return "BT_STRING_ENCODING_ASCII";
-       default:
-               return "(unknown)";
-       }
-};
+BT_HIDDEN
+struct bt_field_type_enumeration_mapping_iterator *
+bt_field_type_common_enumeration_signed_find_mappings_by_value(
+               struct bt_field_type_common *ft, int64_t value);
+
+BT_HIDDEN
+struct bt_field_type_enumeration_mapping_iterator *
+bt_field_type_common_enumeration_unsigned_find_mappings_by_value(
+               struct bt_field_type_common *ft, uint64_t value);
+
+BT_HIDDEN
+int bt_field_type_common_enumeration_signed_get_mapping_by_index(
+               struct bt_field_type_common *ft, uint64_t index,
+               const char **mapping_name, int64_t *range_begin,
+               int64_t *range_end);
+
+BT_HIDDEN
+int bt_field_type_common_enumeration_unsigned_get_mapping_by_index(
+               struct bt_field_type_common *ft, uint64_t index,
+               const char **mapping_name, uint64_t *range_begin,
+               uint64_t *range_end);
+
+BT_HIDDEN
+struct bt_field_type_common *bt_field_type_common_enumeration_get_container_field_type(
+               struct bt_field_type_common *ft);
+
+BT_HIDDEN
+int bt_field_type_common_enumeration_signed_add_mapping(
+               struct bt_field_type_common *ft, const char *string,
+               int64_t range_start, int64_t range_end);
+
+BT_HIDDEN
+int bt_field_type_common_enumeration_unsigned_add_mapping(
+               struct bt_field_type_common *ft, const char *string,
+               uint64_t range_start, uint64_t range_end);
+
+BT_HIDDEN
+int64_t bt_field_type_common_enumeration_get_mapping_count(
+               struct bt_field_type_common *ft);
+
+BT_HIDDEN
+int bt_field_type_common_floating_point_get_exponent_digits(
+               struct bt_field_type_common *ft);
+
+BT_HIDDEN
+int bt_field_type_common_floating_point_set_exponent_digits(
+               struct bt_field_type_common *ft,
+               unsigned int exponent_digits);
+
+BT_HIDDEN
+int bt_field_type_common_floating_point_get_mantissa_digits(
+               struct bt_field_type_common *type);
+
+BT_HIDDEN
+int bt_field_type_common_floating_point_set_mantissa_digits(
+               struct bt_field_type_common *ft, unsigned int mantissa_digits);
+
+BT_HIDDEN
+int bt_field_type_common_structure_replace_field(
+               struct bt_field_type_common *ft,
+               const char *field_name,
+               struct bt_field_type_common *field_type);
 
-static inline
-const char *bt_integer_base_string(enum bt_integer_base base)
-{
-       switch (base) {
-       case BT_INTEGER_BASE_UNKNOWN:
-               return "BT_INTEGER_BASE_UNKNOWN";
-       case BT_INTEGER_BASE_UNSPECIFIED:
-               return "BT_INTEGER_BASE_UNSPECIFIED";
-       case BT_INTEGER_BASE_BINARY:
-               return "BT_INTEGER_BASE_BINARY";
-       case BT_INTEGER_BASE_OCTAL:
-               return "BT_INTEGER_BASE_OCTAL";
-       case BT_INTEGER_BASE_DECIMAL:
-               return "BT_INTEGER_BASE_DECIMAL";
-       case BT_INTEGER_BASE_HEXADECIMAL:
-               return "BT_INTEGER_BASE_HEXADECIMAL";
-       default:
-               return "(unknown)";
-       }
-}
-
-static inline
-const char *bt_scope_string(enum bt_scope scope)
-{
-       switch (scope) {
-       case BT_SCOPE_UNKNOWN:
-               return "BT_SCOPE_UNKNOWN";
-       case BT_SCOPE_TRACE_PACKET_HEADER:
-               return "BT_SCOPE_TRACE_PACKET_HEADER";
-       case BT_SCOPE_STREAM_PACKET_CONTEXT:
-               return "BT_SCOPE_STREAM_PACKET_CONTEXT";
-       case BT_SCOPE_STREAM_EVENT_HEADER:
-               return "BT_SCOPE_STREAM_EVENT_HEADER";
-       case BT_SCOPE_STREAM_EVENT_CONTEXT:
-               return "BT_SCOPE_STREAM_EVENT_CONTEXT";
-       case BT_SCOPE_EVENT_CONTEXT:
-               return "BT_SCOPE_EVENT_CONTEXT";
-       case BT_SCOPE_EVENT_PAYLOAD:
-               return "BT_SCOPE_EVENT_PAYLOAD";
-       case BT_SCOPE_ENV:
-               return "BT_SCOPE_ENV";
-       default:
-               return "(unknown)";
-       }
-}
+BT_HIDDEN
+int bt_field_type_common_structure_add_field(struct bt_field_type_common *ft,
+               struct bt_field_type_common *field_type,
+               const char *field_name);
+
+BT_HIDDEN
+int64_t bt_field_type_common_structure_get_field_count(
+               struct bt_field_type_common *ft);
+
+BT_HIDDEN
+int bt_field_type_common_structure_get_field_by_index(
+               struct bt_field_type_common *ft,
+               const char **field_name,
+               struct bt_field_type_common **field_type, uint64_t index);
+
+BT_HIDDEN
+struct bt_field_type_common *bt_field_type_common_structure_get_field_type_by_name(
+               struct bt_field_type_common *ft, const char *name);
+
+BT_HIDDEN
+struct bt_field_type_common *bt_field_type_common_variant_get_tag_field_type(
+               struct bt_field_type_common *ft);
+
+BT_HIDDEN
+const char *bt_field_type_common_variant_get_tag_name(
+               struct bt_field_type_common *ft);
+
+BT_HIDDEN
+int bt_field_type_common_variant_set_tag_name(
+               struct bt_field_type_common *ft, const char *name);
+
+BT_HIDDEN
+int bt_field_type_common_variant_add_field(struct bt_field_type_common *ft,
+               struct bt_field_type_common *field_type,
+               const char *field_name);
+
+BT_HIDDEN
+struct bt_field_type_common *bt_field_type_common_variant_get_field_type_by_name(
+               struct bt_field_type_common *ft,
+               const char *field_name);
+
+BT_HIDDEN
+struct bt_field_type_common *bt_field_type_common_variant_get_field_type_from_tag(
+               struct bt_field_type_common *ft,
+               struct bt_field_common *tag_field,
+               bt_field_common_create_func field_create_func);
+
+BT_HIDDEN
+int64_t bt_field_type_common_variant_get_field_count(
+               struct bt_field_type_common *ft);
+
+BT_HIDDEN
+int bt_field_type_common_variant_get_field_by_index(
+               struct bt_field_type_common *ft,
+               const char **field_name,
+               struct bt_field_type_common **field_type, uint64_t index);
+
+BT_HIDDEN
+struct bt_field_type_common *bt_field_type_common_array_get_element_field_type(
+               struct bt_field_type_common *ft);
+
+BT_HIDDEN
+int bt_field_type_common_array_set_element_field_type(
+               struct bt_field_type_common *ft,
+               struct bt_field_type_common *element_ft);
+
+BT_HIDDEN
+int64_t bt_field_type_common_array_get_length(struct bt_field_type_common *ft);
+
+BT_HIDDEN
+struct bt_field_type_common *bt_field_type_common_sequence_get_element_field_type(
+               struct bt_field_type_common *ft);
+
+BT_HIDDEN
+int bt_field_type_common_sequence_set_element_field_type(
+               struct bt_field_type_common *ft,
+               struct bt_field_type_common *element_ft);
+
+BT_HIDDEN
+const char *bt_field_type_common_sequence_get_length_field_name(
+               struct bt_field_type_common *ft);
+
+BT_HIDDEN
+enum bt_string_encoding bt_field_type_common_string_get_encoding(
+               struct bt_field_type_common *ft);
+
+BT_HIDDEN
+int bt_field_type_common_string_set_encoding(struct bt_field_type_common *ft,
+               enum bt_string_encoding encoding);
+
+BT_HIDDEN
+int bt_field_type_common_get_alignment(struct bt_field_type_common *type);
+
+BT_HIDDEN
+int bt_field_type_common_set_alignment(struct bt_field_type_common *ft,
+               unsigned int alignment);
+
+BT_HIDDEN
+enum bt_byte_order bt_field_type_common_get_byte_order(
+               struct bt_field_type_common *ft);
+
+BT_HIDDEN
+int bt_field_type_common_set_byte_order(struct bt_field_type_common *ft,
+               enum bt_byte_order byte_order);
+
+BT_HIDDEN
+enum bt_field_type_id bt_field_type_common_get_type_id(
+               struct bt_field_type_common *ft);
+
+BT_HIDDEN
+void _bt_field_type_common_freeze(struct bt_field_type_common *ft);
+
+BT_HIDDEN
+void _bt_field_type_freeze(struct bt_field_type *ft);
+
+BT_HIDDEN
+struct bt_field_type_common *bt_field_type_common_variant_get_field_type_signed(
+               struct bt_field_type_common_variant *var_ft,
+               int64_t tag_value);
+
+BT_HIDDEN
+struct bt_field_type_common *bt_field_type_common_variant_get_field_type_unsigned(
+               struct bt_field_type_common_variant *var_ft,
+               uint64_t tag_value);
+
+BT_HIDDEN
+struct bt_field_type_common *bt_field_type_common_copy(
+               struct bt_field_type_common *ft);
+
+BT_HIDDEN
+int bt_field_type_common_structure_get_field_name_index(
+               struct bt_field_type_common *ft, const char *name);
+
+BT_HIDDEN
+int bt_field_type_common_variant_get_field_name_index(
+               struct bt_field_type_common *ft, const char *name);
+
+BT_HIDDEN
+int bt_field_type_common_sequence_set_length_field_path(
+               struct bt_field_type_common *ft, struct bt_field_path *path);
+
+BT_HIDDEN
+int bt_field_type_common_variant_set_tag_field_path(
+               struct bt_field_type_common *ft,
+               struct bt_field_path *path);
+
+BT_HIDDEN
+int bt_field_type_common_variant_set_tag_field_type(
+               struct bt_field_type_common *ft,
+               struct bt_field_type_common *tag_ft);
+
+BT_HIDDEN
+void bt_field_type_common_generic_freeze(struct bt_field_type_common *ft);
+
+BT_HIDDEN
+void bt_field_type_common_enumeration_freeze_recursive(
+               struct bt_field_type_common *ft);
+
+BT_HIDDEN
+void bt_field_type_common_structure_freeze_recursive(
+               struct bt_field_type_common *ft);
+
+BT_HIDDEN
+void bt_field_type_common_variant_freeze_recursive(
+               struct bt_field_type_common *ft);
+
+BT_HIDDEN
+void bt_field_type_common_array_freeze_recursive(
+               struct bt_field_type_common *ft);
+
+BT_HIDDEN
+void bt_field_type_common_sequence_freeze_recursive(
+               struct bt_field_type_common *type);
+
+BT_HIDDEN
+void bt_field_type_common_integer_set_byte_order(
+               struct bt_field_type_common *ft, enum bt_byte_order byte_order);
+
+BT_HIDDEN
+void bt_field_type_common_enumeration_set_byte_order_recursive(
+               struct bt_field_type_common *ft, enum bt_byte_order byte_order);
+
+BT_HIDDEN
+void bt_field_type_common_floating_point_set_byte_order(
+               struct bt_field_type_common *ft, enum bt_byte_order byte_order);
+
+BT_HIDDEN
+void bt_field_type_common_structure_set_byte_order_recursive(
+               struct bt_field_type_common *ft,
+               enum bt_byte_order byte_order);
+
+BT_HIDDEN
+void bt_field_type_common_variant_set_byte_order_recursive(
+               struct bt_field_type_common *ft,
+               enum bt_byte_order byte_order);
+
+BT_HIDDEN
+void bt_field_type_common_array_set_byte_order_recursive(
+               struct bt_field_type_common *ft,
+               enum bt_byte_order byte_order);
+
+BT_HIDDEN
+void bt_field_type_common_sequence_set_byte_order_recursive(
+               struct bt_field_type_common *ft,
+               enum bt_byte_order byte_order);
+
+BT_HIDDEN
+int bt_field_type_common_integer_compare(struct bt_field_type_common *ft_a,
+               struct bt_field_type_common *ft_b);
+
+BT_HIDDEN
+int bt_field_type_common_floating_point_compare(
+               struct bt_field_type_common *ft_a,
+               struct bt_field_type_common *ft_b);
+
+BT_HIDDEN
+int bt_field_type_common_enumeration_compare_recursive(
+               struct bt_field_type_common *ft_a,
+               struct bt_field_type_common *ft_b);
+
+BT_HIDDEN
+int bt_field_type_common_string_compare(struct bt_field_type_common *ft_a,
+               struct bt_field_type_common *ft_b);
+
+BT_HIDDEN
+int bt_field_type_common_structure_compare_recursive(
+               struct bt_field_type_common *ft_a,
+               struct bt_field_type_common *ft_b);
+
+BT_HIDDEN
+int bt_field_type_common_variant_compare_recursive(
+               struct bt_field_type_common *ft_a,
+               struct bt_field_type_common *ft_b);
+
+BT_HIDDEN
+int bt_field_type_common_array_compare_recursive(
+               struct bt_field_type_common *ft_a,
+               struct bt_field_type_common *ft_b);
+
+BT_HIDDEN
+int bt_field_type_common_sequence_compare_recursive(
+               struct bt_field_type_common *ft_a,
+               struct bt_field_type_common *ft_b);
+
+BT_HIDDEN
+int bt_field_type_common_compare(struct bt_field_type_common *ft_a,
+               struct bt_field_type_common *ft_b);
+
+BT_HIDDEN
+int64_t bt_field_type_common_get_field_count(struct bt_field_type_common *ft);
+
+BT_HIDDEN
+struct bt_field_type_common *bt_field_type_common_get_field_at_index(
+               struct bt_field_type_common *ft, int index);
+
+BT_HIDDEN
+int bt_field_type_common_get_field_index(struct bt_field_type_common *ft,
+               const char *name);
+
+BT_HIDDEN
+struct bt_field_path *bt_field_type_common_variant_get_tag_field_path(
+               struct bt_field_type_common *ft);
+
+BT_HIDDEN
+struct bt_field_path *bt_field_type_common_sequence_get_length_field_path(
+               struct bt_field_type_common *ft);
+
+BT_HIDDEN
+int bt_field_type_common_validate_single_clock_class(
+               struct bt_field_type_common *ft,
+               struct bt_clock_class **expected_clock_class);
 
 #endif /* BABELTRACE_CTF_IR_FIELD_TYPES_INTERNAL_H */
index 6c69bb70768029fa69ae9cee67954eba1e50dc89..f1f6ef7acbe1bb17b57aeb40c8a1bf6bbc665acd 100644 (file)
@@ -59,17 +59,17 @@ In the CTF IR hierarchy, you can set the root field types of three
 objects:
 
 - \ref ctfirtraceclass
-  - Trace packet header field type: bt_trace_set_packet_header_type().
+  - Trace packet header field type: bt_trace_set_packet_header_field_type().
 - \ref ctfirstreamclass
   - Stream packet context field type:
-    bt_stream_class_set_packet_context_type().
+    bt_stream_class_set_packet_context_field_type().
   - Stream event header field type:
-    bt_stream_class_set_event_header_type().
+    bt_stream_class_set_event_header_field_type().
   - Stream event context field type:
-    bt_stream_class_set_event_context_type().
+    bt_stream_class_set_event_context_field_type().
 - \ref ctfireventclass
-  - Event context field type: bt_event_class_set_context_type().
-  - Event payload field type: bt_event_class_set_payload_type().
+  - Event context field type: bt_event_class_set_context_field_type().
+  - Event payload field type: bt_event_class_set_payload_field_type().
 
 As of Babeltrace \btversion, those six previous "root" field types
 \em must be @structft objects.
@@ -1213,8 +1213,8 @@ An enumeration mapping has:
   value, both included in the range.
 
 You can add a mapping to an enumeration field type with
-bt_field_type_enumeration_add_mapping_signed() or
-bt_field_type_enumeration_add_mapping_unsigned(), depending on the
+bt_field_type_enumeration_signed_add_mapping() or
+bt_field_type_enumeration_unsigned_add_mapping(), depending on the
 signedness of the wrapped @intft.
 
 You can find mappings by name or by value with the following find
@@ -1222,10 +1222,10 @@ operations:
 
 - bt_field_type_enumeration_find_mappings_by_name(): Finds the
   mappings with a given name.
-- bt_field_type_enumeration_find_mappings_by_unsigned_value():
+- bt_field_type_enumeration_unsigned_find_mappings_by_value():
   Finds the mappings which contain a given unsigned value in their
   range.
-- bt_field_type_enumeration_find_mappings_by_signed_value():
+- bt_field_type_enumeration_signed_find_mappings_by_value():
   Finds the mappings which contain a given signed value in their range.
 
 Those functions return a @enumftiter on the result set of the find
@@ -1293,7 +1293,7 @@ extern struct bt_field_type *bt_field_type_enumeration_create(
 @postsuccessrefcountretinc
 */
 extern
-struct bt_field_type *bt_field_type_enumeration_get_container_type(
+struct bt_field_type *bt_field_type_enumeration_get_container_field_type(
                struct bt_field_type *enum_field_type);
 
 /**
@@ -1318,7 +1318,7 @@ extern int64_t bt_field_type_enumeration_get_mapping_count(
        \p enum_field_type at index \p index.
 
 The @intft wrapped by \p enum_field_type, as returned by
-bt_field_type_enumeration_get_container_type(), must be \b signed
+bt_field_type_enumeration_get_container_field_type(), must be \b signed
 to use this function.
 
 On success, \p enum_field_type remains the sole owner of \p *name.
@@ -1347,11 +1347,11 @@ On success, \p enum_field_type remains the sole owner of \p *name.
        bt_field_type_enumeration_get_mapping_count()).
 @postrefcountsame{enum_field_type}
 
-@sa bt_field_type_enumeration_get_mapping_unsigned(): Returns the
+@sa bt_field_type_enumeration_unsigned_get_mapping_by_index(): Returns the
        unsigned mapping contained by a given enumeration field type
        at a given index.
 */
-extern int bt_field_type_enumeration_get_mapping_signed(
+extern int bt_field_type_enumeration_signed_get_mapping_by_index(
                struct bt_field_type *enum_field_type, uint64_t index,
                const char **name, int64_t *range_begin, int64_t *range_end);
 
@@ -1360,7 +1360,7 @@ extern int bt_field_type_enumeration_get_mapping_signed(
        \p enum_field_type at index \p index.
 
 The @intft wrapped by \p enum_field_type, as returned by
-bt_field_type_enumeration_get_container_type(), must be
+bt_field_type_enumeration_get_container_field_type(), must be
 \b unsigned to use this function.
 
 On success, \p enum_field_type remains the sole owner of \p *name.
@@ -1389,11 +1389,11 @@ On success, \p enum_field_type remains the sole owner of \p *name.
        bt_field_type_enumeration_get_mapping_count()).
 @postrefcountsame{enum_field_type}
 
-@sa bt_field_type_enumeration_get_mapping_signed(): Returns the
+@sa bt_field_type_enumeration_signed_get_mapping_by_index(): Returns the
        signed mapping contained by a given enumeration field type
        at a given index.
 */
-extern int bt_field_type_enumeration_get_mapping_unsigned(
+extern int bt_field_type_enumeration_unsigned_get_mapping_by_index(
                struct bt_field_type *enum_field_type, uint64_t index,
                const char **name, uint64_t *range_begin,
                uint64_t *range_end);
@@ -1422,10 +1422,10 @@ operation. See \ref ctfirenumftmappingiter for more details.
 @post <strong>On success</strong>, the returned @enumftiter can iterate
        on at least one mapping.
 
-@sa bt_field_type_enumeration_find_mappings_by_signed_value(): Finds
+@sa bt_field_type_enumeration_signed_find_mappings_by_value(): Finds
        the mappings of a given enumeration field type which contain
        a given signed value in their range.
-@sa bt_field_type_enumeration_find_mappings_by_unsigned_value(): Finds
+@sa bt_field_type_enumeration_unsigned_find_mappings_by_value(): Finds
        the mappings of a given enumeration field type which contain
        a given unsigned value in their range.
 */
@@ -1460,12 +1460,12 @@ operation. See \ref ctfirenumftmappingiter for more details.
 @sa bt_field_type_enumeration_find_mappings_by_name(): Finds the
        mappings of a given enumeration field type which have a given
        name.
-@sa bt_field_type_enumeration_find_mappings_by_unsigned_value(): Finds
+@sa bt_field_type_enumeration_unsigned_find_mappings_by_value(): Finds
        the mappings of a given enumeration field type which contain
        a given unsigned value in their range.
 */
 extern struct bt_field_type_enumeration_mapping_iterator *
-bt_field_type_enumeration_find_mappings_by_signed_value(
+bt_field_type_enumeration_signed_find_mappings_by_value(
                struct bt_field_type *enum_field_type,
                int64_t value);
 
@@ -1496,12 +1496,12 @@ operation. See \ref ctfirenumftmappingiter for more details.
 @sa bt_field_type_enumeration_find_mappings_by_name(): Finds the
        mappings of a given enumeration field type which have a given
        name.
-@sa bt_field_type_enumeration_find_mappings_by_signed_value(): Finds
+@sa bt_field_type_enumeration_signed_find_mappings_by_value(): Finds
        the mappings of a given enumeration field type which contain
        a given unsigned value in their range.
 */
 extern struct bt_field_type_enumeration_mapping_iterator *
-bt_field_type_enumeration_find_mappings_by_unsigned_value(
+bt_field_type_enumeration_unsigned_find_mappings_by_value(
                struct bt_field_type *enum_field_type,
                uint64_t value);
 
@@ -1514,7 +1514,7 @@ Make \p range_begin and \p range_end the same value to add a mapping
 to a single value.
 
 The @intft wrapped by \p enum_field_type, as returned by
-bt_field_type_enumeration_get_container_type(), must be
+bt_field_type_enumeration_get_container_field_type(), must be
 \b signed to use this function.
 
 A mapping in \p enum_field_type can exist with the name \p name.
@@ -1537,10 +1537,10 @@ A mapping in \p enum_field_type can exist with the name \p name.
 @pre \p range_end is greater than or equal to \p range_begin.
 @postrefcountsame{enum_field_type}
 
-@sa bt_field_type_enumeration_add_mapping_unsigned(): Adds an
+@sa bt_field_type_enumeration_unsigned_add_mapping(): Adds an
        unsigned mapping to a given enumeration field type.
 */
-extern int bt_field_type_enumeration_add_mapping_signed(
+extern int bt_field_type_enumeration_signed_add_mapping(
                struct bt_field_type *enum_field_type, const char *name,
                int64_t range_begin, int64_t range_end);
 
@@ -1553,7 +1553,7 @@ Make \p range_begin and \p range_end the same value to add a mapping
 to a single value.
 
 The @intft wrapped by \p enum_field_type, as returned by
-bt_field_type_enumeration_get_container_type(), must be
+bt_field_type_enumeration_get_container_field_type(), must be
 \b unsigned to use this function.
 
 A mapping in \p enum_field_type can exist with the name \p name.
@@ -1576,10 +1576,10 @@ A mapping in \p enum_field_type can exist with the name \p name.
 @pre \p range_end is greater than or equal to \p range_begin.
 @postrefcountsame{enum_field_type}
 
-@sa bt_field_type_enumeration_add_mapping_signed(): Adds a signed
+@sa bt_field_type_enumeration_signed_add_mapping(): Adds a signed
        mapping to a given enumeration field type.
 */
-extern int bt_field_type_enumeration_add_mapping_unsigned(
+extern int bt_field_type_enumeration_unsigned_add_mapping(
                struct bt_field_type *enum_field_type, const char *name,
                uint64_t range_begin, uint64_t range_end);
 
@@ -1603,10 +1603,10 @@ functions:
 - Find operations of an @enumft object:
   - bt_field_type_enumeration_find_mappings_by_name(): Finds the
     mappings with a given name.
-  - bt_field_type_enumeration_find_mappings_by_unsigned_value():
+  - bt_field_type_enumeration_unsigned_find_mappings_by_value():
     Finds the mappings which contain a given unsigned value in their
     range.
-  - bt_field_type_enumeration_find_mappings_by_signed_value():
+  - bt_field_type_enumeration_signed_find_mappings_by_value():
     Finds the mappings which contain a given signed value in their range.
 - bt_field_enumeration_get_mappings(): Finds the mappings in the
   @enumft of an @enumfield containing its current integral value in
@@ -1617,9 +1617,9 @@ at least one mapping. Otherwise, they return \c NULL.
 
 You can get the name and the range of a mapping iterator's current
 mapping with
-bt_field_type_enumeration_mapping_iterator_get_signed()
+bt_field_type_enumeration_mapping_iterator_signed_get()
 or
-bt_field_type_enumeration_mapping_iterator_get_unsigned(),
+bt_field_type_enumeration_mapping_iterator_unsigned_get(),
 depending on the signedness of the @intft wrapped by the
 @enumft. If you only need the name of the current mapping, you can
 use any of the two functions and set the \p range_begin and \p range_end
@@ -1655,7 +1655,7 @@ management of Babeltrace objects.
 
 If one of \p range_begin or \p range_end is not \c NULL, the @intft
 wrapped by the @enumft from which \p iter was obtained, as returned by
-bt_field_type_enumeration_get_container_type(), must be
+bt_field_type_enumeration_get_container_field_type(), must be
 \b signed to use this function. Otherwise, if you only need to get the
 name of the current mapping, set \p range_begin and \p range_end to
 \c NULL.
@@ -1681,11 +1681,11 @@ bt_field_type_enumeration_mapping_iterator_next() is
 @prenotnull{iter}
 @postrefcountsame{iter}
 
-@sa bt_field_type_enumeration_mapping_iterator_get_unsigned():
+@sa bt_field_type_enumeration_mapping_iterator_unsigned_get():
        Returns the name and the unsigned range of the current mapping
        of a given enumeration field type mapping iterator.
 */
-extern int bt_field_type_enumeration_mapping_iterator_get_signed(
+extern int bt_field_type_enumeration_mapping_iterator_signed_get(
                struct bt_field_type_enumeration_mapping_iterator *iter,
                const char **name, int64_t *range_begin, int64_t *range_end);
 
@@ -1695,7 +1695,7 @@ extern int bt_field_type_enumeration_mapping_iterator_get_signed(
 
 If one of \p range_begin or \p range_end is not \c NULL, the @intft
 wrapped by the @enumft from which \p iter was obtained, as returned by
-bt_field_type_enumeration_get_container_type(), must be
+bt_field_type_enumeration_get_container_field_type(), must be
 \b unsigned to use this function. Otherwise, if you only need to get the
 name of the current mapping, set \p range_begin and \p range_end to
 \c NULL.
@@ -1722,11 +1722,11 @@ bt_field_type_enumeration_mapping_iterator_next() is
 @postrefcountsame{iter}
 
 @sa
-       bt_field_type_enumeration_mapping_iterator_get_signed():
+       bt_field_type_enumeration_mapping_iterator_signed_get():
        Returns the name and the signed range of the current mapping of
        a given enumeration field type mapping iterator.
 */
-extern int bt_field_type_enumeration_mapping_iterator_get_unsigned(
+extern int bt_field_type_enumeration_mapping_iterator_unsigned_get(
                struct bt_field_type_enumeration_mapping_iterator *iter,
                const char **name, uint64_t *range_begin, uint64_t *range_end);
 
@@ -2059,7 +2059,7 @@ extern struct bt_field_type *bt_field_type_array_create(
 @postrefcountsame{array_field_type}
 @postsuccessrefcountretinc
 */
-extern struct bt_field_type *bt_field_type_array_get_element_type(
+extern struct bt_field_type *bt_field_type_array_get_element_field_type(
                struct bt_field_type *array_field_type);
 
 /**
@@ -2151,7 +2151,7 @@ extern struct bt_field_type *bt_field_type_sequence_create(
 @postrefcountsame{sequence_field_type}
 @postsuccessrefcountretinc
 */
-extern struct bt_field_type *bt_field_type_sequence_get_element_type(
+extern struct bt_field_type *bt_field_type_sequence_get_element_field_type(
                struct bt_field_type *sequence_field_type);
 
 /**
@@ -2286,7 +2286,7 @@ extern struct bt_field_type *bt_field_type_variant_create(
 @postrefcountsame{variant_field_type}
 @postsuccessrefcountretinc
 */
-extern struct bt_field_type *bt_field_type_variant_get_tag_type(
+extern struct bt_field_type *bt_field_type_variant_get_tag_field_type(
                struct bt_field_type *variant_field_type);
 
 /**
@@ -2450,7 +2450,7 @@ struct bt_field_type *bt_field_type_variant_get_field_type_by_name(
 
 The field type of \p tag_field, as returned by bt_field_get_type(),
 \em must be equivalent to the field type returned by
-bt_field_type_variant_get_tag_type() for \p variant_field_type.
+bt_field_type_variant_get_tag_field_type() for \p variant_field_type.
 
 @param[in] variant_field_type  Variant field type of which to get
                                a field's type.
@@ -2516,72 +2516,6 @@ extern int bt_field_type_variant_add_field(
 
 /** @} */
 
-/* Pre-2.0 CTF writer compatibility */
-#define bt_ctf_field_type bt_field_type
-#define bt_ctf_field_type_integer_create bt_field_type_integer_create
-#define bt_ctf_field_type_integer_set_signed bt_field_type_integer_set_is_signed
-#define bt_ctf_field_type_integer_set_base bt_field_type_integer_set_base
-#define bt_ctf_field_type_integer_set_encoding bt_field_type_integer_set_encoding
-#define bt_ctf_field_type_enumeration_create bt_field_type_enumeration_create
-#define bt_ctf_field_type_enumeration_add_mapping bt_field_type_enumeration_add_mapping_signed
-#define bt_ctf_field_type_floating_point_create bt_field_type_floating_point_create
-#define bt_ctf_field_type_floating_point_set_exponent_digits bt_field_type_floating_point_set_exponent_digits
-#define bt_ctf_field_type_floating_point_set_mantissa_digits bt_field_type_floating_point_set_mantissa_digits
-#define bt_ctf_field_type_structure_create bt_field_type_structure_create
-#define bt_ctf_field_type_structure_add_field bt_field_type_structure_add_field
-#define bt_ctf_field_type_structure_add_field bt_field_type_structure_add_field
-#define bt_ctf_field_type_structure_get_field bt_field_type_structure_get_field_by_index
-#define bt_ctf_field_type_variant_create bt_field_type_variant_create
-#define bt_ctf_field_type_variant_add_field bt_field_type_variant_add_field
-#define bt_ctf_field_type_array_create bt_field_type_array_create
-#define bt_ctf_field_type_sequence_create bt_field_type_sequence_create
-#define bt_ctf_field_type_string_create bt_field_type_string_create
-#define bt_ctf_field_type_string_set_encoding bt_field_type_string_set_encoding
-#define bt_ctf_field_type_set_alignment bt_field_type_set_alignment
-#define bt_ctf_field_type_set_byte_order bt_field_type_set_byte_order
-
-extern int bt_ctf_field_type_integer_get_signed(
-               struct bt_ctf_field_type *int_field_type);
-
-#define ctf_type_id bt_field_type_id
-#define CTF_TYPE_UNKNOWN BT_FIELD_TYPE_ID_UNKNOWN
-#define CTF_TYPE_INTEGER BT_FIELD_TYPE_ID_INTEGER
-#define CTF_TYPE_FLOAT BT_FIELD_TYPE_ID_FLOAT
-#define CTF_TYPE_ENUM BT_FIELD_TYPE_ID_ENUM
-#define CTF_TYPE_STRING BT_FIELD_TYPE_ID_STRING
-#define CTF_TYPE_STRUCT BT_FIELD_TYPE_ID_STRUCT
-#define CTF_TYPE_UNTAGGED_VARIANT BT_FIELD_TYPE_ID_VARIANT
-#define CTF_TYPE_VARIANT BT_FIELD_TYPE_ID_VARIANT
-#define CTF_TYPE_ARRAY BT_FIELD_TYPE_ID_ARRAY
-#define CTF_TYPE_SEQUENCE BT_FIELD_TYPE_ID_SEQUENCE
-#define NR_CTF_TYPES BT_FIELD_TYPE_ID_NR
-
-#define ctf_string_encoding bt_string_encoding
-#define CTF_STRING_NONE BT_STRING_ENCODING_NONE
-#define CTF_STRING_UTF8 BT_STRING_ENCODING_UTF8
-#define CTF_STRING_ASCII BT_STRING_ENCODING_ASCII
-#define CTF_STRING_UNKNOWN BT_STRING_ENCODING_UNKNOWN
-
-#define bt_ctf_string_encoding bt_string_encoding
-#define BT_CTF_STRING_ENCODING_NONE BT_STRING_ENCODING_NONE
-#define BT_CTF_STRING_ENCODING_UTF8 BT_STRING_ENCODING_UTF8
-#define BT_CTF_STRING_ENCODING_ASCII BT_STRING_ENCODING_ASCII
-#define BT_CTF_STRING_ENCODING_UNKNOWN BT_STRING_ENCODING_UNKNOWN
-
-#define bt_ctf_byte_order bt_byte_order
-#define BT_CTF_BYTE_ORDER_UNKNOWN BT_BYTE_ORDER_UNKNOWN
-#define BT_CTF_BYTE_ORDER_NATIVE BT_BYTE_ORDER_NATIVE
-#define BT_CTF_BYTE_ORDER_LITTLE_ENDIAN BT_BYTE_ORDER_LITTLE_ENDIAN
-#define BT_CTF_BYTE_ORDER_BIG_ENDIAN BT_BYTE_ORDER_BIG_ENDIAN
-#define BT_CTF_BYTE_ORDER_NETWORK BT_BYTE_ORDER_NETWORK
-
-#define bt_ctf_integer_base bt_integer_base
-#define BT_CTF_INTEGER_BASE_UNKNOWN BT_INTEGER_BASE_UNKNOWN
-#define BT_CTF_INTEGER_BASE_BINARY BT_INTEGER_BASE_BINARY
-#define BT_CTF_INTEGER_BASE_OCTAL BT_INTEGER_BASE_OCTAL
-#define BT_CTF_INTEGER_BASE_DECIMAL BT_INTEGER_BASE_DECIMAL
-#define BT_CTF_INTEGER_BASE_HEXADECIMAL BT_INTEGER_BASE_HEXADECIMAL
-
 #ifdef __cplusplus
 }
 #endif
index 874e75f342a9e2c82fb4ee667928b5a9e3b75563..0f6afca65a8338686e697679ade212d88539a3be 100644 (file)
  * SOFTWARE.
  */
 
-#include <babeltrace/ctf-ir/field-types.h>
-#include <babeltrace/ctf-writer/event-fields.h>
+#include <babeltrace/assert-pre-internal.h>
+#include <babeltrace/common-internal.h>
+#include <babeltrace/ctf-ir/field-types-internal.h>
+#include <babeltrace/ctf-ir/utils-internal.h>
 #include <babeltrace/object-internal.h>
 #include <babeltrace/babeltrace-internal.h>
 #include <babeltrace/types.h>
 #include <stdint.h>
+#include <inttypes.h>
 #include <stdbool.h>
 #include <glib.h>
 
-struct bt_stream_pos;
+#define BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(_field, _type_id, _name)        \
+       BT_ASSERT_PRE((_field)->type->id == (_type_id),                 \
+               _name " has the wrong type ID: expected-type-id=%s, "   \
+               "%![field-]+_f", bt_common_field_type_id_string(_type_id),      \
+               (_field))
 
-struct bt_field {
+#define BT_ASSERT_PRE_FIELD_COMMON_IS_SET(_field, _name)               \
+       BT_ASSERT_PRE(bt_field_common_is_set_recursive(_field),         \
+               _name " is not set: %!+_f", (_field))
+
+#define BT_ASSERT_PRE_FIELD_COMMON_HOT(_field, _name)                  \
+       BT_ASSERT_PRE_HOT((_field), (_name), ": +%!+_f", (_field))
+
+struct bt_field;
+struct bt_field_common;
+
+typedef void (*bt_field_common_method_freeze)(struct bt_field_common *);
+typedef int (*bt_field_common_method_validate)(struct bt_field_common *);
+typedef struct bt_field_common *(*bt_field_common_method_copy)(
+               struct bt_field_common *);
+typedef bt_bool (*bt_field_common_method_is_set)(struct bt_field_common *);
+typedef void (*bt_field_common_method_reset)(struct bt_field_common *);
+
+struct bt_field_common_methods {
+       bt_field_common_method_freeze freeze;
+       bt_field_common_method_validate validate;
+       bt_field_common_method_copy copy;
+       bt_field_common_method_is_set is_set;
+       bt_field_common_method_reset reset;
+};
+
+struct bt_field_common {
        struct bt_object base;
-       struct bt_field_type *type;
+       struct bt_field_type_common *type;
+       struct bt_field_common_methods *methods;
        bool payload_set;
        bool frozen;
+
+       /*
+        * Specialized data for either CTF IR or CTF writer APIs.
+        * See comment in `field-types-internal.h` for more details.
+        */
+       union {
+               struct {
+               } ir;
+               struct {
+                       void *serialize_func;
+               } writer;
+       } spec;
 };
 
-struct bt_field_integer {
-       struct bt_field parent;
+struct bt_field_common_integer {
+       struct bt_field_common common;
        union {
                int64_t signd;
                uint64_t unsignd;
        } payload;
 };
 
-struct bt_field_enumeration {
-       struct bt_field parent;
-       struct bt_field *payload;
+struct bt_field_common_enumeration {
+       struct bt_field_common common;
+       struct bt_field_common *payload;
 };
 
-struct bt_field_floating_point {
-       struct bt_field parent;
+struct bt_field_common_floating_point {
+       struct bt_field_common common;
        double payload;
 };
 
-struct bt_field_structure {
-       struct bt_field parent;
-       GPtrArray *fields; /* Array of pointers to struct bt_field */
+struct bt_field_common_structure {
+       struct bt_field_common common;
+       GPtrArray *fields; /* Array of pointers to struct bt_field_common */
 };
 
-struct bt_field_variant {
-       struct bt_field parent;
-       struct bt_field *tag;
-       struct bt_field *payload;
+struct bt_field_common_variant {
+       struct bt_field_common common;
+       struct bt_field_common *tag;
+       struct bt_field_common *payload;
 };
 
-struct bt_field_array {
-       struct bt_field parent;
-       GPtrArray *elements; /* Array of pointers to struct bt_field */
+struct bt_field_common_array {
+       struct bt_field_common common;
+       GPtrArray *elements; /* Array of pointers to struct bt_field_common */
 };
 
-struct bt_field_sequence {
-       struct bt_field parent;
-       struct bt_field *length;
-       GPtrArray *elements; /* Array of pointers to struct bt_field */
+struct bt_field_common_sequence {
+       struct bt_field_common common;
+       struct bt_field_common *length;
+       GPtrArray *elements; /* Array of pointers to struct bt_field_common */
 };
 
-struct bt_field_string {
-       struct bt_field parent;
+struct bt_field_common_string {
+       struct bt_field_common common;
        GString *payload;
 };
 
+static inline
+struct bt_field_type *bt_field_borrow_type(struct bt_field *field)
+{
+       struct bt_field_common *field_common = (void *) field;
+
+       BT_ASSERT(field);
+       return (void *) field_common->type;
+}
+
+BT_HIDDEN
+int64_t bt_field_sequence_get_int_length(struct bt_field *field);
+
+BT_HIDDEN
+struct bt_field_common *bt_field_common_copy(struct bt_field_common *field);
+
+BT_HIDDEN
+int bt_field_common_structure_initialize(struct bt_field_common *field,
+               struct bt_field_type_common *type,
+               bt_object_release_func release_func,
+               struct bt_field_common_methods *methods,
+               bt_field_common_create_func field_create_func);
+
+BT_HIDDEN
+int bt_field_common_array_initialize(struct bt_field_common *field,
+               struct bt_field_type_common *type,
+               bt_object_release_func release_func,
+               struct bt_field_common_methods *methods);
+
+BT_HIDDEN
+int bt_field_common_generic_validate(struct bt_field_common *field);
+
+BT_HIDDEN
+int bt_field_common_enumeration_validate_recursive(
+               struct bt_field_common *field);
+
+BT_HIDDEN
+int bt_field_common_structure_validate_recursive(struct bt_field_common *field);
+
+BT_HIDDEN
+int bt_field_common_variant_validate_recursive(struct bt_field_common *field);
+
+BT_HIDDEN
+int bt_field_common_array_validate_recursive(struct bt_field_common *field);
+
+BT_HIDDEN
+int bt_field_common_sequence_validate_recursive(struct bt_field_common *field);
+
+BT_HIDDEN
+void bt_field_common_generic_reset(struct bt_field_common *field);
+
+BT_HIDDEN
+void bt_field_common_enumeration_reset_recursive(struct bt_field_common *field);
+
+BT_HIDDEN
+void bt_field_common_structure_reset_recursive(struct bt_field_common *field);
+
+BT_HIDDEN
+void bt_field_common_variant_reset_recursive(struct bt_field_common *field);
+
+BT_HIDDEN
+void bt_field_common_array_reset_recursive(struct bt_field_common *field);
+
+BT_HIDDEN
+void bt_field_common_sequence_reset_recursive(struct bt_field_common *field);
+
+BT_HIDDEN
+void bt_field_common_string_reset(struct bt_field_common *field);
+
+BT_HIDDEN
+void bt_field_common_generic_freeze(struct bt_field_common *field);
+
 BT_HIDDEN
-int bt_field_serialize_recursive(struct bt_field *field,
-               struct bt_stream_pos *pos,
-               enum bt_byte_order native_byte_order);
+void bt_field_common_enumeration_freeze_recursive(struct bt_field_common *field);
 
-/* Validate that the field's payload is set (returns 0 if set). */
 BT_HIDDEN
-int _bt_field_validate_recursive(struct bt_field *field);
+void bt_field_common_structure_freeze_recursive(struct bt_field_common *field);
 
 BT_HIDDEN
-void _bt_field_freeze_recursive(struct bt_field *field);
+void bt_field_common_variant_freeze_recursive(struct bt_field_common *field);
 
 BT_HIDDEN
-bt_bool _bt_field_is_set_recursive(struct bt_field *field);
+void bt_field_common_array_freeze_recursive(struct bt_field_common *field);
 
 BT_HIDDEN
-void _bt_field_reset_recursive(struct bt_field *field);
+void bt_field_common_sequence_freeze_recursive(struct bt_field_common *field);
 
 BT_HIDDEN
-void _bt_field_set(struct bt_field *field, bool val);
+void _bt_field_common_freeze_recursive(struct bt_field_common *field);
+
+BT_HIDDEN
+bt_bool bt_field_common_generic_is_set(struct bt_field_common *field);
+
+BT_HIDDEN
+bt_bool bt_field_common_enumeration_is_set_recursive(
+               struct bt_field_common *field);
+
+BT_HIDDEN
+bt_bool bt_field_common_structure_is_set_recursive(
+               struct bt_field_common *field);
+
+BT_HIDDEN
+bt_bool bt_field_common_variant_is_set_recursive(struct bt_field_common *field);
+
+BT_HIDDEN
+bt_bool bt_field_common_array_is_set_recursive(struct bt_field_common *field);
+
+BT_HIDDEN
+bt_bool bt_field_common_sequence_is_set_recursive(struct bt_field_common *field);
+
+BT_HIDDEN
+void bt_field_common_integer_destroy(struct bt_object *obj);
+
+BT_HIDDEN
+void bt_field_common_enumeration_destroy_recursive(struct bt_object *obj);
+
+BT_HIDDEN
+void bt_field_common_floating_point_destroy(struct bt_object *obj);
+
+BT_HIDDEN
+void bt_field_common_structure_destroy_recursive(struct bt_object *obj);
+
+BT_HIDDEN
+void bt_field_common_variant_destroy_recursive(struct bt_object *obj);
+
+BT_HIDDEN
+void bt_field_common_array_destroy_recursive(struct bt_object *obj);
+
+BT_HIDDEN
+void bt_field_common_sequence_destroy_recursive(struct bt_object *obj);
+
+BT_HIDDEN
+void bt_field_common_string_destroy(struct bt_object *obj);
 
 #ifdef BT_DEV_MODE
+# define bt_field_common_validate_recursive    _bt_field_common_validate_recursive
+# define bt_field_common_freeze_recursive      _bt_field_common_freeze_recursive
+# define bt_field_common_is_set_recursive      _bt_field_common_is_set_recursive
+# define bt_field_common_reset_recursive       _bt_field_common_reset_recursive
+# define bt_field_common_set                   _bt_field_common_set
 # define bt_field_validate_recursive           _bt_field_validate_recursive
 # define bt_field_freeze_recursive             _bt_field_freeze_recursive
 # define bt_field_is_set_recursive             _bt_field_is_set_recursive
 # define bt_field_reset_recursive              _bt_field_reset_recursive
 # define bt_field_set                          _bt_field_set
 #else
-# define bt_field_validate_recursive(_field)   (-1)
+# define bt_field_common_validate_recursive(_field)    (-1)
+# define bt_field_common_freeze_recursive(_field)
+# define bt_field_common_is_set_recursive(_field)      (BT_FALSE)
+# define bt_field_common_reset_recursive(_field)       (BT_TRUE)
+# define bt_field_common_set(_field, _val)
+# define bt_field_validate_recursive(_field)           (-1)
 # define bt_field_freeze_recursive(_field)
-# define bt_field_is_set_recursive(_field)     (BT_FALSE)
+# define bt_field_is_set_recursive(_field)             (BT_FALSE)
 # define bt_field_reset_recursive(_field)              (BT_TRUE)
 # define bt_field_set(_field, _val)
 #endif
 
-BT_HIDDEN
-int64_t bt_field_sequence_get_int_length(struct bt_field *field);
+BT_ASSERT_FUNC
+static inline bool field_type_common_has_known_id(
+               struct bt_field_type_common *ft)
+{
+       return ft->id > BT_FIELD_TYPE_ID_UNKNOWN ||
+               ft->id < BT_FIELD_TYPE_ID_NR;
+}
+
+static inline
+int _bt_field_common_validate_recursive(struct bt_field_common *field)
+{
+       int ret = 0;
+
+       if (!field) {
+               BT_ASSERT_PRE_MSG("%s", "Invalid field: field is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       BT_ASSERT(field_type_common_has_known_id(field->type));
+
+       if (field->methods->validate) {
+               ret = field->methods->validate(field);
+       }
+
+end:
+       return ret;
+}
+
+static inline
+void _bt_field_common_reset_recursive(struct bt_field_common *field)
+{
+       BT_ASSERT(field);
+       BT_ASSERT(field->methods->reset);
+       field->methods->reset(field);
+}
+
+static inline
+void _bt_field_common_set(struct bt_field_common *field, bool value)
+{
+       BT_ASSERT(field);
+       field->payload_set = value;
+}
+
+static inline
+bt_bool _bt_field_common_is_set_recursive(struct bt_field_common *field)
+{
+       bt_bool is_set = BT_FALSE;
+
+       if (!field) {
+               goto end;
+       }
+
+       BT_ASSERT(field_type_common_has_known_id(field->type));
+       BT_ASSERT(field->methods->is_set);
+       is_set = field->methods->is_set(field);
+
+end:
+       return is_set;
+}
+
+static inline
+void bt_field_common_initialize(struct bt_field_common *field,
+               struct bt_field_type_common *ft,
+               bt_object_release_func release_func,
+               struct bt_field_common_methods *methods)
+{
+       BT_ASSERT(field);
+       BT_ASSERT(ft);
+       bt_object_init(field, release_func);
+       field->methods = methods;
+       field->type = bt_get(ft);
+}
+
+static inline
+struct bt_field_type_common *bt_field_common_get_type(
+               struct bt_field_common *field)
+{
+       struct bt_field_type_common *ret = NULL;
+
+       BT_ASSERT_PRE_NON_NULL(field, "Field");
+       ret = bt_get(field->type);
+       return ret;
+}
+
+static inline
+int64_t bt_field_common_sequence_get_int_length(struct bt_field_common *field)
+{
+       struct bt_field_common_sequence *sequence = BT_FROM_COMMON(field);
+       int64_t ret;
+
+       BT_ASSERT(field);
+       BT_ASSERT(field->type->id == BT_FIELD_TYPE_ID_SEQUENCE);
+       if (!sequence->length) {
+               ret = -1;
+               goto end;
+       }
+
+       ret = (int64_t) sequence->elements->len;
+
+end:
+       return ret;
+}
+
+static inline
+struct bt_field_common *bt_field_common_sequence_get_length(
+               struct bt_field_common *field)
+{
+       struct bt_field_common_sequence *sequence = BT_FROM_COMMON(field);
+
+       BT_ASSERT_PRE_NON_NULL(field, "Sequence field");
+       BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_SEQUENCE,
+               "Field");
+       return bt_get(sequence->length);
+}
+
+static inline
+int bt_field_common_sequence_set_length(struct bt_field_common *field,
+               struct bt_field_common *length_field)
+{
+       int ret = 0;
+       struct bt_field_common_integer *length = BT_FROM_COMMON(length_field);
+       struct bt_field_common_sequence *sequence = BT_FROM_COMMON(field);
+       uint64_t sequence_length;
+
+       BT_ASSERT_PRE_NON_NULL(field, "Sequence field");
+       BT_ASSERT_PRE_NON_NULL(length_field, "Length field");
+       BT_ASSERT_PRE_FIELD_COMMON_HOT(field, "Sequence field");
+       BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(length_field,
+               BT_FIELD_TYPE_ID_INTEGER, "Length field");
+       BT_ASSERT_PRE(
+               !bt_field_type_common_integer_is_signed(length->common.type),
+               "Length field's type is signed: %!+_f", length_field);
+       BT_ASSERT_PRE_FIELD_COMMON_IS_SET(length_field, "Length field");
+       sequence_length = length->payload.unsignd;
+       if (sequence->elements) {
+               g_ptr_array_free(sequence->elements, TRUE);
+               bt_put(sequence->length);
+       }
+
+       sequence->elements = g_ptr_array_sized_new((size_t) sequence_length);
+       if (!sequence->elements) {
+               BT_LOGE_STR("Failed to allocate a GPtrArray.");
+               ret = -1;
+               goto end;
+       }
+
+       g_ptr_array_set_free_func(sequence->elements,
+               (GDestroyNotify) bt_put);
+       g_ptr_array_set_size(sequence->elements, (size_t) sequence_length);
+       bt_get(length_field);
+       sequence->length = length_field;
+       bt_field_common_freeze_recursive(length_field);
+
+end:
+       return ret;
+}
+
+static inline
+struct bt_field_common *bt_field_common_structure_get_field_by_name(
+               struct bt_field_common *field, const char *name)
+{
+       struct bt_field_common *ret = NULL;
+       GQuark field_quark;
+       struct bt_field_type_common_structure *structure_ft;
+       struct bt_field_common_structure *structure = BT_FROM_COMMON(field);
+       size_t index;
+       GHashTable *field_name_to_index;
+
+       BT_ASSERT_PRE_NON_NULL(field, "Structure field");
+       BT_ASSERT_PRE_NON_NULL(name, "Field name");
+       BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field,
+               BT_FIELD_TYPE_ID_STRUCT, "Field");
+       structure_ft = BT_FROM_COMMON(field->type);
+       field_name_to_index = structure_ft->field_name_to_index;
+       field_quark = g_quark_from_string(name);
+       if (!g_hash_table_lookup_extended(field_name_to_index,
+                       GUINT_TO_POINTER(field_quark),
+                       NULL, (gpointer *) &index)) {
+               BT_LOGV("Invalid parameter: no such field in structure field's type: "
+                       "struct-field-addr=%p, struct-ft-addr=%p, name=\"%s\"",
+                       field, field->type, name);
+               goto error;
+       }
+
+       ret = bt_get(structure->fields->pdata[index]);
+       BT_ASSERT(ret);
+
+error:
+       return ret;
+}
+
+static inline
+struct bt_field_common *bt_field_common_structure_get_field_by_index(
+               struct bt_field_common *field, uint64_t index)
+{
+       struct bt_field_common_structure *structure = BT_FROM_COMMON(field);
+
+       BT_ASSERT_PRE_NON_NULL(field, "Structure field");
+       BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field,
+               BT_FIELD_TYPE_ID_STRUCT, "Field");
+       BT_ASSERT_PRE(index < structure->fields->len,
+               "Index is out of bound: %![struct-field-]+_f, "
+               "index=%" PRIu64 ", count=%u", field, index,
+               structure->fields->len);
+       return bt_get(structure->fields->pdata[index]);
+}
+
+BT_ASSERT_PRE_FUNC
+static inline bool field_to_set_has_expected_type(
+               struct bt_field_common *struct_field,
+               const char *name, struct bt_field_common *value)
+{
+       bool ret = true;
+       struct bt_field_type_common *expected_field_type = NULL;
+
+       expected_field_type =
+               bt_field_type_common_structure_get_field_type_by_name(
+                       struct_field->type, name);
+
+       if (bt_field_type_common_compare(expected_field_type, value->type)) {
+               BT_ASSERT_PRE_MSG("Value field's type is different from the expected field type: "
+                       "%![value-ft-]+_F, %![expected-ft-]+_F", value->type,
+                       expected_field_type);
+               ret = false;
+               goto end;
+       }
+
+end:
+       bt_put(expected_field_type);
+       return ret;
+}
+
+static inline
+int bt_field_common_structure_set_field_by_name(struct bt_field_common *field,
+               const char *name, struct bt_field_common *value)
+{
+       int ret = 0;
+       GQuark field_quark;
+       struct bt_field_common_structure *structure = BT_FROM_COMMON(field);
+       size_t index;
+       GHashTable *field_name_to_index;
+       struct bt_field_type_common_structure *structure_ft;
+
+       BT_ASSERT_PRE_NON_NULL(field, "Structure field");
+       BT_ASSERT_PRE_NON_NULL(name, "Field name");
+       BT_ASSERT_PRE_NON_NULL(value, "Value field");
+       BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_STRUCT,
+               "Parent field");
+       BT_ASSERT_PRE(field_to_set_has_expected_type(field, name, value),
+               "Value field's type is different from the expected field type.");
+       field_quark = g_quark_from_string(name);
+       structure_ft = BT_FROM_COMMON(field->type);
+       field_name_to_index = structure_ft->field_name_to_index;
+       if (!g_hash_table_lookup_extended(field_name_to_index,
+                       GUINT_TO_POINTER(field_quark), NULL,
+                       (gpointer *) &index)) {
+               BT_LOGV("Invalid parameter: no such field in structure field's type: "
+                       "struct-field-addr=%p, struct-ft-addr=%p, "
+                       "field-ft-addr=%p, name=\"%s\"",
+                       field, field->type, value->type, name);
+               ret = -1;
+               goto end;
+       }
+       bt_get(value);
+       BT_MOVE(structure->fields->pdata[index], value);
+
+end:
+       return ret;
+}
+
+static inline
+struct bt_field_common *bt_field_common_array_get_field(
+               struct bt_field_common *field, uint64_t index,
+               bt_field_common_create_func field_create_func)
+{
+       struct bt_field_common *new_field = NULL;
+       struct bt_field_type_common *field_type = NULL;
+       struct bt_field_common_array *array = BT_FROM_COMMON(field);
+
+       BT_ASSERT_PRE_NON_NULL(field, "Array field");
+       BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_ARRAY, "Field");
+       BT_ASSERT_PRE(index < array->elements->len,
+               "Index is out of bound: %![array-field-]+_f, "
+               "index=%" PRIu64 ", count=%u", field,
+               index, array->elements->len);
+
+       field_type = bt_field_type_common_array_get_element_field_type(
+               field->type);
+       if (array->elements->pdata[(size_t) index]) {
+               new_field = array->elements->pdata[(size_t) index];
+               goto end;
+       }
+
+       /* We don't want to modify this field if it's frozen */
+       BT_ASSERT_PRE_FIELD_COMMON_HOT(field, "Array field");
+       new_field = field_create_func(field_type);
+       array->elements->pdata[(size_t) index] = new_field;
+
+end:
+       bt_put(field_type);
+       bt_get(new_field);
+       return new_field;
+}
+
+static inline
+struct bt_field_common *bt_field_common_sequence_get_field(
+               struct bt_field_common *field, uint64_t index,
+               bt_field_common_create_func field_create_func)
+{
+       struct bt_field_common *new_field = NULL;
+       struct bt_field_type_common *field_type = NULL;
+       struct bt_field_common_sequence *sequence = BT_FROM_COMMON(field);
+
+       BT_ASSERT_PRE_NON_NULL(field, "Sequence field");
+       BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_SEQUENCE,
+               "Field");
+       BT_ASSERT_PRE_NON_NULL(sequence->elements, "Sequence field's element array");
+       BT_ASSERT_PRE(index < sequence->elements->len,
+               "Index is out of bound: %![seq-field-]+_f, "
+               "index=%" PRIu64 ", count=%u", field, index,
+               sequence->elements->len);
+       field_type = bt_field_type_common_sequence_get_element_field_type(
+               field->type);
+       if (sequence->elements->pdata[(size_t) index]) {
+               new_field = sequence->elements->pdata[(size_t) index];
+               goto end;
+       }
+
+       /* We don't want to modify this field if it's frozen */
+       BT_ASSERT_PRE_FIELD_COMMON_HOT(field, "Sequence field");
+       new_field = field_create_func(field_type);
+       sequence->elements->pdata[(size_t) index] = new_field;
+
+end:
+       bt_put(field_type);
+       bt_get(new_field);
+       return new_field;
+}
+
+static inline
+struct bt_field_common *bt_field_common_enumeration_get_container(
+               struct bt_field_common *field,
+               bt_field_common_create_func field_create_func)
+{
+       struct bt_field_common_enumeration *enumeration = BT_FROM_COMMON(field);
+
+       BT_ASSERT_PRE_NON_NULL(field, "Enumeration field");
+       BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field,
+               BT_FIELD_TYPE_ID_ENUM, "Field");
+
+       if (!enumeration->payload) {
+               struct bt_field_type_common_enumeration *enumeration_type;
+
+               /* We don't want to modify this field if it's frozen */
+               BT_ASSERT_PRE_FIELD_COMMON_HOT(field, "Enumeration field");
+
+               enumeration_type = BT_FROM_COMMON(field->type);
+               enumeration->payload =
+                       field_create_func(
+                               BT_TO_COMMON(enumeration_type->container_ft));
+       }
+
+       return bt_get(enumeration->payload);
+}
+
+static inline
+struct bt_field_common *bt_field_common_variant_get_field(
+               struct bt_field_common *field,
+               struct bt_field_common *tag_field,
+               bt_field_common_create_func field_create_func)
+{
+       struct bt_field_common *new_field = NULL;
+       struct bt_field_common_variant *variant = BT_FROM_COMMON(field);
+       struct bt_field_type_common_variant *variant_type;
+       struct bt_field_type_common *field_type;
+       struct bt_field_common *tag_enum = NULL;
+       struct bt_field_common_integer *tag_enum_integer =
+               BT_FROM_COMMON(field);
+       int64_t tag_enum_value;
+
+       BT_ASSERT_PRE_NON_NULL(field, "Variant field");
+       BT_ASSERT_PRE_NON_NULL(tag_field, "Tag field");
+       BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_VARIANT,
+               "Variant field");
+       BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(tag_field, BT_FIELD_TYPE_ID_ENUM,
+               "Tag field");
+       variant_type = BT_FROM_COMMON(field->type);
+       tag_enum = bt_field_common_enumeration_get_container(tag_field,
+               field_create_func);
+       BT_ASSERT_PRE_NON_NULL(tag_enum, "Tag field's container");
+       tag_enum_integer = BT_FROM_COMMON(tag_enum);
+       BT_ASSERT_PRE(bt_field_common_validate_recursive(tag_field) == 0,
+               "Tag field is invalid: %!+_f", tag_field);
+       tag_enum_value = tag_enum_integer->payload.signd;
+
+       /*
+        * If the variant currently has a tag and a payload, and if the
+        * requested tag value is the same as the current one, return
+        * the current payload instead of creating a fresh one.
+        */
+       if (variant->tag && variant->payload) {
+               struct bt_field_common *cur_tag_container = NULL;
+               struct bt_field_common_integer *cur_tag_enum_integer;
+               int64_t cur_tag_value;
+
+               cur_tag_container =
+                       bt_field_common_enumeration_get_container(variant->tag,
+                               field_create_func);
+               BT_ASSERT(cur_tag_container);
+               cur_tag_enum_integer = BT_FROM_COMMON(cur_tag_container);
+               bt_put(cur_tag_container);
+               cur_tag_value = cur_tag_enum_integer->payload.signd;
+
+               if (cur_tag_value == tag_enum_value) {
+                       new_field = variant->payload;
+                       bt_get(new_field);
+                       goto end;
+               }
+       }
+
+       /* We don't want to modify this field if it's frozen */
+       BT_ASSERT_PRE_FIELD_COMMON_HOT(field, "Variant field");
+       field_type = bt_field_type_common_variant_get_field_type_signed(
+               variant_type, tag_enum_value);
+
+       /* It's the caller's job to make sure the tag's value is valid */
+       BT_ASSERT_PRE(field_type,
+               "Variant field's type does not contain a field type for "
+               "this tag value: tag-value-signed=%" PRId64 ", "
+               "%![var-ft-]+_F, %![tag-field-]+_f", tag_enum_value,
+               variant_type, tag_field);
+
+       new_field = field_create_func(field_type);
+       if (!new_field) {
+               BT_LOGW("Cannot create field: "
+                       "variant-field-addr=%p, variant-ft-addr=%p, "
+                       "field-ft-addr=%p", field, field->type, field_type);
+               goto end;
+       }
+
+       bt_put(variant->tag);
+       bt_put(variant->payload);
+       bt_get(new_field);
+       bt_get(tag_field);
+       variant->tag = tag_field;
+       variant->payload = new_field;
+
+end:
+       bt_put(tag_enum);
+       return new_field;
+}
+
+static inline
+struct bt_field_common *bt_field_common_variant_get_current_field(
+               struct bt_field_common *variant_field)
+{
+       struct bt_field_common_variant *variant = BT_FROM_COMMON(variant_field);
+
+       BT_ASSERT_PRE_NON_NULL(variant_field, "Variant field");
+       BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(variant_field,
+               BT_FIELD_TYPE_ID_VARIANT, "Field");
+       return bt_get(variant->payload);
+}
+
+static inline
+struct bt_field_common *bt_field_common_variant_get_tag(
+               struct bt_field_common *variant_field)
+{
+       struct bt_field_common_variant *variant = BT_FROM_COMMON(variant_field);
+
+       BT_ASSERT_PRE_NON_NULL(variant_field, "Variant field");
+       BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(variant_field,
+               BT_FIELD_TYPE_ID_VARIANT, "Field");
+       return bt_get(variant->tag);
+}
+
+static inline
+int bt_field_common_integer_signed_get_value(struct bt_field_common *field,
+               int64_t *value)
+{
+       struct bt_field_common_integer *integer = BT_FROM_COMMON(field);
+
+       BT_ASSERT_PRE_NON_NULL(field, "Integer field");
+       BT_ASSERT_PRE_NON_NULL(value, "Value");
+       BT_ASSERT_PRE_FIELD_COMMON_IS_SET(field, "Integer field");
+       BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field,
+               BT_FIELD_TYPE_ID_INTEGER, "Field");
+       BT_ASSERT_PRE(bt_field_type_common_integer_is_signed(field->type),
+               "Field's type is unsigned: %!+_f", field);
+       *value = integer->payload.signd;
+       return 0;
+}
+
+BT_ASSERT_PRE_FUNC
+static inline bool value_is_in_range_signed(unsigned int size, int64_t value)
+{
+       bool ret = true;
+       int64_t min_value, max_value;
+
+       min_value = -(1ULL << (size - 1));
+       max_value = (1ULL << (size - 1)) - 1;
+       if (value < min_value || value > max_value) {
+               BT_LOGF("Value is out of bounds: value=%" PRId64 ", "
+                       "min-value=%" PRId64 ", max-value=%" PRId64,
+                       value, min_value, max_value);
+               ret = false;
+       }
+
+       return ret;
+}
+
+static inline
+int bt_field_common_integer_signed_set_value(struct bt_field_common *field,
+               int64_t value)
+{
+       int ret = 0;
+       struct bt_field_common_integer *integer = BT_FROM_COMMON(field);
+       struct bt_field_type_common_integer *integer_type;
+
+       BT_ASSERT_PRE_NON_NULL(field, "Integer field");
+       BT_ASSERT_PRE_FIELD_COMMON_HOT(field, "Integer field");
+       BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field,
+               BT_FIELD_TYPE_ID_INTEGER, "Field");
+       integer_type = BT_FROM_COMMON(field->type);
+       BT_ASSERT_PRE(bt_field_type_common_integer_is_signed(field->type),
+               "Field's type is unsigned: %!+_f", field);
+       BT_ASSERT_PRE(value_is_in_range_signed(integer_type->size, value),
+               "Value is out of bounds: value=%" PRId64 ", %![field-]+_f",
+               value, field);
+       integer->payload.signd = value;
+       bt_field_common_set(field, true);
+       return ret;
+}
+
+static inline
+int bt_field_common_integer_unsigned_get_value(struct bt_field_common *field,
+               uint64_t *value)
+{
+       struct bt_field_common_integer *integer = BT_FROM_COMMON(field);
+
+       BT_ASSERT_PRE_NON_NULL(field, "Integer field");
+       BT_ASSERT_PRE_NON_NULL(value, "Value");
+       BT_ASSERT_PRE_FIELD_COMMON_IS_SET(field, "Integer field");
+       BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field,
+               BT_FIELD_TYPE_ID_INTEGER, "Field");
+       BT_ASSERT_PRE(!bt_field_type_common_integer_is_signed(field->type),
+               "Field's type is signed: %!+_f", field);
+       *value = integer->payload.unsignd;
+       return 0;
+}
+
+BT_ASSERT_PRE_FUNC
+static inline bool value_is_in_range_unsigned(unsigned int size, uint64_t value)
+{
+       bool ret = true;
+       int64_t max_value;
+
+       max_value = (size == 64) ? UINT64_MAX : ((uint64_t) 1 << size) - 1;
+       if (value > max_value) {
+               BT_LOGF("Value is out of bounds: value=%" PRIu64 ", "
+                       "max-value=%" PRIu64,
+                       value, max_value);
+               ret = false;
+       }
+
+       return ret;
+}
+
+static inline
+int bt_field_common_integer_unsigned_set_value(struct bt_field_common *field,
+               uint64_t value)
+{
+       struct bt_field_common_integer *integer = BT_FROM_COMMON(field);
+       struct bt_field_type_common_integer *integer_type;
+
+       BT_ASSERT_PRE_NON_NULL(field, "Integer field");
+       BT_ASSERT_PRE_FIELD_COMMON_HOT(field, "Integer field");
+       BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field,
+               BT_FIELD_TYPE_ID_INTEGER, "Field");
+       integer_type = BT_FROM_COMMON(field->type);
+       BT_ASSERT_PRE(!bt_field_type_common_integer_is_signed(field->type),
+               "Field's type is signed: %!+_f", field);
+       BT_ASSERT_PRE(value_is_in_range_unsigned(integer_type->size, value),
+               "Value is out of bounds: value=%" PRIu64 ", %![field-]+_f",
+               value, field);
+       integer->payload.unsignd = value;
+       bt_field_common_set(field, true);
+       return 0;
+}
+
+static inline
+struct bt_field_type_enumeration_mapping_iterator *
+bt_field_common_enumeration_get_mappings(struct bt_field_common *field,
+               bt_field_common_create_func field_create_func)
+{
+       int ret;
+       struct bt_field_common *container = NULL;
+       struct bt_field_type_common_integer *integer_type = NULL;
+       struct bt_field_type_enumeration_mapping_iterator *iter = NULL;
+
+       BT_ASSERT_PRE_NON_NULL(field, "Enumeration field");
+       BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field,
+               BT_FIELD_TYPE_ID_ENUM, "Field");
+       container = bt_field_common_enumeration_get_container(field,
+               field_create_func);
+       BT_ASSERT_PRE(container,
+               "Enumeration field has no container field: %!+_f", field);
+       BT_ASSERT(container->type);
+       integer_type = BT_FROM_COMMON(container->type);
+       BT_ASSERT_PRE_FIELD_COMMON_IS_SET(container,
+               "Enumeration field's payload field");
+
+       if (!integer_type->is_signed) {
+               uint64_t value;
+
+               ret = bt_field_common_integer_unsigned_get_value(container,
+                       &value);
+               BT_ASSERT(ret == 0);
+               iter = bt_field_type_common_enumeration_unsigned_find_mappings_by_value(
+                               field->type, value);
+       } else {
+               int64_t value;
+
+               ret = bt_field_common_integer_signed_get_value(container, &value);
+               BT_ASSERT(ret == 0);
+               iter = bt_field_type_common_enumeration_signed_find_mappings_by_value(
+                               field->type, value);
+       }
+
+       bt_put(container);
+       return iter;
+}
+
+static inline
+int bt_field_common_floating_point_get_value(struct bt_field_common *field,
+               double *value)
+{
+       struct bt_field_common_floating_point *floating_point =
+               BT_FROM_COMMON(field);
+
+       BT_ASSERT_PRE_NON_NULL(field, "Floating point number field");
+       BT_ASSERT_PRE_NON_NULL(value, "Value");
+       BT_ASSERT_PRE_FIELD_COMMON_IS_SET(field, "Floating point number field");
+       BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field,
+               BT_FIELD_TYPE_ID_FLOAT, "Field");
+       *value = floating_point->payload;
+       return 0;
+}
+
+static inline
+int bt_field_common_floating_point_set_value(struct bt_field_common *field,
+               double value)
+{
+       struct bt_field_common_floating_point *floating_point =
+               BT_FROM_COMMON(field);
+
+       BT_ASSERT_PRE_NON_NULL(field, "Floating point number field");
+       BT_ASSERT_PRE_FIELD_COMMON_HOT(field, "Floating point number field");
+       BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field,
+               BT_FIELD_TYPE_ID_FLOAT, "Field");
+       floating_point->payload = value;
+       bt_field_common_set(field, true);
+       return 0;
+}
+
+static inline
+const char *bt_field_common_string_get_value(struct bt_field_common *field)
+{
+       struct bt_field_common_string *string = BT_FROM_COMMON(field);
+
+       BT_ASSERT_PRE_NON_NULL(field, "String field");
+       BT_ASSERT_PRE_FIELD_COMMON_IS_SET(field, "String field");
+       BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field,
+               BT_FIELD_TYPE_ID_STRING, "Field");
+       return string->payload->str;
+}
+
+static inline
+int bt_field_common_string_set_value(struct bt_field_common *field,
+               const char *value)
+{
+       struct bt_field_common_string *string = BT_FROM_COMMON(field);
+
+       BT_ASSERT_PRE_NON_NULL(field, "String field");
+       BT_ASSERT_PRE_NON_NULL(value, "Value");
+       BT_ASSERT_PRE_FIELD_COMMON_HOT(field, "String field");
+       BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field,
+               BT_FIELD_TYPE_ID_STRING, "Field");
+
+       if (string->payload) {
+               g_string_assign(string->payload, value);
+       } else {
+               string->payload = g_string_new(value);
+       }
+
+       bt_field_common_set(field, true);
+       return 0;
+}
+
+static inline
+int bt_field_common_string_append(struct bt_field_common *field,
+               const char *value)
+{
+       struct bt_field_common_string *string_field = BT_FROM_COMMON(field);
+
+       BT_ASSERT_PRE_NON_NULL(field, "String field");
+       BT_ASSERT_PRE_NON_NULL(value, "Value");
+       BT_ASSERT_PRE_FIELD_COMMON_HOT(field, "String field");
+       BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field,
+               BT_FIELD_TYPE_ID_STRING, "Field");
+
+       if (string_field->payload) {
+               g_string_append(string_field->payload, value);
+       } else {
+               string_field->payload = g_string_new(value);
+       }
+
+       bt_field_common_set(field, true);
+       return 0;
+}
+
+static inline
+int bt_field_common_string_append_len(struct bt_field_common *field,
+               const char *value, unsigned int length)
+{
+       struct bt_field_common_string *string_field = BT_FROM_COMMON(field);
+
+       BT_ASSERT_PRE_NON_NULL(field, "String field");
+       BT_ASSERT_PRE_NON_NULL(value, "Value");
+       BT_ASSERT_PRE_FIELD_COMMON_HOT(field, "String field");
+       BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field,
+               BT_FIELD_TYPE_ID_STRING, "Field");
+
+       /* make sure no null bytes are appended */
+       BT_ASSERT_PRE(memchr(value, '\0', length) == NULL,
+               "String value to append contains a null character: "
+               "partial-value=\"%.32s\", length=%u", value, length);
+
+       if (string_field->payload) {
+               g_string_append_len(string_field->payload, value, length);
+       } else {
+               string_field->payload = g_string_new_len(value, length);
+       }
+
+       bt_field_common_set(field, true);
+       return 0;
+}
+
+static inline
+int _bt_field_validate_recursive(struct bt_field *field)
+{
+       return _bt_field_common_validate_recursive((void *) field);
+}
+
+static inline
+void _bt_field_freeze_recursive(struct bt_field *field)
+{
+       return _bt_field_common_freeze_recursive((void *) field);
+}
+
+static inline
+bt_bool _bt_field_is_set_recursive(struct bt_field *field)
+{
+       return _bt_field_common_is_set_recursive((void *) field);
+}
+
+static inline
+void _bt_field_reset_recursive(struct bt_field *field)
+{
+       _bt_field_common_reset_recursive((void *) field);
+}
+
+static inline
+void _bt_field_set(struct bt_field *field, bool value)
+{
+       _bt_field_common_set((void *) field, value);
+}
 
 #endif /* BABELTRACE_CTF_IR_FIELDS_INTERNAL_H */
index 03e6052e7cd077b948385a410de0b27d082f71cd..896cd4e41ac48db58bb30064a108f449a349c072 100644 (file)
@@ -160,8 +160,7 @@ its specific setters.
 @postsuccessrefcountret1
 @postsuccessfrozen{field_type}
 */
-extern struct bt_field *bt_field_create(
-               struct bt_field_type *field_type);
+extern struct bt_field *bt_field_create(struct bt_field_type *field_type);
 
 /**
 @brief Returns the parent @ft of the @field \p field.
@@ -177,8 +176,7 @@ create the field object in the first place with bt_field_create().
 @postrefcountsame{field}
 @postsuccessrefcountretinc
 */
-extern struct bt_field_type *bt_field_get_type(
-       struct bt_field *field);
+extern struct bt_field_type *bt_field_get_type(struct bt_field *field);
 
 /** @} */
 
@@ -216,21 +214,7 @@ extern struct bt_field_type *bt_field_get_type(
 @sa bt_field_is_variant(): Returns whether or not a given field is a
        @varfield.
 */
-extern enum bt_field_type_id bt_field_get_type_id(
-               struct bt_field *field);
-
-/*
- * bt_field_signed_integer_get_value: get a signed integer field's value
- *
- * Get a signed integer field's value.
- *
- * @param integer Signed integer field instance.
- * @param value Pointer to a signed integer where the value will be stored.
- *
- * Returns 0 on success, a negative value on error.
- */
-extern int bt_field_signed_integer_get_value(struct bt_field *integer,
-               int64_t *value);
+extern enum bt_field_type_id bt_field_get_type_id(struct bt_field *field);
 
 /**
 @brief Returns whether or not the @field \p field is a @intfield.
@@ -403,17 +387,17 @@ a @intft.
 An integer field object is considered \em unsigned if
 bt_field_type_integer_get_signed() on its parent field type returns
 0. Otherwise it is considered \em signed. You \em must use
-bt_field_unsigned_integer_get_value() and
-bt_field_unsigned_integer_set_value() with an unsigned integer
-field, and bt_field_signed_integer_get_value() and
-bt_field_signed_integer_set_value() with a signed integer field.
+bt_field_integer_unsigned_get_value() and
+bt_field_integer_unsigned_set_value() with an unsigned integer
+field, and bt_field_integer_signed_get_value() and
+bt_field_integer_signed_set_value() with a signed integer field.
 
 After you create an integer field with bt_field_create(), you
 \em must set an integral value with
-bt_field_unsigned_integer_set_value() or
-bt_field_signed_integer_set_value() before you can get the
-field's value with bt_field_unsigned_integer_get_value() or
-bt_field_signed_integer_get_value().
+bt_field_integer_unsigned_set_value() or
+bt_field_integer_signed_set_value() before you can get the
+field's value with bt_field_integer_unsigned_get_value() or
+bt_field_integer_signed_get_value().
 
 @sa ctfirintfieldtype
 @sa ctfirfields
@@ -440,13 +424,13 @@ bt_field_signed_integer_get_value().
 @pre bt_field_type_integer_get_signed() returns 1 for the parent
        @ft of \p integer_field.
 @pre \p integer_field contains a signed integral value previously
-       set with bt_field_signed_integer_set_value().
+       set with bt_field_integer_signed_set_value().
 @postrefcountsame{integer_field}
 
-@sa bt_field_signed_integer_set_value(): Sets the signed integral
+@sa bt_field_integer_signed_set_value(): Sets the signed integral
        value of a given integer field.
 */
-extern int bt_field_signed_integer_get_value(
+extern int bt_field_integer_signed_get_value(
                struct bt_field *integer_field, int64_t *value);
 
 /**
@@ -466,10 +450,10 @@ extern int bt_field_signed_integer_get_value(
        @ft of \p integer_field.
 @postrefcountsame{integer_field}
 
-@sa bt_field_signed_integer_get_value(): Returns the signed integral
+@sa bt_field_integer_signed_get_value(): Returns the signed integral
        value of a given integer field.
 */
-extern int bt_field_signed_integer_set_value(
+extern int bt_field_integer_signed_set_value(
                struct bt_field *integer_field, int64_t value);
 
 /**
@@ -490,13 +474,13 @@ extern int bt_field_signed_integer_set_value(
 @pre bt_field_type_integer_get_signed() returns 0 for the parent
        @ft of \p integer_field.
 @pre \p integer_field contains an unsigned integral value previously
-       set with bt_field_unsigned_integer_set_value().
+       set with bt_field_integer_unsigned_set_value().
 @postrefcountsame{integer_field}
 
-@sa bt_field_unsigned_integer_set_value(): Sets the unsigned
+@sa bt_field_integer_unsigned_set_value(): Sets the unsigned
        integral value of a given integer field.
 */
-extern int bt_field_unsigned_integer_get_value(
+extern int bt_field_integer_unsigned_get_value(
                struct bt_field *integer_field, uint64_t *value);
 
 /**
@@ -516,10 +500,10 @@ extern int bt_field_unsigned_integer_get_value(
        @ft of \p integer_field.
 @postrefcountsame{integer_field}
 
-@sa bt_field_unsigned_integer_get_value(): Returns the unsigned
+@sa bt_field_integer_unsigned_get_value(): Returns the unsigned
        integral value of a given integer field.
 */
-extern int bt_field_unsigned_integer_set_value(
+extern int bt_field_integer_unsigned_set_value(
                struct bt_field *integer_field, uint64_t value);
 
 /** @} */
@@ -593,8 +577,7 @@ extern int bt_field_floating_point_get_value(
        number value of a given floating point number field.
 */
 extern int bt_field_floating_point_set_value(
-               struct bt_field *float_field,
-               double value);
+               struct bt_field *float_field, double value);
 
 /** @} */
 
@@ -613,8 +596,8 @@ holds a @intfield, and which is described by a @enumft.
 To set the current integral value of an enumeration field, you need to
 get its wrapped @intfield with bt_field_enumeration_get_container(),
 and then set the integral value with either
-bt_field_signed_integer_set_value() or
-bt_field_unsigned_integer_set_value().
+bt_field_integer_signed_set_value() or
+bt_field_integer_unsigned_set_value().
 
 Once you set the integral value of an enumeration field by following the
 previous paragraph, you can get the mappings containing this value in
@@ -733,8 +716,7 @@ value.
 @sa bt_field_string_set_value(): Sets the string value of a given
        string field.
 */
-extern const char *bt_field_string_get_value(
-               struct bt_field *string_field);
+extern const char *bt_field_string_get_value(struct bt_field *string_field);
 
 /**
 @brief Sets the string value of the @stringfield \p string_field to
@@ -1193,20 +1175,6 @@ extern struct bt_field *bt_field_variant_get_tag(
 
 /** @} */
 
-/* Pre-2.0 CTF writer compatibility */
-#define bt_ctf_field bt_field
-#define bt_ctf_field_create bt_field_create
-#define bt_ctf_field_structure_get_field bt_field_structure_get_field_by_name
-#define bt_ctf_field_variant_get_field bt_field_variant_get_field
-#define bt_ctf_field_array_get_field bt_field_array_get_field
-#define bt_ctf_field_sequence_set_length bt_field_sequence_set_length
-#define bt_ctf_field_sequence_get_field bt_field_sequence_get_field
-#define bt_ctf_field_enumeration_get_container bt_field_enumeration_get_container
-#define bt_ctf_field_signed_integer_set_value bt_field_signed_integer_set_value
-#define bt_ctf_field_unsigned_integer_set_value bt_field_unsigned_integer_set_value
-#define bt_ctf_field_floating_point_set_value bt_field_floating_point_set_value
-#define bt_ctf_field_string_set_value bt_field_string_set_value
-
 #ifdef __cplusplus
 }
 #endif
index a844ca165a2a786a0aabb3e26ca9aa704dba6747..f3fe96cf2fe2283b4e630470338b35a1f740af5b 100644 (file)
  * SOFTWARE.
  */
 
+#include <babeltrace/assert-internal.h>
 #include <babeltrace/ctf-ir/fields.h>
 #include <babeltrace/ctf-ir/stream.h>
 #include <babeltrace/object-internal.h>
 #include <babeltrace/babeltrace-internal.h>
-#include <babeltrace/assert-internal.h>
 
 struct bt_packet {
        struct bt_object base;
index dad97907b0614fec1f5f834590ffc760f9646d02..619ae818fa036f4564bcb07a4e31f3ef82e099d0 100644 (file)
@@ -61,12 +61,12 @@ enum bt_resolve_flag {
  */
 BT_HIDDEN
 int bt_resolve_types(struct bt_value *environment,
-               struct bt_field_type *packet_header_type,
-               struct bt_field_type *packet_context_type,
-               struct bt_field_type *event_header_type,
-               struct bt_field_type *stream_event_ctx_type,
-               struct bt_field_type *event_context_type,
-               struct bt_field_type *event_payload_type,
+               struct bt_field_type_common *packet_header_type,
+               struct bt_field_type_common *packet_context_type,
+               struct bt_field_type_common *event_header_type,
+               struct bt_field_type_common *stream_event_ctx_type,
+               struct bt_field_type_common *event_context_type,
+               struct bt_field_type_common *event_payload_type,
                enum bt_resolve_flag flags);
 
 #endif /* BABELTRACE_CTF_IR_RESOLVE_INTERNAL_H */
index fecf8f298fc01e57d2ab049a8bc67b005b9ae3ee..4041110854ccbf1b101a12fced395bcdadaf432f 100644 (file)
  * SOFTWARE.
  */
 
-#include <babeltrace/ctf-writer/clock.h>
-#include <babeltrace/ctf-writer/event-fields.h>
-#include <babeltrace/ctf-writer/event-types.h>
-#include <babeltrace/ctf-ir/trace.h>
+#include <babeltrace/assert-internal.h>
+#include <babeltrace/common-internal.h>
+#include <babeltrace/ctf-ir/validation-internal.h>
+#include <babeltrace/ctf-ir/field-types-internal.h>
+#include <babeltrace/ctf-ir/utils-internal.h>
+#include <babeltrace/ctf-ir/visitor.h>
 #include <babeltrace/object-internal.h>
 #include <babeltrace/babeltrace-internal.h>
-#include <babeltrace/ctf-ir/trace-internal.h>
-#include <babeltrace/assert-internal.h>
 #include <glib.h>
+#include <inttypes.h>
 
-struct bt_stream_class {
+struct bt_stream_class_common {
        struct bt_object base;
        GString *name;
-       struct bt_ctf_clock *clock;
-       GPtrArray *event_classes; /* Array of pointers to bt_event_class */
-       /* event class id (int64_t) to event class */
+
+       /* Array of pointers to event class addresses */
+       GPtrArray *event_classes;
+
+       /* event class id (int64_t) to event class address */
        GHashTable *event_classes_ht;
        int id_set;
        int64_t id;
        int64_t next_event_id;
-       int64_t next_stream_id;
-       struct bt_field_type *packet_context_type;
-       struct bt_field_type *event_header_type;
-       struct bt_field_type *event_context_type;
+       struct bt_field_type_common *packet_context_field_type;
+       struct bt_field_type_common *event_header_field_type;
+       struct bt_field_type_common *event_context_field_type;
        int frozen;
        int byte_order;
 
@@ -80,43 +82,450 @@ struct bt_stream_class {
        struct bt_clock_class *clock_class;
 };
 
-BT_HIDDEN
-void bt_stream_class_freeze(struct bt_stream_class *stream_class);
+struct bt_stream_class {
+       struct bt_stream_class_common common;
+};
+
+struct bt_event_class_common;
 
 BT_HIDDEN
-int bt_stream_class_serialize(struct bt_stream_class *stream_class,
-               struct metadata_context *context);
+int bt_stream_class_common_initialize(struct bt_stream_class_common *stream_class,
+               const char *name, bt_object_release_func release_func);
 
 BT_HIDDEN
-void bt_stream_class_set_byte_order(
-               struct bt_stream_class *stream_class, int byte_order);
+void bt_stream_class_common_finalize(struct bt_stream_class_common *stream_class);
 
-/* Set stream_class id without checking if the stream class is frozen */
 BT_HIDDEN
-void _bt_stream_class_set_id(struct bt_stream_class *stream_class,
-               int64_t id);
+void bt_stream_class_common_freeze(struct bt_stream_class_common *stream_class);
 
 BT_HIDDEN
-int bt_stream_class_set_id_no_check(
-               struct bt_stream_class *stream_class, int64_t id);
+void bt_stream_class_freeze(struct bt_stream_class *stream_class);
+
+static inline
+const char *bt_stream_class_common_get_name(
+               struct bt_stream_class_common *stream_class)
+{
+       BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
+       return stream_class->name->len > 0 ? stream_class->name->str : NULL;
+}
+
+static inline
+int64_t bt_stream_class_common_get_id(
+               struct bt_stream_class_common *stream_class)
+{
+       int64_t ret;
+
+       BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
+
+       if (!stream_class->id_set) {
+               BT_LOGV("Stream class's ID is not set: addr=%p, name=\"%s\"",
+                       stream_class,
+                       bt_stream_class_common_get_name(stream_class));
+               ret = (int64_t) -1;
+               goto end;
+       }
+
+       ret = stream_class->id;
+
+end:
+       return ret;
+}
 
 BT_HIDDEN
-int bt_stream_class_map_clock_class(
-               struct bt_stream_class *stream_class,
-               struct bt_field_type *packet_context_type,
-               struct bt_field_type *event_header_type);
+void bt_stream_class_common_set_byte_order(
+               struct bt_stream_class_common *stream_class, int byte_order);
 
 BT_HIDDEN
-int bt_stream_class_validate_single_clock_class(
-               struct bt_stream_class *stream_class,
+int bt_stream_class_common_validate_single_clock_class(
+               struct bt_stream_class_common *stream_class,
                struct bt_clock_class **expected_clock_class);
 
+BT_HIDDEN
+int bt_stream_class_common_add_event_class(
+               struct bt_stream_class_common *stream_class,
+               struct bt_event_class_common *event_class,
+               bt_validation_flag_copy_field_type_func copy_field_type_func);
+
+BT_HIDDEN
+int bt_stream_class_common_visit(struct bt_stream_class_common *stream_class,
+               bt_visitor visitor, void *data);
+
+static inline
+struct bt_trace_common *bt_stream_class_common_borrow_trace(
+               struct bt_stream_class_common *stream_class)
+{
+       BT_ASSERT(stream_class);
+       return (void *) bt_object_borrow_parent(stream_class);
+}
+
 static inline
 struct bt_trace *bt_stream_class_borrow_trace(
                struct bt_stream_class *stream_class)
+{
+       return BT_FROM_COMMON(bt_stream_class_common_borrow_trace(
+               BT_TO_COMMON(stream_class)));
+}
+
+static inline
+struct bt_trace_common *bt_stream_class_common_get_trace(
+               struct bt_stream_class_common *stream_class)
+{
+       BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
+       return bt_get(bt_stream_class_common_borrow_trace(stream_class));
+}
+
+static inline
+int bt_stream_class_common_set_name(struct bt_stream_class_common *stream_class,
+               const char *name)
+{
+       int ret = 0;
+
+       if (!stream_class) {
+               BT_LOGW_STR("Invalid parameter: stream class is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       if (stream_class->frozen) {
+               BT_LOGW("Invalid parameter: stream class is frozen: "
+                       "addr=%p, name=\"%s\", id=%" PRId64,
+                       stream_class,
+                       bt_stream_class_common_get_name(stream_class),
+                       bt_stream_class_common_get_id(stream_class));
+               ret = -1;
+               goto end;
+       }
+
+       if (!name) {
+               g_string_assign(stream_class->name, "");
+       } else {
+               if (strlen(name) == 0) {
+                       BT_LOGW("Invalid parameter: name is empty.");
+                       ret = -1;
+                       goto end;
+               }
+
+               g_string_assign(stream_class->name, name);
+       }
+
+       BT_LOGV("Set stream class's name: "
+               "addr=%p, name=\"%s\", id=%" PRId64,
+               stream_class, bt_stream_class_common_get_name(stream_class),
+               bt_stream_class_common_get_id(stream_class));
+end:
+       return ret;
+}
+
+static inline
+void _bt_stream_class_common_set_id(
+               struct bt_stream_class_common *stream_class, int64_t id)
 {
        BT_ASSERT(stream_class);
-       return (void *) bt_object_borrow_parent(stream_class);
+       stream_class->id = id;
+       stream_class->id_set = 1;
+       BT_LOGV("Set stream class's ID (internal): "
+               "addr=%p, name=\"%s\", id=%" PRId64,
+               stream_class, bt_stream_class_common_get_name(stream_class),
+               bt_stream_class_common_get_id(stream_class));
+}
+
+static inline
+int bt_stream_class_common_set_id_no_check(
+               struct bt_stream_class_common *stream_class, int64_t id)
+{
+       _bt_stream_class_common_set_id(stream_class, id);
+       return 0;
+}
+
+static inline
+int bt_stream_class_common_set_id(struct bt_stream_class_common *stream_class,
+               uint64_t id_param)
+{
+       int ret = 0;
+       int64_t id = (int64_t) id_param;
+
+       if (!stream_class) {
+               BT_LOGW_STR("Invalid parameter: stream class is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       if (stream_class->frozen) {
+               BT_LOGW("Invalid parameter: stream class is frozen: "
+                       "addr=%p, name=\"%s\", id=%" PRId64,
+                       stream_class,
+                       bt_stream_class_common_get_name(stream_class),
+                       bt_stream_class_common_get_id(stream_class));
+               ret = -1;
+               goto end;
+       }
+
+       if (id < 0) {
+               BT_LOGW("Invalid parameter: invalid stream class's ID: "
+                       "stream-class-addr=%p, stream-class-name=\"%s\", "
+                       "stream-class-id=%" PRId64 ", id=%" PRIu64,
+                       stream_class,
+                       bt_stream_class_common_get_name(stream_class),
+                       bt_stream_class_common_get_id(stream_class),
+                       id_param);
+               ret = -1;
+               goto end;
+       }
+
+       ret = bt_stream_class_common_set_id_no_check(stream_class, id);
+       if (ret == 0) {
+               BT_LOGV("Set stream class's ID: "
+                       "addr=%p, name=\"%s\", id=%" PRId64,
+                       stream_class,
+                       bt_stream_class_common_get_name(stream_class),
+                       bt_stream_class_common_get_id(stream_class));
+       }
+end:
+       return ret;
+}
+
+static inline
+int64_t bt_stream_class_common_get_event_class_count(
+               struct bt_stream_class_common *stream_class)
+{
+       int64_t ret;
+
+       if (!stream_class) {
+               BT_LOGW_STR("Invalid parameter: stream class is NULL.");
+               ret = (int64_t) -1;
+               goto end;
+       }
+
+       ret = (int64_t) stream_class->event_classes->len;
+end:
+       return ret;
+}
+
+static inline
+struct bt_event_class_common *bt_stream_class_common_get_event_class_by_index(
+               struct bt_stream_class_common *stream_class, uint64_t index)
+{
+       BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
+       BT_ASSERT_PRE(index < stream_class->event_classes->len,
+               "Index is out of bounds: index=%" PRIu64 ", "
+               "count=%u",
+               index, stream_class->event_classes->len);
+       return bt_get(g_ptr_array_index(stream_class->event_classes, index));
+}
+
+static inline
+struct bt_event_class_common *bt_stream_class_common_get_event_class_by_id(
+               struct bt_stream_class_common *stream_class, uint64_t id)
+{
+       int64_t id_key = (int64_t) id;
+
+       BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
+       BT_ASSERT_PRE(id_key >= 0,
+               "Invalid event class ID: %" PRIu64, id);
+       return bt_get(g_hash_table_lookup(stream_class->event_classes_ht,
+                       &id_key));
+}
+
+static inline
+struct bt_field_type_common *bt_stream_class_common_get_packet_context_field_type(
+               struct bt_stream_class_common *stream_class)
+{
+       BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
+       return bt_get(stream_class->packet_context_field_type);
+}
+
+static inline
+int bt_stream_class_common_set_packet_context_field_type(
+               struct bt_stream_class_common *stream_class,
+               struct bt_field_type_common *packet_context_type)
+{
+       int ret = 0;
+
+       if (!stream_class) {
+               BT_LOGW_STR("Invalid parameter: stream class is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       if (stream_class->frozen) {
+               BT_LOGW("Invalid parameter: stream class is frozen: "
+                       "addr=%p, name=\"%s\", id=%" PRId64,
+                       stream_class, bt_stream_class_common_get_name(stream_class),
+                       bt_stream_class_common_get_id(stream_class));
+               ret = -1;
+               goto end;
+       }
+
+       if (packet_context_type &&
+                       bt_field_type_common_get_type_id(packet_context_type) !=
+                               BT_FIELD_TYPE_ID_STRUCT) {
+               /* A packet context must be a structure. */
+               BT_LOGW("Invalid parameter: stream class's packet context field type must be a structure: "
+                       "addr=%p, name=\"%s\", id=%" PRId64 ", "
+                       "packet-context-ft-addr=%p, packet-context-ft-id=%s",
+                       stream_class, bt_stream_class_common_get_name(stream_class),
+                       bt_stream_class_common_get_id(stream_class),
+                       packet_context_type,
+                       bt_common_field_type_id_string(
+                               bt_field_type_common_get_type_id(packet_context_type)));
+               ret = -1;
+               goto end;
+       }
+
+       bt_put(stream_class->packet_context_field_type);
+       bt_get(packet_context_type);
+       stream_class->packet_context_field_type = packet_context_type;
+       BT_LOGV("Set stream class's packet context field type: "
+               "addr=%p, name=\"%s\", id=%" PRId64 ", "
+               "packet-context-ft-addr=%p",
+               stream_class, bt_stream_class_common_get_name(stream_class),
+               bt_stream_class_common_get_id(stream_class),
+               packet_context_type);
+
+end:
+       return ret;
+}
+
+static inline
+struct bt_field_type_common *bt_stream_class_common_get_event_header_field_type(
+               struct bt_stream_class_common *stream_class)
+{
+       struct bt_field_type_common *ret = NULL;
+
+       BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
+
+       if (!stream_class->event_header_field_type) {
+               BT_LOGV("Stream class has no event header field type: "
+                       "addr=%p, name=\"%s\", id=%" PRId64,
+                       stream_class,
+                       bt_stream_class_common_get_name(stream_class),
+                       bt_stream_class_common_get_id(stream_class));
+               goto end;
+       }
+
+       ret = bt_get(stream_class->event_header_field_type);
+
+end:
+       return ret;
+}
+
+static inline
+int bt_stream_class_common_set_event_header_field_type(
+               struct bt_stream_class_common *stream_class,
+               struct bt_field_type_common *event_header_type)
+{
+       int ret = 0;
+
+       if (!stream_class) {
+               BT_LOGW_STR("Invalid parameter: stream class is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       if (stream_class->frozen) {
+               BT_LOGW("Invalid parameter: stream class is frozen: "
+                       "addr=%p, name=\"%s\", id=%" PRId64,
+                       stream_class,
+                       bt_stream_class_common_get_name(stream_class),
+                       bt_stream_class_common_get_id(stream_class));
+               ret = -1;
+               goto end;
+       }
+
+       if (event_header_type &&
+                       bt_field_type_common_get_type_id(event_header_type) !=
+                               BT_FIELD_TYPE_ID_STRUCT) {
+               /* An event header must be a structure. */
+               BT_LOGW("Invalid parameter: stream class's event header field type must be a structure: "
+                       "addr=%p, name=\"%s\", id=%" PRId64 ", "
+                       "event-header-ft-addr=%p, event-header-ft-id=%s",
+                       stream_class, bt_stream_class_common_get_name(stream_class),
+                       bt_stream_class_common_get_id(stream_class),
+                       event_header_type,
+                       bt_common_field_type_id_string(
+                               bt_field_type_common_get_type_id(event_header_type)));
+               ret = -1;
+               goto end;
+       }
+
+       bt_put(stream_class->event_header_field_type);
+       stream_class->event_header_field_type = bt_get(event_header_type);
+       BT_LOGV("Set stream class's event header field type: "
+               "addr=%p, name=\"%s\", id=%" PRId64 ", "
+               "event-header-ft-addr=%p",
+               stream_class, bt_stream_class_common_get_name(stream_class),
+               bt_stream_class_common_get_id(stream_class),
+               event_header_type);
+end:
+       return ret;
+}
+
+static inline
+struct bt_field_type_common *bt_stream_class_common_get_event_context_field_type(
+               struct bt_stream_class_common *stream_class)
+{
+       struct bt_field_type_common *ret = NULL;
+
+       BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
+
+       if (!stream_class->event_context_field_type) {
+               goto end;
+       }
+
+       ret = bt_get(stream_class->event_context_field_type);
+
+end:
+       return ret;
+}
+
+static inline
+int bt_stream_class_common_set_event_context_field_type(
+               struct bt_stream_class_common *stream_class,
+               struct bt_field_type_common *event_context_type)
+{
+       int ret = 0;
+
+       if (!stream_class) {
+               BT_LOGW_STR("Invalid parameter: stream class is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       if (stream_class->frozen) {
+               BT_LOGW("Invalid parameter: stream class is frozen: "
+                       "addr=%p, name=\"%s\", id=%" PRId64,
+                       stream_class, bt_stream_class_common_get_name(stream_class),
+                       bt_stream_class_common_get_id(stream_class));
+               ret = -1;
+               goto end;
+       }
+
+       if (event_context_type &&
+                       bt_field_type_common_get_type_id(event_context_type) !=
+                               BT_FIELD_TYPE_ID_STRUCT) {
+               /* A packet context must be a structure. */
+               BT_LOGW("Invalid parameter: stream class's event context field type must be a structure: "
+                       "addr=%p, name=\"%s\", id=%" PRId64 ", "
+                       "event-context-ft-addr=%p, event-context-ft-id=%s",
+                       stream_class, bt_stream_class_common_get_name(stream_class),
+                       bt_stream_class_common_get_id(stream_class),
+                       event_context_type,
+                       bt_common_field_type_id_string(
+                               bt_field_type_common_get_type_id(event_context_type)));
+               ret = -1;
+               goto end;
+       }
+
+       bt_put(stream_class->event_context_field_type);
+       stream_class->event_context_field_type = bt_get(event_context_type);
+       BT_LOGV("Set stream class's event context field type: "
+               "addr=%p, name=\"%s\", id=%" PRId64 ", "
+               "event-context-ft-addr=%p",
+               stream_class, bt_stream_class_common_get_name(stream_class),
+               bt_stream_class_common_get_id(stream_class),
+               event_context_type);
+end:
+       return ret;
 }
 
 #endif /* BABELTRACE_CTF_IR_STREAM_CLASS_INTERNAL_H */
index 175bb68850f5db89964fe55f924fff7c231a1720..94d7c9b889507870757bdaba6305f3a33d107e1a 100644 (file)
@@ -145,28 +145,6 @@ struct bt_clock;
 @{
 */
 
-/**
-@brief Creates an empty CTF IR stream class named \p name, or an
-       unnamed empty stream class if \p name is \c NULL.
-
-On success, the packet context, event header, and event context field
-types are empty structure field types. You can modify those default
-field types after the stream class is created with
-bt_stream_class_set_packet_context_type(),
-bt_stream_class_set_event_header_type(), and
-bt_stream_class_set_event_context_type().
-
-@param[in] name        Name of the stream class to create (copied on success),
-               or \c NULL to create an unnamed stream class.
-@returns       Created empty stream class, or \c NULL on error.
-
-@postsuccessrefcountret1
-
-@sa bt_stream_class_create(): Creates a default stream class.
-*/
-extern struct bt_stream_class *bt_stream_class_create_empty(
-               const char *name);
-
 /**
 @brief Creates a default CTF IR stream class named \p name­, or a
        default unnamed stream class if \p name is \c NULL.
@@ -187,8 +165,8 @@ has the following fields:
 - <code>timestamp</code>: a 64-bit unsigned integer field type.
 
 You can modify those default field types after the stream class is
-created with bt_stream_class_set_packet_context_type() and
-bt_stream_class_set_event_header_type().
+created with bt_stream_class_set_packet_context_field_type() and
+bt_stream_class_set_event_header_field_type().
 
 @param[in] name        Name of the stream class to create (copied on success),
                or \c NULL to create an unnamed stream class.
@@ -337,10 +315,10 @@ extern int bt_stream_class_set_id(
 @post <strong>On success, if the return value is a field type</strong>, its
        reference count is incremented.
 
-@sa bt_stream_class_set_packet_context_type(): Sets the packet
+@sa bt_stream_class_set_packet_context_field_type(): Sets the packet
        context field type of a given stream class.
 */
-extern struct bt_field_type *bt_stream_class_get_packet_context_type(
+extern struct bt_field_type *bt_stream_class_get_packet_context_field_type(
                struct bt_stream_class *stream_class);
 
 /**
@@ -369,10 +347,10 @@ As of Babeltrace \btversion, if \p packet_context_type is not \c NULL,
 @post <strong>On success, if \p packet_context_type is not \c NULL</strong>,
        the reference count of \p packet_context_type is incremented.
 
-@sa bt_stream_class_get_packet_context_type(): Returns the packet
+@sa bt_stream_class_get_packet_context_field_type(): Returns the packet
        context field type of a given stream class.
 */
-extern int bt_stream_class_set_packet_context_type(
+extern int bt_stream_class_set_packet_context_field_type(
                struct bt_stream_class *stream_class,
                struct bt_field_type *packet_context_type);
 
@@ -391,11 +369,11 @@ extern int bt_stream_class_set_packet_context_type(
 @post <strong>On success, if the return value is a field type</strong>, its
        reference count is incremented.
 
-@sa bt_stream_class_set_event_header_type(): Sets the event
+@sa bt_stream_class_set_event_header_field_type(): Sets the event
        header field type of a given stream class.
 */
 extern struct bt_field_type *
-bt_stream_class_get_event_header_type(
+bt_stream_class_get_event_header_field_type(
                struct bt_stream_class *stream_class);
 
 /**
@@ -424,10 +402,10 @@ As of Babeltrace \btversion, if \p event_header_type is not \c NULL,
 @post <strong>On success, if \p event_header_type is not \c NULL</strong>,
        the reference count of \p event_header_type is incremented.
 
-@sa bt_stream_class_get_event_header_type(): Returns the event
+@sa bt_stream_class_get_event_header_field_type(): Returns the event
        header field type of a given stream class.
 */
-extern int bt_stream_class_set_event_header_type(
+extern int bt_stream_class_set_event_header_field_type(
                struct bt_stream_class *stream_class,
                struct bt_field_type *event_header_type);
 
@@ -447,11 +425,11 @@ extern int bt_stream_class_set_event_header_type(
        its reference count is incremented.
 
 
-@sa bt_stream_class_set_event_context_type(): Sets the event
+@sa bt_stream_class_set_event_context_field_type(): Sets the event
        context field type of a given stream class.
 */
 extern struct bt_field_type *
-bt_stream_class_get_event_context_type(
+bt_stream_class_get_event_context_field_type(
                struct bt_stream_class *stream_class);
 
 /**
@@ -480,10 +458,10 @@ As of Babeltrace \btversion, if \p event_context_type is not \c NULL,
 @post <strong>On success, if \p event_context_type is not \c NULL</strong>,
        the reference count of \p event_context_type is incremented.
 
-@sa bt_stream_class_get_event_context_type(): Returns the event context
+@sa bt_stream_class_get_event_context_field_type(): Returns the event context
        field type of a given stream class.
 */
-extern int bt_stream_class_set_event_context_type(
+extern int bt_stream_class_set_event_context_field_type(
                struct bt_stream_class *stream_class,
                struct bt_field_type *event_context_type);
 
@@ -621,12 +599,6 @@ extern int bt_stream_class_visit(struct bt_stream_class *stream_class,
 
 /** @} */
 
-/* Pre-2.0 CTF writer compatibility */
-#define bt_ctf_stream_class bt_stream_class
-#define bt_ctf_stream_class_create bt_stream_class_create
-#define bt_ctf_stream_class_add_event_class bt_stream_class_add_event_class
-#define bt_ctf_stream_class_get_packet_context_type bt_stream_class_get_packet_context_type
-
 #ifdef __cplusplus
 }
 #endif
index 3214c1653c09073b79019712f6b8193b35a0a124..14765f490d27c6c0d4fb007c936faef9ddc1d0fb 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef BABELTRACE_CTF_WRITER_STREAM_INTERNAL_H
-#define BABELTRACE_CTF_WRITER_STREAM_INTERNAL_H
+#ifndef BABELTRACE_CTF_IR_STREAM_INTERNAL_H
+#define BABELTRACE_CTF_IR_STREAM_INTERNAL_H
 
 /*
  * BabelTrace - CTF Writer: Stream internal
  * SOFTWARE.
  */
 
+#include <babeltrace/assert-pre-internal.h>
+#include <babeltrace/assert-internal.h>
 #include <babeltrace/ctf-ir/stream.h>
+#include <babeltrace/ctf-ir/utils-internal.h>
 #include <babeltrace/object-internal.h>
-#include <babeltrace/ctf-writer/clock.h>
-#include <babeltrace/ctf-writer/event-fields.h>
-#include <babeltrace/ctf-writer/event-types.h>
-#include <babeltrace/ctf-writer/serialize-internal.h>
 #include <babeltrace/babeltrace-internal.h>
-#include <babeltrace/assert-internal.h>
 #include <glib.h>
 
-struct bt_port;
-struct bt_component;
+struct bt_stream_class;
+struct bt_stream_common;
 
-typedef void (*bt_stream_destroy_listener_func)(
-               struct bt_stream *stream, void *data);
+typedef void (*bt_stream_common_destroy_listener_func)(
+               struct bt_stream_common *stream, void *data);
 
-struct bt_stream_destroy_listener {
-       bt_stream_destroy_listener_func func;
+struct bt_stream_common_destroy_listener {
+       bt_stream_common_destroy_listener_func func;
        void *data;
 };
 
-struct bt_stream {
+struct bt_stream_common {
        struct bt_object base;
        int64_t id;
-       struct bt_stream_class *stream_class;
+       struct bt_stream_class_common *stream_class;
        GString *name;
-       struct bt_field *packet_header;
-       struct bt_field *packet_context;
-
-       /* Writer-specific members. */
-       /* Array of pointers to bt_event for the current packet */
-       GPtrArray *events;
-       struct bt_stream_pos pos;
-       unsigned int flushed_packet_count;
-       uint64_t discarded_events;
-       uint64_t size;
-       uint64_t last_ts_end;
-
-       /* Array of struct bt_stream_destroy_listener */
+
+       /* Array of struct bt_stream_common_destroy_listener */
        GArray *destroy_listeners;
 };
 
+struct bt_stream {
+       struct bt_stream_common common;
+};
+
 BT_HIDDEN
-int bt_stream_set_fd(struct bt_stream *stream, int fd);
+void bt_stream_common_add_destroy_listener(struct bt_stream_common *stream,
+               bt_stream_common_destroy_listener_func func, void *data);
 
 BT_HIDDEN
-void bt_stream_add_destroy_listener(struct bt_stream *stream,
-               bt_stream_destroy_listener_func func, void *data);
+void bt_stream_common_remove_destroy_listener(struct bt_stream_common *stream,
+               bt_stream_common_destroy_listener_func func, void *data);
 
 BT_HIDDEN
-void bt_stream_remove_destroy_listener(struct bt_stream *stream,
-               bt_stream_destroy_listener_func func, void *data);
+int bt_stream_common_initialize(
+               struct bt_stream_common *stream,
+               struct bt_stream_class_common *stream_class, const char *name,
+               uint64_t id, bt_object_release_func release_func);
+
+BT_HIDDEN
+void bt_stream_common_finalize(struct bt_stream_common *stream);
 
 static inline
-struct bt_stream_class *bt_stream_borrow_stream_class(
-               struct bt_stream *stream)
+struct bt_stream_class_common *bt_stream_common_borrow_class(
+               struct bt_stream_common *stream)
 {
        BT_ASSERT(stream);
        return stream->stream_class;
 }
 
-#endif /* BABELTRACE_CTF_WRITER_STREAM_INTERNAL_H */
+static inline
+struct bt_stream_class *bt_stream_borrow_class(struct bt_stream *stream)
+{
+       BT_ASSERT(stream);
+       return BT_FROM_COMMON(bt_stream_common_borrow_class(BT_TO_COMMON(stream)));
+}
+
+static inline
+struct bt_stream_class_common *bt_stream_common_get_class(
+               struct bt_stream_common *stream)
+{
+       return bt_get(bt_stream_common_borrow_class(stream));
+}
+
+static inline
+const char *bt_stream_common_get_name(struct bt_stream_common *stream)
+{
+       BT_ASSERT_PRE_NON_NULL(stream, "Stream");
+       return stream->name ? stream->name->str : NULL;
+}
+
+static inline
+int64_t bt_stream_common_get_id(struct bt_stream_common *stream)
+{
+       int64_t ret;
+
+       BT_ASSERT_PRE_NON_NULL(stream, "Stream");
+       ret = stream->id;
+       if (ret < 0) {
+               BT_LOGV("Stream's ID is not set: addr=%p, name=\"%s\"",
+                       stream, bt_stream_common_get_name(stream));
+       }
+
+       return ret;
+}
+
+#endif /* BABELTRACE_CTF_IR_STREAM_INTERNAL_H */
index 443e757e269e7bd6fefe6702c4242454f61a5c98..4b4ac3cfe42d9859d283aa612764c2f25ae16d31 100644 (file)
@@ -100,39 +100,6 @@ management of Babeltrace objects.
 struct bt_stream;
 struct bt_event;
 
-/**
-@brief  Creates a default CTF IR stream named \p name from the CTF IR
-       stream class \p stream_class.
-
-\p stream_class \em must have a parent
-\link ctfirtraceclass CTF IR trace class\endlink.
-
-If the parent \link ctfirtraceclass trace class\endlink of
-\p stream_class was created by a \link ctfwriter CTF writer\endlink
-object, then the stream object is created in CTF writer mode, and
-you can use the functions of \ref ctfwriterstream on it.
-Otherwise it is created in normal mode: you should only use the
-functions documented in this module on it.
-
-\p name can be \c NULL to create an unnamed stream object.
-
-@param[in] stream_class        CTF IR stream class to use to create the
-                       CTF IR stream.
-@param[in] name                Name of the stream object to create (copied on
-                       success) or \c NULL to create an unnamed stream.
-@returns               Created stream object, or \c NULL on error.
-
-@prenotnull{stream_class}
-@pre \p stream_class has a parent trace class.
-@postsuccessrefcountret1
-
-@sa bt_stream_create_with_id(): Create a CTF IR stream with a
-       specific ID.
-*/
-extern struct bt_stream *bt_stream_create(
-               struct bt_stream_class *stream_class,
-               const char *name);
-
 /**
 @brief  Creates a default CTF IR stream named \p name with ID \p id
        from the CTF IR stream class \p stream_class.
@@ -140,10 +107,6 @@ extern struct bt_stream *bt_stream_create(
 \p stream_class \em must have a parent
 \link ctfirtraceclass CTF IR trace class\endlink.
 
-You \em must have created the trace class of \p stream class directly
-with bt_trace_create(), not through bt_writer_create() (use
-bt_stream_create() for this).
-
 \p id \em must be unique amongst the IDs of all the streams created
 from \p stream_class with bt_stream_create_with_id().
 
@@ -160,11 +123,8 @@ from \p stream_class with bt_stream_create_with_id().
 @pre \p id is lesser than or equal to 9223372036854775807 (\c INT64_MAX).
 @pre \p stream_class has a parent trace class.
 @postsuccessrefcountret1
-
-@sa bt_stream_create(): Create a CTF IR stream without an ID.
 */
-extern struct bt_stream *bt_stream_create_with_id(
-               struct bt_stream_class *stream_class,
+extern struct bt_stream *bt_stream_create(struct bt_stream_class *stream_class,
                const char *name, uint64_t id);
 
 /**
@@ -214,9 +174,6 @@ extern struct bt_stream_class *bt_stream_get_class(
 
 /** @} */
 
-/* Pre-2.0 CTF writer compatibility */
-#define bt_ctf_stream bt_stream
-
 #ifdef __cplusplus
 }
 #endif
index 1ea43f691267e51bcd64c37df238b4f2382047ce..05f25bebd905f9cdf4328a8dde607596a9eb3381 100644 (file)
  * SOFTWARE.
  */
 
+#include <babeltrace/assert-pre-internal.h>
 #include <babeltrace/ctf-ir/trace.h>
+#include <babeltrace/ctf-ir/stream-class-internal.h>
 #include <babeltrace/ctf-ir/field-types.h>
 #include <babeltrace/ctf-ir/fields.h>
+#include <babeltrace/ctf-ir/validation-internal.h>
+#include <babeltrace/ctf-ir/attributes-internal.h>
+#include <babeltrace/ctf-ir/clock-class-internal.h>
 #include <babeltrace/object-internal.h>
 #include <babeltrace/babeltrace-internal.h>
 #include <babeltrace/values.h>
 #include <sys/types.h>
 #include <babeltrace/compat/uuid-internal.h>
 
-enum field_type_alias {
-       FIELD_TYPE_ALIAS_UINT5_T = 0,
-       FIELD_TYPE_ALIAS_UINT8_T,
-       FIELD_TYPE_ALIAS_UINT16_T,
-       FIELD_TYPE_ALIAS_UINT27_T,
-       FIELD_TYPE_ALIAS_UINT32_T,
-       FIELD_TYPE_ALIAS_UINT64_T,
-       NR_FIELD_TYPE_ALIAS,
-};
-
-struct bt_trace {
+struct bt_trace_common {
        struct bt_object base;
        GString *name;
        int frozen;
@@ -56,42 +51,33 @@ struct bt_trace {
        bt_bool uuid_set;
        enum bt_byte_order native_byte_order;
        struct bt_value *environment;
-       GPtrArray *clocks; /* Array of pointers to bt_clock_class */
-       GPtrArray *stream_classes; /* Array of ptrs to bt_stream_class */
-       GPtrArray *streams; /* Array of ptrs to bt_stream */
-       struct bt_field_type *packet_header_type;
+       GPtrArray *clock_classes; /* Array of pointers to bt_clock_class */
+       GPtrArray *stream_classes; /* Array of ptrs to bt_stream_class_common */
+       GPtrArray *streams; /* Array of ptrs to bt_stream_common */
+       struct bt_field_type_common *packet_header_field_type;
        int64_t next_stream_id;
-       int is_created_by_writer;
 
        /*
         * This flag indicates if the trace is valid. A valid
         * trace is _always_ frozen.
         */
        int valid;
+};
+
+struct bt_trace {
+       struct bt_trace_common common;
        GPtrArray *listeners; /* Array of struct listener_wrapper */
        GArray *is_static_listeners;
        bt_bool is_static;
        bt_bool in_remove_listener;
 };
 
-struct metadata_context {
-       GString *string;
-       GString *field_name;
-       unsigned int current_indentation_level;
-};
-
-BT_HIDDEN
-const char *get_byte_order_string(int byte_order);
-
-BT_HIDDEN
-struct bt_field_type *get_field_type(enum field_type_alias alias);
-
 BT_HIDDEN
 int bt_trace_object_modification(struct bt_visitor_object *object,
                void *trace_ptr);
 
 BT_HIDDEN
-bt_bool bt_trace_has_clock_class(struct bt_trace *trace,
+bt_bool bt_trace_common_has_clock_class(struct bt_trace_common *trace,
                struct bt_clock_class *clock_class);
 
 /**
@@ -126,17 +112,269 @@ BT_HIDDEN
 int bt_trace_add_listener(struct bt_trace *trace_class,
                bt_listener_cb listener, void *data);
 
-/*
- * bt_trace_get_metadata_string: get metadata string.
- *
- * Get the trace's TSDL metadata. The caller assumes the ownership of the
- * returned string.
- *
- * @param trace Trace instance.
- *
- * Returns the metadata string on success, NULL on error.
- */
 BT_HIDDEN
-char *bt_trace_get_metadata_string(struct bt_trace *trace);
+int bt_trace_common_initialize(struct bt_trace_common *trace,
+               bt_object_release_func release_func);
+
+BT_HIDDEN
+void bt_trace_common_finalize(struct bt_trace_common *trace);
+
+static inline
+const char *bt_trace_common_get_name(struct bt_trace_common *trace)
+{
+       BT_ASSERT_PRE_NON_NULL(trace, "Trace");
+       return trace->name ? trace->name->str : NULL;
+}
+
+BT_HIDDEN
+int bt_trace_common_set_name(struct bt_trace_common *trace, const char *name);
+
+static inline
+const unsigned char *bt_trace_common_get_uuid(struct bt_trace_common *trace)
+{
+       BT_ASSERT_PRE_NON_NULL(trace, "Trace");
+       return trace->uuid_set ? trace->uuid : NULL;
+}
+
+BT_HIDDEN
+int bt_trace_common_set_uuid(struct bt_trace_common *trace, const unsigned char *uuid);
+
+BT_HIDDEN
+int bt_trace_common_set_environment_field(struct bt_trace_common *trace,
+               const char *name, struct bt_value *value);
+
+BT_HIDDEN
+int bt_trace_common_set_environment_field_string(struct bt_trace_common *trace,
+               const char *name, const char *value);
+
+BT_HIDDEN
+int bt_trace_common_set_environment_field_integer(struct bt_trace_common *trace,
+               const char *name, int64_t value);
+
+static inline
+int64_t bt_trace_common_get_environment_field_count(
+               struct bt_trace_common *trace)
+{
+       int64_t ret;
+
+       BT_ASSERT_PRE_NON_NULL(trace, "Trace");
+       ret = bt_attributes_get_count(trace->environment);
+       BT_ASSERT(ret >= 0);
+       return ret;
+}
+
+static inline
+const char *
+bt_trace_common_get_environment_field_name_by_index(
+               struct bt_trace_common *trace,
+               uint64_t index)
+{
+       BT_ASSERT_PRE_NON_NULL(trace, "Trace");
+       return bt_attributes_get_field_name(trace->environment, index);
+}
+
+static inline
+struct bt_value *bt_trace_common_get_environment_field_value_by_index(
+               struct bt_trace_common *trace, uint64_t index)
+{
+       BT_ASSERT_PRE_NON_NULL(trace, "Trace");
+       return bt_attributes_get_field_value(trace->environment, index);
+}
+
+static inline
+struct bt_value *bt_trace_common_get_environment_field_value_by_name(
+               struct bt_trace_common *trace, const char *name)
+{
+       BT_ASSERT_PRE_NON_NULL(trace, "Trace");
+       BT_ASSERT_PRE_NON_NULL(name, "Name");
+       return bt_attributes_get_field_value_by_name(trace->environment,
+               name);
+}
+
+BT_HIDDEN
+int bt_trace_common_add_clock_class(struct bt_trace_common *trace,
+               struct bt_clock_class *clock_class);
+
+static inline
+int64_t bt_trace_common_get_clock_class_count(struct bt_trace_common *trace)
+{
+       BT_ASSERT_PRE_NON_NULL(trace, "Trace");
+       return trace->clock_classes->len;
+}
+
+static inline
+struct bt_clock_class *bt_trace_common_get_clock_class_by_index(
+               struct bt_trace_common *trace, uint64_t index)
+{
+       BT_ASSERT_PRE_NON_NULL(trace, "Trace");
+       BT_ASSERT_PRE(index < trace->clock_classes->len,
+               "Index is out of bounds: index=%" PRIu64 ", "
+               "count=%u",
+               index, trace->clock_classes->len);
+       return bt_get(g_ptr_array_index(trace->clock_classes, index));
+}
+
+static inline
+int64_t bt_trace_common_get_stream_count(struct bt_trace_common *trace)
+{
+       BT_ASSERT_PRE_NON_NULL(trace, "Trace");
+       return (int64_t) trace->streams->len;
+}
+
+static inline
+struct bt_stream_common *bt_trace_common_get_stream_by_index(
+               struct bt_trace_common *trace,
+               uint64_t index)
+{
+       BT_ASSERT_PRE_NON_NULL(trace, "Trace");
+       BT_ASSERT_PRE(index < trace->streams->len,
+               "Index is out of bounds: index=%" PRIu64 ", "
+               "count=%u",
+               index, trace->streams->len);
+       return bt_get(g_ptr_array_index(trace->streams, index));
+}
+
+static inline
+int64_t bt_trace_common_get_stream_class_count(struct bt_trace_common *trace)
+{
+       BT_ASSERT_PRE_NON_NULL(trace, "Trace");
+       return (int64_t) trace->stream_classes->len;
+}
+
+static inline
+struct bt_stream_class_common *bt_trace_common_get_stream_class_by_index(
+               struct bt_trace_common *trace, uint64_t index)
+{
+       BT_ASSERT_PRE_NON_NULL(trace, "Trace");
+       BT_ASSERT_PRE(index < trace->stream_classes->len,
+               "Index is out of bounds: index=%" PRIu64 ", "
+               "count=%u",
+               index, trace->stream_classes->len);
+       return bt_get(g_ptr_array_index(trace->stream_classes, index));
+}
+
+static inline
+struct bt_stream_class_common *bt_trace_common_get_stream_class_by_id(
+               struct bt_trace_common *trace, uint64_t id_param)
+{
+       int i;
+       struct bt_stream_class_common *stream_class = NULL;
+       int64_t id = (int64_t) id_param;
+
+       BT_ASSERT_PRE_NON_NULL(trace, "Trace");
+       BT_ASSERT_PRE(id >= 0,
+               "Invalid stream class ID: %" PRIu64, id_param);
+
+       for (i = 0; i < trace->stream_classes->len; i++) {
+               struct bt_stream_class_common *stream_class_candidate;
+
+               stream_class_candidate =
+                       g_ptr_array_index(trace->stream_classes, i);
+
+               if (bt_stream_class_common_get_id(stream_class_candidate) ==
+                               (int64_t) id) {
+                       stream_class = stream_class_candidate;
+                       bt_get(stream_class);
+                       goto end;
+               }
+       }
+
+end:
+       return stream_class;
+}
+
+static inline
+struct bt_clock_class *bt_trace_common_get_clock_class_by_name(
+               struct bt_trace_common *trace, const char *name)
+{
+       size_t i;
+       struct bt_clock_class *clock_class = NULL;
+
+       BT_ASSERT_PRE_NON_NULL(trace, "Trace");
+       BT_ASSERT_PRE_NON_NULL(name, "Name");
+
+       for (i = 0; i < trace->clock_classes->len; i++) {
+               struct bt_clock_class *cur_clk =
+                       g_ptr_array_index(trace->clock_classes, i);
+               const char *cur_clk_name = bt_clock_class_get_name(cur_clk);
+
+               if (!cur_clk_name) {
+                       goto end;
+               }
+
+               if (!strcmp(cur_clk_name, name)) {
+                       clock_class = cur_clk;
+                       bt_get(clock_class);
+                       goto end;
+               }
+       }
+
+end:
+       return clock_class;
+}
+
+static inline
+enum bt_byte_order bt_trace_common_get_native_byte_order(
+               struct bt_trace_common *trace)
+{
+       BT_ASSERT_PRE_NON_NULL(trace, "Trace");
+       return trace->native_byte_order;
+}
+
+BT_HIDDEN
+int bt_trace_common_set_native_byte_order(struct bt_trace_common *trace,
+               enum bt_byte_order byte_order, bool allow_unspecified);
+
+static inline
+struct bt_field_type_common *bt_trace_common_get_packet_header_field_type(
+               struct bt_trace_common *trace)
+{
+       BT_ASSERT_PRE_NON_NULL(trace, "Trace");
+       return bt_get(trace->packet_header_field_type);
+}
+
+BT_HIDDEN
+int bt_trace_common_set_packet_header_field_type(struct bt_trace_common *trace,
+               struct bt_field_type_common *packet_header_field_type);
+
+static inline
+void bt_trace_common_freeze(struct bt_trace_common *trace)
+{
+       int i;
+
+       if (trace->frozen) {
+               return;
+       }
+
+       BT_LOGD("Freezing trace: addr=%p, name=\"%s\"",
+               trace, bt_trace_common_get_name(trace));
+       BT_LOGD_STR("Freezing packet header field type.");
+       bt_field_type_common_freeze(trace->packet_header_field_type);
+       BT_LOGD_STR("Freezing environment attributes.");
+       bt_attributes_freeze(trace->environment);
+
+       if (trace->clock_classes->len > 0) {
+               BT_LOGD_STR("Freezing clock classes.");
+       }
+
+       for (i = 0; i < trace->clock_classes->len; i++) {
+               struct bt_clock_class *clock_class =
+                       g_ptr_array_index(trace->clock_classes, i);
+
+               bt_clock_class_freeze(clock_class);
+       }
+
+       trace->frozen = 1;
+}
+
+BT_HIDDEN
+int bt_trace_common_add_stream_class(struct bt_trace_common *trace,
+               struct bt_stream_class_common *stream_class,
+               bt_validation_flag_copy_field_type_func copy_field_type_func,
+               struct bt_clock_class *init_expected_clock_class,
+               int (*map_clock_classes_func)(struct bt_stream_class_common *stream_class,
+                       struct bt_field_type_common *packet_context_field_type,
+                       struct bt_field_type_common *event_header_field_type),
+               bool check_ts_begin_end_mapped);
 
 #endif /* BABELTRACE_CTF_IR_TRACE_INTERNAL_H */
index 4035c2bdd2073a64b6f75dfac8ad154143115496..a80cfc01abf8ba962de61c18d16356f5cd931a89 100644 (file)
@@ -189,8 +189,8 @@ typedef void (* bt_trace_listener_removed)(
 On success, the trace packet header field type of the created trace
 class is an empty structure field type. You can modify this default
 trace packet header field type after the trace class is created with
-bt_trace_get_packet_header_type() and
-bt_trace_set_packet_header_type().
+bt_trace_get_packet_header_field_type() and
+bt_trace_set_packet_header_field_type().
 
 The created trace class has the following initial properties:
 
@@ -554,10 +554,10 @@ extern int bt_trace_set_environment_field_string(
 @post <strong>On success, if the return value is a field type</strong>, its
        reference count is incremented.
 
-@sa bt_trace_set_packet_header_type(): Sets the packet
+@sa bt_trace_set_packet_header_field_type(): Sets the packet
        header field type of a given trace class.
 */
-extern struct bt_field_type *bt_trace_get_packet_header_type(
+extern struct bt_field_type *bt_trace_get_packet_header_field_type(
                struct bt_trace *trace_class);
 
 /**
@@ -586,10 +586,10 @@ As of Babeltrace \btversion, if \p packet_header_type is not \c NULL,
 @post <strong>On success, if \p packet_header_type is not \c NULL</strong>,
        the reference count of \p packet_header_type is incremented.
 
-@sa bt_trace_get_packet_header_type(): Returns the packet
+@sa bt_trace_get_packet_header_field_type(): Returns the packet
        header field type of a given trace class.
 */
-extern int bt_trace_set_packet_header_type(struct bt_trace *trace_class,
+extern int bt_trace_set_packet_header_field_type(struct bt_trace *trace_class,
                struct bt_field_type *packet_header_type);
 
 /** @} */
@@ -983,9 +983,6 @@ extern int bt_trace_visit(struct bt_trace *trace_class,
 
 /** @} */
 
-/* Pre-2.0 CTF writer compatibility */
-#define bt_ctf_trace bt_trace
-
 #ifdef __cplusplus
 }
 #endif
index ac5612ffd768c84790d9ab1f7b02f6747cba9c0d..12b2494028000f6bd431671e4df1ce3161e089a2 100644 (file)
 #include <babeltrace/ctf-ir/field-types.h>
 #include <stdint.h>
 
+#define BT_TO_COMMON(_obj)     (&(_obj)->common)
+#define BT_FROM_COMMON(_obj)   ((void *) _obj)
+
+struct search_query {
+       gpointer value;
+       int found;
+};
+
 BT_HIDDEN
-int bt_validate_single_clock_class(struct bt_field_type *field_type,
-               struct bt_clock_class **expected_clock_class);
+const char *get_byte_order_string(enum bt_byte_order byte_order);
 
 #endif /* BABELTRACE_CTF_IR_UTILS_INTERNAL_H */
index 9120730204bfec72f1118a241f1ddab7030fe6ea..483e69463f0df2b7f39100adcf98a04dfc42466e 100644 (file)
@@ -72,7 +72,11 @@ extern bt_bool bt_identifier_is_valid(const char *identifier);
 /** @} */
 
 /* Pre-2.0 CTF writer compatibility */
-extern int bt_ctf_validate_identifier(const char *identifier);
+static inline
+int bt_ctf_validate_identifier(const char *identifier)
+{
+       return bt_identifier_is_valid(identifier) ? 1 : 0;
+}
 
 #ifdef __cplusplus
 }
index cf05a23b164e19f3ff28fff4433fe90811265022..81d48b8f78f362f3773ff85d208b1b6355d433f8 100644 (file)
  * SOFTWARE.
  */
 
-#include <babeltrace/ctf-ir/field-types.h>
-#include <babeltrace/ctf-ir/event.h>
-#include <babeltrace/ctf-ir/stream-class.h>
-#include <babeltrace/ctf-ir/trace.h>
 #include <babeltrace/values.h>
 #include <babeltrace/babeltrace-internal.h>
 
+struct bt_trace_common;
+struct bt_stream_class_common;
+struct bt_event_class_common;
+struct bt_field_type_common;
+
+typedef struct bt_field_type_common *(*bt_validation_flag_copy_field_type_func)(
+               struct bt_field_type_common *);
+
 enum bt_validation_flag {
        BT_VALIDATION_FLAG_TRACE        = 1,
        BT_VALIDATION_FLAG_STREAM       = 2,
@@ -48,12 +52,12 @@ enum bt_validation_flag {
  * `valid_flags` contains the results of the validation.
  */
 struct bt_validation_output {
-       struct bt_field_type *packet_header_type;
-       struct bt_field_type *packet_context_type;
-       struct bt_field_type *event_header_type;
-       struct bt_field_type *stream_event_ctx_type;
-       struct bt_field_type *event_context_type;
-       struct bt_field_type *event_payload_type;
+       struct bt_field_type_common *packet_header_type;
+       struct bt_field_type_common *packet_context_type;
+       struct bt_field_type_common *event_header_type;
+       struct bt_field_type_common *stream_event_ctx_type;
+       struct bt_field_type_common *event_context_type;
+       struct bt_field_type_common *event_payload_type;
        enum bt_validation_flag valid_flags;
 };
 
@@ -79,15 +83,16 @@ struct bt_validation_output {
  */
 BT_HIDDEN
 int bt_validate_class_types(struct bt_value *environment,
-               struct bt_field_type *packet_header_type,
-               struct bt_field_type *packet_context_type,
-               struct bt_field_type *event_header_type,
-               struct bt_field_type *stream_event_ctx_type,
-               struct bt_field_type *event_context_type,
-               struct bt_field_type *event_payload_type,
+               struct bt_field_type_common *packet_header_type,
+               struct bt_field_type_common *packet_context_type,
+               struct bt_field_type_common *event_header_type,
+               struct bt_field_type_common *stream_event_ctx_type,
+               struct bt_field_type_common *event_context_type,
+               struct bt_field_type_common *event_payload_type,
                int trace_valid, int stream_class_valid, int event_class_valid,
                struct bt_validation_output *output,
-               enum bt_validation_flag validate_flags);
+               enum bt_validation_flag validate_flags,
+               bt_validation_flag_copy_field_type_func copy_field_type_func);
 
 /*
  * This function replaces the actual field types of a trace, a stream
@@ -105,9 +110,9 @@ int bt_validate_class_types(struct bt_value *environment,
  * All parameters are owned by the caller.
  */
 BT_HIDDEN
-void bt_validation_replace_types(struct bt_trace *trace,
-               struct bt_stream_class *stream_class,
-               struct bt_event_class *event_class,
+void bt_validation_replace_types(struct bt_trace_common *trace,
+               struct bt_stream_class_common *stream_class,
+               struct bt_event_class_common *event_class,
                struct bt_validation_output *output,
                enum bt_validation_flag replace_flags);
 
diff --git a/include/babeltrace/ctf-writer/clock-class.h b/include/babeltrace/ctf-writer/clock-class.h
new file mode 100644 (file)
index 0000000..2ba1d8e
--- /dev/null
@@ -0,0 +1,288 @@
+#ifndef BABELTRACE_CTF_WRITER_CLOCK_H
+#define BABELTRACE_CTF_WRITER_CLOCK_H
+
+/*
+ * BabelTrace - CTF Writer: Clock
+ *
+ * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * The Common Trace Format (CTF) Specification is available at
+ * http://www.efficios.com/ctf
+ */
+
+#include <stdint.h>
+#include <babeltrace/ref.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct bt_ctf_clock;
+
+/*
+ * bt_ctf_clock_create: create a clock.
+ *
+ * Allocate a new clock setting its reference count to 1.
+ *
+ * @param name Name of the clock (will be copied); can be set to NULL
+ *             for nameless clocks.
+ *
+ * Returns an allocated clock on success, NULL on error.
+ */
+extern struct bt_ctf_clock *bt_ctf_clock_create(const char *name);
+
+/*
+ * bt_ctf_clock_get_name: get a clock's name.
+ *
+ * Get the clock's name.
+ *
+ * @param clock Clock instance.
+ *
+ * Returns the clock's name, NULL on error.
+ */
+extern const char *bt_ctf_clock_get_name(struct bt_ctf_clock *clock);
+
+/*
+ * bt_ctf_clock_get_description: get a clock's description.
+ *
+ * Get the clock's description.
+ *
+ * @param clock Clock instance.
+ *
+ * Returns the clock's description, NULL if unset.
+ */
+extern const char *bt_ctf_clock_get_description(struct bt_ctf_clock *clock);
+
+/*
+ * bt_ctf_clock_set_description: set a clock's description.
+ *
+ * Set the clock's description. The description appears in the clock's TSDL
+ * meta-data.
+ *
+ * @param clock Clock instance.
+ * @param desc Description of the clock.
+ *
+ * Returns 0 on success, a negative value on error.
+ */
+extern int bt_ctf_clock_set_description(struct bt_ctf_clock *clock,
+        const char *desc);
+
+/*
+ * bt_ctf_clock_get_frequency: get a clock's frequency.
+ *
+ * Get the clock's frequency (Hz).
+ *
+ * @param clock Clock instance.
+ *
+ * Returns the clock's frequency, -1ULL on error.
+ */
+extern uint64_t bt_ctf_clock_get_frequency(struct bt_ctf_clock *clock);
+
+/*
+ * bt_ctf_clock_set_frequency: set a clock's frequency.
+ *
+ * Set the clock's frequency (Hz).
+ *
+ * @param clock Clock instance.
+ * @param freq Clock's frequency in Hz, defaults to 1 000 000 000 Hz (1ns).
+ *
+ * Returns 0 on success, a negative value on error.
+ */
+extern int bt_ctf_clock_set_frequency(struct bt_ctf_clock *clock,
+        uint64_t freq);
+
+/*
+ * bt_ctf_clock_get_precision: get a clock's precision.
+ *
+ * Get the clock's precision (in clock ticks).
+ *
+ * @param clock Clock instance.
+ *
+ * Returns the clock's precision, -1ULL on error.
+ */
+extern uint64_t bt_ctf_clock_get_precision(struct bt_ctf_clock *clock);
+
+/*
+ * bt_ctf_clock_set_precision: set a clock's precision.
+ *
+ * Set the clock's precision.
+ *
+ * @param clock Clock instance.
+ * @param precision Clock's precision in clock ticks, defaults to 1.
+ *
+ * Returns 0 on success, a negative value on error.
+ */
+extern int bt_ctf_clock_set_precision(struct bt_ctf_clock *clock,
+        uint64_t precision);
+
+/*
+ * bt_ctf_clock_get_offset_s: get a clock's offset in seconds.
+ *
+ * Get the clock's offset in seconds from POSIX.1 Epoch, 1970-01-01.
+ *
+ * @param clock Clock instance.
+ * @param offset_s Pointer to clock offset in seconds (output).
+ *
+ * Returns 0 on success, a negative value on error.
+ */
+extern int bt_ctf_clock_get_offset_s(struct bt_ctf_clock *clock,
+        int64_t *offset_s);
+
+/*
+ * bt_ctf_clock_set_offset_s: set a clock's offset in seconds.
+ *
+ * Set the clock's offset in seconds from POSIX.1 Epoch, 1970-01-01,
+ * defaults to 0.
+ *
+ * @param clock Clock instance.
+ * @param offset_s Clock's offset in seconds, defaults to 0.
+ *
+ * Returns 0 on success, a negative value on error.
+ */
+extern int bt_ctf_clock_set_offset_s(struct bt_ctf_clock *clock,
+        int64_t offset_s);
+
+/*
+ * bt_ctf_clock_get_offset: get a clock's offset in ticks.
+ *
+ * Get the clock's offset in ticks from Epoch + offset_t.
+ *
+ * @param clock Clock instance.
+ * @param offset Clock offset in ticks from Epoch + offset_s (output).
+ *
+ * Returns 0 on success, a negative value on error.
+ */
+extern int bt_ctf_clock_get_offset(struct bt_ctf_clock *clock,
+        int64_t *offset);
+
+/*
+ * bt_ctf_clock_set_offset: set a clock's offset in ticks.
+ *
+ * Set the clock's offset in ticks from Epoch + offset_s.
+ *
+ * @param clock Clock instance.
+ * @param offset Clock's offset in ticks from Epoch + offset_s, defaults to 0.
+ *
+ * Returns 0 on success, a negative value on error.
+ */
+extern int bt_ctf_clock_set_offset(struct bt_ctf_clock *clock,
+        int64_t offset);
+
+/*
+ * bt_ctf_clock_get_is_absolute: get a clock's absolute attribute.
+ *
+ * Get the clock's absolute attribute. A clock is absolute if the clock is a
+ * global reference across the trace's other clocks.
+ *
+ * @param clock Clock instance.
+ *
+ * Returns the clock's absolute attribute, a negative value on error.
+ */
+extern int bt_ctf_clock_get_is_absolute(struct bt_ctf_clock *clock);
+
+/*
+ * bt_ctf_clock_set_is_absolute: set a clock's absolute attribute.
+ *
+ * Set the clock's absolute attribute. A clock is absolute if the clock is a
+ * global reference across the trace's other clocks.
+ *
+ * @param clock Clock instance.
+ * @param is_absolute Clock's absolute attribute, defaults to FALSE.
+ *
+ * Returns 0 on success, a negative value on error.
+ */
+extern int bt_ctf_clock_set_is_absolute(struct bt_ctf_clock *clock,
+        int is_absolute);
+
+/*
+ * bt_ctf_clock_get_uuid: get a clock's UUID.
+ *
+ * Get the clock's UUID.
+ *
+ * @param clock Clock instance.
+ *
+ * Returns a pointer to the clock's UUID (16 byte array) on success,
+ * NULL on error.
+ */
+extern const unsigned char *bt_ctf_clock_get_uuid(struct bt_ctf_clock *clock);
+
+/*
+ * bt_ctf_clock_set_uuid: set a clock's UUID.
+ *
+ * Set a clock's UUID.
+ *
+ * @param clock Clock instance.
+ * @param uuid A 16-byte array containing a UUID.
+ *
+ * Returns 0 on success, a negative value on error.
+ */
+extern int bt_ctf_clock_set_uuid(struct bt_ctf_clock *clock,
+        const unsigned char *uuid);
+
+/*
+ * bt_ctf_clock_set_time: set a clock's current time value.
+ *
+ * Set the current time in nanoseconds since the clock's origin (offset and
+ * offset_s attributes). Defaults to 0.
+ *
+ * Returns 0 on success, a negative value on error.
+ */
+extern int bt_ctf_clock_set_time(struct bt_ctf_clock *clock,
+               int64_t time);
+
+/*
+ * bt_ctf_clock_get and bt_ctf_clock_put: increment and decrement the
+ * refcount of the clock
+ *
+ * You may also use bt_ctf_get() and bt_ctf_put() with clock objects.
+ *
+ * These functions ensure that the clock won't be destroyed when it
+ * is in use. The same number of get and put (plus one extra put to
+ * release the initial reference done at creation) has to be done to
+ * destroy a clock.
+ *
+ * When the clock refcount is decremented to 0 by a bt_ctf_clock_put,
+ * the clock is freed.
+ *
+ * @param clock Clock instance.
+ */
+
+/* Pre-2.0 CTF writer compatibility */
+static inline
+void bt_ctf_clock_get(struct bt_ctf_clock *clock)
+{
+        bt_get(clock);
+}
+
+/* Pre-2.0 CTF writer compatibility */
+static inline
+void bt_ctf_clock_put(struct bt_ctf_clock *clock)
+{
+        bt_put(clock);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BABELTRACE_CTF_WRITER_CLOCK_H */
index 031cf8dedcad79d7cb6031b6d70dff199566ea46..5c59e29a5bda3ed1b4f4cde723fa9d3581cb2c62 100644 (file)
 #include <glib.h>
 #include <babeltrace/compat/uuid-internal.h>
 
+struct bt_ctf_clock_class {
+       struct bt_clock_class common;
+};
+
 struct bt_ctf_clock {
        struct bt_object base;
-       struct bt_clock_class *clock_class;
+       struct bt_ctf_clock_class *clock_class;
        uint64_t value;         /* Current clock value */
 };
 
+struct metadata_context;
+
 BT_HIDDEN
 int bt_ctf_clock_get_value(struct bt_ctf_clock *clock, uint64_t *value);
 
+BT_HIDDEN
+void bt_ctf_clock_class_serialize(struct bt_ctf_clock_class *clock_class,
+               struct metadata_context *context);
+
 #endif /* BABELTRACE_CTF_WRITER_CLOCK_INTERNAL_H */
index 7276f451853827b3f1c92739f3ed9cd69b5d4046..a1a53e82e4fd3b8202ce86aa04d85f75cd065da9 100644 (file)
  */
 
 #include <stdint.h>
+#include <babeltrace/ref.h>
+#include <babeltrace/types.h>
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 struct bt_ctf_clock;
+struct bt_ctf_clock_class;
 
 /*
  * bt_ctf_clock_create: create a clock.
@@ -265,8 +268,72 @@ extern int bt_ctf_clock_set_time(struct bt_ctf_clock *clock,
  *
  * @param clock Clock instance.
  */
-extern void bt_ctf_clock_get(struct bt_ctf_clock *clock);
-extern void bt_ctf_clock_put(struct bt_ctf_clock *clock);
+
+/* Pre-2.0 CTF writer compatibility */
+static inline
+void bt_ctf_clock_get(struct bt_ctf_clock *clock)
+{
+        bt_get(clock);
+}
+
+/* Pre-2.0 CTF writer compatibility */
+static inline
+void bt_ctf_clock_put(struct bt_ctf_clock *clock)
+{
+        bt_put(clock);
+}
+
+extern struct bt_ctf_clock_class *bt_ctf_clock_class_create(const char *name,
+                uint64_t freq);
+
+extern const char *bt_ctf_clock_class_get_name(
+                struct bt_ctf_clock_class *clock_class);
+
+extern int bt_ctf_clock_class_set_name(struct bt_ctf_clock_class *clock_class,
+                const char *name);
+
+extern const char *bt_ctf_clock_class_get_description(
+                struct bt_ctf_clock_class *clock_class);
+
+extern int bt_ctf_clock_class_set_description(
+                struct bt_ctf_clock_class *clock_class,
+                const char *desc);
+
+extern uint64_t bt_ctf_clock_class_get_frequency(
+                struct bt_ctf_clock_class *clock_class);
+
+extern int bt_ctf_clock_class_set_frequency(
+                struct bt_ctf_clock_class *clock_class, uint64_t freq);
+
+extern uint64_t bt_ctf_clock_class_get_precision(
+                struct bt_ctf_clock_class *clock_class);
+
+extern int bt_ctf_clock_class_set_precision(
+                struct bt_ctf_clock_class *clock_class, uint64_t precision);
+
+extern int bt_ctf_clock_class_get_offset_s(
+                struct bt_ctf_clock_class *clock_class, int64_t *seconds);
+
+extern int bt_ctf_clock_class_set_offset_s(
+                struct bt_ctf_clock_class *clock_class, int64_t seconds);
+
+extern int bt_ctf_clock_class_get_offset_cycles(
+                struct bt_ctf_clock_class *clock_class, int64_t *cycles);
+
+extern int bt_ctf_clock_class_set_offset_cycles(
+                struct bt_ctf_clock_class *clock_class, int64_t cycles);
+
+extern bt_bool bt_ctf_clock_class_is_absolute(
+                struct bt_ctf_clock_class *clock_class);
+
+extern int bt_ctf_clock_class_set_is_absolute(
+                struct bt_ctf_clock_class *clock_class, bt_bool is_absolute);
+
+extern const unsigned char *bt_ctf_clock_class_get_uuid(
+                struct bt_ctf_clock_class *clock_class);
+
+extern int bt_ctf_clock_class_set_uuid(struct bt_ctf_clock_class *clock_class,
+                const unsigned char *uuid);
 
 #ifdef __cplusplus
 }
index f4b8216df3be92699b2d137f64b3b4b79dbbf080..e06c354c50659a6f07be4161b194ba668c7e5c43 100644 (file)
@@ -30,7 +30,9 @@
  * http://www.efficios.com/ctf
  */
 
-#include <babeltrace/ctf-ir/fields.h>
+#include <babeltrace/ref.h>
+#include <babeltrace/ctf-writer/field-types.h>
+#include <babeltrace/ctf-writer/fields.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -52,8 +54,20 @@ extern "C" {
  *
  * @param field Field instance.
  */
-extern void bt_ctf_field_get(struct bt_field *field);
-extern void bt_ctf_field_put(struct bt_field *field);
+
+/* Pre-2.0 CTF writer compatibility */
+static inline
+void bt_ctf_field_get(struct bt_field *field)
+{
+       bt_get(field);
+}
+
+/* Pre-2.0 CTF writer compatibility */
+static inline
+void bt_ctf_field_put(struct bt_field *field)
+{
+       bt_put(field);
+}
 
 #ifdef __cplusplus
 }
diff --git a/include/babeltrace/ctf-writer/event-internal.h b/include/babeltrace/ctf-writer/event-internal.h
new file mode 100644 (file)
index 0000000..6c987a6
--- /dev/null
@@ -0,0 +1,67 @@
+#ifndef BABELTRACE_CTF_WRITER_EVENT_INTERNAL_H
+#define BABELTRACE_CTF_WRITER_EVENT_INTERNAL_H
+
+/*
+ * BabelTrace - CTF Writer: Event
+ *
+ * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * The Common Trace Format (CTF) Specification is available at
+ * http://www.efficios.com/ctf
+ */
+
+#include <babeltrace/babeltrace-internal.h>
+#include <babeltrace/ctf-ir/event-class-internal.h>
+#include <babeltrace/ctf-ir/event-internal.h>
+#include <babeltrace/ctf-writer/field-types.h>
+
+struct bt_ctf_stream_class;
+struct bt_ctf_stream_pos;
+struct metadata_context;
+
+struct bt_ctf_event {
+       struct bt_event_common common;
+};
+
+struct bt_ctf_event_class {
+       struct bt_event_class_common common;
+};
+
+BT_HIDDEN
+int bt_ctf_event_class_serialize(struct bt_ctf_event_class *event_class,
+               struct metadata_context *context);
+
+BT_HIDDEN
+int bt_ctf_event_serialize(struct bt_ctf_event *event,
+               struct bt_ctf_stream_pos *pos,
+               enum bt_ctf_byte_order native_byte_order);
+
+static inline
+struct bt_ctf_stream_class *bt_ctf_event_class_borrow_stream_class(
+               struct bt_ctf_event_class *event_class)
+{
+       return BT_FROM_COMMON(bt_event_class_common_borrow_stream_class(
+               BT_TO_COMMON(event_class)));
+}
+
+#endif /* BABELTRACE_CTF_WRITER_EVENT_INTERNAL_H */
index fa5cf8caa2808b6398d31fe99edcb0328ec1756a..9b41bf09b04f0416e54cd9f8a5ca03aa33b7701b 100644 (file)
@@ -30,6 +30,7 @@
  * http://www.efficios.com/ctf
  */
 
+#include <babeltrace/ref.h>
 #include <babeltrace/ctf-ir/field-types.h>
 
 #ifdef __cplusplus
@@ -52,8 +53,20 @@ extern "C" {
  *
  * @param type Field type.
  */
-extern void bt_ctf_field_type_get(struct bt_field_type *type);
-extern void bt_ctf_field_type_put(struct bt_field_type *type);
+
+/* Pre-2.0 CTF writer compatibility */
+static inline
+void bt_ctf_field_type_get(struct bt_field_type *type)
+{
+       bt_get(type);
+}
+
+/* Pre-2.0 CTF writer compatibility */
+static inline
+void bt_ctf_field_type_put(struct bt_field_type *type)
+{
+       bt_put(type);
+}
 
 #ifdef __cplusplus
 }
index 804ad7a6b11e70e47584c08c7c5a1ffef7c3dfb1..1a827a3f3a42f51a9b4d59035811f3616859581a 100644 (file)
@@ -30,6 +30,7 @@
  * http://www.efficios.com/ctf
  */
 
+#include <babeltrace/ref.h>
 #include <babeltrace/ctf-ir/event-class.h>
 #include <babeltrace/ctf-ir/event.h>
 
 extern "C" {
 #endif
 
-/*
- * bt_ctf_event_get and bt_ctf_event_put: increment and decrement
- * the event's reference count.
- *
- * You may also use bt_get() and bt_put() with event objects.
- *
- * These functions ensure that the event won't be destroyed while it
- * is in use. The same number of get and put (plus one extra put to
- * release the initial reference done at creation) have to be done to
- * destroy an event.
- *
- * When the event's reference count is decremented to 0 by a
- * bt_ctf_event_put, the event is freed.
- *
- * @param event Event instance.
- */
-extern void bt_ctf_event_get(struct bt_event *event);
-extern void bt_ctf_event_put(struct bt_event *event);
+struct bt_ctf_event;
+struct bt_ctf_event_class;
+struct bt_ctf_stream;
+struct bt_ctf_field;
+struct bt_ctf_field_type;
 
-/*
- * bt_ctf_event_class_get and bt_ctf_event_class_put: increment and decrement
- * the event class' reference count.
- *
- * You may also use bt_get() and bt_put() with event class objects.
- *
- * These functions ensure that the event class won't be destroyed while it
- * is in use. The same number of get and put (plus one extra put to
- * release the initial reference done at creation) have to be done to
- * destroy an event class.
- *
- * When the event class' reference count is decremented to 0 by a
- * bt_ctf_event_class_put, the event class is freed.
- *
- * @param event_class Event class.
- */
-extern void bt_ctf_event_class_get(struct bt_event_class *event_class);
-extern void bt_ctf_event_class_put(struct bt_event_class *event_class);
+enum bt_ctf_event_class_log_level {
+       /// Unknown, used for errors.
+       BT_CTF_EVENT_CLASS_LOG_LEVEL_UNKNOWN            = BT_EVENT_CLASS_LOG_LEVEL_UNKNOWN,
+
+       /// Unspecified log level.
+       BT_CTF_EVENT_CLASS_LOG_LEVEL_UNSPECIFIED        = BT_EVENT_CLASS_LOG_LEVEL_UNSPECIFIED,
+
+       /// System is unusable.
+       BT_CTF_EVENT_CLASS_LOG_LEVEL_EMERGENCY          = BT_EVENT_CLASS_LOG_LEVEL_EMERGENCY,
+
+       /// Action must be taken immediately.
+       BT_CTF_EVENT_CLASS_LOG_LEVEL_ALERT              = BT_EVENT_CLASS_LOG_LEVEL_ALERT,
+
+       /// Critical conditions.
+       BT_CTF_EVENT_CLASS_LOG_LEVEL_CRITICAL           = BT_EVENT_CLASS_LOG_LEVEL_CRITICAL,
+
+       /// Error conditions.
+       BT_CTF_EVENT_CLASS_LOG_LEVEL_ERROR              = BT_EVENT_CLASS_LOG_LEVEL_ERROR,
+
+       /// Warning conditions.
+       BT_CTF_EVENT_CLASS_LOG_LEVEL_WARNING            = BT_EVENT_CLASS_LOG_LEVEL_WARNING,
+
+       /// Normal, but significant, condition.
+       BT_CTF_EVENT_CLASS_LOG_LEVEL_NOTICE             = BT_EVENT_CLASS_LOG_LEVEL_NOTICE,
+
+       /// Informational message.
+       BT_CTF_EVENT_CLASS_LOG_LEVEL_INFO               = BT_EVENT_CLASS_LOG_LEVEL_INFO,
+
+       /// Debug information with system-level scope (set of programs).
+       BT_CTF_EVENT_CLASS_LOG_LEVEL_DEBUG_SYSTEM       = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_SYSTEM,
+
+       /// Debug information with program-level scope (set of processes).
+       BT_CTF_EVENT_CLASS_LOG_LEVEL_DEBUG_PROGRAM      = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROGRAM,
+
+       /// Debug information with process-level scope (set of modules).
+       BT_CTF_EVENT_CLASS_LOG_LEVEL_DEBUG_PROCESS      = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROCESS,
+
+       /// Debug information with module (executable/library) scope (set of units).
+       BT_CTF_EVENT_CLASS_LOG_LEVEL_DEBUG_MODULE       = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_MODULE,
+
+       /// Debug information with compilation unit scope (set of functions).
+       BT_CTF_EVENT_CLASS_LOG_LEVEL_DEBUG_UNIT         = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_UNIT,
+
+       /// Debug information with function-level scope.
+       BT_CTF_EVENT_CLASS_LOG_LEVEL_DEBUG_FUNCTION     = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_FUNCTION,
+
+       /// Debug information with line-level scope (default log level).
+       BT_CTF_EVENT_CLASS_LOG_LEVEL_DEBUG_LINE         = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_LINE,
+
+       /// Debug-level message.
+       BT_CTF_EVENT_CLASS_LOG_LEVEL_DEBUG              = BT_EVENT_CLASS_LOG_LEVEL_DEBUG,
+};
+
+extern struct bt_ctf_event *bt_ctf_event_create(
+               struct bt_ctf_event_class *event_class);
+
+extern struct bt_ctf_field *bt_ctf_event_get_payload(struct bt_ctf_event *event,
+               const char *name);
+
+extern int bt_ctf_event_set_payload(struct bt_ctf_event *event,
+               const char *name, struct bt_ctf_field *field);
+
+extern struct bt_ctf_field *bt_ctf_event_get_payload_field(
+               struct bt_ctf_event *event);
+
+extern int bt_ctf_event_set_payload_field(struct bt_ctf_event *event,
+               struct bt_ctf_field *field);
+
+extern int bt_ctf_event_set_context(struct bt_ctf_event *event,
+               struct bt_ctf_field *field);
+
+extern struct bt_ctf_field *bt_ctf_event_get_context(
+               struct bt_ctf_event *event);
+
+extern int bt_ctf_event_set_stream_event_context(struct bt_ctf_event *event,
+               struct bt_ctf_field *field);
+
+extern struct bt_ctf_field *bt_ctf_event_get_stream_event_context(
+               struct bt_ctf_event *event);
+
+extern int bt_ctf_event_set_header(struct bt_ctf_event *event,
+               struct bt_ctf_field *field);
+
+extern struct bt_ctf_field *bt_ctf_event_get_header(
+               struct bt_ctf_event *event);
+
+extern struct bt_ctf_stream *bt_ctf_event_get_stream(
+               struct bt_ctf_event *event);
+
+extern struct bt_ctf_event_class *bt_ctf_event_get_class(
+               struct bt_ctf_event *event);
+
+/* Pre-2.0 CTF writer compatibility */
+static inline
+void bt_ctf_event_get(struct bt_ctf_event *event)
+{
+       bt_get(event);
+}
+
+/* Pre-2.0 CTF writer compatibility */
+static inline
+void bt_ctf_event_put(struct bt_ctf_event *event)
+{
+       bt_put(event);
+}
+
+extern struct bt_ctf_event_class *bt_ctf_event_class_create(const char *name);
+
+extern struct bt_ctf_stream_class *bt_ctf_event_class_get_stream_class(
+               struct bt_ctf_event_class *event_class);
+
+extern const char *bt_ctf_event_class_get_name(
+               struct bt_ctf_event_class *event_class);
+
+extern int64_t bt_ctf_event_class_get_id(
+               struct bt_ctf_event_class *event_class);
+
+extern int bt_ctf_event_class_set_id(
+               struct bt_ctf_event_class *event_class, uint64_t id);
+
+extern enum bt_ctf_event_class_log_level bt_ctf_event_class_get_log_level(
+               struct bt_ctf_event_class *event_class);
+
+extern int bt_ctf_event_class_set_log_level(
+               struct bt_ctf_event_class *event_class,
+               enum bt_ctf_event_class_log_level log_level);
+
+extern const char *bt_ctf_event_class_get_emf_uri(
+               struct bt_ctf_event_class *event_class);
+
+extern int bt_ctf_event_class_set_emf_uri(
+               struct bt_ctf_event_class *event_class,
+               const char *emf_uri);
+
+extern struct bt_ctf_field_type *bt_ctf_event_class_get_context_field_type(
+               struct bt_ctf_event_class *event_class);
+
+extern int bt_ctf_event_class_set_context_field_type(
+               struct bt_ctf_event_class *event_class,
+               struct bt_ctf_field_type *context_type);
+
+extern struct bt_ctf_field_type *bt_ctf_event_class_get_payload_field_type(
+               struct bt_ctf_event_class *event_class);
+
+extern int bt_ctf_event_class_set_payload_field_type(
+               struct bt_ctf_event_class *event_class,
+               struct bt_ctf_field_type *payload_type);
+
+extern int bt_ctf_event_class_add_field(struct bt_ctf_event_class *event_class,
+               struct bt_ctf_field_type *field_type,
+               const char *name);
+
+extern struct bt_ctf_field_type *bt_ctf_event_class_get_field_by_name(
+               struct bt_ctf_event_class *event_class, const char *name);
+
+/* Pre-2.0 CTF writer compatibility */
+static inline
+void bt_ctf_event_class_get(struct bt_ctf_event_class *event_class)
+{
+       bt_get(event_class);
+}
+
+/* Pre-2.0 CTF writer compatibility */
+static inline
+void bt_ctf_event_class_put(struct bt_ctf_event_class *event_class)
+{
+       bt_put(event_class);
+}
 
 #ifdef __cplusplus
 }
diff --git a/include/babeltrace/ctf-writer/field-types-internal.h b/include/babeltrace/ctf-writer/field-types-internal.h
new file mode 100644 (file)
index 0000000..48ab3c3
--- /dev/null
@@ -0,0 +1,47 @@
+#ifndef BABELTRACE_CTF_WRITER_FIELD_TYPES_INTERNAL_H
+#define BABELTRACE_CTF_WRITER_FIELD_TYPES_INTERNAL_H
+
+/*
+ * Babeltrace - CTF writer: Event Fields
+ *
+ * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * The Common Trace Format (CTF) Specification is available at
+ * http://www.efficios.com/ctf
+ */
+
+#include <stdint.h>
+#include <stddef.h>
+
+/* For bt_bool */
+#include <babeltrace/ctf-writer/field-types.h>
+#include <babeltrace/ctf-writer/writer-internal.h>
+
+BT_HIDDEN
+int bt_ctf_field_type_serialize_recursive(struct bt_ctf_field_type *type,
+               struct metadata_context *context);
+
+BT_HIDDEN
+struct bt_ctf_field_type *bt_ctf_field_type_copy(struct bt_ctf_field_type *ft);
+
+#endif /* BABELTRACE_CTF_WRITER_FIELD_TYPES_INTERNAL_H */
diff --git a/include/babeltrace/ctf-writer/field-types.h b/include/babeltrace/ctf-writer/field-types.h
new file mode 100644 (file)
index 0000000..36bfbfe
--- /dev/null
@@ -0,0 +1,320 @@
+#ifndef BABELTRACE_CTF_WRITER_FIELD_TYPES_H
+#define BABELTRACE_CTF_WRITER_FIELD_TYPES_H
+
+/*
+ * Babeltrace - CTF writer: Event Fields
+ *
+ * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * The Common Trace Format (CTF) Specification is available at
+ * http://www.efficios.com/ctf
+ */
+
+#include <stdint.h>
+#include <stddef.h>
+
+#include <babeltrace/types.h>
+#include <babeltrace/ctf-ir/field-types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct bt_ctf_field;
+struct bt_ctf_field_type;
+
+enum bt_ctf_field_type_id {
+       BT_CTF_FIELD_TYPE_ID_UNKNOWN    = BT_FIELD_TYPE_ID_UNKNOWN,
+       BT_CTF_FIELD_TYPE_ID_INTEGER    = BT_FIELD_TYPE_ID_INTEGER,
+       BT_CTF_FIELD_TYPE_ID_FLOAT      = BT_FIELD_TYPE_ID_FLOAT,
+       BT_CTF_FIELD_TYPE_ID_ENUM       = BT_FIELD_TYPE_ID_ENUM,
+       BT_CTF_FIELD_TYPE_ID_STRING     = BT_FIELD_TYPE_ID_STRING,
+       BT_CTF_FIELD_TYPE_ID_STRUCT     = BT_FIELD_TYPE_ID_STRUCT,
+       BT_CTF_FIELD_TYPE_ID_ARRAY      = BT_FIELD_TYPE_ID_ARRAY,
+       BT_CTF_FIELD_TYPE_ID_SEQUENCE   = BT_FIELD_TYPE_ID_SEQUENCE,
+       BT_CTF_FIELD_TYPE_ID_VARIANT    = BT_FIELD_TYPE_ID_VARIANT,
+       BT_CTF_FIELD_TYPE_ID_NR         = BT_FIELD_TYPE_ID_NR,
+};
+
+extern enum bt_ctf_field_type_id bt_ctf_field_type_get_type_id(
+               struct bt_ctf_field_type *field_type);
+
+enum bt_ctf_byte_order {
+       BT_CTF_BYTE_ORDER_UNKNOWN               = BT_BYTE_ORDER_UNKNOWN,
+       BT_CTF_BYTE_ORDER_NATIVE                = BT_BYTE_ORDER_NATIVE,
+       BT_CTF_BYTE_ORDER_UNSPECIFIED           = BT_BYTE_ORDER_UNSPECIFIED,
+       BT_CTF_BYTE_ORDER_LITTLE_ENDIAN         = BT_BYTE_ORDER_LITTLE_ENDIAN,
+       BT_CTF_BYTE_ORDER_BIG_ENDIAN            = BT_BYTE_ORDER_BIG_ENDIAN,
+       BT_CTF_BYTE_ORDER_NETWORK               = BT_BYTE_ORDER_NETWORK,
+};
+
+enum bt_ctf_string_encoding {
+       BT_CTF_STRING_ENCODING_UNKNOWN  = BT_STRING_ENCODING_UNKNOWN,
+       BT_CTF_STRING_ENCODING_NONE     = BT_STRING_ENCODING_NONE,
+       BT_CTF_STRING_ENCODING_UTF8     = BT_STRING_ENCODING_UTF8,
+       BT_CTF_STRING_ENCODING_ASCII    = BT_STRING_ENCODING_ASCII,
+};
+
+/* Pre-2.0 CTF writer compatibility */
+#define ctf_string_encoding    bt_ctf_string_encoding
+
+extern int bt_ctf_field_type_get_alignment(
+               struct bt_ctf_field_type *field_type);
+
+extern int bt_ctf_field_type_set_alignment(struct bt_ctf_field_type *field_type,
+               unsigned int alignment);
+
+extern enum bt_ctf_byte_order bt_ctf_field_type_get_byte_order(
+               struct bt_ctf_field_type *field_type);
+
+extern int bt_ctf_field_type_set_byte_order(
+               struct bt_ctf_field_type *field_type,
+               enum bt_ctf_byte_order byte_order);
+
+enum bt_ctf_integer_base {
+       /// Unknown, used for errors.
+       BT_CTF_INTEGER_BASE_UNKNOWN             = -1,
+
+       /// Unspecified by the tracer.
+       BT_CTF_INTEGER_BASE_UNSPECIFIED         = 0,
+
+       /// Binary.
+       BT_CTF_INTEGER_BASE_BINARY              = 2,
+
+       /// Octal.
+       BT_CTF_INTEGER_BASE_OCTAL               = 8,
+
+       /// Decimal.
+       BT_CTF_INTEGER_BASE_DECIMAL             = 10,
+
+       /// Hexadecimal.
+       BT_CTF_INTEGER_BASE_HEXADECIMAL         = 16,
+};
+
+extern struct bt_ctf_field_type *bt_ctf_field_type_integer_create(
+               unsigned int size);
+
+extern int bt_ctf_field_type_integer_get_size(
+               struct bt_ctf_field_type *int_field_type);
+
+extern int bt_ctf_field_type_integer_set_size(
+               struct bt_ctf_field_type *int_field_type, unsigned int size);
+
+extern bt_bool bt_ctf_field_type_integer_is_signed(
+               struct bt_ctf_field_type *int_field_type);
+
+/* Pre-2.0 CTF writer compatibility */
+static inline
+int bt_ctf_field_type_integer_get_signed(
+               struct bt_ctf_field_type *int_field_type)
+{
+       return bt_ctf_field_type_integer_is_signed(int_field_type) ? 1 : 0;
+}
+
+extern int bt_ctf_field_type_integer_set_is_signed(
+               struct bt_ctf_field_type *int_field_type, bt_bool is_signed);
+
+/* Pre-2.0 CTF writer compatibility */
+static inline
+int bt_ctf_field_type_integer_set_signed(
+               struct bt_ctf_field_type *int_field_type, int is_signed)
+{
+       return bt_ctf_field_type_integer_set_is_signed(int_field_type,
+               is_signed ? BT_TRUE : BT_FALSE);
+}
+
+extern enum bt_ctf_integer_base bt_ctf_field_type_integer_get_base(
+               struct bt_ctf_field_type *int_field_type);
+
+extern int bt_ctf_field_type_integer_set_base(
+               struct bt_ctf_field_type *int_field_type,
+               enum bt_ctf_integer_base base);
+
+extern enum bt_ctf_string_encoding bt_ctf_field_type_integer_get_encoding(
+               struct bt_ctf_field_type *int_field_type);
+
+extern int bt_ctf_field_type_integer_set_encoding(
+               struct bt_ctf_field_type *int_field_type,
+               enum bt_ctf_string_encoding encoding);
+
+extern struct bt_ctf_clock_class *bt_ctf_field_type_integer_get_mapped_clock_class(
+               struct bt_ctf_field_type *int_field_type);
+
+extern int bt_ctf_field_type_integer_set_mapped_clock_class(
+               struct bt_ctf_field_type *int_field_type,
+               struct bt_ctf_clock_class *clock_class);
+
+extern struct bt_ctf_field_type *bt_ctf_field_type_floating_point_create(void);
+
+extern int bt_ctf_field_type_floating_point_get_exponent_digits(
+               struct bt_ctf_field_type *float_field_type);
+
+extern int bt_ctf_field_type_floating_point_set_exponent_digits(
+               struct bt_ctf_field_type *float_field_type,
+               unsigned int exponent_size);
+
+extern int bt_ctf_field_type_floating_point_get_mantissa_digits(
+               struct bt_ctf_field_type *float_field_type);
+
+extern int bt_ctf_field_type_floating_point_set_mantissa_digits(
+               struct bt_ctf_field_type *float_field_type,
+               unsigned int mantissa_sign_size);
+
+extern struct bt_ctf_field_type *bt_ctf_field_type_enumeration_create(
+               struct bt_ctf_field_type *int_field_type);
+
+extern
+struct bt_ctf_field_type *bt_ctf_field_type_enumeration_get_container_field_type(
+               struct bt_ctf_field_type *enum_field_type);
+
+extern int64_t bt_ctf_field_type_enumeration_get_mapping_count(
+               struct bt_ctf_field_type *enum_field_type);
+
+extern int bt_ctf_field_type_enumeration_signed_get_mapping_by_index(
+               struct bt_ctf_field_type *enum_field_type, uint64_t index,
+               const char **name, int64_t *range_begin, int64_t *range_end);
+
+extern int bt_ctf_field_type_enumeration_unsigned_get_mapping_by_index(
+               struct bt_ctf_field_type *enum_field_type, uint64_t index,
+               const char **name, uint64_t *range_begin,
+               uint64_t *range_end);
+
+extern int bt_ctf_field_type_enumeration_signed_add_mapping(
+               struct bt_ctf_field_type *enum_field_type,
+               const char *name, int64_t range_begin, int64_t range_end);
+
+extern int bt_ctf_field_type_enumeration_unsigned_add_mapping(
+               struct bt_ctf_field_type *enum_field_type,
+               const char *name, uint64_t range_begin, uint64_t range_end);
+
+/* Pre-2.0 CTF writer compatibility */
+static inline
+int bt_ctf_field_type_enumeration_add_mapping(
+               struct bt_ctf_field_type *enumeration, const char *name,
+               int64_t range_start, int64_t range_end)
+{
+       return bt_ctf_field_type_enumeration_signed_add_mapping(enumeration,
+               name, range_start, range_end);
+}
+
+extern struct bt_ctf_field_type *bt_ctf_field_type_string_create(void);
+
+extern enum bt_ctf_string_encoding bt_ctf_field_type_string_get_encoding(
+               struct bt_ctf_field_type *string_field_type);
+
+extern int bt_ctf_field_type_string_set_encoding(
+               struct bt_ctf_field_type *string_field_type,
+               enum bt_ctf_string_encoding encoding);
+
+extern struct bt_ctf_field_type *bt_ctf_field_type_structure_create(void);
+
+extern int64_t bt_ctf_field_type_structure_get_field_count(
+               struct bt_ctf_field_type *struct_field_type);
+
+extern int bt_ctf_field_type_structure_get_field_by_index(
+               struct bt_ctf_field_type *struct_field_type,
+               const char **field_name, struct bt_ctf_field_type **field_type,
+               uint64_t index);
+
+/* Pre-2.0 CTF writer compatibility */
+static inline
+int bt_ctf_field_type_structure_get_field(struct bt_ctf_field_type *structure,
+               const char **field_name, struct bt_ctf_field_type **field_type,
+               int index)
+{
+       return bt_ctf_field_type_structure_get_field_by_index(structure,
+               field_name, field_type, (uint64_t) index);
+}
+
+extern
+struct bt_ctf_field_type *bt_ctf_field_type_structure_get_field_type_by_name(
+               struct bt_ctf_field_type *struct_field_type,
+               const char *field_name);
+
+extern int bt_ctf_field_type_structure_add_field(
+               struct bt_ctf_field_type *struct_field_type,
+               struct bt_ctf_field_type *field_type,
+               const char *field_name);
+
+extern struct bt_ctf_field_type *bt_ctf_field_type_array_create(
+               struct bt_ctf_field_type *element_field_type,
+               unsigned int length);
+
+extern struct bt_ctf_field_type *bt_ctf_field_type_array_get_element_field_type(
+               struct bt_ctf_field_type *array_field_type);
+
+extern int64_t bt_ctf_field_type_array_get_length(
+               struct bt_ctf_field_type *array_field_type);
+
+extern struct bt_ctf_field_type *bt_ctf_field_type_sequence_create(
+               struct bt_ctf_field_type *element_field_type,
+               const char *length_name);
+
+extern struct bt_ctf_field_type *bt_ctf_field_type_sequence_get_element_field_type(
+               struct bt_ctf_field_type *sequence_field_type);
+
+extern const char *bt_ctf_field_type_sequence_get_length_field_name(
+               struct bt_ctf_field_type *sequence_field_type);
+
+extern struct bt_ctf_field_type *bt_ctf_field_type_variant_create(
+               struct bt_ctf_field_type *tag_field_type,
+               const char *tag_name);
+
+extern struct bt_ctf_field_type *bt_ctf_field_type_variant_get_tag_field_type(
+               struct bt_ctf_field_type *variant_field_type);
+
+extern const char *bt_ctf_field_type_variant_get_tag_name(
+               struct bt_ctf_field_type *variant_field_type);
+
+extern int bt_ctf_field_type_variant_set_tag_name(
+               struct bt_ctf_field_type *variant_field_type,
+               const char *tag_name);
+
+extern int64_t bt_ctf_field_type_variant_get_field_count(
+               struct bt_ctf_field_type *variant_field_type);
+
+extern int bt_ctf_field_type_variant_get_field_by_index(
+               struct bt_ctf_field_type *variant_field_type,
+               const char **field_name,
+               struct bt_ctf_field_type **field_type, uint64_t index);
+
+extern
+struct bt_ctf_field_type *bt_ctf_field_type_variant_get_field_type_by_name(
+               struct bt_ctf_field_type *variant_field_type,
+               const char *field_name);
+
+extern
+struct bt_ctf_field_type *bt_ctf_field_type_variant_get_field_type_from_tag(
+               struct bt_ctf_field_type *variant_field_type,
+               struct bt_ctf_field *tag_field);
+
+extern int bt_ctf_field_type_variant_add_field(
+               struct bt_ctf_field_type *variant_field_type,
+               struct bt_ctf_field_type *field_type,
+               const char *field_name);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BABELTRACE_CTF_WRITER_FIELD_TYPES_H */
diff --git a/include/babeltrace/ctf-writer/fields-internal.h b/include/babeltrace/ctf-writer/fields-internal.h
new file mode 100644 (file)
index 0000000..47e1fd0
--- /dev/null
@@ -0,0 +1,53 @@
+#ifndef BABELTRACE_CTF_WRITER_FIELDS_INTERNAL_H
+#define BABELTRACE_CTF_WRITER_FIELDS_INTERNAL_H
+
+/*
+ * Babeltrace - CTF writer: Event Fields
+ *
+ * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * The Common Trace Format (CTF) Specification is available at
+ * http://www.efficios.com/ctf
+ */
+
+#include <stdint.h>
+#include <stddef.h>
+
+/* For bt_bool */
+#include <babeltrace/babeltrace.h>
+#include <babeltrace/ctf-ir/fields-internal.h>
+#include <babeltrace/ctf-writer/fields.h>
+#include <babeltrace/ctf-writer/serialize-internal.h>
+
+BT_HIDDEN
+int bt_ctf_field_serialize_recursive(struct bt_ctf_field *field,
+               struct bt_ctf_stream_pos *pos,
+               enum bt_ctf_byte_order native_byte_order);
+
+static inline
+bt_bool bt_ctf_field_is_set_recursive(struct bt_ctf_field *field)
+{
+       return bt_field_common_is_set_recursive((void *) field);
+}
+
+#endif /* BABELTRACE_CTF_WRITER_FIELDS_INTERNAL_H */
diff --git a/include/babeltrace/ctf-writer/fields.h b/include/babeltrace/ctf-writer/fields.h
new file mode 100644 (file)
index 0000000..b00a737
--- /dev/null
@@ -0,0 +1,157 @@
+#ifndef BABELTRACE_CTF_WRITER_FIELDS_H
+#define BABELTRACE_CTF_WRITER_FIELDS_H
+
+/*
+ * Babeltrace - CTF writer: Event Fields
+ *
+ * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * The Common Trace Format (CTF) Specification is available at
+ * http://www.efficios.com/ctf
+ */
+
+#include <stdint.h>
+#include <stddef.h>
+
+/* For bt_bool */
+#include <babeltrace/ctf-writer/fields.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct bt_ctf_field;
+struct bt_ctf_event_class;
+struct bt_ctf_event;
+struct bt_ctf_field_type;
+struct bt_ctf_field_type_enumeration_mapping_iterator;
+
+extern struct bt_ctf_field *bt_ctf_field_create(
+               struct bt_ctf_field_type *field_type);
+
+extern struct bt_ctf_field_type *bt_ctf_field_get_type(
+               struct bt_ctf_field *field);
+
+extern enum bt_ctf_field_type_id bt_ctf_field_get_type_id(
+               struct bt_ctf_field *field);
+
+extern struct bt_ctf_field *bt_ctf_field_copy(struct bt_ctf_field *field);
+
+extern int bt_ctf_field_integer_signed_get_value(
+               struct bt_ctf_field *integer_field, int64_t *value);
+
+/* Pre-2.0 CTF writer compatibility */
+static inline
+int bt_ctf_field_signed_integer_set_value(
+               struct bt_ctf_field *integer_field, int64_t *value)
+{
+       return bt_ctf_field_integer_signed_get_value(integer_field, value);
+}
+
+extern int bt_ctf_field_integer_signed_set_value(
+               struct bt_ctf_field *integer_field, int64_t value);
+
+extern int bt_ctf_field_integer_unsigned_get_value(
+               struct bt_ctf_field *integer_field, uint64_t *value);
+
+extern int bt_ctf_field_integer_unsigned_set_value(
+               struct bt_ctf_field *integer_field, uint64_t value);
+
+/* Pre-2.0 CTF writer compatibility */
+static inline
+int bt_ctf_field_unsigned_integer_set_value(
+               struct bt_ctf_field *integer_field, uint64_t *value)
+{
+       return bt_ctf_field_integer_unsigned_get_value(integer_field, value);
+}
+
+extern int bt_ctf_field_floating_point_get_value(
+               struct bt_ctf_field *float_field, double *value);
+
+extern int bt_ctf_field_floating_point_set_value(
+               struct bt_ctf_field *float_field, double value);
+
+extern struct bt_ctf_field *bt_ctf_field_enumeration_get_container(
+               struct bt_ctf_field *enum_field);
+
+extern struct bt_ctf_field_type_enumeration_mapping_iterator *
+bt_ctf_field_enumeration_get_mappings(struct bt_ctf_field *enum_field);
+
+extern const char *bt_ctf_field_string_get_value(
+               struct bt_ctf_field *string_field);
+
+extern int bt_ctf_field_string_set_value(struct bt_ctf_field *string_field,
+               const char *value);
+
+extern int bt_ctf_field_string_append(struct bt_ctf_field *string_field,
+               const char *value);
+
+extern int bt_ctf_field_string_append_len(
+               struct bt_ctf_field *string_field, const char *value,
+               unsigned int length);
+
+extern struct bt_ctf_field *bt_ctf_field_structure_get_field_by_name(
+               struct bt_ctf_field *struct_field, const char *name);
+
+/* Pre-2.0 CTF writer compatibility */
+static inline
+struct bt_ctf_field *bt_ctf_field_structure_get_field(
+               struct bt_ctf_field *structure, const char *name)
+{
+       return bt_ctf_field_structure_get_field_by_name(structure, name);
+}
+
+extern struct bt_ctf_field *bt_ctf_field_structure_get_field_by_index(
+               struct bt_ctf_field *struct_field, uint64_t index);
+
+extern int bt_ctf_field_structure_set_field_by_name(
+               struct bt_ctf_field *struct_field,
+               const char *name, struct bt_ctf_field *field);
+
+extern struct bt_ctf_field *bt_ctf_field_array_get_field(
+               struct bt_ctf_field *array_field, uint64_t index);
+
+extern struct bt_ctf_field *bt_ctf_field_sequence_get_field(
+               struct bt_ctf_field *sequence_field, uint64_t index);
+
+extern struct bt_ctf_field *bt_ctf_field_sequence_get_length(
+               struct bt_ctf_field *sequence_field);
+
+extern int bt_ctf_field_sequence_set_length(struct bt_ctf_field *sequence_field,
+               struct bt_ctf_field *length_field);
+
+extern struct bt_ctf_field *bt_ctf_field_variant_get_field(
+               struct bt_ctf_field *variant_field,
+               struct bt_ctf_field *tag_field);
+
+extern struct bt_ctf_field *bt_ctf_field_variant_get_current_field(
+               struct bt_ctf_field *variant_field);
+
+extern struct bt_ctf_field *bt_ctf_field_variant_get_tag(
+               struct bt_ctf_field *variant_field);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BABELTRACE_CTF_WRITER_FIELDS_H */
index 1db2d296f162cad0a3bd08f4e7220af2f3c59eb0..e11f8b087aad7a1602d3b629d13922a311c83c33 100644 (file)
 #include <glib.h>
 #include <babeltrace/babeltrace-internal.h>
 
-struct search_query {
-       gpointer value;
-       int found;
-};
-
 BT_HIDDEN
 void value_exists(gpointer element, gpointer search_query);
 
index 09acfc1c2106db76d134a4b73157cd73088bff50..5728841e2405e43d28355b43fd1c9fc306d94cf4 100644 (file)
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
-#include <babeltrace/ctf-ir/field-types.h>
-#include <babeltrace/ctf-ir/fields.h>
-#include <babeltrace/ctf-ir/fields-internal.h>
 #include <babeltrace/align-internal.h>
 #include <babeltrace/common-internal.h>
 #include <babeltrace/mmap-align-internal.h>
 #include <babeltrace/types.h>
+#include <babeltrace/ctf-writer/fields.h>
+#include <babeltrace/ctf-writer/field-types.h>
+#include <babeltrace/ctf-ir/fields-internal.h>
 #include <babeltrace/assert-internal.h>
 
 #define PACKET_LEN_INCREMENT   (bt_common_get_page_size() * 8 * CHAR_BIT)
 
-struct bt_stream_pos {
+struct bt_ctf_stream_pos {
        int fd;
        int prot;               /* mmap protection */
        int flags;              /* mmap flags */
@@ -58,17 +58,17 @@ struct bt_stream_pos {
 };
 
 BT_HIDDEN
-int bt_field_integer_write(struct bt_field_integer *field,
-               struct bt_stream_pos *pos,
-               enum bt_byte_order native_byte_order);
+int bt_ctf_field_integer_write(struct bt_field_common *field,
+               struct bt_ctf_stream_pos *pos,
+               enum bt_ctf_byte_order native_byte_order);
 
 BT_HIDDEN
-int bt_field_floating_point_write(struct bt_field_floating_point *field,
-               struct bt_stream_pos *pos,
-               enum bt_byte_order native_byte_order);
+int bt_ctf_field_floating_point_write(struct bt_field_common *field,
+               struct bt_ctf_stream_pos *pos,
+               enum bt_ctf_byte_order native_byte_order);
 
 static inline
-int bt_stream_pos_access_ok(struct bt_stream_pos *pos, uint64_t bit_len)
+int bt_ctf_stream_pos_access_ok(struct bt_ctf_stream_pos *pos, uint64_t bit_len)
 {
        uint64_t max_len;
 
@@ -94,11 +94,11 @@ int bt_stream_pos_access_ok(struct bt_stream_pos *pos, uint64_t bit_len)
 }
 
 static inline
-int bt_stream_pos_move(struct bt_stream_pos *pos, uint64_t bit_offset)
+int bt_ctf_stream_pos_move(struct bt_ctf_stream_pos *pos, uint64_t bit_offset)
 {
        int ret = 0;
 
-       ret = bt_stream_pos_access_ok(pos, bit_offset);
+       ret = bt_ctf_stream_pos_access_ok(pos, bit_offset);
        if (!ret) {
                goto end;
        }
@@ -108,14 +108,14 @@ end:
 }
 
 static inline
-int bt_stream_pos_align(struct bt_stream_pos *pos, uint64_t bit_offset)
+int bt_ctf_stream_pos_align(struct bt_ctf_stream_pos *pos, uint64_t bit_offset)
 {
-       return bt_stream_pos_move(pos,
+       return bt_ctf_stream_pos_move(pos,
                offset_align(pos->offset, bit_offset));
 }
 
 static inline
-char *bt_stream_pos_get_addr(struct bt_stream_pos *pos)
+char *bt_ctf_stream_pos_get_addr(struct bt_ctf_stream_pos *pos)
 {
        /* Only makes sense to get the address after aligning on CHAR_BIT */
        BT_ASSERT(!(pos->offset % CHAR_BIT));
@@ -124,7 +124,7 @@ char *bt_stream_pos_get_addr(struct bt_stream_pos *pos)
 }
 
 static inline
-int bt_stream_pos_init(struct bt_stream_pos *pos,
+int bt_ctf_stream_pos_init(struct bt_ctf_stream_pos *pos,
                int fd, int open_flags)
 {
        pos->fd = fd;
@@ -146,7 +146,7 @@ int bt_stream_pos_init(struct bt_stream_pos *pos,
 }
 
 static inline
-int bt_stream_pos_fini(struct bt_stream_pos *pos)
+int bt_ctf_stream_pos_fini(struct bt_ctf_stream_pos *pos)
 {
        if (pos->base_mma) {
                int ret;
@@ -162,7 +162,7 @@ int bt_stream_pos_fini(struct bt_stream_pos *pos)
 }
 
 BT_HIDDEN
-void bt_stream_pos_packet_seek(struct bt_stream_pos *pos, size_t index,
+void bt_ctf_stream_pos_packet_seek(struct bt_ctf_stream_pos *pos, size_t index,
        int whence);
 
 #endif /* BABELTRACE_CTF_WRITER_SERIALIZE_INTERNAL_H */
diff --git a/include/babeltrace/ctf-writer/stream-class-internal.h b/include/babeltrace/ctf-writer/stream-class-internal.h
new file mode 100644 (file)
index 0000000..3021559
--- /dev/null
@@ -0,0 +1,55 @@
+#ifndef BABELTRACE_CTF_WRITER_STREAM_CLASS_INTERNAL_H
+#define BABELTRACE_CTF_WRITER_STREAM_CLASS_INTERNAL_H
+
+/*
+ * BabelTrace - CTF Writer: Stream Class
+ *
+ * Copyright 2014 EfficiOS Inc.
+ *
+ * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * The Common Trace Format (CTF) Specification is available at
+ * http://www.efficios.com/ctf
+ */
+
+#include <babeltrace/ctf-ir/stream-class-internal.h>
+#include <babeltrace/ctf-writer/field-types.h>
+#include <babeltrace/ctf-writer/clock-internal.h>
+
+struct bt_ctf_stream_class {
+       struct bt_stream_class_common common;
+       struct bt_ctf_clock *clock;
+       int64_t next_stream_id;
+};
+
+struct metadata_context;
+
+BT_HIDDEN
+int bt_ctf_stream_class_serialize(struct bt_ctf_stream_class *stream_class,
+               struct metadata_context *context);
+
+BT_HIDDEN
+int bt_ctf_stream_class_map_clock_class(
+               struct bt_ctf_stream_class *stream_class,
+               struct bt_ctf_field_type *packet_context_type,
+               struct bt_ctf_field_type *event_header_type);
+
+#endif /* BABELTRACE_CTF_WRITER_STREAM_CLASS_INTERNAL_H */
index a1d0ba929934eec2c3e530befef4ad621095b3f0..1cc00689a1d4fd613ba94aa4ad9b32119f66ed5f 100644 (file)
  * http://www.efficios.com/ctf
  */
 
+#include <babeltrace/ref.h>
 #include <babeltrace/ctf-ir/stream-class.h>
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-/*
- * bt_stream_class_set_clock: assign a clock to a stream class.
- *
- * Assign a clock to a stream class. This clock will be sampled each time an
- * event is appended to an instance of this stream class.
- *
- * @param stream_class Stream class.
- * @param clock Clock to assign to the provided stream class.
- *
- * Returns 0 on success, a negative value on error.
- */
-extern int bt_stream_class_set_clock(
-               struct bt_stream_class *stream_class,
+struct bt_ctf_stream_class;
+struct bt_ctf_trace;
+struct bt_ctf_event_class;
+struct bt_ctf_field_type;
+struct bt_ctf_clock;
+
+extern struct bt_ctf_stream_class *bt_ctf_stream_class_create(
+               const char *name);
+
+extern struct bt_ctf_trace *bt_ctf_stream_class_get_trace(
+               struct bt_ctf_stream_class *stream_class);
+
+extern const char *bt_ctf_stream_class_get_name(
+               struct bt_ctf_stream_class *stream_class);
+
+extern int bt_ctf_stream_class_set_name(
+               struct bt_ctf_stream_class *stream_class, const char *name);
+
+extern int64_t bt_ctf_stream_class_get_id(
+               struct bt_ctf_stream_class *stream_class);
+
+extern int bt_ctf_stream_class_set_id(
+               struct bt_ctf_stream_class *stream_class, uint64_t id);
+
+extern struct bt_ctf_field_type *bt_ctf_stream_class_get_packet_context_type(
+               struct bt_ctf_stream_class *stream_class);
+
+extern int bt_ctf_stream_class_set_packet_context_type(
+               struct bt_ctf_stream_class *stream_class,
+               struct bt_ctf_field_type *packet_context_type);
+
+extern struct bt_ctf_field_type *
+bt_ctf_stream_class_get_event_header_type(
+               struct bt_ctf_stream_class *stream_class);
+
+extern int bt_ctf_stream_class_set_event_header_type(
+               struct bt_ctf_stream_class *stream_class,
+               struct bt_ctf_field_type *event_header_type);
+
+extern struct bt_ctf_field_type *
+bt_ctf_stream_class_get_event_context_type(
+               struct bt_ctf_stream_class *stream_class);
+
+extern int bt_ctf_stream_class_set_event_context_type(
+               struct bt_ctf_stream_class *stream_class,
+               struct bt_ctf_field_type *event_context_type);
+
+extern int64_t bt_ctf_stream_class_get_event_class_count(
+               struct bt_ctf_stream_class *stream_class);
+
+extern struct bt_ctf_event_class *bt_ctf_stream_class_get_event_class_by_index(
+               struct bt_ctf_stream_class *stream_class, uint64_t index);
+
+extern struct bt_ctf_event_class *bt_ctf_stream_class_get_event_class_by_id(
+               struct bt_ctf_stream_class *stream_class, uint64_t id);
+
+extern int bt_ctf_stream_class_add_event_class(
+               struct bt_ctf_stream_class *stream_class,
+               struct bt_ctf_event_class *event_class);
+
+extern int bt_ctf_stream_class_set_clock(
+               struct bt_ctf_stream_class *ctf_stream_class,
                struct bt_ctf_clock *clock);
 
-extern struct bt_ctf_clock *bt_stream_class_get_clock(
-        struct bt_stream_class *stream_class);
+extern struct bt_ctf_clock *bt_ctf_stream_class_get_clock(
+        struct bt_ctf_stream_class *stream_class);
 
 /* Pre-2.0 CTF writer compatibility */
-#define bt_ctf_stream_class_set_clock bt_stream_class_set_clock
+static inline
+void bt_ctf_stream_class_get(struct bt_ctf_stream_class *stream_class)
+{
+       bt_get(stream_class);
+}
 
-extern void bt_ctf_stream_class_get(struct bt_ctf_stream_class *stream_class);
-extern void bt_ctf_stream_class_put(struct bt_ctf_stream_class *stream_class);
+/* Pre-2.0 CTF writer compatibility */
+static inline
+void bt_ctf_stream_class_put(struct bt_ctf_stream_class *stream_class)
+{
+       bt_put(stream_class);
+}
 
 #ifdef __cplusplus
 }
diff --git a/include/babeltrace/ctf-writer/stream-internal.h b/include/babeltrace/ctf-writer/stream-internal.h
new file mode 100644 (file)
index 0000000..1d6e8fc
--- /dev/null
@@ -0,0 +1,61 @@
+#ifndef BABELTRACE_CTF_WRITER_STREAM_INTERNAL_H
+#define BABELTRACE_CTF_WRITER_STREAM_INTERNAL_H
+
+/*
+ * BabelTrace - CTF Writer: Stream
+ *
+ * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * The Common Trace Format (CTF) Specification is available at
+ * http://www.efficios.com/ctf
+ */
+
+#include <babeltrace/assert-pre-internal.h>
+#include <babeltrace/ctf-ir/stream-internal.h>
+#include <babeltrace/ctf-writer/serialize-internal.h>
+#include <babeltrace/babeltrace.h>
+#include <stdint.h>
+
+struct bt_ctf_stream {
+       struct bt_stream_common common;
+       struct bt_ctf_field *packet_header;
+       struct bt_ctf_field *packet_context;
+
+       /* Array of pointers to bt_ctf_event for the current packet */
+       GPtrArray *events;
+       struct bt_ctf_stream_pos pos;
+       unsigned int flushed_packet_count;
+       uint64_t discarded_events;
+       uint64_t size;
+       uint64_t last_ts_end;
+};
+
+BT_HIDDEN
+int bt_stream_set_fd(struct bt_stream *stream, int fd);
+
+BT_HIDDEN
+struct bt_ctf_stream *bt_ctf_stream_create_with_id(
+               struct bt_ctf_stream_class *stream_class,
+               const char *name, uint64_t id);
+
+#endif /* BABELTRACE_CTF_WRITER_STREAM_INTERNAL_H */
index 6d36e543bdbd80867e993e5825648a4ed71e4219..e0b6474830db4ec03123146b5222ccb5eb00b2f3 100644 (file)
  * http://www.efficios.com/ctf
  */
 
-#include <babeltrace/ctf-ir/event.h>
-#include <babeltrace/ctf-ir/stream.h>
-#include <babeltrace/ctf-writer/stream-class.h>
+#include <stdint.h>
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+struct bt_ctf_stream;
+struct bt_ctf_event;
+
 /*
- * bt_stream_get_discarded_events_count: get the number of discarded
+ * bt_ctf_stream_get_discarded_events_count: get the number of discarded
  * events associated with this stream.
  *
  * Note that discarded events are not stored if the stream's packet
@@ -50,11 +51,11 @@ extern "C" {
  *
  * Returns the number of discarded events, a negative value on error.
  */
-extern int bt_stream_get_discarded_events_count(
-               struct bt_stream *stream, uint64_t *count);
+extern int bt_ctf_stream_get_discarded_events_count(
+               struct bt_ctf_stream *stream, uint64_t *count);
 
 /*
- * bt_stream_append_discarded_events: increment discarded events count.
+ * bt_ctf_stream_append_discarded_events: increment discarded events count.
  *
  * Increase the current packet's discarded event count. Has no effect if the
  * stream class' packet context has no "events_discarded" field.
@@ -63,17 +64,17 @@ extern int bt_stream_get_discarded_events_count(
  * @param event_count Number of discarded events to add to the stream's current
  *     packet.
  */
-extern void bt_stream_append_discarded_events(struct bt_stream *stream,
+extern void bt_ctf_stream_append_discarded_events(struct bt_ctf_stream *stream,
                uint64_t event_count);
 
 /*
- * bt_stream_append_event: append an event to the stream.
+ * bt_ctf_stream_append_event: append an event to the stream.
  *
  * Append "event" to the stream's current packet. The stream's associated clock
  * will be sampled during this call. The event shall not be modified after
  * being appended to a stream. The stream will share the event's ownership by
  * incrementing its reference count. The current packet is not flushed to disk
- * until the next call to bt_stream_flush.
+ * until the next call to bt_ctf_stream_flush.
  *
  * The stream event context will be sampled for every appended event if
  * a stream event context was defined.
@@ -83,21 +84,21 @@ extern void bt_stream_append_discarded_events(struct bt_stream *stream,
  *
  * Returns 0 on success, a negative value on error.
  */
-extern int bt_stream_append_event(struct bt_stream *stream,
-               struct bt_event *event);
+extern int bt_ctf_stream_append_event(struct bt_ctf_stream *stream,
+               struct bt_ctf_event *event);
 
 /*
- * bt_stream_get_packet_header: get a stream's packet header.
+ * bt_ctf_stream_get_packet_header: get a stream's packet header.
  *
  * @param stream Stream instance.
  *
  * Returns a field instance on success, NULL on error.
  */
-extern struct bt_field *bt_stream_get_packet_header(
-               struct bt_stream *stream);
+extern struct bt_ctf_field *bt_ctf_stream_get_packet_header(
+               struct bt_ctf_stream *stream);
 
 /*
- * bt_stream_set_packet_header: set a stream's packet header.
+ * bt_ctf_stream_set_packet_header: set a stream's packet header.
  *
  * The packet header's type must match the trace's packet header
  * type.
@@ -107,22 +108,22 @@ extern struct bt_field *bt_stream_get_packet_header(
  *
  * Returns a field instance on success, NULL on error.
  */
-extern int bt_stream_set_packet_header(
-               struct bt_stream *stream,
-               struct bt_field *packet_header);
+extern int bt_ctf_stream_set_packet_header(
+               struct bt_ctf_stream *stream,
+               struct bt_ctf_field *packet_header);
 
 /*
- * bt_stream_get_packet_context: get a stream's packet context.
+ * bt_ctf_stream_get_packet_context: get a stream's packet context.
  *
  * @param stream Stream instance.
  *
  * Returns a field instance on success, NULL on error.
  */
-extern struct bt_field *bt_stream_get_packet_context(
-               struct bt_stream *stream);
+extern struct bt_ctf_field *bt_ctf_stream_get_packet_context(
+               struct bt_ctf_stream *stream);
 
 /*
- * bt_stream_set_packet_context: set a stream's packet context.
+ * bt_ctf_stream_set_packet_context: set a stream's packet context.
  *
  * The packet context's type must match the stream class' packet
  * context type.
@@ -132,12 +133,12 @@ extern struct bt_field *bt_stream_get_packet_context(
  *
  * Returns a field instance on success, NULL on error.
  */
-extern int bt_stream_set_packet_context(
-               struct bt_stream *stream,
-               struct bt_field *packet_context);
+extern int bt_ctf_stream_set_packet_context(
+               struct bt_ctf_stream *stream,
+               struct bt_ctf_field *packet_context);
 
 /*
- * bt_stream_flush: flush a stream.
+ * bt_ctf_stream_flush: flush a stream.
  *
  * The stream's current packet's events will be flushed, thus closing the
  * current packet. Events subsequently appended to the stream will be
@@ -151,19 +152,35 @@ extern int bt_stream_set_packet_context(
  *
  * Returns 0 on success, a negative value on error.
  */
-extern int bt_stream_flush(struct bt_stream *stream);
+extern int bt_ctf_stream_flush(struct bt_ctf_stream *stream);
+
+extern int bt_ctf_stream_is_writer(struct bt_ctf_stream *stream);
+
+extern
+struct bt_ctf_stream *bt_ctf_stream_create(
+               struct bt_ctf_stream_class *stream_class,
+               const char *name, uint64_t id);
+
+extern struct bt_ctf_stream_class *bt_ctf_stream_get_class(
+               struct bt_ctf_stream *stream);
+
+extern const char *bt_ctf_stream_get_name(struct bt_ctf_stream *stream);
 
-extern int bt_stream_is_writer(struct bt_stream *stream);
+extern int64_t bt_ctf_stream_get_id(struct bt_ctf_stream *stream);
 
 /* Pre-2.0 CTF writer compatibility */
-#define bt_ctf_stream_get_discarded_events_count bt_stream_get_discarded_events_count
-#define bt_ctf_stream_append_discarded_events bt_stream_append_discarded_events
-#define bt_ctf_stream_append_event bt_stream_append_event
-#define bt_ctf_stream_get_packet_context bt_stream_get_packet_context
-#define bt_ctf_stream_flush bt_stream_flush
-
-extern void bt_ctf_stream_get(struct bt_stream *stream);
-extern void bt_ctf_stream_put(struct bt_stream *stream);
+static inline
+void bt_ctf_stream_get(struct bt_ctf_stream *stream)
+{
+       bt_get(stream);
+}
+
+/* Pre-2.0 CTF writer compatibility */
+static inline
+void bt_ctf_stream_put(struct bt_ctf_stream *stream)
+{
+       bt_put(stream);
+}
 
 #ifdef __cplusplus
 }
diff --git a/include/babeltrace/ctf-writer/trace-internal.h b/include/babeltrace/ctf-writer/trace-internal.h
new file mode 100644 (file)
index 0000000..47d746e
--- /dev/null
@@ -0,0 +1,55 @@
+#ifndef BABELTRACE_CTF_WRITER_TRACE_INTERNAL_H
+#define BABELTRACE_CTF_WRITER_TRACE_INTERNAL_H
+
+/*
+ * BabelTrace - CTF Writer: Trace
+ *
+ * Copyright 2014 EfficiOS Inc.
+ *
+ * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * The Common Trace Format (CTF) Specification is available at
+ * http://www.efficios.com/ctf
+ */
+
+#include <babeltrace/ctf-ir/trace-internal.h>
+
+struct bt_ctf_trace {
+       struct bt_trace_common common;
+};
+
+/*
+ * bt_ctf_trace_get_metadata_string: get metadata string.
+ *
+ * Get the trace's TSDL metadata. The caller assumes the ownership of the
+ * returned string.
+ *
+ * @param trace Trace instance.
+ *
+ * Returns the metadata string on success, NULL on error.
+ */
+BT_HIDDEN
+char *bt_ctf_trace_get_metadata_string(struct bt_ctf_trace *trace);
+
+BT_HIDDEN
+struct bt_ctf_trace *bt_ctf_trace_create(void);
+
+#endif /* BABELTRACE_CTF_WRITER_TRACE_INTERNAL_H */
diff --git a/include/babeltrace/ctf-writer/trace.h b/include/babeltrace/ctf-writer/trace.h
new file mode 100644 (file)
index 0000000..e8947cb
--- /dev/null
@@ -0,0 +1,122 @@
+#ifndef BABELTRACE_CTF_WRITER_TRACE_H
+#define BABELTRACE_CTF_WRITER_TRACE_H
+
+/*
+ * BabelTrace - CTF Writer: Stream Class
+ *
+ * Copyright 2014 EfficiOS Inc.
+ *
+ * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * The Common Trace Format (CTF) Specification is available at
+ * http://www.efficios.com/ctf
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct bt_ctf_trace;
+struct bt_ctf_stream_class;
+struct bt_ctf_stream;
+struct bt_ctf_clock_class;
+
+extern enum bt_ctf_byte_order bt_ctf_trace_get_native_byte_order(
+               struct bt_ctf_trace *trace);
+
+extern int bt_ctf_trace_set_native_byte_order(struct bt_ctf_trace *trace,
+               enum bt_ctf_byte_order native_byte_order);
+
+extern const unsigned char *bt_ctf_trace_get_uuid(
+               struct bt_ctf_trace *trace);
+
+extern int bt_ctf_trace_set_uuid(struct bt_ctf_trace *trace,
+               const unsigned char *uuid);
+
+extern int64_t bt_ctf_trace_get_environment_field_count(
+               struct bt_ctf_trace *trace);
+
+extern const char *
+bt_ctf_trace_get_environment_field_name_by_index(
+               struct bt_ctf_trace *trace, uint64_t index);
+
+extern struct bt_value *
+bt_ctf_trace_get_environment_field_value_by_index(struct bt_ctf_trace *trace,
+               uint64_t index);
+
+extern struct bt_value *
+bt_ctf_trace_get_environment_field_value_by_name(
+               struct bt_ctf_trace *trace, const char *name);
+
+extern int bt_ctf_trace_set_environment_field(
+               struct bt_ctf_trace *trace, const char *name,
+               struct bt_value *value);
+
+extern int bt_ctf_trace_set_environment_field_integer(
+               struct bt_ctf_trace *trace, const char *name,
+               int64_t value);
+
+extern int bt_ctf_trace_set_environment_field_string(
+               struct bt_ctf_trace *trace, const char *name,
+               const char *value);
+
+extern struct bt_ctf_field_type *bt_ctf_trace_get_packet_header_field_type(
+               struct bt_ctf_trace *trace);
+
+extern int bt_ctf_trace_set_packet_header_field_type(struct bt_ctf_trace *trace,
+               struct bt_ctf_field_type *packet_header_type);
+
+extern int64_t bt_ctf_trace_get_clock_class_count(
+               struct bt_ctf_trace *trace);
+
+extern struct bt_ctf_clock_class *bt_ctf_trace_get_clock_class_by_index(
+               struct bt_ctf_trace *trace, uint64_t index);
+
+extern struct bt_ctf_clock_class *bt_ctf_trace_get_clock_class_by_name(
+               struct bt_ctf_trace *trace, const char *name);
+
+extern int bt_ctf_trace_add_clock_class(struct bt_ctf_trace *trace,
+               struct bt_ctf_clock_class *clock_class);
+
+extern int64_t bt_ctf_trace_get_stream_class_count(
+               struct bt_ctf_trace *trace);
+
+extern struct bt_ctf_stream_class *bt_ctf_trace_get_stream_class_by_index(
+               struct bt_ctf_trace *trace, uint64_t index);
+
+extern struct bt_ctf_stream_class *bt_ctf_trace_get_stream_class_by_id(
+               struct bt_ctf_trace *trace, uint64_t id);
+
+extern int bt_ctf_trace_add_stream_class(struct bt_ctf_trace *trace,
+               struct bt_ctf_stream_class *stream_class);
+
+extern int64_t bt_ctf_trace_get_stream_count(struct bt_ctf_trace *trace);
+
+extern struct bt_ctf_stream *bt_ctf_trace_get_stream_by_index(
+               struct bt_ctf_trace *trace, uint64_t index);
+
+extern const char *bt_ctf_trace_get_name(struct bt_ctf_trace *trace);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BABELTRACE_CTF_WRITER_TRACE_H */
index ced679ec43470cb686a3172f988628be4a704b0c..55ad145d8b88b22419472f73c6fade795196218b 100644 (file)
 #include <babeltrace/ctf-ir/trace.h>
 #include <babeltrace/object-internal.h>
 
+struct metadata_context {
+       GString *string;
+       GString *field_name;
+       unsigned int current_indentation_level;
+};
+
 struct bt_ctf_writer {
        struct bt_object base;
        int frozen; /* Protects attributes that can't be changed mid-trace */
-       struct bt_trace *trace;
+       struct bt_ctf_trace *trace;
        GString *path;
        int metadata_fd;
 };
 
+enum field_type_alias {
+       FIELD_TYPE_ALIAS_UINT5_T = 0,
+       FIELD_TYPE_ALIAS_UINT8_T,
+       FIELD_TYPE_ALIAS_UINT16_T,
+       FIELD_TYPE_ALIAS_UINT27_T,
+       FIELD_TYPE_ALIAS_UINT32_T,
+       FIELD_TYPE_ALIAS_UINT64_T,
+       NR_FIELD_TYPE_ALIAS,
+};
+
+BT_HIDDEN
+struct bt_ctf_field_type *get_field_type(enum field_type_alias alias);
+
+BT_HIDDEN
+const char *get_byte_order_string(enum bt_byte_order byte_order);
+
 BT_HIDDEN
 void bt_ctf_writer_freeze(struct bt_ctf_writer *writer);
 
index e1f28bc0bf13f38a19a124570fed79a754076dc0..f496d3c5e4285f50fb31dc34a8e18b77e7603f50 100644 (file)
  * http://www.efficios.com/ctf
  */
 
-#include <babeltrace/ctf-ir/field-types.h>
-#include <babeltrace/ctf-ir/stream-class.h>
-#include <babeltrace/ctf-ir/stream.h>
-#include <babeltrace/ctf-ir/trace.h>
+#include <babeltrace/ctf-writer/field-types.h>
+#include <babeltrace/ctf-writer/stream-class.h>
+#include <babeltrace/ctf-writer/stream.h>
+#include <babeltrace/ctf-writer/trace.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -184,8 +184,20 @@ extern int bt_ctf_writer_set_byte_order(struct bt_ctf_writer *writer,
  *
  * @param writer Writer instance.
  */
-extern void bt_ctf_writer_get(struct bt_ctf_writer *writer);
-extern void bt_ctf_writer_put(struct bt_ctf_writer *writer);
+
+/* Pre-2.0 CTF writer compatibility */
+static inline
+void bt_ctf_writer_get(struct bt_ctf_writer *writer)
+{
+       bt_get(writer);
+}
+
+/* Pre-2.0 CTF writer compatibility */
+static inline
+void bt_ctf_writer_put(struct bt_ctf_writer *writer)
+{
+       bt_put(writer);
+}
 
 #ifdef __cplusplus
 }
index 4f4f04348c0b13a0256a8f85b8873c572666bf00..376be0bc88535e0495eb7832246c627cde17686d 100644 (file)
 extern
 int bt_lib_log_level;
 
+#define BT_LIB_LOG(_lvl, _fmt, ...)                                    \
+       do {                                                            \
+               if (BT_LOG_ON(_lvl)) {                                  \
+                       bt_lib_log(_BT_LOG_SRCLOC_FUNCTION, __FILE__,   \
+                               __LINE__, _lvl, _BT_LOG_TAG,            \
+                               (_fmt), ##__VA_ARGS__);                 \
+               }                                                       \
+       } while (0)
+
 /*
  * The six macros below are logging statements which are specialized
  * for the Babeltrace library.
@@ -61,77 +70,137 @@ int bt_lib_log_level;
  * 3. Optional: `+` to print extended fields. This depends on the
  *    provided format specifier.
  *
- * 4. Format specifier.
+ * 4. Objet category: `w` for CTF writer objects, `_` for common
+ *    objects, or nothing for default objects (includes CTF IR).
+ *
+ * 5. Format specifier (see below).
  *
  * The available format specifiers are:
  *
- * `r`:
- *     Reference count information. The parameter is any Babeltrace
- *     object.
+ * Default category:
+ *   `r`:
+ *       Reference count information. The parameter is any Babeltrace
+ *       object.
+ *
+ *   `F`:
+ *       CTF IR field type. The parameter type is `struct bt_field_type *`.
+ *
+ *   `f`:
+ *       CTF IR field. The parameter type is `struct bt_field *`.
+ *
+ *   `P`:
+ *       Field path. The parameter type is `struct bt_field_path *`.
+ *
+ *   `E`:
+ *       CTF IR event class. The parameter type is `struct bt_event_class *`.
+ *
+ *   `e`:
+ *       CTF IR event. The parameter type is `struct bt_event *`.
+ *
+ *   `S`:
+ *       CTF IR stream class. The parameter type is `struct bt_stream_class *`.
+ *
+ *   `s`:
+ *       CTF IR stream. The parameter type is `struct bt_stream *`.
+ *
+ *   `a`:
+ *       Packet. The parameter type is `struct bt_packet *`.
  *
- * `F`:
- *     Field type. The parameter type is `struct bt_field_type *`.
+ *   `t`:
+ *       CTF IR trace. The parameter type is `struct bt_trace *`.
  *
- * `f`:
- *     Field. The parameter type is `struct bt_field *`.
+ *   `K`:
+ *       Clock class. The parameter type is `struct bt_clock_class *`.
  *
- * `P`:
- *     Field path. The parameter type is `struct bt_field_path *`.
+ *   `k`:
+ *       Clock value. The parameter type is `struct bt_clock_value *`.
  *
- * `E`:
- *     Event class. The parameter type is `struct bt_event_class *`.
+ *   `v`:
+ *       Value. The parameter type is `struct bt_value *`.
  *
- * `e`:
- *     Event. The parameter type is `struct bt_event *`.
+ *   `n`:
+ *       Notification. The parameter type is `struct bt_notification *`.
  *
- * `S`:
- *     Stream class. The parameter type is `struct bt_stream_class *`.
+ *   `i`:
+ *       Notification iterator. The parameter type is
+ *       `struct bt_notification_iterator *`.
  *
- * `s`:
- *     Stream. The parameter type is `struct bt_stream *`.
+ *   `C`:
+ *       Component class. The parameter type is `struct bt_component_class *`.
  *
- * `a`:
- *     Packet. The parameter type is `struct bt_packet *`.
+ *   `c`:
+ *       Component. The parameter type is `struct bt_component *`.
  *
- * `t`:
- *     Trace. The parameter type is `struct bt_trace *`.
+ *   `p`:
+ *       Port. The parameter type is `struct bt_port *`.
  *
- * `K`:
- *     Clock class. The parameter type is `struct bt_clock_class *`.
+ *   `x`:
+ *       Connection. The parameter type is `struct bt_connection *`.
  *
- * `k`:
- *     Clock value. The parameter type is `struct bt_clock_value *`.
+ *   `g`:
+ *       Graph. The parameter type is `struct bt_graph *`.
  *
- * `v`:
- *     Value. The parameter type is `struct bt_value *`.
+ *   `u`:
+ *       Plugin. The parameter type is `struct bt_plugin *`.
  *
- * `n`:
- *     Notification. The parameter type is `struct bt_notification *`.
+ * CTF writer category:
+ *   `F`:
+ *       CTF writer field type. The parameter type is `struct bt_field_type *`.
  *
- * `i`:
- *     Notification iterator. The parameter type is
- *     `struct bt_notification_iterator *`.
+ *   `f`:
+ *       CTF writer field. The parameter type is `struct bt_field *`.
  *
- * `C`:
- *     Component class. The parameter type is `struct bt_component_class *`.
+ *   `E`:
+ *       CTF writer event class. The parameter type is
+ *       `struct bt_event_class *`.
  *
- * `c`:
- *     Component. The parameter type is `struct bt_component *`.
+ *   `e`:
+ *       CTF writer event. The parameter type is `struct bt_event *`.
  *
- * `p`:
- *     Port. The parameter type is `struct bt_port *`.
+ *   `S`:
+ *       CTF writer stream class. The parameter type is
+ *       `struct bt_stream_class *`.
  *
- * `x`:
- *     Connection. The parameter type is `struct bt_connection *`.
+ *   `s`:
+ *       CTF writer stream. The parameter type is `struct bt_stream *`.
  *
- * `g`:
- *     Graph. The parameter type is `struct bt_graph *`.
+ *   `t`:
+ *       CTF writer trace. The parameter type is `struct bt_trace *`.
  *
- * `u`:
- *     Plugin. The parameter type is `struct bt_plugin *`.
+ *   `w`:
+ *       CTF writer. The parameter type is `struct bt_ctf_writer *`.
  *
- * `w`:
- *     CTF writer. The parameter type is `struct bt_ctf_writer *`.
+ * Common category:
+ *   `F`:
+ *       Common field type. The parameter type is `struct bt_field_type *`.
+ *
+ *   `f`:
+ *       Common field. The parameter type is `struct bt_field *`.
+ *
+ *   `E`:
+ *       Common event class. The parameter type is
+ *       `struct bt_event_class *`.
+ *
+ *   `e`:
+ *       Common event. The parameter type is `struct bt_event *`.
+ *
+ *   `S`:
+ *       Common stream class. The parameter type is
+ *       `struct bt_stream_class *`.
+ *
+ *   `s`:
+ *       Common stream. The parameter type is `struct bt_stream *`.
+ *
+ *   `t`:
+ *       Common trace. The parameter type is `struct bt_trace *`.
+ *
+ * Conversion specifier examples:
+ *
+ *     %!f
+ *     %![my-event-]+e
+ *     %!_t
+ *     %![ctf-writer-ec-]wE
+ *     %!+_F
  *
  * The string `, ` is printed between individual fields, but not after
  * the last one. Therefore you must put this separator in the format
@@ -147,15 +216,6 @@ int bt_lib_log_level;
  * It is safe to pass NULL as any Babeltrace object parameter: the
  * macros only print its null address.
  */
-#define BT_LIB_LOG(_lvl, _fmt, ...)                                    \
-       do {                                                            \
-               if (BT_LOG_ON(_lvl)) {                                  \
-                       bt_lib_log(_BT_LOG_SRCLOC_FUNCTION, __FILE__,   \
-                               __LINE__, _lvl, _BT_LOG_TAG,            \
-                               (_fmt), ##__VA_ARGS__);                 \
-               }                                                       \
-       } while (0)
-
 #define BT_LIB_LOGF(_fmt, ...) BT_LIB_LOG(BT_LOG_FATAL, _fmt, ##__VA_ARGS__)
 #define BT_LIB_LOGE(_fmt, ...) BT_LIB_LOG(BT_LOG_ERROR, _fmt, ##__VA_ARGS__)
 #define BT_LIB_LOGW(_fmt, ...) BT_LIB_LOG(BT_LOG_WARN, _fmt, ##__VA_ARGS__)
index 990cb08e7d5dffa221553b73d70811b89c908137..40654e990144c9dace17d393a47828f1be9517a2 100644 (file)
@@ -69,7 +69,7 @@ int bt_clock_class_set_name(struct bt_clock_class *clock_class,
        }
 
        if (!bt_identifier_is_valid(name)) {
-               BT_LOGE("Clock class's name is not a valid CTF identifier: "
+               BT_LOGW("Clock class's name is not a valid CTF identifier: "
                        "addr=%p, name=\"%s\"",
                        clock_class, name);
                ret = -1;
@@ -139,9 +139,7 @@ struct bt_clock_class *bt_clock_class_create(const char *name,
        if (name) {
                ret = bt_clock_class_set_name(clock_class, name);
                if (ret) {
-                       BT_LOGE("Cannot set clock class's name: "
-                               "addr=%p, name=\"%s\"",
-                               clock_class, name);
+                       /* bt_clock_class_set_name() logs errors */
                        goto error;
                }
        }
@@ -531,66 +529,13 @@ static uint64_t ns_from_value(uint64_t frequency, uint64_t value)
 BT_HIDDEN
 void bt_clock_class_freeze(struct bt_clock_class *clock_class)
 {
-       if (!clock_class) {
-               BT_LOGW_STR("Invalid parameter: clock class is NULL.");
-               return;
-       }
-
-       if (!clock_class->frozen) {
-               BT_LOGD("Freezing clock class: addr=%p, name=\"%s\"",
-                       clock_class, bt_clock_class_get_name(clock_class));
-               clock_class->frozen = 1;
-       }
-}
-
-BT_HIDDEN
-void bt_clock_class_serialize(struct bt_clock_class *clock_class,
-               struct metadata_context *context)
-{
-       unsigned char *uuid;
-
-       BT_LOGD("Serializing clock class's metadata: clock-class-addr=%p, "
-               "name=\"%s\", metadata-context-addr=%p", clock_class,
-               bt_clock_class_get_name(clock_class), context);
-
-       if (!clock_class || !context) {
-               BT_LOGW("Invalid parameter: clock class or metadata context is NULL: "
-                       "clock-class-addr=%p, name=\"%s\", metadata-context-addr=%p",
-                       clock_class, bt_clock_class_get_name(clock_class),
-                       context);
+       if (!clock_class || clock_class->frozen) {
                return;
        }
 
-       uuid = clock_class->uuid;
-       g_string_append(context->string, "clock {\n");
-       g_string_append_printf(context->string, "\tname = %s;\n",
-               clock_class->name->str);
-
-       if (clock_class->uuid_set) {
-               g_string_append_printf(context->string,
-                       "\tuuid = \"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\";\n",
-                       uuid[0], uuid[1], uuid[2], uuid[3],
-                       uuid[4], uuid[5], uuid[6], uuid[7],
-                       uuid[8], uuid[9], uuid[10], uuid[11],
-                       uuid[12], uuid[13], uuid[14], uuid[15]);
-       }
-
-       if (clock_class->description) {
-               g_string_append_printf(context->string, "\tdescription = \"%s\";\n",
-                       clock_class->description->str);
-       }
-
-       g_string_append_printf(context->string, "\tfreq = %" PRIu64 ";\n",
-               clock_class->frequency);
-       g_string_append_printf(context->string, "\tprecision = %" PRIu64 ";\n",
-               clock_class->precision);
-       g_string_append_printf(context->string, "\toffset_s = %" PRIu64 ";\n",
-               clock_class->offset_s);
-       g_string_append_printf(context->string, "\toffset = %" PRIu64 ";\n",
-               clock_class->offset);
-       g_string_append_printf(context->string, "\tabsolute = %s;\n",
-               clock_class->absolute ? "true" : "false");
-       g_string_append(context->string, "};\n\n");
+       BT_LOGD("Freezing clock class: addr=%p, name=\"%s\"",
+               clock_class, bt_clock_class_get_name(clock_class));
+       clock_class->frozen = 1;
 }
 
 static
index 5ff9d0d481c06feea7c9df1ef6ee6dd46509461d..7780095bf95b2a1715ce2933b34355a1fbdd32a2 100644 (file)
@@ -29,6 +29,7 @@
 #define BT_LOG_TAG "EVENT-CLASS"
 #include <babeltrace/lib-logging-internal.h>
 
+#include <babeltrace/assert-pre-internal.h>
 #include <babeltrace/ctf-ir/fields-internal.h>
 #include <babeltrace/ctf-ir/field-types-internal.h>
 #include <babeltrace/ctf-ir/event-class.h>
 #include <babeltrace/types.h>
 #include <babeltrace/values-internal.h>
 #include <babeltrace/assert-internal.h>
-#include <babeltrace/assert-pre-internal.h>
 #include <inttypes.h>
 #include <stdlib.h>
 
-static
-void bt_event_class_destroy(struct bt_object *obj);
-
-struct bt_event_class *bt_event_class_create(const char *name)
+BT_HIDDEN
+void bt_event_class_common_finalize(struct bt_object *obj)
 {
-       struct bt_value *obj = NULL;
-       struct bt_event_class *event_class = NULL;
+       struct bt_event_class_common *event_class;
 
-       BT_LOGD("Creating event class object: name=\"%s\"",
-               name);
+       event_class = container_of(obj, struct bt_event_class_common, base);
+       BT_LOGD("Finalizing common event class: addr=%p, name=\"%s\", id=%" PRId64,
+               event_class, bt_event_class_common_get_name(event_class),
+               bt_event_class_common_get_id(event_class));
 
-       if (!name) {
-               BT_LOGW_STR("Invalid parameter: name is NULL.");
-               goto error;
+       if (event_class->name) {
+               g_string_free(event_class->name, TRUE);
        }
 
-       event_class = g_new0(struct bt_event_class, 1);
-       if (!event_class) {
-               BT_LOGE_STR("Failed to allocate one event class.");
-               goto error;
+       if (event_class->emf_uri) {
+               g_string_free(event_class->emf_uri, TRUE);
        }
 
-       bt_object_init(event_class, bt_event_class_destroy);
-       event_class->fields = bt_field_type_structure_create();
-       if (!event_class->fields) {
+       BT_LOGD_STR("Putting context field type.");
+       bt_put(event_class->context_field_type);
+       BT_LOGD_STR("Putting payload field type.");
+       bt_put(event_class->payload_field_type);
+}
+
+BT_HIDDEN
+int bt_event_class_common_initialize(struct bt_event_class_common *event_class,
+               const char *name, bt_object_release_func release_func,
+               bt_field_type_structure_create_func ft_struct_create_func)
+{
+       int ret = 0;
+
+       BT_LOGD("Initializing common event class object: name=\"%s\"",
+               name);
+       bt_object_init(event_class, release_func);
+       event_class->payload_field_type = ft_struct_create_func();
+       if (!event_class->payload_field_type) {
                BT_LOGE_STR("Cannot create event class's initial payload field type object.");
                goto error;
        }
@@ -93,492 +104,138 @@ struct bt_event_class *bt_event_class_create(const char *name)
        }
 
        event_class->log_level = BT_EVENT_CLASS_LOG_LEVEL_UNSPECIFIED;
-       BT_PUT(obj);
-       BT_LOGD("Created event class object: addr=%p, name=\"%s\"",
-               event_class, bt_event_class_get_name(event_class));
-       return event_class;
+       BT_LOGD("Initialized common event class object: addr=%p, name=\"%s\"",
+               event_class, bt_event_class_common_get_name(event_class));
+       return ret;
 
 error:
-        BT_PUT(event_class);
-       BT_PUT(obj);
-       return event_class;
-}
-
-const char *bt_event_class_get_name(struct bt_event_class *event_class)
-{
-       BT_ASSERT_PRE_NON_NULL(event_class, "Event class");
-       BT_ASSERT(event_class->name);
-       return event_class->name->str;
-}
-
-int64_t bt_event_class_get_id(struct bt_event_class *event_class)
-{
-       BT_ASSERT_PRE_NON_NULL(event_class, "Event class");
-       return event_class->id;
-}
-
-int bt_event_class_set_id(struct bt_event_class *event_class,
-               uint64_t id_param)
-{
-       int ret = 0;
-       int64_t id = (int64_t) id_param;
-
-       if (!event_class) {
-               BT_LOGW_STR("Invalid parameter: event class is NULL.");
-               ret = -1;
-               goto end;
-       }
-
-       if (event_class->frozen) {
-               BT_LOGW("Invalid parameter: event class is frozen: "
-                       "addr=%p, name=\"%s\", id=%" PRId64,
-                       event_class, bt_event_class_get_name(event_class),
-                       bt_event_class_get_id(event_class));
-               ret = -1;
-               goto end;
-       }
-
-       if (id < 0) {
-               BT_LOGW("Invalid parameter: invalid event class's ID: "
-                       "addr=%p, name=\"%s\", id=%" PRIu64,
-                       event_class, bt_event_class_get_name(event_class),
-                       id_param);
-               ret = -1;
-               goto end;
-       }
-
-       event_class->id = id;
-       BT_LOGV("Set event class's ID: "
-               "addr=%p, name=\"%s\", id=%" PRId64,
-               event_class, bt_event_class_get_name(event_class), id);
-
-end:
+       ret = -1;
        return ret;
 }
 
-enum bt_event_class_log_level bt_event_class_get_log_level(
-               struct bt_event_class *event_class)
-{
-       BT_ASSERT_PRE_NON_NULL(event_class, "Event class");
-       return event_class->log_level;
-}
-
-int bt_event_class_set_log_level(struct bt_event_class *event_class,
-               enum bt_event_class_log_level log_level)
+static
+void bt_event_class_destroy(struct bt_object *obj)
 {
-       int ret = 0;
-
-       if (!event_class) {
-               BT_LOGW_STR("Invalid parameter: event class is NULL.");
-               ret = -1;
-               goto end;
-       }
-
-       if (event_class->frozen) {
-               BT_LOGW("Invalid parameter: event class is frozen: "
-                       "addr=%p, name=\"%s\", id=%" PRId64,
-                       event_class, bt_event_class_get_name(event_class),
-                       bt_event_class_get_id(event_class));
-               ret = -1;
-               goto end;
-       }
-
-       switch (log_level) {
-       case BT_EVENT_CLASS_LOG_LEVEL_UNSPECIFIED:
-       case BT_EVENT_CLASS_LOG_LEVEL_EMERGENCY:
-       case BT_EVENT_CLASS_LOG_LEVEL_ALERT:
-       case BT_EVENT_CLASS_LOG_LEVEL_CRITICAL:
-       case BT_EVENT_CLASS_LOG_LEVEL_ERROR:
-       case BT_EVENT_CLASS_LOG_LEVEL_WARNING:
-       case BT_EVENT_CLASS_LOG_LEVEL_NOTICE:
-       case BT_EVENT_CLASS_LOG_LEVEL_INFO:
-       case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_SYSTEM:
-       case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROGRAM:
-       case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROCESS:
-       case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_MODULE:
-       case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_UNIT:
-       case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_FUNCTION:
-       case BT_EVENT_CLASS_LOG_LEVEL_DEBUG_LINE:
-       case BT_EVENT_CLASS_LOG_LEVEL_DEBUG:
-               break;
-       default:
-               BT_LOGW("Invalid parameter: unknown event class log level: "
-                       "addr=%p, name=\"%s\", id=%" PRId64 ", log-level=%d",
-                       event_class, bt_event_class_get_name(event_class),
-                       bt_event_class_get_id(event_class), log_level);
-               ret = -1;
-               goto end;
-       }
-
-       event_class->log_level = log_level;
-       BT_LOGV("Set event class's log level: "
-               "addr=%p, name=\"%s\", id=%" PRId64 ", log-level=%s",
-               event_class, bt_event_class_get_name(event_class),
-               bt_event_class_get_id(event_class),
-               bt_event_class_log_level_string(log_level));
-
-end:
-       return ret;
+       BT_LOGD("Destroying event class: addr=%p", obj);
+       bt_event_class_common_finalize(obj);
+       g_free(obj);
 }
 
-const char *bt_event_class_get_emf_uri(
-               struct bt_event_class *event_class)
+struct bt_event_class *bt_event_class_create(const char *name)
 {
-       const char *emf_uri = NULL;
-
-       BT_ASSERT_PRE_NON_NULL(event_class, "Event class");
+       int ret;
+       struct bt_event_class *event_class = NULL;
 
-       if (event_class->emf_uri->len > 0) {
-               emf_uri = event_class->emf_uri->str;
+       if (!name) {
+               BT_LOGW_STR("Invalid parameter: name is NULL.");
+               goto error;
        }
 
-       return emf_uri;
-}
-
-int bt_event_class_set_emf_uri(struct bt_event_class *event_class,
-               const char *emf_uri)
-{
-       int ret = 0;
-
+       BT_LOGD("Creating event class object: name=\"%s\"",
+               name);
+       event_class = g_new0(struct bt_event_class, 1);
        if (!event_class) {
-               BT_LOGW_STR("Invalid parameter: event class is NULL.");
-               ret = -1;
-               goto end;
+               BT_LOGE_STR("Failed to allocate one event class.");
+               goto error;
        }
 
-       if (emf_uri && strlen(emf_uri) == 0) {
-               BT_LOGW_STR("Invalid parameter: EMF URI is empty.");
-               ret = -1;
-               goto end;
+       ret = bt_event_class_common_initialize(BT_TO_COMMON(event_class),
+               name, bt_event_class_destroy,
+               (bt_field_type_structure_create_func)
+                       bt_field_type_structure_create);
+       if (ret) {
+               goto error;
        }
 
-       if (event_class->frozen) {
-               BT_LOGW("Invalid parameter: event class is frozen: "
-                       "addr=%p, name=\"%s\", id=%" PRId64,
-                       event_class, bt_event_class_get_name(event_class),
-                       bt_event_class_get_id(event_class));
-               ret = -1;
-               goto end;
-       }
+       BT_LOGD("Created event class object: addr=%p, name=\"%s\"",
+               event_class, bt_event_class_get_name(event_class));
+       goto end;
 
-       if (emf_uri) {
-               g_string_assign(event_class->emf_uri, emf_uri);
-               BT_LOGV("Set event class's EMF URI: "
-                       "addr=%p, name=\"%s\", id=%" PRId64 ", emf-uri=\"%s\"",
-                       event_class, bt_event_class_get_name(event_class),
-                       bt_event_class_get_id(event_class), emf_uri);
-       } else {
-               g_string_assign(event_class->emf_uri, "");
-               BT_LOGV("Reset event class's EMF URI: "
-                       "addr=%p, name=\"%s\", id=%" PRId64,
-                       event_class, bt_event_class_get_name(event_class),
-                       bt_event_class_get_id(event_class));
-       }
+error:
+       bt_put(event_class);
 
 end:
-       return ret;
+       return event_class;
 }
 
-struct bt_stream_class *bt_event_class_get_stream_class(
-               struct bt_event_class *event_class)
+const char *bt_event_class_get_name(struct bt_event_class *event_class)
 {
-       BT_ASSERT_PRE_NON_NULL(event_class, "Event class");
-       return bt_get(bt_event_class_borrow_stream_class(event_class));
+       return bt_event_class_common_get_name(BT_TO_COMMON(event_class));
 }
 
-struct bt_field_type *bt_event_class_get_payload_type(
-               struct bt_event_class *event_class)
+int64_t bt_event_class_get_id(struct bt_event_class *event_class)
 {
-       BT_ASSERT_PRE_NON_NULL(event_class, "Event class");
-       return bt_get(event_class->fields);
+       return bt_event_class_common_get_id(BT_TO_COMMON(event_class));
 }
 
-int bt_event_class_set_payload_type(struct bt_event_class *event_class,
-               struct bt_field_type *payload)
+int bt_event_class_set_id(struct bt_event_class *event_class, uint64_t id)
 {
-       int ret = 0;
-
-       if (!event_class) {
-               BT_LOGW_STR("Invalid parameter: event class is NULL.");
-               ret = -1;
-               goto end;
-       }
-
-       if (payload && bt_field_type_get_type_id(payload) !=
-                       BT_FIELD_TYPE_ID_STRUCT) {
-               BT_LOGW("Invalid parameter: event class's payload field type must be a structure: "
-                       "addr=%p, name=\"%s\", id=%" PRId64 ", "
-                       "payload-ft-addr=%p, payload-ft-id=%s",
-                       event_class, bt_event_class_get_name(event_class),
-                       bt_event_class_get_id(event_class), payload,
-                       bt_field_type_id_string(
-                               bt_field_type_get_type_id(payload)));
-               ret = -1;
-               goto end;
-       }
-
-       bt_put(event_class->fields);
-       event_class->fields = bt_get(payload);
-       BT_LOGV("Set event class's payload field type: "
-               "event-class-addr=%p, event-class-name=\"%s\", "
-               "event-class-id=%" PRId64 ", payload-ft-addr=%p",
-               event_class, bt_event_class_get_name(event_class),
-               bt_event_class_get_id(event_class), payload);
-end:
-       return ret;
+       return bt_event_class_common_set_id(BT_TO_COMMON(event_class), id);
 }
 
-int bt_event_class_add_field(struct bt_event_class *event_class,
-               struct bt_field_type *type,
-               const char *name)
+enum bt_event_class_log_level bt_event_class_get_log_level(
+               struct bt_event_class *event_class)
 {
-       int ret = 0;
-
-       if (!event_class || !type) {
-               BT_LOGW("Invalid parameter: event class or field type is NULL: "
-                       "event-class-addr=%p, field-type-addr=%p",
-                       event_class, type);
-               ret = -1;
-               goto end;
-       }
-
-       if (!bt_identifier_is_valid(name)) {
-               BT_LOGW("Invalid parameter: event class's payload field type's field name is not a valid CTF identifier: "
-                       "addr=%p, name=\"%s\", id=%" PRId64 ", field-name=\"%s\"",
-                       event_class, bt_event_class_get_name(event_class),
-                       bt_event_class_get_id(event_class),
-                       name);
-               ret = -1;
-               goto end;
-       }
-
-       if (event_class->frozen) {
-               BT_LOGW("Invalid parameter: event class is frozen: "
-                       "addr=%p, name=\"%s\", id=%" PRId64,
-                       event_class, bt_event_class_get_name(event_class),
-                       bt_event_class_get_id(event_class));
-               ret = -1;
-               goto end;
-       }
-
-       if (!event_class->fields) {
-               BT_LOGW("Event class has no payload field type: "
-                       "addr=%p, name=\"%s\", id=%" PRId64,
-                       event_class, bt_event_class_get_name(event_class),
-                       bt_event_class_get_id(event_class));
-               ret = -1;
-               goto end;
-       }
-
-       BT_ASSERT(bt_field_type_get_type_id(event_class->fields) ==
-               BT_FIELD_TYPE_ID_STRUCT);
-       ret = bt_field_type_structure_add_field(event_class->fields,
-               type, name);
-       BT_LOGV("Added field to event class's payload field type: "
-               "event-class-addr=%p, event-class-name=\"%s\", "
-               "event-class-id=%" PRId64 ", field-name=\"%s\", ft-addr=%p",
-               event_class, bt_event_class_get_name(event_class),
-               bt_event_class_get_id(event_class), name, type);
-end:
-       return ret;
+       return bt_event_class_common_get_log_level(BT_TO_COMMON(event_class));
 }
 
-int64_t bt_event_class_get_payload_type_field_count(
-               struct bt_event_class *event_class)
+int bt_event_class_set_log_level(struct bt_event_class *event_class,
+               enum bt_event_class_log_level log_level)
 {
-       int64_t ret;
-
-       if (!event_class) {
-               BT_LOGW_STR("Invalid parameter: event class is NULL.");
-               ret = (int64_t) -1;
-               goto end;
-       }
-
-       if (!event_class->fields) {
-               BT_LOGV("Event class has no payload field type: "
-                       "addr=%p, name=\"%s\", id=%" PRId64,
-                       event_class, bt_event_class_get_name(event_class),
-                       bt_event_class_get_id(event_class));
-               ret = (int64_t) -1;
-               goto end;
-       }
-
-       BT_ASSERT(bt_field_type_get_type_id(event_class->fields) ==
-               BT_FIELD_TYPE_ID_STRUCT);
-       ret = bt_field_type_structure_get_field_count(event_class->fields);
-end:
-       return ret;
+       return bt_event_class_common_set_log_level(BT_TO_COMMON(event_class),
+               log_level);
 }
 
-int bt_event_class_get_payload_type_field_by_index(
-               struct bt_event_class *event_class,
-               const char **field_name, struct bt_field_type **field_type,
-               uint64_t index)
+const char *bt_event_class_get_emf_uri(struct bt_event_class *event_class)
 {
-       int ret;
-
-       if (!event_class) {
-               BT_LOGW_STR("Invalid parameter: event class is NULL.");
-               ret = -1;
-               goto end;
-       }
-
-       if (!event_class->fields) {
-               BT_LOGV("Event class has no payload field type: "
-                       "addr=%p, name=\"%s\", id=%" PRId64 ", index=%" PRIu64,
-                       event_class, bt_event_class_get_name(event_class),
-                       bt_event_class_get_id(event_class), index);
-               ret = -1;
-               goto end;
-       }
-
-       BT_ASSERT(bt_field_type_get_type_id(event_class->fields) ==
-               BT_FIELD_TYPE_ID_STRUCT);
-       ret = bt_field_type_structure_get_field_by_index(event_class->fields,
-               field_name, field_type, index);
-end:
-       return ret;
+       return bt_event_class_common_get_emf_uri(BT_TO_COMMON(event_class));
 }
 
-struct bt_field_type *
-bt_event_class_get_payload_type_field_type_by_name(
-               struct bt_event_class *event_class, const char *name)
+int bt_event_class_set_emf_uri(struct bt_event_class *event_class,
+               const char *emf_uri)
 {
-       GQuark name_quark;
-       struct bt_field_type *field_type = NULL;
-
-       if (!event_class || !name) {
-               BT_LOGW("Invalid parameter: event class or name is NULL: "
-                       "event-class-addr=%p, name-addr=%p",
-                       event_class, name);
-               goto end;
-       }
-
-       if (!event_class->fields) {
-               BT_LOGV("Event class has no payload field type: "
-                       "addr=%p, name=\"%s\", id=%" PRId64,
-                       event_class, bt_event_class_get_name(event_class),
-                       bt_event_class_get_id(event_class));
-               goto end;
-       }
-
-       BT_ASSERT(bt_field_type_get_type_id(event_class->fields) ==
-               BT_FIELD_TYPE_ID_STRUCT);
-       name_quark = g_quark_try_string(name);
-       if (!name_quark) {
-               BT_LOGE("Cannot get GQuark: string=\"%s\"", name);
-               goto end;
-       }
-
-       /*
-        * No need to increment field_type's reference count since getting it
-        * from the structure already does.
-        */
-       field_type = bt_field_type_structure_get_field_type_by_name(
-               event_class->fields, name);
-end:
-       return field_type;
+       return bt_event_class_common_set_emf_uri(BT_TO_COMMON(event_class),
+               emf_uri);
 }
 
-struct bt_field_type *bt_event_class_get_context_type(
+struct bt_stream_class *bt_event_class_get_stream_class(
                struct bt_event_class *event_class)
 {
-       struct bt_field_type *context_type = NULL;
-
        BT_ASSERT_PRE_NON_NULL(event_class, "Event class");
-
-       if (!event_class->context) {
-               BT_LOGV("Event class has no context field type: "
-                       "addr=%p, name=\"%s\", id=%" PRId64,
-                       event_class, bt_event_class_get_name(event_class),
-                       bt_event_class_get_id(event_class));
-               goto end;
-       }
-
-       context_type = bt_get(event_class->context);
-
-end:
-       return context_type;
+       return bt_get(bt_event_class_borrow_stream_class(event_class));
 }
 
-int bt_event_class_set_context_type(
-               struct bt_event_class *event_class,
-               struct bt_field_type *context)
+struct bt_field_type *bt_event_class_get_payload_field_type(
+               struct bt_event_class *event_class)
 {
-       int ret = 0;
-
-       if (!event_class) {
-               BT_LOGW_STR("Invalid parameter: event class is NULL.");
-               ret = -1;
-               goto end;
-       }
-
-       if (event_class->frozen) {
-               BT_LOGW("Invalid parameter: event class is frozen: "
-                       "addr=%p, name=\"%s\", id=%" PRId64,
-                       event_class, bt_event_class_get_name(event_class),
-                       bt_event_class_get_id(event_class));
-               ret = -1;
-               goto end;
-       }
-
-       if (context && bt_field_type_get_type_id(context) !=
-                       BT_FIELD_TYPE_ID_STRUCT) {
-               BT_LOGW("Invalid parameter: event class's context field type must be a structure: "
-                       "addr=%p, name=\"%s\", id=%" PRId64 ", "
-                       "context-ft-id=%s",
-                       event_class, bt_event_class_get_name(event_class),
-                       bt_event_class_get_id(event_class),
-                       bt_field_type_id_string(
-                               bt_field_type_get_type_id(context)));
-               ret = -1;
-               goto end;
-       }
-
-       bt_put(event_class->context);
-       event_class->context = bt_get(context);
-       BT_LOGV("Set event class's context field type: "
-               "event-class-addr=%p, event-class-name=\"%s\", "
-               "event-class-id=%" PRId64 ", context-ft-addr=%p",
-               event_class, bt_event_class_get_name(event_class),
-               bt_event_class_get_id(event_class), context);
-end:
-       return ret;
-
+       return BT_FROM_COMMON(bt_event_class_common_get_payload_field_type(
+               BT_TO_COMMON(event_class)));
 }
 
-/* Pre-2.0 CTF writer backward compatibility */
-void bt_ctf_event_class_get(struct bt_event_class *event_class)
+int bt_event_class_set_payload_field_type(struct bt_event_class *event_class,
+               struct bt_field_type *field_type)
 {
-       bt_get(event_class);
+       return bt_event_class_common_set_payload_field_type(
+               BT_TO_COMMON(event_class), (void *) field_type);
 }
 
-/* Pre-2.0 CTF writer backward compatibility */
-void bt_ctf_event_class_put(struct bt_event_class *event_class)
+struct bt_field_type *bt_event_class_get_context_field_type(
+               struct bt_event_class *event_class)
 {
-       bt_put(event_class);
+       return BT_FROM_COMMON(bt_event_class_common_get_context_field_type(
+               BT_TO_COMMON(event_class)));
 }
 
-static
-void bt_event_class_destroy(struct bt_object *obj)
+int bt_event_class_set_context_field_type(
+               struct bt_event_class *event_class,
+               struct bt_field_type *field_type)
 {
-       struct bt_event_class *event_class;
-
-       event_class = container_of(obj, struct bt_event_class, base);
-       BT_LOGD("Destroying event class: addr=%p, name=\"%s\", id=%" PRId64,
-               event_class, bt_event_class_get_name(event_class),
-               bt_event_class_get_id(event_class));
-       g_string_free(event_class->name, TRUE);
-       g_string_free(event_class->emf_uri, TRUE);
-       BT_LOGD_STR("Putting context field type.");
-       bt_put(event_class->context);
-       BT_LOGD_STR("Putting payload field type.");
-       bt_put(event_class->fields);
-       g_free(event_class);
+       return bt_event_class_common_set_context_field_type(
+               BT_TO_COMMON(event_class), (void *) field_type);
 }
 
 BT_HIDDEN
-void bt_event_class_freeze(struct bt_event_class *event_class)
+void bt_event_class_common_freeze(struct bt_event_class_common *event_class)
 {
        BT_ASSERT(event_class);
 
@@ -587,97 +244,26 @@ void bt_event_class_freeze(struct bt_event_class *event_class)
        }
 
        BT_LOGD("Freezing event class: addr=%p, name=\"%s\", id=%" PRId64,
-               event_class, bt_event_class_get_name(event_class),
-               bt_event_class_get_id(event_class));
+               event_class, bt_event_class_common_get_name(event_class),
+               bt_event_class_common_get_id(event_class));
        event_class->frozen = 1;
        BT_LOGD_STR("Freezing event class's context field type.");
-       bt_field_type_freeze(event_class->context);
+       bt_field_type_common_freeze(event_class->context_field_type);
        BT_LOGD_STR("Freezing event class's payload field type.");
-       bt_field_type_freeze(event_class->fields);
-}
-
-BT_HIDDEN
-int bt_event_class_serialize(struct bt_event_class *event_class,
-               struct metadata_context *context)
-{
-       int ret = 0;
-       struct bt_value *attr_value = NULL;
-
-       BT_ASSERT(event_class);
-       BT_ASSERT(context);
-       BT_LOGD("Serializing event class's metadata: "
-               "event-class-addr=%p, event-class-name=\"%s\", "
-               "event-class-id=%" PRId64 ", metadata-context-addr=%p",
-               event_class, bt_event_class_get_name(event_class),
-               bt_event_class_get_id(event_class), context);
-       context->current_indentation_level = 1;
-       g_string_assign(context->field_name, "");
-       g_string_append(context->string, "event {\n");
-
-       /* Serialize attributes */
-       g_string_append_printf(context->string, "\tname = \"%s\";\n",
-               event_class->name->str);
-       BT_ASSERT(event_class->id >= 0);
-       g_string_append_printf(context->string, "\tid = %" PRId64 ";\n",
-               event_class->id);
-       g_string_append_printf(context->string, "\tstream_id = %" PRId64 ";\n",
-               bt_stream_class_get_id(
-                       bt_event_class_borrow_stream_class(event_class)));
-
-       if (event_class->log_level != BT_EVENT_CLASS_LOG_LEVEL_UNSPECIFIED) {
-               g_string_append_printf(context->string, "\tloglevel = %d;\n",
-                       (int) event_class->log_level);
-       }
-
-       if (event_class->emf_uri->len > 0) {
-               g_string_append_printf(context->string, "\tmodel.emf.uri = \"%s\";\n",
-                       event_class->emf_uri->str);
-       }
-
-       /* Serialize context field type */
-       if (event_class->context) {
-               g_string_append(context->string, "\tcontext := ");
-               BT_LOGD_STR("Serializing event class's context field type metadata.");
-               ret = bt_field_type_serialize(event_class->context,
-                       context);
-               if (ret) {
-                       BT_LOGW("Cannot serialize event class's context field type's metadata: "
-                               "ret=%d", ret);
-                       goto end;
-               }
-               g_string_append(context->string, ";\n");
-       }
-
-       /* Serialize payload field type */
-       if (event_class->fields) {
-               g_string_append(context->string, "\tfields := ");
-               BT_LOGD_STR("Serializing event class's payload field type metadata.");
-               ret = bt_field_type_serialize(event_class->fields, context);
-               if (ret) {
-                       BT_LOGW("Cannot serialize event class's payload field type's metadata: "
-                               "ret=%d", ret);
-                       goto end;
-               }
-               g_string_append(context->string, ";\n");
-       }
-
-       g_string_append(context->string, "};\n\n");
-end:
-       context->current_indentation_level = 0;
-       BT_PUT(attr_value);
-       return ret;
+       bt_field_type_common_freeze(event_class->payload_field_type);
 }
 
 BT_HIDDEN
-int bt_event_class_validate_single_clock_class(
-               struct bt_event_class *event_class,
+int bt_event_class_common_validate_single_clock_class(
+               struct bt_event_class_common *event_class,
                struct bt_clock_class **expected_clock_class)
 {
        int ret = 0;
 
        BT_ASSERT(event_class);
        BT_ASSERT(expected_clock_class);
-       ret = bt_validate_single_clock_class(event_class->context,
+       ret = bt_field_type_common_validate_single_clock_class(
+               event_class->context_field_type,
                expected_clock_class);
        if (ret) {
                BT_LOGW("Event class's context field type "
@@ -688,13 +274,14 @@ int bt_event_class_validate_single_clock_class(
                        "event-class-id=%" PRId64 ", "
                        "ft-addr=%p",
                        event_class,
-                       bt_event_class_get_name(event_class),
+                       bt_event_class_common_get_name(event_class),
                        event_class->id,
-                       event_class->context);
+                       event_class->context_field_type);
                goto end;
        }
 
-       ret = bt_validate_single_clock_class(event_class->fields,
+       ret = bt_field_type_common_validate_single_clock_class(
+               event_class->payload_field_type,
                expected_clock_class);
        if (ret) {
                BT_LOGW("Event class's payload field type "
@@ -705,9 +292,9 @@ int bt_event_class_validate_single_clock_class(
                        "event-class-id=%" PRId64 ", "
                        "ft-addr=%p",
                        event_class,
-                       bt_event_class_get_name(event_class),
+                       bt_event_class_common_get_name(event_class),
                        event_class->id,
-                       event_class->fields);
+                       event_class->payload_field_type);
                goto end;
        }
 
index 2fa1e953b19c12b21c736cb6c7fde3f5c51daf59..a026cac998a5b8e8328f59d75ce7242892e13a86 100644 (file)
@@ -29,6 +29,7 @@
 #define BT_LOG_TAG "EVENT"
 #include <babeltrace/lib-logging-internal.h>
 
+#include <babeltrace/assert-pre-internal.h>
 #include <babeltrace/ctf-ir/fields-internal.h>
 #include <babeltrace/ctf-ir/field-types-internal.h>
 #include <babeltrace/ctf-ir/clock-class.h>
 #include <babeltrace/ctf-ir/stream-internal.h>
 #include <babeltrace/ctf-ir/packet.h>
 #include <babeltrace/ctf-ir/packet-internal.h>
+#include <babeltrace/ctf-ir/trace.h>
 #include <babeltrace/ctf-ir/trace-internal.h>
 #include <babeltrace/ctf-ir/validation-internal.h>
 #include <babeltrace/ctf-ir/packet-internal.h>
 #include <babeltrace/ctf-ir/utils.h>
-#include <babeltrace/ctf-writer/serialize-internal.h>
-#include <babeltrace/ctf-writer/clock-internal.h>
 #include <babeltrace/ref.h>
 #include <babeltrace/ctf-ir/attributes-internal.h>
 #include <babeltrace/compiler-internal.h>
 #include <babeltrace/assert-internal.h>
-#include <babeltrace/assert-pre-internal.h>
 #include <inttypes.h>
 
-#define BT_ASSERT_PRE_EVENT_HOT(_event, _name)                         \
-       BT_ASSERT_PRE_HOT((_event), (_name), ": +%!+e", (_event))
-
 static
 void bt_event_destroy(struct bt_object *obj);
 
-struct bt_event *bt_event_create(struct bt_event_class *event_class)
+static
+int bt_event_common_validate_types_for_create(
+               struct bt_event_class_common *event_class,
+               struct bt_validation_output *validation_output,
+               bt_validation_flag_copy_field_type_func copy_field_type_func)
 {
        int ret;
        enum bt_validation_flag validation_flags =
                BT_VALIDATION_FLAG_STREAM |
                BT_VALIDATION_FLAG_EVENT;
-       struct bt_event *event = NULL;
-       struct bt_trace *trace = NULL;
-       struct bt_stream_class *stream_class = NULL;
-       struct bt_field_type *packet_header_type = NULL;
-       struct bt_field_type *packet_context_type = NULL;
-       struct bt_field_type *event_header_type = NULL;
-       struct bt_field_type *stream_event_ctx_type = NULL;
-       struct bt_field_type *event_context_type = NULL;
-       struct bt_field_type *event_payload_type = NULL;
-       struct bt_field *event_header = NULL;
-       struct bt_field *stream_event_context = NULL;
-       struct bt_field *event_context = NULL;
-       struct bt_field *event_payload = NULL;
-       struct bt_value *environment = NULL;
-       struct bt_validation_output validation_output = { 0 };
+       struct bt_trace_common *trace = NULL;
+       struct bt_stream_class_common *stream_class = NULL;
+       struct bt_field_type_common *packet_header_type = NULL;
+       struct bt_field_type_common *packet_context_type = NULL;
+       struct bt_field_type_common *event_header_type = NULL;
+       struct bt_field_type_common *stream_event_ctx_type = NULL;
+       struct bt_field_type_common *event_context_type = NULL;
+       struct bt_field_type_common *event_payload_type = NULL;
        int trace_valid = 0;
-       struct bt_clock_class *expected_clock_class = NULL;
-
-       BT_ASSERT_PRE_NON_NULL(event_class, "Event class");
-       BT_LOGD("Creating event object: event-class-addr=%p, "
-               "event-class-name=\"%s\", event-class-id=%" PRId64,
-               event_class, bt_event_class_get_name(event_class),
-               bt_event_class_get_id(event_class));
-
-       stream_class = bt_event_class_get_stream_class(event_class);
-       BT_ASSERT_PRE(stream_class,
-               "Event class is not part of a stream class: %!+E", event_class);
-
-       /* The event class was frozen when added to its stream class */
-       BT_ASSERT(event_class->frozen);
-
-       if (!stream_class->frozen) {
-               if (stream_class->clock) {
-                       expected_clock_class =
-                               bt_get(stream_class->clock->clock_class);
-               }
-
-               /*
-                * Because this function freezes the stream class,
-                * validate that this stream class contains at most a
-                * single clock class so that we set its expected clock
-                * class for future checks.
-                */
-               ret = bt_stream_class_validate_single_clock_class(
-                       stream_class, &expected_clock_class);
-               if (ret) {
-                       BT_LOGW("Event class's stream class or one of its event "
-                               "classes contains a field type which is not "
-                               "recursively mapped to the expected "
-                               "clock class: "
-                               "stream-class-addr=%p, "
-                               "stream-class-id=%" PRId64 ", "
-                               "stream-class-name=\"%s\", "
-                               "expected-clock-class-addr=%p, "
-                               "expected-clock-class-name=\"%s\"",
-                               stream_class, bt_stream_class_get_id(stream_class),
-                               bt_stream_class_get_name(stream_class),
-                               expected_clock_class,
-                               expected_clock_class ?
-                                       bt_clock_class_get_name(expected_clock_class) :
-                                       NULL);
-                       goto error;
-               }
-       }
+       struct bt_value *environment = NULL;
 
-       /* Validate the trace (if any), the stream class, and the event class */
-       trace = bt_stream_class_get_trace(stream_class);
+       stream_class = bt_event_class_common_borrow_stream_class(event_class);
+       BT_ASSERT(stream_class);
+       trace = bt_stream_class_common_borrow_trace(stream_class);
        if (trace) {
-               BT_LOGD_STR("Event's class is part of a trace.");
-               packet_header_type = bt_trace_get_packet_header_type(trace);
+               BT_LOGD_STR("Event class is part of a trace.");
+               packet_header_type = bt_trace_common_get_packet_header_field_type(trace);
                trace_valid = trace->valid;
                BT_ASSERT(trace_valid);
                environment = trace->environment;
        }
 
-       packet_context_type = bt_stream_class_get_packet_context_type(
+       packet_context_type = bt_stream_class_common_get_packet_context_field_type(
                stream_class);
-       event_header_type = bt_stream_class_get_event_header_type(
+       event_header_type = bt_stream_class_common_get_event_header_field_type(
                stream_class);
-       stream_event_ctx_type = bt_stream_class_get_event_context_type(
+       stream_event_ctx_type = bt_stream_class_common_get_event_context_field_type(
                stream_class);
-       event_context_type = bt_event_class_get_context_type(event_class);
-       event_payload_type = bt_event_class_get_payload_type(event_class);
+       event_context_type = bt_event_class_common_get_context_field_type(event_class);
+       event_payload_type = bt_event_class_common_get_payload_field_type(event_class);
        ret = bt_validate_class_types(environment, packet_header_type,
                packet_context_type, event_header_type, stream_event_ctx_type,
                event_context_type, event_payload_type, trace_valid,
                stream_class->valid, event_class->valid,
-               &validation_output, validation_flags);
+               validation_output, validation_flags, copy_field_type_func);
        BT_PUT(packet_header_type);
        BT_PUT(packet_context_type);
        BT_PUT(event_header_type);
@@ -171,108 +118,314 @@ struct bt_event *bt_event_create(struct bt_event_class *event_class)
                goto error;
        }
 
-       if ((validation_output.valid_flags & validation_flags) !=
+       if ((validation_output->valid_flags & validation_flags) !=
                        validation_flags) {
                /* Invalid trace/stream class/event class */
                BT_LOGW("Invalid trace, stream class, or event class: "
-                       "valid-flags=0x%x", validation_output.valid_flags);
+                       "valid-flags=0x%x", validation_output->valid_flags);
                goto error;
        }
 
-       /*
-        * Safe to automatically map selected fields to the stream's
-        * clock's class here because the stream class is about to be
-        * frozen.
-        */
-       if (bt_stream_class_map_clock_class(stream_class,
-                       validation_output.packet_context_type,
-                       validation_output.event_header_type)) {
-               BT_LOGW_STR("Cannot automatically map selected stream class's "
-                       "field types to stream class's clock's class.");
-               goto error;
-       }
+       goto end;
 
-       /*
-        * At this point we know the trace (if associated to the stream
-        * class), the stream class, and the event class, with their
-        * current types, are valid. We may proceed with creating
-        * the event.
-        */
-       event = g_new0(struct bt_event, 1);
-       if (!event) {
-               BT_LOGE_STR("Failed to allocate one event.");
-               goto error;
-       }
+error:
+       bt_validation_output_put_types(validation_output);
+       ret = -1;
 
-       bt_object_init(event, bt_event_destroy);
+end:
+       BT_ASSERT(!packet_header_type);
+       BT_ASSERT(!packet_context_type);
+       BT_ASSERT(!event_header_type);
+       BT_ASSERT(!stream_event_ctx_type);
+       BT_ASSERT(!event_context_type);
+       BT_ASSERT(!event_payload_type);
+       return ret;
+}
 
-       /*
-        * event does not share a common ancestor with the event class; it has
-        * to guarantee its existence by holding a reference. This reference
-        * shall be released once the event is associated to a stream since,
-        * from that point, the event and its class will share the same
-        * lifetime.
-        */
-       event->event_class = bt_get(event_class);
-       event->clock_values = g_hash_table_new_full(g_direct_hash,
-                       g_direct_equal, bt_put, bt_put);
+static
+int bt_event_common_create_fields(
+               struct bt_validation_output *validation_output,
+               void *(*create_field_func)(void *),
+               struct bt_field_common **header_field,
+               struct bt_field_common **stream_event_context_field,
+               struct bt_field_common **context_field,
+               struct bt_field_common **payload_field)
+{
+       int ret = 0;
 
-       if (validation_output.event_header_type) {
+       if (validation_output->event_header_type) {
                BT_LOGD("Creating initial event header field: ft-addr=%p",
-                       validation_output.event_header_type);
-               event_header =
-                       bt_field_create(validation_output.event_header_type);
-               if (!event_header) {
+                       validation_output->event_header_type);
+               *header_field =
+                       create_field_func(validation_output->event_header_type);
+               if (!*header_field) {
                        BT_LOGE_STR("Cannot create initial event header field object.");
                        goto error;
                }
        }
 
-       if (validation_output.stream_event_ctx_type) {
+       if (validation_output->stream_event_ctx_type) {
                BT_LOGD("Creating initial stream event context field: ft-addr=%p",
-                       validation_output.stream_event_ctx_type);
-               stream_event_context = bt_field_create(
-                       validation_output.stream_event_ctx_type);
-               if (!stream_event_context) {
+                       validation_output->stream_event_ctx_type);
+               *stream_event_context_field = create_field_func(
+                       validation_output->stream_event_ctx_type);
+               if (!*stream_event_context_field) {
                        BT_LOGE_STR("Cannot create initial stream event context field object.");
                        goto error;
                }
        }
 
-       if (validation_output.event_context_type) {
+       if (validation_output->event_context_type) {
                BT_LOGD("Creating initial event context field: ft-addr=%p",
-                       validation_output.event_context_type);
-               event_context = bt_field_create(
-                       validation_output.event_context_type);
-               if (!event_context) {
+                       validation_output->event_context_type);
+               *context_field = create_field_func(
+                       validation_output->event_context_type);
+               if (!*context_field) {
                        BT_LOGE_STR("Cannot create initial event context field object.");
                        goto error;
                }
        }
 
-       if (validation_output.event_payload_type) {
+       if (validation_output->event_payload_type) {
                BT_LOGD("Creating initial event payload field: ft-addr=%p",
-                       validation_output.event_payload_type);
-               event_payload = bt_field_create(
-                       validation_output.event_payload_type);
-               if (!event_payload) {
+                       validation_output->event_payload_type);
+               *payload_field = create_field_func(
+                       validation_output->event_payload_type);
+               if (!*payload_field) {
                        BT_LOGE_STR("Cannot create initial event payload field object.");
                        goto error;
                }
        }
 
+       goto end;
+
+error:
+       BT_PUT(*header_field);
+       BT_PUT(*stream_event_context_field);
+       BT_PUT(*context_field);
+       BT_PUT(*payload_field);
+       ret = -1;
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+int _bt_event_common_validate(struct bt_event_common *event)
+{
+       int ret = 0;
+       struct bt_stream_class_common *stream_class;
+
+       BT_ASSERT(event);
+       if (event->header_field) {
+               ret = bt_field_common_validate_recursive(event->header_field);
+               if (ret) {
+                       BT_ASSERT_PRE_MSG("Invalid event's header field: "
+                               "%![event-]+_e, %![field-]+_f",
+                               event, event->header_field);
+                       goto end;
+               }
+       }
+
+       stream_class = bt_event_class_common_borrow_stream_class(event->class);
+
+       /*
+        * We should not have been able to create the event without associating
+        * the event class to a stream class.
+        */
+       BT_ASSERT(stream_class);
+
+       if (stream_class->event_context_field_type) {
+               ret = bt_field_common_validate_recursive(
+                       event->stream_event_context_field);
+               if (ret) {
+                       BT_ASSERT_PRE_MSG("Invalid event's stream event context field: "
+                               "%![event-]+_e, %![field-]+_f",
+                               event, event->stream_event_context_field);
+                       goto end;
+               }
+       }
+
+       if (event->class->context_field_type) {
+               ret = bt_field_common_validate_recursive(event->context_field);
+               if (ret) {
+                       BT_ASSERT_PRE_MSG("Invalid event's payload field: "
+                               "%![event-]+_e, %![field-]+_f",
+                               event, event->context_field);
+                       goto end;
+               }
+       }
+
+       ret = bt_field_common_validate_recursive(event->payload_field);
+       if (ret) {
+               BT_ASSERT_PRE_MSG("Invalid event's payload field: "
+                       "%![event-]+_e, %![field-]+_f",
+                       event, event->payload_field);
+               goto end;
+       }
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+void _bt_event_common_freeze(struct bt_event_common *event)
+{
+       BT_ASSERT(event);
+
+       if (event->frozen) {
+               return;
+       }
+
+       BT_LOGD("Freezing event: addr=%p, "
+               "event-class-name=\"%s\", event-class-id=%" PRId64,
+               event, bt_event_class_common_get_name(event->class),
+               bt_event_class_common_get_id(event->class));
+       BT_LOGD_STR("Freezing event's header field.");
+       bt_field_common_freeze_recursive(event->header_field);
+       BT_LOGD_STR("Freezing event's stream event context field.");
+       bt_field_common_freeze_recursive(event->stream_event_context_field);
+       BT_LOGD_STR("Freezing event's context field.");
+       bt_field_common_freeze_recursive(event->context_field);
+       BT_LOGD_STR("Freezing event's payload field.");
+       bt_field_common_freeze_recursive(event->payload_field);
+       event->frozen = 1;
+}
+
+BT_HIDDEN
+int bt_event_common_initialize(struct bt_event_common *event,
+               struct bt_event_class_common *event_class,
+               struct bt_clock_class *init_expected_clock_class,
+               bt_object_release_func release_func,
+               bt_validation_flag_copy_field_type_func field_type_copy_func,
+               bool must_be_in_trace,
+               int (*map_clock_classes_func)(struct bt_stream_class_common *stream_class,
+                       struct bt_field_type_common *packet_context_field_type,
+                       struct bt_field_type_common *event_header_field_type),
+               void *(*create_field_func)(void *))
+{
+       int ret;
+       struct bt_trace_common *trace = NULL;
+       struct bt_stream_class_common *stream_class = NULL;
+       struct bt_field_common *event_header = NULL;
+       struct bt_field_common *stream_event_context = NULL;
+       struct bt_field_common *event_context = NULL;
+       struct bt_field_common *event_payload = NULL;
+       struct bt_validation_output validation_output = { 0 };
+       struct bt_clock_class *expected_clock_class =
+               init_expected_clock_class ? bt_get(init_expected_clock_class) :
+               NULL;
+
+       BT_ASSERT_PRE_NON_NULL(event_class, "Event class");
+       BT_LOGD("Initializing common event object: event-class-addr=%p, "
+               "event-class-name=\"%s\", event-class-id=%" PRId64,
+               event_class, bt_event_class_common_get_name(event_class),
+               bt_event_class_common_get_id(event_class));
+
+       stream_class = bt_event_class_common_borrow_stream_class(event_class);
+       BT_ASSERT_PRE(stream_class,
+               "Event class is not part of a stream class: %!+_E", event_class);
+
+       /* The event class was frozen when added to its stream class */
+       BT_ASSERT(event_class->frozen);
+       trace = bt_stream_class_common_borrow_trace(stream_class);
+
+       if (must_be_in_trace) {
+               BT_ASSERT_PRE(trace,
+                       "Event class's stream class is not part of a trace: "
+                       "%![ec-]+_E, %![ec-]+_S", event_class, stream_class);
+       }
+
+       /*
+        * This must be called before anything that can fail because on
+        * failure, the caller releases the reference to `event` to
+        * destroy it.
+        */
+       bt_object_init(event, release_func);
+
+       if (!stream_class->frozen) {
+               /*
+                * Because this function freezes the stream class,
+                * validate that this stream class contains at most a
+                * single clock class so that we set its expected clock
+                * class for future checks.
+                */
+               ret = bt_stream_class_common_validate_single_clock_class(
+                       stream_class, &expected_clock_class);
+               if (ret) {
+                       BT_LOGW("Event class's stream class or one of its event "
+                               "classes contains a field type which is not "
+                               "recursively mapped to the expected "
+                               "clock class: "
+                               "stream-class-addr=%p, "
+                               "stream-class-id=%" PRId64 ", "
+                               "stream-class-name=\"%s\", "
+                               "expected-clock-class-addr=%p, "
+                               "expected-clock-class-name=\"%s\"",
+                               stream_class,
+                               bt_stream_class_common_get_id(stream_class),
+                               bt_stream_class_common_get_name(stream_class),
+                               expected_clock_class,
+                               expected_clock_class ?
+                                       bt_clock_class_get_name(expected_clock_class) :
+                                       NULL);
+                       goto error;
+               }
+       }
+
+       /* Validate the trace, the stream class, and the event class */
+       ret = bt_event_common_validate_types_for_create(
+               event_class, &validation_output, field_type_copy_func);
+       if (ret) {
+               /* bt_event_common_validate_types_for_create() logs errors */
+               goto error;
+       }
+
+       if (map_clock_classes_func) {
+               /*
+                * Safe to automatically map selected fields to the
+                * stream's clock's class here because the stream class
+                * is about to be frozen.
+                */
+               if (map_clock_classes_func(stream_class,
+                               validation_output.packet_context_type,
+                               validation_output.event_header_type)) {
+                       BT_LOGW_STR("Cannot automatically map selected stream class's "
+                               "field types to stream class's clock's class.");
+                       goto error;
+               }
+       }
+
+       /*
+        * event does not share a common ancestor with the event class; it has
+        * to guarantee its existence by holding a reference. This reference
+        * shall be released once the event is associated to a stream since,
+        * from that point, the event and its class will share the same
+        * lifetime.
+        */
+       event->class = bt_get(event_class);
+
+       ret = bt_event_common_create_fields(&validation_output,
+               create_field_func, &event_header,
+               &stream_event_context, &event_context, &event_payload);
+       if (ret) {
+               /* bt_event_common_create_fields() logs errors */
+               goto error;
+       }
+
        /*
         * At this point all the fields are created, potentially from
         * validated copies of field types, so that the field types and
         * fields can be replaced in the trace, stream class,
         * event class, and created event.
         */
-       bt_validation_replace_types(trace, stream_class,
-               event_class, &validation_output, validation_flags);
-       BT_MOVE(event->event_header, event_header);
-       BT_MOVE(event->stream_event_context, stream_event_context);
-       BT_MOVE(event->context_payload, event_context);
-       BT_MOVE(event->fields_payload, event_payload);
+       bt_validation_replace_types(trace, stream_class, event_class,
+               &validation_output,
+               BT_VALIDATION_FLAG_STREAM | BT_VALIDATION_FLAG_EVENT);
+       BT_MOVE(event->header_field, event_header);
+       BT_MOVE(event->stream_event_context_field, stream_event_context);
+       BT_MOVE(event->context_field, event_context);
+       BT_MOVE(event->payload_field, event_payload);
 
        /*
         * Put what was not moved in bt_validation_replace_types().
@@ -283,7 +436,7 @@ struct bt_event *bt_event_create(struct bt_event_class *event_class)
         * Freeze the stream class since the event header must not be changed
         * anymore.
         */
-       bt_stream_class_freeze(stream_class);
+       bt_stream_class_common_freeze(stream_class);
 
        /*
         * It is safe to set the stream class's unique clock class
@@ -301,37 +454,61 @@ struct bt_event *bt_event_create(struct bt_event_class *event_class)
        event_class->valid = 1;
 
        /* Put stuff we borrowed from the event class */
-       BT_PUT(stream_class);
-       BT_PUT(trace);
-       BT_LOGD("Created event object: addr=%p, event-class-name=\"%s\", "
+       BT_LOGD("Initialized event object: addr=%p, event-class-name=\"%s\", "
                "event-class-id=%" PRId64,
-               event, bt_event_class_get_name(event->event_class),
-               bt_event_class_get_id(event_class));
-       return event;
+               event, bt_event_class_common_get_name(event->class),
+               bt_event_class_common_get_id(event->class));
+       goto end;
 
 error:
        bt_validation_output_put_types(&validation_output);
-       BT_PUT(event);
-       BT_PUT(stream_class);
-       BT_PUT(trace);
-       BT_PUT(event_header);
-       BT_PUT(stream_event_context);
-       BT_PUT(event_context);
-       BT_PUT(event_payload);
        bt_put(expected_clock_class);
-       BT_ASSERT(!packet_header_type);
-       BT_ASSERT(!packet_context_type);
-       BT_ASSERT(!event_header_type);
-       BT_ASSERT(!stream_event_ctx_type);
-       BT_ASSERT(!event_context_type);
-       BT_ASSERT(!event_payload_type);
+       bt_put(event_header);
+       bt_put(stream_event_context);
+       bt_put(event_context);
+       bt_put(event_payload);
+       ret = -1;
+
+end:
+       return ret;
+}
+
+struct bt_event *bt_event_create(struct bt_event_class *event_class)
+{
+       int ret;
+       struct bt_event *event = NULL;
+
+       event = g_new0(struct bt_event, 1);
+       if (!event) {
+               BT_LOGE_STR("Failed to allocate one event.");
+               goto error;
+       }
+
+       ret = bt_event_common_initialize(BT_TO_COMMON(event),
+               BT_TO_COMMON(event_class), NULL, bt_event_destroy,
+               (bt_validation_flag_copy_field_type_func) bt_field_type_copy,
+               true, NULL, (void *) bt_field_create);
+       if (ret) {
+               /* bt_event_common_initialize() logs errors */
+               goto error;
+       }
+
+       event->clock_values = g_hash_table_new_full(g_direct_hash,
+                       g_direct_equal, bt_put, bt_put);
+       assert(event->clock_values);
+       goto end;
+
+error:
+       BT_PUT(event);
+
+end:
        return event;
 }
 
 struct bt_event_class *bt_event_get_class(struct bt_event *event)
 {
        BT_ASSERT_PRE_NON_NULL(event, "Event");
-       return bt_get(bt_event_borrow_event_class(event));
+       return bt_get(bt_event_common_borrow_class(BT_TO_COMMON(event)));
 }
 
 BT_HIDDEN
@@ -341,17 +518,8 @@ struct bt_stream *bt_event_borrow_stream(struct bt_event *event)
 
        BT_ASSERT(event);
 
-       /*
-        * If the event has a parent, then this is its (writer) stream.
-        * If the event has no parent, then if it has a packet, this
-        * is its (non-writer) stream.
-        */
-       if (event->base.parent) {
-               stream = (struct bt_stream *) bt_object_borrow_parent(event);
-       } else {
-               if (event->packet) {
-                       stream = event->packet->stream;
-               }
+       if (event->packet) {
+               stream = event->packet->stream;
        }
 
        return stream;
@@ -363,309 +531,57 @@ struct bt_stream *bt_event_get_stream(struct bt_event *event)
        return bt_get(bt_event_borrow_stream(event));
 }
 
-int bt_event_set_payload(struct bt_event *event, const char *name,
-               struct bt_field *payload)
-{
-       int ret = 0;
-
-       BT_ASSERT_PRE_NON_NULL(event, "Event");
-       BT_ASSERT_PRE_NON_NULL(payload, "Payload field");
-       BT_ASSERT_PRE_EVENT_HOT(event, "Event");
-
-       if (name) {
-               ret = bt_field_structure_set_field_by_name(
-                       event->fields_payload, name, payload);
-       } else {
-               BT_ASSERT_PRE(bt_field_type_compare(payload->type,
-                       event->event_class->fields) == 0,
-                       "Payload field's type is different from the "
-                       "expected field type: %![event-]+e, %![ft-]+F, "
-                       "%![expected-ft-]+F",
-                       event, payload->type, event->event_class->fields);
-
-               bt_put(event->fields_payload);
-               bt_get(payload);
-               event->fields_payload = payload;
-       }
-
-       if (ret) {
-               BT_LOGW("Failed to set event's payload field: event-addr=%p, "
-                       "event-class-name=\"%s\", event-class-id=%" PRId64 ", "
-                       "payload-field-name=\"%s\", payload-field-addr=%p",
-                       event, bt_event_class_get_name(event->event_class),
-                       bt_event_class_get_id(event->event_class),
-                       name, payload);
-       } else {
-               BT_LOGV("Set event's payload field: event-addr=%p, "
-                       "event-class-name=\"%s\", event-class-id=%" PRId64 ", "
-                       "payload-field-name=\"%s\", payload-field-addr=%p",
-                       event, bt_event_class_get_name(event->event_class),
-                       bt_event_class_get_id(event->event_class),
-                       name, payload);
-       }
-
-       return ret;
-}
-
-struct bt_field *bt_event_get_event_payload(struct bt_event *event)
-{
-       struct bt_field *payload = NULL;
-
-       BT_ASSERT_PRE_NON_NULL(event, "Event");
-
-       if (!event->fields_payload) {
-               BT_LOGV("Event has no current payload field: addr=%p, "
-                       "event-class-name=\"%s\", event-class-id=%" PRId64,
-                       event, bt_event_class_get_name(event->event_class),
-                       bt_event_class_get_id(event->event_class));
-               goto end;
-       }
-
-       payload = event->fields_payload;
-       bt_get(payload);
-
-end:
-       return payload;
-}
-
-int bt_event_set_event_payload(struct bt_event *event,
-               struct bt_field *payload)
+struct bt_field *bt_event_get_payload(struct bt_event *event)
 {
-       return bt_event_set_payload(event, NULL, payload);
+       return BT_FROM_COMMON(bt_event_common_get_payload(BT_TO_COMMON(event)));
 }
 
-struct bt_field *bt_event_get_payload(struct bt_event *event,
-               const char *name)
+int bt_event_set_payload(struct bt_event *event, struct bt_field *field)
 {
-       struct bt_field *field = NULL;
-
-       BT_ASSERT_PRE_NON_NULL(event, "Event");
-
-       if (name) {
-               field = bt_field_structure_get_field_by_name(
-                       event->fields_payload, name);
-       } else {
-               field = event->fields_payload;
-               bt_get(field);
-       }
-
-       return field;
-}
-
-struct bt_field *bt_event_get_payload_by_index(
-               struct bt_event *event, uint64_t index)
-{
-       struct bt_field *field = NULL;
-
-       BT_ASSERT_PRE_NON_NULL(event, "Event");
-       field = bt_field_structure_get_field_by_index(event->fields_payload,
-               index);
-
-       return field;
+       return bt_event_common_set_payload(BT_TO_COMMON(event),
+               (void *) field);
 }
 
 struct bt_field *bt_event_get_header(struct bt_event *event)
 {
-       struct bt_field *header = NULL;
-
-       BT_ASSERT_PRE_NON_NULL(event, "Event");
-
-       if (!event->event_header) {
-               BT_LOGV("Event has no current header field: addr=%p, "
-                       "event-class-name=\"%s\", event-class-id=%" PRId64,
-                       event, bt_event_class_get_name(event->event_class),
-                       bt_event_class_get_id(event->event_class));
-               goto end;
-       }
-
-       header = event->event_header;
-       bt_get(header);
-
-end:
-       return header;
+       return BT_FROM_COMMON(bt_event_common_get_header(BT_TO_COMMON(event)));
 }
 
-int bt_event_set_header(struct bt_event *event, struct bt_field *header)
+int bt_event_set_header(struct bt_event *event, struct bt_field *field)
 {
-       BT_ASSERT_PRE_NON_NULL(event, "Event");
-       BT_ASSERT_PRE_EVENT_HOT(event, "Event");
-
-       /*
-        * Ensure the provided header's type matches the one registered to the
-        * stream class.
-        */
-       if (header) {
-               BT_ASSERT_PRE(bt_field_type_compare(header->type,
-                       bt_event_class_borrow_stream_class(event->event_class)->event_header_type) == 0,
-                       "Header field's type is different from the "
-                       "expected field type: %![event-]+e, %![ft-]+F, "
-                       "%![expected-ft-]+F",
-                       event, header->type,
-                       bt_event_class_borrow_stream_class(event->event_class)->event_header_type);
-       } else {
-               BT_ASSERT_PRE(!bt_event_class_borrow_stream_class(event->event_class)->event_header_type,
-                       "Setting no event header field, "
-                       "but event header field type is not NULL: ",
-                       "%![event-]+e, %![header-ft-]+F",
-                       event,
-                       bt_event_class_borrow_stream_class(event->event_class)->event_header_type);
-       }
-
-       bt_put(event->event_header);
-       event->event_header = bt_get(header);
-       BT_LOGV("Set event's header field: event-addr=%p, "
-               "event-class-name=\"%s\", event-class-id=%" PRId64 ", "
-               "header-field-addr=%p",
-               event, bt_event_class_get_name(event->event_class),
-               bt_event_class_get_id(event->event_class), header);
-       return 0;
+       return bt_event_common_set_header(BT_TO_COMMON(event), (void *) field);
 }
 
-struct bt_field *bt_event_get_event_context(struct bt_event *event)
+struct bt_field *bt_event_get_context(struct bt_event *event)
 {
-       struct bt_field *context = NULL;
-
-       BT_ASSERT_PRE_NON_NULL(event, "Event");
-
-       if (!event->context_payload) {
-               BT_LOGV("Event has no current context field: addr=%p, "
-                       "event-class-name=\"%s\", event-class-id=%" PRId64,
-                       event, bt_event_class_get_name(event->event_class),
-                       bt_event_class_get_id(event->event_class));
-               goto end;
-       }
-
-       context = event->context_payload;
-       bt_get(context);
-
-end:
-       return context;
+       return BT_FROM_COMMON(bt_event_common_get_context(BT_TO_COMMON(event)));
 }
 
-int bt_event_set_event_context(struct bt_event *event, struct bt_field *context)
+int bt_event_set_context(struct bt_event *event, struct bt_field *field)
 {
-       BT_ASSERT_PRE_NON_NULL(event, "Event");
-       BT_ASSERT_PRE_EVENT_HOT(event, "Event");
-
-       if (context) {
-               BT_ASSERT_PRE(bt_field_type_compare(context->type,
-                       event->event_class->context) == 0,
-                       "Context field's type is different from the "
-                       "expected field type: %![event-]+e, %![ft-]+F, "
-                       "%![expected-ft-]+F",
-                       event, context->type, event->event_class->context);
-       } else {
-               BT_ASSERT_PRE(!event->event_class->context,
-                       "Setting no event context field, "
-                       "but event context field type is not NULL: ",
-                       "%![event-]+e, %![context-ft-]+F",
-                       event, event->event_class->context);
-       }
-
-       bt_put(event->context_payload);
-       event->context_payload = bt_get(context);
-       BT_LOGV("Set event's context field: event-addr=%p, "
-               "event-class-name=\"%s\", event-class-id=%" PRId64 ", "
-               "context-field-addr=%p",
-               event, bt_event_class_get_name(event->event_class),
-               bt_event_class_get_id(event->event_class), context);
-       return 0;
+       return bt_event_common_set_context(BT_TO_COMMON(event), (void *) field);
 }
 
 struct bt_field *bt_event_get_stream_event_context(
                struct bt_event *event)
 {
-       struct bt_field *stream_event_context = NULL;
-
-       BT_ASSERT_PRE_NON_NULL(event, "Event");
-
-       if (!event->stream_event_context) {
-               BT_LOGV("Event has no current stream event context field: addr=%p, "
-                       "event-class-name=\"%s\", event-class-id=%" PRId64,
-                       event, bt_event_class_get_name(event->event_class),
-                       bt_event_class_get_id(event->event_class));
-               goto end;
-       }
-
-       stream_event_context = event->stream_event_context;
-
-end:
-       return bt_get(stream_event_context);
+       return BT_FROM_COMMON(bt_event_common_get_stream_event_context(
+               BT_TO_COMMON(event)));
 }
 
 int bt_event_set_stream_event_context(struct bt_event *event,
-               struct bt_field *stream_event_context)
-{
-       BT_ASSERT_PRE_NON_NULL(event, "Event");
-       BT_ASSERT_PRE_EVENT_HOT(event, "Event");
-
-       if (stream_event_context) {
-               BT_ASSERT_PRE(bt_field_type_compare(stream_event_context->type,
-                       bt_event_class_borrow_stream_class(event->event_class)->event_context_type) == 0,
-                       "Stream event context field's type is different from the "
-                       "expected field type: %![event-]+e, %![ft-]+F, "
-                       "%![expected-ft-]+F",
-                       event, stream_event_context->type,
-                       bt_event_class_borrow_stream_class(event->event_class)->event_context_type);
-       } else {
-               BT_ASSERT_PRE(!bt_event_class_borrow_stream_class(event->event_class)->event_context_type,
-                       "Setting no stream event context field, "
-                       "but stream event context field type is not NULL: ",
-                       "%![event-]+e, %![context-ft-]+F",
-                       event,
-                       bt_event_class_borrow_stream_class(event->event_class)->event_context_type);
-       }
-
-       bt_get(stream_event_context);
-       BT_MOVE(event->stream_event_context, stream_event_context);
-       BT_LOGV("Set event's stream event context field: event-addr=%p, "
-               "event-class-name=\"%s\", event-class-id=%" PRId64 ", "
-               "stream-event-context-field-addr=%p",
-               event, bt_event_class_get_name(event->event_class),
-               bt_event_class_get_id(event->event_class),
-               stream_event_context);
-       return 0;
-}
-
-/* Pre-2.0 CTF writer backward compatibility */
-void bt_ctf_event_get(struct bt_event *event)
-{
-       bt_get(event);
-}
-
-/* Pre-2.0 CTF writer backward compatibility */
-void bt_ctf_event_put(struct bt_event *event)
+               struct bt_field *field)
 {
-       bt_put(event);
+       return bt_event_common_set_stream_event_context(
+               BT_TO_COMMON(event), (void *) field);
 }
 
 void bt_event_destroy(struct bt_object *obj)
 {
-       struct bt_event *event;
-
-       event = container_of(obj, struct bt_event, base);
-       BT_LOGD("Destroying event: addr=%p, "
-               "event-class-name=\"%s\", event-class-id=%" PRId64,
-               event, bt_event_class_get_name(event->event_class),
-               bt_event_class_get_id(event->event_class));
+       struct bt_event *event = (void *) obj;
 
-       if (!event->base.parent) {
-               /*
-                * Event was keeping a reference to its class since it shared no
-                * common ancestor with it to guarantee they would both have the
-                * same lifetime.
-                */
-               bt_put(event->event_class);
-       }
+       bt_event_common_finalize(obj);
        g_hash_table_destroy(event->clock_values);
-       BT_LOGD_STR("Putting event's header field.");
-       bt_put(event->event_header);
-       BT_LOGD_STR("Putting event's stream event context field.");
-       bt_put(event->stream_event_context);
-       BT_LOGD_STR("Putting event's context field.");
-       bt_put(event->context_payload);
-       BT_LOGD_STR("Putting event's payload field.");
-       bt_put(event->fields_payload);
        BT_LOGD_STR("Putting event's packet.");
        bt_put(event->packet);
        g_free(event);
@@ -684,8 +600,8 @@ struct bt_clock_value *bt_event_get_clock_value(
                        "event-addr=%p, event-class-name=\"%s\", "
                        "event-class-id=%" PRId64 ", clock-class-addr=%p, "
                        "clock-class-name=\"%s\"", event,
-                       bt_event_class_get_name(event->event_class),
-                       bt_event_class_get_id(event->event_class),
+                       bt_event_class_common_get_name(event->common.class),
+                       bt_event_class_common_get_id(event->common.class),
                        clock_class, bt_clock_class_get_name(clock_class));
                goto end;
        }
@@ -706,15 +622,16 @@ int bt_event_set_clock_value(struct bt_event *event,
 
        BT_ASSERT_PRE_NON_NULL(event, "Event");
        BT_ASSERT_PRE_NON_NULL(value, "Clock value");
-       BT_ASSERT_PRE_EVENT_HOT(event, "Event");
+       BT_ASSERT_PRE_EVENT_COMMON_HOT(BT_TO_COMMON(event), "Event");
        clock_class = bt_clock_value_get_class(value);
-       event_class = bt_event_borrow_event_class(event);
+       event_class = BT_FROM_COMMON(event->common.class);
        BT_ASSERT(event_class);
        stream_class = bt_event_class_borrow_stream_class(event_class);
        BT_ASSERT(stream_class);
        trace = bt_stream_class_borrow_trace(stream_class);
        BT_ASSERT(trace);
-       BT_ASSERT_PRE(bt_trace_has_clock_class(trace, clock_class),
+       BT_ASSERT_PRE(bt_trace_common_has_clock_class(BT_TO_COMMON(trace),
+               clock_class),
                "Clock class is not part of event's trace: "
                "%![event-]+e, %![clock-class-]+K",
                event, clock_class);
@@ -724,8 +641,8 @@ int bt_event_set_clock_value(struct bt_event *event,
                "event-class-id=%" PRId64 ", clock-class-addr=%p, "
                "clock-class-name=\"%s\", clock-value-addr=%p, "
                "clock-value-cycles=%" PRIu64,
-               event, bt_event_class_get_name(event->event_class),
-               bt_event_class_get_id(event->event_class),
+               event, bt_event_class_common_get_name(event->common.class),
+               bt_event_class_common_get_id(event->common.class),
                clock_class, bt_clock_class_get_name(clock_class),
                value, value->value);
        clock_class = NULL;
@@ -733,105 +650,6 @@ int bt_event_set_clock_value(struct bt_event *event,
        return 0;
 }
 
-BT_HIDDEN
-int _bt_event_validate(struct bt_event *event)
-{
-       int ret = 0;
-       struct bt_stream_class *stream_class;
-
-       BT_ASSERT(event);
-       if (event->event_header) {
-               ret = bt_field_validate_recursive(event->event_header);
-               if (ret) {
-                       BT_ASSERT_PRE_MSG("Invalid event's header field: "
-                               "%![event-]+e, %![field-]+f",
-                               event, event->event_header);
-                       goto end;
-               }
-       }
-
-       stream_class = bt_event_class_borrow_stream_class(event->event_class);
-
-       /*
-        * We should not have been able to create the event without associating
-        * the event class to a stream class.
-        */
-       BT_ASSERT(stream_class);
-
-       if (stream_class->event_context_type) {
-               ret = bt_field_validate_recursive(event->stream_event_context);
-               if (ret) {
-                       BT_ASSERT_PRE_MSG("Invalid event's stream event context field: "
-                               "%![event-]+e, %![field-]+f",
-                               event, event->stream_event_context);
-                       goto end;
-               }
-       }
-
-       if (event->event_class->context) {
-               ret = bt_field_validate_recursive(event->context_payload);
-               if (ret) {
-                       BT_ASSERT_PRE_MSG("Invalid event's payload field: "
-                               "%![event-]+e, %![field-]+f",
-                               event, event->context_payload);
-                       goto end;
-               }
-       }
-
-       ret = bt_field_validate_recursive(event->fields_payload);
-       if (ret) {
-               BT_ASSERT_PRE_MSG("Invalid event's payload field: "
-                       "%![event-]+e, %![field-]+f",
-                       event, event->fields_payload);
-               goto end;
-       }
-
-end:
-       return ret;
-}
-
-BT_HIDDEN
-int bt_event_serialize(struct bt_event *event, struct bt_stream_pos *pos,
-               enum bt_byte_order native_byte_order)
-{
-       int ret = 0;
-
-       BT_ASSERT(event);
-       BT_ASSERT(pos);
-
-       BT_LOGV_STR("Serializing event's context field.");
-       if (event->context_payload) {
-               ret = bt_field_serialize_recursive(event->context_payload, pos,
-                       native_byte_order);
-               if (ret) {
-                       BT_LOGW("Cannot serialize event's context field: "
-                               "event-addr=%p, event-class-name=\"%s\", "
-                               "event-class-id=%" PRId64,
-                               event,
-                               bt_event_class_get_name(event->event_class),
-                               bt_event_class_get_id(event->event_class));
-                       goto end;
-               }
-       }
-
-       BT_LOGV_STR("Serializing event's payload field.");
-       if (event->fields_payload) {
-               ret = bt_field_serialize_recursive(event->fields_payload, pos,
-                       native_byte_order);
-               if (ret) {
-                       BT_LOGW("Cannot serialize event's payload field: "
-                               "event-addr=%p, event-class-name=\"%s\", "
-                               "event-class-id=%" PRId64,
-                               event,
-                               bt_event_class_get_name(event->event_class),
-                               bt_event_class_get_id(event->event_class));
-                       goto end;
-               }
-       }
-end:
-       return ret;
-}
-
 struct bt_packet *bt_event_get_packet(struct bt_event *event)
 {
        struct bt_packet *packet = NULL;
@@ -840,8 +658,8 @@ struct bt_packet *bt_event_get_packet(struct bt_event *event)
        if (!event->packet) {
                BT_LOGV("Event has no current packet: addr=%p, "
                        "event-class-name=\"%s\", event-class-id=%" PRId64,
-                       event, bt_event_class_get_name(event->event_class),
-                       bt_event_class_get_id(event->event_class));
+                       event, bt_event_class_common_get_name(event->common.class),
+                       bt_event_class_common_get_id(event->common.class));
                goto end;
        }
 
@@ -856,7 +674,7 @@ int bt_event_set_packet(struct bt_event *event,
 {
        BT_ASSERT_PRE_NON_NULL(event, "Event");
        BT_ASSERT_PRE_NON_NULL(packet, "Packet");
-       BT_ASSERT_PRE_EVENT_HOT(event, "Event");
+       BT_ASSERT_PRE_EVENT_COMMON_HOT(BT_TO_COMMON(event), "Event");
 
        /*
         * Make sure the new packet was created by this event's
@@ -868,8 +686,9 @@ int bt_event_set_packet(struct bt_event *event,
                        "%![event-]+e, %![packet-]+a",
                        event, packet);
        } else {
-               BT_ASSERT_PRE(bt_event_class_borrow_stream_class(event->event_class) ==
-                       packet->stream->stream_class,
+               BT_ASSERT_PRE(bt_event_class_borrow_stream_class(
+                       BT_FROM_COMMON(event->common.class)) ==
+                       BT_FROM_COMMON(packet->stream->common.stream_class),
                        "Packet's stream class and event's stream class differ: "
                        "%![event-]+e, %![packet-]+a",
                        event, packet);
@@ -880,32 +699,15 @@ int bt_event_set_packet(struct bt_event *event,
        BT_LOGV("Set event's packet: event-addr=%p, "
                "event-class-name=\"%s\", event-class-id=%" PRId64 ", "
                "packet-addr=%p",
-               event, bt_event_class_get_name(event->event_class),
-               bt_event_class_get_id(event->event_class), packet);
+               event, bt_event_class_common_get_name(event->common.class),
+               bt_event_class_common_get_id(event->common.class), packet);
        return 0;
 }
 
 BT_HIDDEN
 void _bt_event_freeze(struct bt_event *event)
 {
-       BT_ASSERT(event);
-
-       if (event->frozen) {
-               return;
-       }
-
-       BT_LOGD("Freezing event: addr=%p, "
-               "event-class-name=\"%s\", event-class-id=%" PRId64,
-               event, bt_event_class_get_name(event->event_class),
-               bt_event_class_get_id(event->event_class));
+       _bt_event_common_freeze(BT_TO_COMMON(event));
+       BT_LOGD_STR("Freezing event's packet.");
        bt_packet_freeze(event->packet);
-       BT_LOGD_STR("Freezing event's header field.");
-       bt_field_freeze_recursive(event->event_header);
-       BT_LOGD_STR("Freezing event's stream event context field.");
-       bt_field_freeze_recursive(event->stream_event_context);
-       BT_LOGD_STR("Freezing event's context field.");
-       bt_field_freeze_recursive(event->context_payload);
-       BT_LOGD_STR("Freezing event's payload field.");
-       bt_field_freeze_recursive(event->fields_payload);
-       event->frozen = 1;
 }
index 09fa586510d0f8732fae80b6f0233267f723e63f..deb9c0ed296636d5e5403533a42bc920a83d404e 100644 (file)
 #define BT_LOG_TAG "FIELD-TYPES"
 #include <babeltrace/lib-logging-internal.h>
 
+#include <babeltrace/assert-pre-internal.h>
 #include <babeltrace/ctf-ir/field-types-internal.h>
 #include <babeltrace/ctf-ir/field-path-internal.h>
+#include <babeltrace/ctf-ir/fields-internal.h>
+#include <babeltrace/ctf-ir/fields.h>
 #include <babeltrace/ctf-ir/utils.h>
+#include <babeltrace/ctf-ir/utils-internal.h>
 #include <babeltrace/ref.h>
 #include <babeltrace/ctf-ir/clock-class.h>
 #include <babeltrace/ctf-ir/clock-class-internal.h>
-#include <babeltrace/ctf-writer/writer-internal.h>
 #include <babeltrace/object-internal.h>
 #include <babeltrace/ref.h>
 #include <babeltrace/compiler-internal.h>
 #include <babeltrace/endian-internal.h>
 #include <babeltrace/assert-internal.h>
-#include <babeltrace/assert-pre-internal.h>
 #include <float.h>
 #include <inttypes.h>
 #include <stdlib.h>
 
-#define BT_ASSERT_PRE_FT_HAS_ID(_ft, _type_id, _name)                  \
-       BT_ASSERT_PRE((_ft)->id == (_type_id),                          \
-               _name " has the wrong type ID: expected-type-id=%s, "   \
-               "%![ft-]+F", bt_field_type_id_string(_type_id), (_ft))
-
-#define BT_ASSERT_PRE_FT_HOT(_ft, _name)                               \
-       BT_ASSERT_PRE_HOT((_ft), (_name), ": +%!+F", (_ft))
-
-struct range_overlap_query {
-       union {
-               uint64_t _unsigned;
-               int64_t _signed;
-       } range_start;
-
-       union {
-               uint64_t _unsigned;
-               int64_t _signed;
-       } range_end;
-       int overlaps;
-       GQuark mapping_name;
-};
-
-static
-void bt_field_type_destroy(struct bt_object *);
-static
-void bt_field_type_integer_destroy(struct bt_field_type *);
-static
-void bt_field_type_enumeration_destroy(struct bt_field_type *);
-static
-void bt_field_type_floating_point_destroy(struct bt_field_type *);
-static
-void bt_field_type_structure_destroy(struct bt_field_type *);
-static
-void bt_field_type_variant_destroy(struct bt_field_type *);
 static
-void bt_field_type_array_destroy(struct bt_field_type *);
-static
-void bt_field_type_sequence_destroy(struct bt_field_type *);
-static
-void bt_field_type_string_destroy(struct bt_field_type *);
+struct bt_field_type *bt_field_type_integer_copy(
+               struct bt_field_type *ft);
 
 static
-void (* const type_destroy_funcs[])(struct bt_field_type *) = {
-       [BT_FIELD_TYPE_ID_INTEGER] = bt_field_type_integer_destroy,
-       [BT_FIELD_TYPE_ID_ENUM] =
-               bt_field_type_enumeration_destroy,
-       [BT_FIELD_TYPE_ID_FLOAT] =
-               bt_field_type_floating_point_destroy,
-       [BT_FIELD_TYPE_ID_STRUCT] = bt_field_type_structure_destroy,
-       [BT_FIELD_TYPE_ID_VARIANT] = bt_field_type_variant_destroy,
-       [BT_FIELD_TYPE_ID_ARRAY] = bt_field_type_array_destroy,
-       [BT_FIELD_TYPE_ID_SEQUENCE] = bt_field_type_sequence_destroy,
-       [BT_FIELD_TYPE_ID_STRING] = bt_field_type_string_destroy,
-};
+struct bt_field_type *bt_field_type_enumeration_copy_recursive(
+               struct bt_field_type *ft);
 
 static
-void generic_field_type_freeze(struct bt_field_type *);
-static
-void bt_field_type_integer_freeze(struct bt_field_type *);
-static
-void bt_field_type_enumeration_freeze(struct bt_field_type *);
-static
-void bt_field_type_structure_freeze(struct bt_field_type *);
-static
-void bt_field_type_variant_freeze(struct bt_field_type *);
-static
-void bt_field_type_array_freeze(struct bt_field_type *);
-static
-void bt_field_type_sequence_freeze(struct bt_field_type *);
+struct bt_field_type *bt_field_type_floating_point_copy(
+               struct bt_field_type *ft);
 
 static
-type_freeze_func const type_freeze_funcs[] = {
-       [BT_FIELD_TYPE_ID_INTEGER] = bt_field_type_integer_freeze,
-       [BT_FIELD_TYPE_ID_ENUM] = bt_field_type_enumeration_freeze,
-       [BT_FIELD_TYPE_ID_FLOAT] = generic_field_type_freeze,
-       [BT_FIELD_TYPE_ID_STRUCT] = bt_field_type_structure_freeze,
-       [BT_FIELD_TYPE_ID_VARIANT] = bt_field_type_variant_freeze,
-       [BT_FIELD_TYPE_ID_ARRAY] = bt_field_type_array_freeze,
-       [BT_FIELD_TYPE_ID_SEQUENCE] = bt_field_type_sequence_freeze,
-       [BT_FIELD_TYPE_ID_STRING] = generic_field_type_freeze,
-};
+struct bt_field_type *bt_field_type_structure_copy_recursive(
+               struct bt_field_type *ft);
 
 static
-int bt_field_type_integer_serialize(struct bt_field_type *,
-               struct metadata_context *);
-static
-int bt_field_type_enumeration_serialize(struct bt_field_type *,
-               struct metadata_context *);
-static
-int bt_field_type_floating_point_serialize(
-               struct bt_field_type *, struct metadata_context *);
-static
-int bt_field_type_structure_serialize(struct bt_field_type *,
-               struct metadata_context *);
-static
-int bt_field_type_variant_serialize(struct bt_field_type *,
-               struct metadata_context *);
-static
-int bt_field_type_array_serialize(struct bt_field_type *,
-               struct metadata_context *);
-static
-int bt_field_type_sequence_serialize(struct bt_field_type *,
-               struct metadata_context *);
-static
-int bt_field_type_string_serialize(struct bt_field_type *,
-               struct metadata_context *);
+struct bt_field_type *bt_field_type_variant_copy_recursive(
+               struct bt_field_type *ft);
 
 static
-type_serialize_func const type_serialize_funcs[] = {
-       [BT_FIELD_TYPE_ID_INTEGER] = bt_field_type_integer_serialize,
-       [BT_FIELD_TYPE_ID_ENUM] =
-               bt_field_type_enumeration_serialize,
-       [BT_FIELD_TYPE_ID_FLOAT] =
-               bt_field_type_floating_point_serialize,
-       [BT_FIELD_TYPE_ID_STRUCT] =
-               bt_field_type_structure_serialize,
-       [BT_FIELD_TYPE_ID_VARIANT] = bt_field_type_variant_serialize,
-       [BT_FIELD_TYPE_ID_ARRAY] = bt_field_type_array_serialize,
-       [BT_FIELD_TYPE_ID_SEQUENCE] = bt_field_type_sequence_serialize,
-       [BT_FIELD_TYPE_ID_STRING] = bt_field_type_string_serialize,
-};
+struct bt_field_type *bt_field_type_array_copy_recursive(
+               struct bt_field_type *ft);
 
 static
-void bt_field_type_integer_set_byte_order(struct bt_field_type *,
-               enum bt_byte_order byte_order);
-static
-void bt_field_type_enumeration_set_byte_order(struct bt_field_type *,
-               enum bt_byte_order byte_order);
-static
-void bt_field_type_floating_point_set_byte_order(
-               struct bt_field_type *, enum bt_byte_order byte_order);
-static
-void bt_field_type_structure_set_byte_order(struct bt_field_type *,
-               enum bt_byte_order byte_order);
-static
-void bt_field_type_variant_set_byte_order(struct bt_field_type *,
-               enum bt_byte_order byte_order);
-static
-void bt_field_type_array_set_byte_order(struct bt_field_type *,
-               enum bt_byte_order byte_order);
-static
-void bt_field_type_sequence_set_byte_order(struct bt_field_type *,
-               enum bt_byte_order byte_order);
+struct bt_field_type *bt_field_type_sequence_copy_recursive(
+               struct bt_field_type *type);
 
 static
-void (* const set_byte_order_funcs[])(struct bt_field_type *,
-               enum bt_byte_order) = {
-       [BT_FIELD_TYPE_ID_INTEGER] = bt_field_type_integer_set_byte_order,
-       [BT_FIELD_TYPE_ID_ENUM] =
-               bt_field_type_enumeration_set_byte_order,
-       [BT_FIELD_TYPE_ID_FLOAT] =
-               bt_field_type_floating_point_set_byte_order,
-       [BT_FIELD_TYPE_ID_STRUCT] =
-               bt_field_type_structure_set_byte_order,
-       [BT_FIELD_TYPE_ID_VARIANT] = bt_field_type_variant_set_byte_order,
-       [BT_FIELD_TYPE_ID_ARRAY] = bt_field_type_array_set_byte_order,
-       [BT_FIELD_TYPE_ID_SEQUENCE] = bt_field_type_sequence_set_byte_order,
-       [BT_FIELD_TYPE_ID_STRING] = NULL,
+struct bt_field_type *bt_field_type_string_copy(struct bt_field_type *ft);
+
+static struct bt_field_type_common_methods bt_field_type_integer_methods = {
+       .freeze = bt_field_type_common_generic_freeze,
+       .validate = bt_field_type_common_integer_validate,
+       .set_byte_order = bt_field_type_common_integer_set_byte_order,
+       .copy = (bt_field_type_common_method_copy)
+               bt_field_type_integer_copy,
+       .compare = bt_field_type_common_integer_compare,
 };
 
-static
-struct bt_field_type *bt_field_type_integer_copy(
-               struct bt_field_type *);
-static
-struct bt_field_type *bt_field_type_enumeration_copy(
-               struct bt_field_type *);
-static
-struct bt_field_type *bt_field_type_floating_point_copy(
-               struct bt_field_type *);
-static
-struct bt_field_type *bt_field_type_structure_copy(
-               struct bt_field_type *);
-static
-struct bt_field_type *bt_field_type_variant_copy(
-               struct bt_field_type *);
-static
-struct bt_field_type *bt_field_type_array_copy(
-               struct bt_field_type *);
-static
-struct bt_field_type *bt_field_type_sequence_copy(
-               struct bt_field_type *);
-static
-struct bt_field_type *bt_field_type_string_copy(
-               struct bt_field_type *);
+static struct bt_field_type_common_methods bt_field_type_floating_point_methods = {
+       .freeze = bt_field_type_common_generic_freeze,
+       .validate = NULL,
+       .set_byte_order = bt_field_type_common_floating_point_set_byte_order,
+       .copy = (bt_field_type_common_method_copy)
+               bt_field_type_floating_point_copy,
+       .compare = bt_field_type_common_floating_point_compare,
+};
 
-static
-struct bt_field_type *(* const type_copy_funcs[])(
-               struct bt_field_type *) = {
-       [BT_FIELD_TYPE_ID_INTEGER] = bt_field_type_integer_copy,
-       [BT_FIELD_TYPE_ID_ENUM] = bt_field_type_enumeration_copy,
-       [BT_FIELD_TYPE_ID_FLOAT] = bt_field_type_floating_point_copy,
-       [BT_FIELD_TYPE_ID_STRUCT] = bt_field_type_structure_copy,
-       [BT_FIELD_TYPE_ID_VARIANT] = bt_field_type_variant_copy,
-       [BT_FIELD_TYPE_ID_ARRAY] = bt_field_type_array_copy,
-       [BT_FIELD_TYPE_ID_SEQUENCE] = bt_field_type_sequence_copy,
-       [BT_FIELD_TYPE_ID_STRING] = bt_field_type_string_copy,
+static struct bt_field_type_common_methods bt_field_type_enumeration_methods = {
+       .freeze = bt_field_type_common_enumeration_freeze_recursive,
+       .validate = bt_field_type_common_enumeration_validate_recursive,
+       .set_byte_order = bt_field_type_common_enumeration_set_byte_order_recursive,
+       .copy = (bt_field_type_common_method_copy)
+               bt_field_type_enumeration_copy_recursive,
+       .compare = bt_field_type_common_enumeration_compare_recursive,
 };
 
-static
-int bt_field_type_integer_compare(struct bt_field_type *,
-               struct bt_field_type *);
-static
-int bt_field_type_floating_point_compare(struct bt_field_type *,
-               struct bt_field_type *);
-static
-int bt_field_type_enumeration_compare(struct bt_field_type *,
-               struct bt_field_type *);
-static
-int bt_field_type_string_compare(struct bt_field_type *,
-               struct bt_field_type *);
-static
-int bt_field_type_structure_compare(struct bt_field_type *,
-               struct bt_field_type *);
-static
-int bt_field_type_variant_compare(struct bt_field_type *,
-               struct bt_field_type *);
-static
-int bt_field_type_array_compare(struct bt_field_type *,
-               struct bt_field_type *);
-static
-int bt_field_type_sequence_compare(struct bt_field_type *,
-               struct bt_field_type *);
+static struct bt_field_type_common_methods bt_field_type_string_methods = {
+       .freeze = bt_field_type_common_generic_freeze,
+       .validate = NULL,
+       .set_byte_order = NULL,
+       .copy = (bt_field_type_common_method_copy)
+               bt_field_type_string_copy,
+       .compare = bt_field_type_common_string_compare,
+};
 
-static
-int (* const type_compare_funcs[])(struct bt_field_type *,
-               struct bt_field_type *) = {
-       [BT_FIELD_TYPE_ID_INTEGER] = bt_field_type_integer_compare,
-       [BT_FIELD_TYPE_ID_ENUM] = bt_field_type_enumeration_compare,
-       [BT_FIELD_TYPE_ID_FLOAT] = bt_field_type_floating_point_compare,
-       [BT_FIELD_TYPE_ID_STRUCT] = bt_field_type_structure_compare,
-       [BT_FIELD_TYPE_ID_VARIANT] = bt_field_type_variant_compare,
-       [BT_FIELD_TYPE_ID_ARRAY] = bt_field_type_array_compare,
-       [BT_FIELD_TYPE_ID_SEQUENCE] = bt_field_type_sequence_compare,
-       [BT_FIELD_TYPE_ID_STRING] = bt_field_type_string_compare,
+static struct bt_field_type_common_methods bt_field_type_array_methods = {
+       .freeze = bt_field_type_common_array_freeze_recursive,
+       .validate = bt_field_type_common_array_validate_recursive,
+       .set_byte_order = bt_field_type_common_array_set_byte_order_recursive,
+       .copy = (bt_field_type_common_method_copy)
+               bt_field_type_array_copy_recursive,
+       .compare = bt_field_type_common_array_compare_recursive,
 };
 
-static
-int bt_field_type_integer_validate(struct bt_field_type *);
-static
-int bt_field_type_enumeration_validate(struct bt_field_type *);
-static
-int bt_field_type_structure_validate(struct bt_field_type *);
-static
-int bt_field_type_variant_validate(struct bt_field_type *);
-static
-int bt_field_type_array_validate(struct bt_field_type *);
-static
-int bt_field_type_sequence_validate(struct bt_field_type *);
+static struct bt_field_type_common_methods bt_field_type_sequence_methods = {
+       .freeze = bt_field_type_common_sequence_freeze_recursive,
+       .validate = bt_field_type_common_sequence_validate_recursive,
+       .set_byte_order = bt_field_type_common_sequence_set_byte_order_recursive,
+       .copy = (bt_field_type_common_method_copy)
+               bt_field_type_sequence_copy_recursive,
+       .compare = bt_field_type_common_sequence_compare_recursive,
+};
 
-static
-int (* const type_validate_funcs[])(struct bt_field_type *) = {
-       [BT_FIELD_TYPE_ID_INTEGER] = bt_field_type_integer_validate,
-       [BT_FIELD_TYPE_ID_FLOAT] = NULL,
-       [BT_FIELD_TYPE_ID_STRING] = NULL,
-       [BT_FIELD_TYPE_ID_ENUM] = bt_field_type_enumeration_validate,
-       [BT_FIELD_TYPE_ID_STRUCT] = bt_field_type_structure_validate,
-       [BT_FIELD_TYPE_ID_VARIANT] = bt_field_type_variant_validate,
-       [BT_FIELD_TYPE_ID_ARRAY] = bt_field_type_array_validate,
-       [BT_FIELD_TYPE_ID_SEQUENCE] = bt_field_type_sequence_validate,
+static struct bt_field_type_common_methods bt_field_type_structure_methods = {
+       .freeze = bt_field_type_common_structure_freeze_recursive,
+       .validate = bt_field_type_common_structure_validate_recursive,
+       .set_byte_order = bt_field_type_common_structure_set_byte_order_recursive,
+       .copy = (bt_field_type_common_method_copy)
+               bt_field_type_structure_copy_recursive,
+       .compare = bt_field_type_common_structure_compare_recursive,
+};
+
+static struct bt_field_type_common_methods bt_field_type_variant_methods = {
+       .freeze = bt_field_type_common_variant_freeze_recursive,
+       .validate = bt_field_type_common_variant_validate_recursive,
+       .set_byte_order = bt_field_type_common_variant_set_byte_order_recursive,
+       .copy = (bt_field_type_common_method_copy)
+               bt_field_type_variant_copy_recursive,
+       .compare = bt_field_type_common_variant_compare_recursive,
 };
 
 static
@@ -314,7 +158,7 @@ void destroy_enumeration_mapping(struct enumeration_mapping *mapping)
 }
 
 static
-void destroy_structure_field(struct structure_field *field)
+void destroy_structure_field_common(struct structure_field_common *field)
 {
        if (!field) {
                return;
@@ -328,6 +172,339 @@ void destroy_structure_field(struct structure_field *field)
        g_free(field);
 }
 
+BT_HIDDEN
+void bt_field_type_common_initialize(struct bt_field_type_common *ft,
+               bool init_bo, bt_object_release_func release_func,
+               struct bt_field_type_common_methods *methods)
+{
+       BT_ASSERT(ft && (ft->id > BT_FIELD_TYPE_ID_UNKNOWN) &&
+               (ft->id < BT_FIELD_TYPE_ID_NR));
+
+       bt_object_init(ft, release_func);
+       ft->methods = methods;
+
+       if (init_bo) {
+               int ret;
+               const enum bt_byte_order bo = BT_BYTE_ORDER_NATIVE;
+
+               BT_LOGD("Setting initial field type's byte order: bo=%s",
+                       bt_common_byte_order_string(bo));
+               ret = bt_field_type_common_set_byte_order(ft, bo);
+               BT_ASSERT(ret == 0);
+       }
+
+       ft->alignment = 1;
+}
+
+BT_HIDDEN
+void bt_field_type_common_integer_initialize(
+               struct bt_field_type_common *ft,
+               unsigned int size, bt_object_release_func release_func,
+               struct bt_field_type_common_methods *methods)
+{
+       struct bt_field_type_common_integer *int_ft = BT_FROM_COMMON(ft);
+
+       BT_ASSERT(size > 0);
+       BT_LOGD("Initializing common integer field type object: size=%u",
+               size);
+       ft->id = BT_FIELD_TYPE_ID_INTEGER;
+       int_ft->size = size;
+       int_ft->base = BT_INTEGER_BASE_DECIMAL;
+       int_ft->encoding = BT_STRING_ENCODING_NONE;
+       bt_field_type_common_initialize(ft, true, release_func, methods);
+       BT_LOGD("Initialized common integer field type object: addr=%p, size=%u",
+               ft, size);
+}
+
+BT_HIDDEN
+void bt_field_type_common_floating_point_initialize(
+               struct bt_field_type_common *ft,
+               bt_object_release_func release_func,
+               struct bt_field_type_common_methods *methods)
+{
+       struct bt_field_type_common_floating_point *flt_ft = BT_FROM_COMMON(ft);
+
+       BT_LOGD_STR("Initializing common floating point number field type object.");
+       ft->id = BT_FIELD_TYPE_ID_FLOAT;
+       flt_ft->exp_dig = sizeof(float) * CHAR_BIT - FLT_MANT_DIG;
+       flt_ft->mant_dig = FLT_MANT_DIG;
+       bt_field_type_common_initialize(ft, true, release_func, methods);
+       BT_LOGD("Initialized common floating point number field type object: addr=%p, "
+               "exp-size=%u, mant-size=%u", ft, flt_ft->exp_dig,
+               flt_ft->mant_dig);
+}
+
+BT_HIDDEN
+void bt_field_type_common_enumeration_initialize(
+               struct bt_field_type_common *ft,
+               struct bt_field_type_common *container_ft,
+               bt_object_release_func release_func,
+               struct bt_field_type_common_methods *methods)
+{
+       struct bt_field_type_common_enumeration *enum_ft = BT_FROM_COMMON(ft);
+
+       BT_ASSERT(container_ft);
+       BT_LOGD("Initializing common enumeration field type object: int-ft-addr=%p",
+               container_ft);
+       ft->id = BT_FIELD_TYPE_ID_ENUM;
+       enum_ft->container_ft = bt_get(container_ft);
+       enum_ft->entries = g_ptr_array_new_with_free_func(
+               (GDestroyNotify) destroy_enumeration_mapping);
+       bt_field_type_common_initialize(ft, false, release_func, methods);
+       BT_LOGD("Initialized common enumeration field type object: addr=%p, "
+               "int-ft-addr=%p, int-ft-size=%u", ft, container_ft,
+               bt_field_type_common_integer_get_size(container_ft));
+}
+
+BT_HIDDEN
+void bt_field_type_common_string_initialize(
+               struct bt_field_type_common *ft,
+               bt_object_release_func release_func,
+               struct bt_field_type_common_methods *methods)
+{
+       struct bt_field_type_common_string *string_ft = BT_FROM_COMMON(ft);
+
+       BT_LOGD_STR("Initializing common string field type object.");
+       ft->id = BT_FIELD_TYPE_ID_STRING;
+       bt_field_type_common_initialize(ft, true, release_func, methods);
+       string_ft->encoding = BT_STRING_ENCODING_UTF8;
+       ft->alignment = CHAR_BIT;
+       BT_LOGD("Initialized common string field type object: addr=%p", ft);
+}
+
+BT_HIDDEN
+void bt_field_type_common_structure_initialize(
+               struct bt_field_type_common *ft,
+               bt_object_release_func release_func,
+               struct bt_field_type_common_methods *methods)
+{
+       struct bt_field_type_common_structure *struct_ft = BT_FROM_COMMON(ft);
+
+       BT_LOGD_STR("Initializing common structure field type object.");
+       ft->id = BT_FIELD_TYPE_ID_STRUCT;
+       struct_ft->fields = g_ptr_array_new_with_free_func(
+               (GDestroyNotify) destroy_structure_field_common);
+       struct_ft->field_name_to_index = g_hash_table_new(NULL, NULL);
+       bt_field_type_common_initialize(ft, true, release_func, methods);
+       BT_LOGD("Initialized common structure field type object: addr=%p", ft);
+}
+
+BT_HIDDEN
+void bt_field_type_common_array_initialize(
+               struct bt_field_type_common *ft,
+               struct bt_field_type_common *element_ft,
+               unsigned int length, bt_object_release_func release_func,
+               struct bt_field_type_common_methods *methods)
+{
+       struct bt_field_type_common_array *array_ft = BT_FROM_COMMON(ft);
+
+       BT_ASSERT(element_ft);
+       BT_LOGD("Initializing common array field type object: element-ft-addr=%p, "
+               "length=%u", element_ft, length);
+       ft->id = BT_FIELD_TYPE_ID_ARRAY;
+       array_ft->element_ft = bt_get(element_ft);
+       array_ft->length = length;
+       bt_field_type_common_initialize(ft, false, release_func, methods);
+       BT_LOGD("Initialized common array field type object: addr=%p, "
+               "element-ft-addr=%p, length=%u", ft, element_ft, length);
+}
+
+BT_HIDDEN
+void bt_field_type_common_sequence_initialize(
+               struct bt_field_type_common *ft,
+               struct bt_field_type_common *element_ft,
+               const char *length_field_name,
+               bt_object_release_func release_func,
+               struct bt_field_type_common_methods *methods)
+{
+       struct bt_field_type_common_sequence *seq_ft = BT_FROM_COMMON(ft);
+
+       BT_ASSERT(element_ft);
+       BT_ASSERT(length_field_name);
+       BT_ASSERT(bt_identifier_is_valid(length_field_name));
+       BT_LOGD("Initializing common sequence field type object: element-ft-addr=%p, "
+               "length-field-name=\"%s\"", element_ft, length_field_name);
+       ft->id = BT_FIELD_TYPE_ID_SEQUENCE;
+       seq_ft->element_ft = bt_get(element_ft);
+       seq_ft->length_field_name = g_string_new(length_field_name);
+       bt_field_type_common_initialize(ft, false, release_func, methods);
+       BT_LOGD("Initialized common sequence field type object: addr=%p, "
+               "element-ft-addr=%p, length-field-name=\"%s\"",
+               ft, element_ft, length_field_name);
+}
+
+BT_HIDDEN
+void bt_field_type_common_variant_initialize(
+               struct bt_field_type_common *ft,
+               struct bt_field_type_common *tag_ft,
+               const char *tag_name,
+               bt_object_release_func release_func,
+               struct bt_field_type_common_methods *methods)
+{
+       struct bt_field_type_common_variant *var_ft = BT_FROM_COMMON(ft);
+
+       BT_ASSERT(!tag_name || bt_identifier_is_valid(tag_name));
+       BT_LOGD("Initializing common variant field type object: "
+               "tag-ft-addr=%p, tag-field-name=\"%s\"",
+               tag_ft, tag_name);
+       ft->id = BT_FIELD_TYPE_ID_VARIANT;
+       var_ft->tag_name = g_string_new(tag_name);
+       var_ft->field_name_to_index = g_hash_table_new(NULL, NULL);
+       var_ft->fields = g_ptr_array_new_with_free_func(
+               (GDestroyNotify) destroy_structure_field_common);
+
+       if (tag_ft) {
+               var_ft->tag_ft = bt_get(tag_ft);
+       }
+
+       bt_field_type_common_initialize(ft, true, release_func, methods);
+       /* A variant's alignment is undefined */
+       ft->alignment = 0;
+       BT_LOGD("Initialized common variant field type object: addr=%p, "
+               "tag-ft-addr=%p, tag-field-name=\"%s\"",
+               ft, tag_ft, tag_name);
+}
+
+BT_HIDDEN
+void bt_field_type_common_integer_destroy(struct bt_object *obj)
+{
+       struct bt_field_type_common_integer *ft = (void *) obj;
+
+       if (!ft) {
+               return;
+       }
+
+       BT_LOGD("Destroying integer field type object: addr=%p", ft);
+       BT_LOGD_STR("Putting mapped clock class.");
+       bt_put(ft->mapped_clock_class);
+       g_free(ft);
+}
+
+BT_HIDDEN
+void bt_field_type_common_floating_point_destroy(struct bt_object *obj)
+{
+       struct bt_field_type_common_floating_point *ft = (void *) obj;
+
+       if (!ft) {
+               return;
+       }
+
+       BT_LOGD("Destroying floating point number field type object: addr=%p", ft);
+       g_free(ft);
+}
+
+BT_HIDDEN
+void bt_field_type_common_enumeration_destroy_recursive(struct bt_object *obj)
+{
+       struct bt_field_type_common_enumeration *ft = (void *) obj;
+
+       if (!ft) {
+               return;
+       }
+
+       BT_LOGD("Destroying enumeration field type object: addr=%p", ft);
+       g_ptr_array_free(ft->entries, TRUE);
+       BT_LOGD_STR("Putting container field type.");
+       bt_put(ft->container_ft);
+       g_free(ft);
+}
+
+BT_HIDDEN
+void bt_field_type_common_string_destroy(struct bt_object *obj)
+{
+       struct bt_field_type_common_string *ft = (void *) obj;
+
+       if (!ft) {
+               return;
+       }
+
+       BT_LOGD("Destroying string field type object: addr=%p", ft);
+       g_free(ft);
+}
+
+
+BT_HIDDEN
+void bt_field_type_common_structure_destroy_recursive(struct bt_object *obj)
+{
+       struct bt_field_type_common_structure *ft = (void *) obj;
+
+       if (!ft) {
+               return;
+       }
+
+       BT_LOGD("Destroying structure field type object: addr=%p", ft);
+       g_ptr_array_free(ft->fields, TRUE);
+       g_hash_table_destroy(ft->field_name_to_index);
+       g_free(ft);
+}
+
+BT_HIDDEN
+void bt_field_type_common_array_destroy_recursive(struct bt_object *obj)
+{
+       struct bt_field_type_common_array *ft = (void *) obj;
+
+       if (!ft) {
+               return;
+       }
+
+       BT_LOGD("Destroying array field type object: addr=%p", ft);
+       BT_LOGD_STR("Putting element field type.");
+       bt_put(ft->element_ft);
+       g_free(ft);
+}
+
+BT_HIDDEN
+void bt_field_type_common_sequence_destroy_recursive(struct bt_object *obj)
+{
+       struct bt_field_type_common_sequence *ft = (void *) obj;
+
+       if (!ft) {
+               return;
+       }
+
+       BT_LOGD("Destroying sequence field type object: addr=%p", ft);
+       BT_LOGD_STR("Putting element field type.");
+       bt_put(ft->element_ft);
+       g_string_free(ft->length_field_name, TRUE);
+       BT_LOGD_STR("Putting length field path.");
+       bt_put(ft->length_field_path);
+       g_free(ft);
+}
+
+BT_HIDDEN
+void bt_field_type_common_variant_destroy_recursive(struct bt_object *obj)
+{
+       struct bt_field_type_common_variant *ft = (void *) obj;
+
+       if (!ft) {
+               return;
+       }
+
+       BT_LOGD("Destroying variant field type object: addr=%p", ft);
+       g_ptr_array_free(ft->fields, TRUE);
+       g_hash_table_destroy(ft->field_name_to_index);
+       g_string_free(ft->tag_name, TRUE);
+       BT_LOGD_STR("Putting tag field type.");
+       bt_put(ft->tag_ft);
+       BT_LOGD_STR("Putting tag field path.");
+       bt_put(ft->tag_field_path);
+       g_free(ft);
+}
+
+struct range_overlap_query {
+       union {
+               uint64_t _unsigned;
+               int64_t _signed;
+       } range_start;
+
+       union {
+               uint64_t _unsigned;
+               int64_t _signed;
+       } range_end;
+       int overlaps;
+       GQuark mapping_name;
+};
+
 static
 void check_ranges_overlap(gpointer element, gpointer query)
 {
@@ -404,38 +581,14 @@ gint compare_enumeration_mappings_unsigned(struct enumeration_mapping **a,
        return ((*a)->range_start._unsigned < (*b)->range_start._unsigned) ? -1 : 1;
 }
 
-static
-void bt_field_type_init(struct bt_field_type *type, bt_bool init_bo)
-{
-       BT_ASSERT(type && (type->id > BT_FIELD_TYPE_ID_UNKNOWN) &&
-               (type->id < BT_FIELD_TYPE_ID_NR));
-
-       bt_object_init(type, bt_field_type_destroy);
-       type->freeze = type_freeze_funcs[type->id];
-       type->serialize = type_serialize_funcs[type->id];
-
-       if (init_bo) {
-               int ret;
-               const enum bt_byte_order bo = BT_BYTE_ORDER_NATIVE;
-
-               BT_LOGD("Setting initial field type's byte order: bo=%s",
-                       bt_byte_order_string(bo));
-               ret = bt_field_type_set_byte_order(type, bo);
-               BT_ASSERT(ret == 0);
-       }
-
-       type->alignment = 1;
-}
-
 static
 int add_structure_field(GPtrArray *fields,
                GHashTable *field_name_to_index,
-               struct bt_field_type *field_type,
-               const char *field_name)
+               struct bt_field_type_common *field_type, const char *field_name)
 {
        int ret = 0;
        GQuark name_quark = g_quark_from_string(field_name);
-       struct structure_field *field;
+       struct structure_field_common *field;
 
        /* Make sure structure does not contain a field of the same name */
        if (g_hash_table_lookup_extended(field_name_to_index,
@@ -446,7 +599,7 @@ int add_structure_field(GPtrArray *fields,
                goto end;
        }
 
-       field = g_new0(struct structure_field, 1);
+       field = g_new0(struct structure_field_common, 1);
        if (!field) {
                BT_LOGE_STR("Failed to allocate one structure/variant field type field.");
                ret = -1;
@@ -457,8 +610,7 @@ int add_structure_field(GPtrArray *fields,
        field->name = name_quark;
        field->type = field_type;
        g_hash_table_insert(field_name_to_index,
-               GUINT_TO_POINTER(name_quark),
-               GUINT_TO_POINTER(fields->len));
+               GUINT_TO_POINTER(name_quark), GUINT_TO_POINTER(fields->len));
        g_ptr_array_add(fields, field);
        BT_LOGV("Added structure/variant field type field: field-ft-addr=%p, "
                "field-name=\"%s\"", field_type, field_name);
@@ -466,33 +618,17 @@ end:
        return ret;
 }
 
-static
-void bt_field_type_destroy(struct bt_object *obj)
-{
-       struct bt_field_type *type;
-       enum bt_field_type_id type_id;
-
-       type = container_of(obj, struct bt_field_type, base);
-       type_id = type->id;
-       BT_ASSERT(type_id > BT_FIELD_TYPE_ID_UNKNOWN &&
-               type_id < BT_FIELD_TYPE_ID_NR);
-       type_destroy_funcs[type_id](type);
-}
-
-static
-int bt_field_type_integer_validate(struct bt_field_type *type)
+BT_HIDDEN
+int bt_field_type_common_integer_validate(struct bt_field_type_common *ft)
 {
        int ret = 0;
+       struct bt_field_type_common_integer *int_ft = BT_FROM_COMMON(ft);
 
-       struct bt_field_type_integer *integer =
-               container_of(type, struct bt_field_type_integer,
-                       parent);
-
-       if (integer->mapped_clock && integer->is_signed) {
+       if (int_ft->mapped_clock_class && int_ft->is_signed) {
                BT_LOGW("Invalid integer field type: cannot be signed and have a mapped clock class: "
                        "ft-addr=%p, clock-class-addr=%p, clock-class-name=\"%s\"",
-                       type, integer->mapped_clock,
-                       bt_clock_class_get_name(integer->mapped_clock));
+                       ft, int_ft->mapped_clock_class,
+                       bt_clock_class_get_name(int_ft->mapped_clock_class));
                ret = -1;
                goto end;
        }
@@ -502,22 +638,21 @@ end:
 }
 
 static
-struct enumeration_mapping *get_enumeration_mapping(
-               struct bt_field_type *type, uint64_t index)
+struct enumeration_mapping *bt_field_type_common_enumeration_get_mapping_by_index(
+               struct bt_field_type_common *ft, uint64_t index)
 {
+       struct bt_field_type_common_enumeration *enum_ft = BT_FROM_COMMON(ft);
        struct enumeration_mapping *mapping = NULL;
-       struct bt_field_type_enumeration *enumeration;
 
-       enumeration = container_of(type, struct bt_field_type_enumeration,
-               parent);
-       if (index >= enumeration->entries->len) {
+       if (index >= enum_ft->entries->len) {
                BT_LOGW("Invalid parameter: index is out of bounds: "
                        "addr=%p, index=%" PRIu64 ", count=%u",
-                       type, index, enumeration->entries->len);
+                       ft, index, enum_ft->entries->len);
                goto end;
        }
 
-       mapping = g_ptr_array_index(enumeration->entries, index);
+       mapping = g_ptr_array_index(enum_ft->entries, index);
+
 end:
        return mapping;
 }
@@ -527,35 +662,32 @@ end:
  * Only used when freezing an enumeration.
  */
 static
-void set_enumeration_range_overlap(
-               struct bt_field_type *type)
+void bt_field_type_common_enumeration_set_range_overlap(
+               struct bt_field_type_common_enumeration *ft)
 {
        int64_t i, j, len;
-       struct bt_field_type *container_type;
-       struct bt_field_type_enumeration *enumeration_type;
        int is_signed;
 
        BT_LOGV("Setting enumeration field type's overlap flag: addr=%p",
-               type);
-       enumeration_type = container_of(type,
-                       struct bt_field_type_enumeration, parent);
-
-       len = enumeration_type->entries->len;
-       container_type = enumeration_type->container;
-       is_signed = bt_field_type_integer_is_signed(container_type);
+               ft);
+       len = ft->entries->len;
+       is_signed = bt_field_type_common_integer_is_signed(
+               BT_TO_COMMON(ft->container_ft));
 
        for (i = 0; i < len; i++) {
                for (j = i + 1; j < len; j++) {
                        struct enumeration_mapping *mapping[2];
 
-                       mapping[0] = get_enumeration_mapping(type, i);
-                       mapping[1] = get_enumeration_mapping(type, j);
+                       mapping[0] = bt_field_type_common_enumeration_get_mapping_by_index(
+                               BT_TO_COMMON(ft), i);
+                       mapping[1] = bt_field_type_common_enumeration_get_mapping_by_index(
+                               BT_TO_COMMON(ft), j);
                        if (is_signed) {
                                if (mapping[0]->range_start._signed
                                                        <= mapping[1]->range_end._signed
                                                && mapping[0]->range_end._signed
                                                        >= mapping[1]->range_start._signed) {
-                                       enumeration_type->has_overlapping_ranges = BT_TRUE;
+                                       ft->has_overlapping_ranges = BT_TRUE;
                                        goto end;
                                }
                        } else {
@@ -563,7 +695,7 @@ void set_enumeration_range_overlap(
                                                        <= mapping[1]->range_end._unsigned
                                                && mapping[0]->range_end._unsigned
                                                        >= mapping[1]->range_start._unsigned) {
-                                       enumeration_type->has_overlapping_ranges = BT_TRUE;
+                                       ft->has_overlapping_ranges = BT_TRUE;
                                        goto end;
                                }
                        }
@@ -571,103 +703,92 @@ void set_enumeration_range_overlap(
        }
 
 end:
-       if (enumeration_type->has_overlapping_ranges) {
+       if (ft->has_overlapping_ranges) {
                BT_LOGV_STR("Enumeration field type has overlapping ranges.");
        } else {
                BT_LOGV_STR("Enumeration field type has no overlapping ranges.");
        }
 }
 
-static
-int bt_field_type_enumeration_validate(struct bt_field_type *type)
+BT_HIDDEN
+int bt_field_type_common_enumeration_validate_recursive(
+               struct bt_field_type_common *ft)
 {
        int ret = 0;
+       struct bt_field_type_common_enumeration *enum_ft = BT_FROM_COMMON(ft);
 
-       struct bt_field_type_enumeration *enumeration =
-               container_of(type, struct bt_field_type_enumeration,
-                       parent);
-       struct bt_field_type *container_type =
-               bt_field_type_enumeration_get_container_type(type);
-
-       BT_ASSERT(container_type);
-       ret = bt_field_type_validate(container_type);
+       ret = bt_field_type_common_integer_validate(
+                       BT_TO_COMMON(enum_ft->container_ft));
        if (ret) {
                BT_LOGW("Invalid enumeration field type: container type is invalid: "
                        "enum-ft-addr=%p, int-ft-addr=%p",
-                       type, container_type);
+                       ft, enum_ft->container_ft);
                goto end;
        }
 
        /* Ensure enum has entries */
-       if (enumeration->entries->len == 0) {
+       if (enum_ft->entries->len == 0) {
                BT_LOGW("Invalid enumeration field type: no entries: "
-                       "addr=%p", type);
+                       "addr=%p", ft);
                ret = -1;
                goto end;
        }
 
 end:
-       BT_PUT(container_type);
        return ret;
 }
 
-static
-int bt_field_type_sequence_validate(struct bt_field_type *type)
+BT_HIDDEN
+int bt_field_type_common_sequence_validate_recursive(
+               struct bt_field_type_common *ft)
 {
        int ret = 0;
-       struct bt_field_type *element_type = NULL;
-       struct bt_field_type_sequence *sequence =
-               container_of(type, struct bt_field_type_sequence,
-               parent);
+       struct bt_field_type_common_sequence *seq_ft = BT_FROM_COMMON(ft);
 
        /* Length field name should be set at this point */
-       if (sequence->length_field_name->len == 0) {
+       if (seq_ft->length_field_name->len == 0) {
                BT_LOGW("Invalid sequence field type: no length field name: "
-                       "addr=%p", type);
+                       "addr=%p", ft);
                ret = -1;
                goto end;
        }
 
-       element_type = bt_field_type_sequence_get_element_type(type);
-       BT_ASSERT(element_type);
-       ret = bt_field_type_validate(element_type);
+       ret = bt_field_type_common_validate(seq_ft->element_ft);
        if (ret) {
                BT_LOGW("Invalid sequence field type: invalid element field type: "
                        "seq-ft-addr=%p, element-ft-add=%p",
-                       type, element_type);
+                       ft, seq_ft->element_ft);
        }
 
 end:
-       BT_PUT(element_type);
-
        return ret;
 }
 
-static
-int bt_field_type_array_validate(struct bt_field_type *type)
+BT_HIDDEN
+int bt_field_type_common_array_validate_recursive(
+               struct bt_field_type_common *ft)
 {
        int ret = 0;
-       struct bt_field_type *element_type = NULL;
+       struct bt_field_type_common_array *array_ft = BT_FROM_COMMON(ft);
 
-       element_type = bt_field_type_array_get_element_type(type);
-       BT_ASSERT(element_type);
-       ret = bt_field_type_validate(element_type);
+       ret = bt_field_type_common_validate(array_ft->element_ft);
        if (ret) {
                BT_LOGW("Invalid array field type: invalid element field type: "
                        "array-ft-addr=%p, element-ft-add=%p",
-                       type, element_type);
+                       ft, array_ft->element_ft);
        }
 
-       BT_PUT(element_type);
        return ret;
 }
 
-static
-int bt_field_type_structure_validate(struct bt_field_type *type)
+BT_HIDDEN
+int bt_field_type_common_structure_validate_recursive(
+               struct bt_field_type_common *ft)
 {
        int ret = 0;
-       struct bt_field_type *child_type = NULL;
-       int64_t field_count = bt_field_type_structure_get_field_count(type);
+       struct bt_field_type_common *child_ft = NULL;
+       int64_t field_count =
+               bt_field_type_common_structure_get_field_count(ft);
        int64_t i;
 
        BT_ASSERT(field_count >= 0);
@@ -675,70 +796,68 @@ int bt_field_type_structure_validate(struct bt_field_type *type)
        for (i = 0; i < field_count; ++i) {
                const char *field_name;
 
-               ret = bt_field_type_structure_get_field_by_index(type,
-                       &field_name, &child_type, i);
+               ret = bt_field_type_common_structure_get_field_by_index(ft,
+                       &field_name, &child_ft, i);
                BT_ASSERT(ret == 0);
-               ret = bt_field_type_validate(child_type);
+               ret = bt_field_type_common_validate(child_ft);
                if (ret) {
                        BT_LOGW("Invalid structure field type: "
                                "a contained field type is invalid: "
                                "struct-ft-addr=%p, field-ft-addr=%p, "
                                "field-name=\"%s\", field-index=%" PRId64,
-                               type, child_type, field_name, i);
+                               ft, child_ft, field_name, i);
                        goto end;
                }
 
-               BT_PUT(child_type);
+               BT_PUT(child_ft);
        }
 
 end:
-       BT_PUT(child_type);
-
+       BT_PUT(child_ft);
        return ret;
 }
 
 static
-bt_bool bt_field_type_enumeration_has_overlapping_ranges(
-               struct bt_field_type_enumeration *enumeration_type)
+bt_bool bt_field_type_common_enumeration_has_overlapping_ranges(
+               struct bt_field_type_common_enumeration *enum_ft)
 {
-       if (!enumeration_type->parent.frozen) {
-               set_enumeration_range_overlap(&enumeration_type->parent);
+       if (!enum_ft->common.frozen) {
+               bt_field_type_common_enumeration_set_range_overlap(enum_ft);
        }
-       return enumeration_type->has_overlapping_ranges;
+
+       return enum_ft->has_overlapping_ranges;
 }
 
-static
-int bt_field_type_variant_validate(struct bt_field_type *type)
+BT_HIDDEN
+int bt_field_type_common_variant_validate_recursive(
+               struct bt_field_type_common *ft)
 {
        int ret = 0;
        int64_t field_count;
-       struct bt_field_type *child_type = NULL;
-       struct bt_field_type_variant *variant =
-               container_of(type, struct bt_field_type_variant,
-                       parent);
+       struct bt_field_type_common *child_ft = NULL;
+       struct bt_field_type_common_variant *var_ft = BT_FROM_COMMON(ft);
        int64_t i;
 
-       if (variant->tag_name->len == 0) {
+       if (var_ft->tag_name->len == 0) {
                BT_LOGW("Invalid variant field type: no tag field name: "
-                       "addr=%p", type);
+                       "addr=%p", ft);
                ret = -1;
                goto end;
        }
 
-       if (!variant->tag) {
+       if (!var_ft->tag_ft) {
                BT_LOGW("Invalid variant field type: no tag field type: "
-                       "addr=%p, tag-field-name=\"%s\"", type,
-                       variant->tag_name->str);
+                       "addr=%p, tag-field-name=\"%s\"", var_ft,
+                       var_ft->tag_name->str);
                ret = -1;
                goto end;
        }
 
-       if (bt_field_type_enumeration_has_overlapping_ranges(
-                       variant->tag)) {
+       if (bt_field_type_common_enumeration_has_overlapping_ranges(var_ft->tag_ft)) {
                BT_LOGW("Invalid variant field type: enumeration tag field type has overlapping ranges: "
                        "variant-ft-addr=%p, tag-field-name=\"%s\", "
-                       "enum-ft-addr=%p", type, variant->tag_name->str,
-                       variant->tag);
+                       "enum-ft-addr=%p", ft, var_ft->tag_name->str,
+                       var_ft->tag_ft);
                ret = -1;
                goto end;
        }
@@ -757,11 +876,11 @@ int bt_field_type_variant_validate(struct bt_field_type *type)
         * enumeration while reading a variant field, an error will be
         * generated at that point (while reading the stream).
         */
-       field_count = bt_field_type_variant_get_field_count(type);
+       field_count = bt_field_type_common_variant_get_field_count(ft);
        if (field_count < 0) {
                BT_LOGW("Invalid variant field type: no fields: "
                        "addr=%p, tag-field-name=\"%s\"",
-                       type, variant->tag_name->str);
+                       ft, var_ft->tag_name->str);
                ret = -1;
                goto end;
        }
@@ -769,27 +888,26 @@ int bt_field_type_variant_validate(struct bt_field_type *type)
        for (i = 0; i < field_count; ++i) {
                const char *field_name;
 
-               ret = bt_field_type_variant_get_field_by_index(type,
-                       &field_name, &child_type, i);
+               ret = bt_field_type_common_variant_get_field_by_index(ft,
+                       &field_name, &child_ft, i);
                BT_ASSERT(ret == 0);
-               ret = bt_field_type_validate(child_type);
+               ret = bt_field_type_common_validate(child_ft);
                if (ret) {
                        BT_LOGW("Invalid variant field type: "
                                "a contained field type is invalid: "
                                "variant-ft-addr=%p, tag-field-name=\"%s\", "
                                "field-ft-addr=%p, field-name=\"%s\", "
                                "field-index=%" PRId64,
-                               type, variant->tag_name->str, child_type,
+                               ft, var_ft->tag_name->str, child_ft,
                                field_name, i);
                        goto end;
                }
 
-               BT_PUT(child_type);
+               BT_PUT(child_ft);
        }
 
 end:
-       BT_PUT(child_type);
-
+       BT_PUT(child_ft);
        return ret;
 }
 
@@ -800,26 +918,25 @@ end:
  * applicable.
  */
 BT_HIDDEN
-int bt_field_type_validate(struct bt_field_type *type)
+int bt_field_type_common_validate(struct bt_field_type_common *ft)
 {
        int ret = 0;
-       enum bt_field_type_id id = bt_field_type_get_type_id(type);
 
-       BT_ASSERT(type);
+       BT_ASSERT(ft);
 
-       if (type->valid) {
+       if (ft->valid) {
                /* Already marked as valid */
                goto end;
        }
 
-       if (type_validate_funcs[id]) {
-               ret = type_validate_funcs[id](type);
+       if (ft->methods->validate) {
+               ret = ft->methods->validate(ft);
        }
 
-       if (!ret && type->frozen) {
+       if (ret == 0 && ft->frozen) {
                /* Field type is valid */
-               BT_LOGV("Marking field type as valid: addr=%p", type);
-               type->valid = 1;
+               BT_LOGV("Marking field type as valid: addr=%p", ft);
+               ft->valid = 1;
        }
 
 end:
@@ -828,169 +945,202 @@ end:
 
 struct bt_field_type *bt_field_type_integer_create(unsigned int size)
 {
-       struct bt_field_type_integer *integer =
-               g_new0(struct bt_field_type_integer, 1);
+       struct bt_field_type_common_integer *integer = NULL;
 
        BT_LOGD("Creating integer field type object: size=%u", size);
 
-       if (!integer) {
-               BT_LOGE_STR("Failed to allocate one integer field type.");
-               return NULL;
-       }
-
        if (size == 0 || size > 64) {
                BT_LOGW("Invalid parameter: size must be between 1 and 64: "
                        "size=%u", size);
-               return NULL;
+               goto error;
+       }
+
+       integer = g_new0(struct bt_field_type_common_integer, 1);
+       if (!integer) {
+               BT_LOGE_STR("Failed to allocate one integer field type.");
+               goto error;
        }
 
-       integer->parent.id = BT_FIELD_TYPE_ID_INTEGER;
-       integer->size = size;
-       integer->base = BT_INTEGER_BASE_DECIMAL;
-       integer->encoding = BT_STRING_ENCODING_NONE;
-       bt_field_type_init(&integer->parent, TRUE);
+       bt_field_type_common_integer_initialize(BT_TO_COMMON(integer),
+               size, bt_field_type_common_integer_destroy,
+               &bt_field_type_integer_methods);
        BT_LOGD("Created integer field type object: addr=%p, size=%u",
-               &integer->parent, size);
-       return &integer->parent;
+               integer, size);
+       goto end;
+
+error:
+       BT_PUT(integer);
+
+end:
+       return (void *) integer;
 }
 
-int bt_field_type_integer_get_size(struct bt_field_type *type)
+BT_HIDDEN
+int bt_field_type_common_integer_get_size(struct bt_field_type_common *ft)
 {
-       struct bt_field_type_integer *integer;
+       struct bt_field_type_common_integer *int_ft = BT_FROM_COMMON(ft);
+
+       BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+       BT_ASSERT_PRE_FT_COMMON_HAS_ID(ft, BT_FIELD_TYPE_ID_INTEGER,
+               "Field type");
+       return (int) int_ft->size;
+}
 
-       BT_ASSERT_PRE_NON_NULL(type, "Field type");
-       BT_ASSERT_PRE_FT_HAS_ID(type, BT_FIELD_TYPE_ID_INTEGER, "Field type");
-       integer = container_of(type, struct bt_field_type_integer, parent);
-       return (int) integer->size;
+int bt_field_type_integer_get_size(struct bt_field_type *ft)
+{
+       return bt_field_type_common_integer_get_size((void *) ft);
 }
 
-int bt_ctf_field_type_integer_get_signed(struct bt_field_type *type)
+BT_HIDDEN
+bt_bool bt_field_type_common_integer_is_signed(struct bt_field_type_common *ft)
 {
-       struct bt_field_type_integer *integer;
+       struct bt_field_type_common_integer *int_ft = BT_FROM_COMMON(ft);
 
-       BT_ASSERT_PRE_NON_NULL(type, "Field type");
-       BT_ASSERT_PRE_FT_HAS_ID(type, BT_FIELD_TYPE_ID_INTEGER, "Field type");
-       integer = container_of(type, struct bt_field_type_integer, parent);
-       return integer->is_signed;
+       BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+       BT_ASSERT_PRE_FT_COMMON_HAS_ID(ft, BT_FIELD_TYPE_ID_INTEGER,
+               "Field type");
+       return int_ft->is_signed;
 }
 
-bt_bool bt_field_type_integer_is_signed(
-               struct bt_field_type *int_field_type)
+bt_bool bt_field_type_integer_is_signed(struct bt_field_type *ft)
 {
-       return bt_ctf_field_type_integer_get_signed(int_field_type) ?
-               BT_TRUE : BT_FALSE;
+       return bt_field_type_common_integer_is_signed((void *) ft);
 }
 
-int bt_field_type_integer_set_is_signed(struct bt_field_type *type,
+BT_HIDDEN
+int bt_field_type_common_integer_set_is_signed(struct bt_field_type_common *ft,
                bt_bool is_signed)
 {
        int ret = 0;
-       struct bt_field_type_integer *integer;
+       struct bt_field_type_common_integer *int_ft = BT_FROM_COMMON(ft);
 
-       if (!type) {
+       if (!ft) {
                BT_LOGW_STR("Invalid parameter: field type is NULL.");
                ret = -1;
                goto end;
        }
 
-       if (type->frozen) {
+       if (ft->frozen) {
                BT_LOGW("Invalid parameter: field type is frozen: addr=%p",
-                       type);
+                       ft);
                ret = -1;
                goto end;
        }
 
-       if (type->id != BT_FIELD_TYPE_ID_INTEGER) {
+       if (ft->id != BT_FIELD_TYPE_ID_INTEGER) {
                BT_LOGW("Invalid parameter: field type is not an integer field type: "
-                       "addr=%p, ft-id=%s", type,
-                       bt_field_type_id_string(type->id));
+                       "addr=%p, ft-id=%s", ft,
+                       bt_common_field_type_id_string(ft->id));
                ret = -1;
                goto end;
        }
 
-       integer = container_of(type, struct bt_field_type_integer, parent);
-       integer->is_signed = !!is_signed;
+       int_ft->is_signed = !!is_signed;
        BT_LOGV("Set integer field type's signedness: addr=%p, is-signed=%d",
-               type, is_signed);
+               ft, is_signed);
+
 end:
        return ret;
 }
 
-int bt_field_type_integer_set_size(struct bt_field_type *type,
+int bt_field_type_integer_set_is_signed(struct bt_field_type *ft,
+               bt_bool is_signed)
+{
+       return bt_field_type_common_integer_set_is_signed((void *) ft,
+               is_signed);
+}
+
+BT_HIDDEN
+int bt_field_type_common_integer_set_size(struct bt_field_type_common *ft,
                unsigned int size)
 {
        int ret = 0;
-       struct bt_field_type_integer *integer;
+       struct bt_field_type_common_integer *int_ft = BT_FROM_COMMON(ft);
 
-       if (!type) {
+       if (!ft) {
                BT_LOGW_STR("Invalid parameter: field type is NULL.");
                ret = -1;
                goto end;
        }
 
-       if (type->frozen) {
+       if (ft->frozen) {
                BT_LOGW("Invalid parameter: field type is frozen: addr=%p",
-                       type);
+                       ft);
                ret = -1;
                goto end;
        }
 
-       if (type->id != BT_FIELD_TYPE_ID_INTEGER) {
+       if (ft->id != BT_FIELD_TYPE_ID_INTEGER) {
                BT_LOGW("Invalid parameter: field type is not an integer field type: "
-                       "addr=%p, ft-id=%s", type,
-                       bt_field_type_id_string(type->id));
+                       "addr=%p, ft-id=%s", ft,
+                       bt_common_field_type_id_string(ft->id));
                ret = -1;
                goto end;
        }
 
        if (size == 0 || size > 64) {
                BT_LOGW("Invalid parameter: size must be between 1 and 64: "
-                       "addr=%p, size=%u", type, size);
+                       "addr=%p, size=%u", ft, size);
                ret = -1;
                goto end;
        }
 
-       integer = container_of(type, struct bt_field_type_integer, parent);
-       integer->size = size;
+       int_ft->size = size;
        BT_LOGV("Set integer field type's size: addr=%p, size=%u",
-               type, size);
+               ft, size);
+
 end:
        return ret;
 }
 
-enum bt_integer_base bt_field_type_integer_get_base(
-               struct bt_field_type *type)
+int bt_field_type_integer_set_size(struct bt_field_type *ft,
+               unsigned int size)
+{
+       return bt_field_type_common_integer_set_size((void *) ft, size);
+}
+
+BT_HIDDEN
+enum bt_integer_base bt_field_type_common_integer_get_base(
+               struct bt_field_type_common *ft)
 {
-       struct bt_field_type_integer *integer;
+       struct bt_field_type_common_integer *int_ft = BT_FROM_COMMON(ft);
+
+       BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+       BT_ASSERT_PRE_FT_COMMON_HAS_ID(ft, BT_FIELD_TYPE_ID_INTEGER,
+               "Field type");
+       return int_ft->base;
+}
 
-       BT_ASSERT_PRE_NON_NULL(type, "Field type");
-       BT_ASSERT_PRE_FT_HAS_ID(type, BT_FIELD_TYPE_ID_INTEGER, "Field type");
-       integer = container_of(type, struct bt_field_type_integer, parent);
-       return integer->base;
+enum bt_integer_base bt_field_type_integer_get_base(
+               struct bt_field_type *ft)
+{
+       return bt_field_type_common_integer_get_base((void *) ft);
 }
 
-int bt_field_type_integer_set_base(struct bt_field_type *type,
+BT_HIDDEN
+int bt_field_type_common_integer_set_base(struct bt_field_type_common *ft,
                enum bt_integer_base base)
 {
        int ret = 0;
+       struct bt_field_type_common_integer *int_ft = BT_FROM_COMMON(ft);
 
-       if (!type) {
+       if (!ft) {
                BT_LOGW_STR("Invalid parameter: field type is NULL.");
                ret = -1;
                goto end;
        }
 
-       if (type->frozen) {
+       if (ft->frozen) {
                BT_LOGW("Invalid parameter: field type is frozen: addr=%p",
-                       type);
+                       ft);
                ret = -1;
                goto end;
        }
 
-       if (type->id != BT_FIELD_TYPE_ID_INTEGER) {
+       if (ft->id != BT_FIELD_TYPE_ID_INTEGER) {
                BT_LOGW("Invalid parameter: field type is not an integer field type: "
-                       "addr=%p, ft-id=%s", type,
-                       bt_field_type_id_string(type->id));
+                       "addr=%p, ft-id=%s", ft,
+                       bt_common_field_type_id_string(ft->id));
                ret = -1;
                goto end;
        }
@@ -1002,58 +1152,70 @@ int bt_field_type_integer_set_base(struct bt_field_type *type,
        case BT_INTEGER_BASE_DECIMAL:
        case BT_INTEGER_BASE_HEXADECIMAL:
        {
-               struct bt_field_type_integer *integer = container_of(type,
-                       struct bt_field_type_integer, parent);
-               integer->base = base;
+               int_ft->base = base;
                break;
        }
        default:
                BT_LOGW("Invalid parameter: unknown integer field type base: "
-                       "addr=%p, base=%d", type, base);
+                       "addr=%p, base=%d", ft, base);
                ret = -1;
        }
 
        BT_LOGV("Set integer field type's base: addr=%p, base=%s",
-               type, bt_integer_base_string(base));
+               ft, bt_common_integer_base_string(base));
 
 end:
        return ret;
 }
 
-enum bt_string_encoding bt_field_type_integer_get_encoding(
-               struct bt_field_type *type)
+int bt_field_type_integer_set_base(struct bt_field_type *ft,
+               enum bt_integer_base base)
+{
+       return bt_field_type_common_integer_set_base((void *) ft, base);
+}
+
+BT_HIDDEN
+enum bt_string_encoding bt_field_type_common_integer_get_encoding(
+               struct bt_field_type_common *ft)
 {
-       struct bt_field_type_integer *integer;
+       struct bt_field_type_common_integer *int_ft = BT_FROM_COMMON(ft);
+
+       BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+       BT_ASSERT_PRE_FT_COMMON_HAS_ID(ft, BT_FIELD_TYPE_ID_INTEGER,
+               "Field type");
+       return int_ft->encoding;
+}
 
-       BT_ASSERT_PRE_NON_NULL(type, "Field type");
-       BT_ASSERT_PRE_FT_HAS_ID(type, BT_FIELD_TYPE_ID_INTEGER, "Field type");
-       integer = container_of(type, struct bt_field_type_integer, parent);
-       return integer->encoding;
+enum bt_string_encoding bt_field_type_integer_get_encoding(
+               struct bt_field_type *ft)
+{
+       return bt_field_type_common_integer_get_encoding((void *) ft);
 }
 
-int bt_field_type_integer_set_encoding(struct bt_field_type *type,
+BT_HIDDEN
+int bt_field_type_common_integer_set_encoding(struct bt_field_type_common *ft,
                enum bt_string_encoding encoding)
 {
        int ret = 0;
-       struct bt_field_type_integer *integer;
+       struct bt_field_type_common_integer *int_ft = BT_FROM_COMMON(ft);
 
-       if (!type) {
+       if (!ft) {
                BT_LOGW_STR("Invalid parameter: field type is NULL.");
                ret = -1;
                goto end;
        }
 
-       if (type->frozen) {
+       if (ft->frozen) {
                BT_LOGW("Invalid parameter: field type is frozen: addr=%p",
-                       type);
+                       ft);
                ret = -1;
                goto end;
        }
 
-       if (type->id != BT_FIELD_TYPE_ID_INTEGER) {
+       if (ft->id != BT_FIELD_TYPE_ID_INTEGER) {
                BT_LOGW("Invalid parameter: field type is not an integer field type: "
-                       "addr=%p, ft-id=%s", type,
-                       bt_field_type_id_string(type->id));
+                       "addr=%p, ft-id=%s", ft,
+                       bt_common_field_type_id_string(ft->id));
                ret = -1;
                goto end;
        }
@@ -1062,102 +1224,117 @@ int bt_field_type_integer_set_encoding(struct bt_field_type *type,
                        encoding != BT_STRING_ENCODING_ASCII &&
                        encoding != BT_STRING_ENCODING_NONE) {
                BT_LOGW("Invalid parameter: unknown string encoding: "
-                       "addr=%p, encoding=%d", type, encoding);
+                       "addr=%p, encoding=%d", ft, encoding);
                ret = -1;
                goto end;
        }
 
-       integer = container_of(type, struct bt_field_type_integer, parent);
-       integer->encoding = encoding;
+       int_ft->encoding = encoding;
        BT_LOGV("Set integer field type's encoding: addr=%p, encoding=%s",
-               type, bt_string_encoding_string(encoding));
+               ft, bt_common_string_encoding_string(encoding));
+
 end:
        return ret;
 }
 
-struct bt_clock_class *bt_field_type_integer_get_mapped_clock_class(
-               struct bt_field_type *type)
+int bt_field_type_integer_set_encoding(struct bt_field_type *ft,
+               enum bt_string_encoding encoding)
+{
+       return bt_field_type_common_integer_set_encoding((void *) ft, encoding);
+}
+
+BT_HIDDEN
+struct bt_clock_class *bt_field_type_common_integer_get_mapped_clock_class(
+               struct bt_field_type_common *ft)
 {
-       struct bt_field_type_integer *integer;
+       struct bt_field_type_common_integer *int_ft = BT_FROM_COMMON(ft);
+
+       BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+       BT_ASSERT_PRE_FT_COMMON_HAS_ID(ft, BT_FIELD_TYPE_ID_INTEGER,
+               "Field type");
+       return bt_get(int_ft->mapped_clock_class);
+}
 
-       BT_ASSERT_PRE_NON_NULL(type, "Field type");
-       BT_ASSERT_PRE_FT_HAS_ID(type, BT_FIELD_TYPE_ID_INTEGER, "Field type");
-       integer = container_of(type, struct bt_field_type_integer, parent);
-       return bt_get(integer->mapped_clock);
+struct bt_clock_class *bt_field_type_integer_get_mapped_clock_class(
+               struct bt_field_type *ft)
+{
+       return bt_field_type_common_integer_get_mapped_clock_class((void *) ft);
 }
 
 BT_HIDDEN
-int bt_field_type_integer_set_mapped_clock_class_no_check(
-               struct bt_field_type *type,
+int bt_field_type_common_integer_set_mapped_clock_class_no_check_frozen(
+               struct bt_field_type_common *ft,
                struct bt_clock_class *clock_class)
 {
-       struct bt_field_type_integer *integer;
+       struct bt_field_type_common_integer *int_ft = BT_FROM_COMMON(ft);
        int ret = 0;
 
-       if (!type) {
-               BT_LOGW_STR("Invalid parameter: field type is NULL.");
-               ret = -1;
-               goto end;
-       }
-
        if (!clock_class) {
                BT_LOGW_STR("Invalid parameter: clock class is NULL.");
                ret = -1;
                goto end;
        }
 
-       if (type->id != BT_FIELD_TYPE_ID_INTEGER) {
+       if (ft->id != BT_FIELD_TYPE_ID_INTEGER) {
                BT_LOGW("Invalid parameter: field type is not an integer field type: "
-                       "addr=%p, ft-id=%s", type,
-                       bt_field_type_id_string(type->id));
+                       "addr=%p, ft-id=%s", ft,
+                       bt_common_field_type_id_string(ft->id));
                goto end;
        }
 
        if (!bt_clock_class_is_valid(clock_class)) {
                BT_LOGW("Invalid parameter: clock class is invalid: ft-addr=%p"
                        "clock-class-addr=%p, clock-class-name=\"%s\"",
-                       type, clock_class,
+                       ft, clock_class,
                        bt_clock_class_get_name(clock_class));
                ret = -1;
                goto end;
        }
 
-       integer = container_of(type, struct bt_field_type_integer, parent);
-       bt_put(integer->mapped_clock);
-       integer->mapped_clock = bt_get(clock_class);
+       bt_put(int_ft->mapped_clock_class);
+       int_ft->mapped_clock_class = bt_get(clock_class);
        BT_LOGV("Set integer field type's mapped clock class: ft-addr=%p, "
                "clock-class-addr=%p, clock-class-name=\"%s\"",
-               type, clock_class, bt_clock_class_get_name(clock_class));
+               ft, clock_class, bt_clock_class_get_name(clock_class));
+
 end:
        return ret;
 }
 
-int bt_field_type_integer_set_mapped_clock_class(
-               struct bt_field_type *type,
+BT_HIDDEN
+int bt_field_type_common_integer_set_mapped_clock_class(
+               struct bt_field_type_common *ft,
                struct bt_clock_class *clock_class)
 {
        int ret = 0;
 
-       if (!type) {
+       if (!ft) {
                BT_LOGW_STR("Invalid parameter: field type is NULL.");
                ret = -1;
                goto end;
        }
 
-       if (type->frozen) {
+       if (ft->frozen) {
                BT_LOGW("Invalid parameter: field type is frozen: addr=%p",
-                       type);
+                       ft);
                ret = -1;
                goto end;
        }
 
-       ret = bt_field_type_integer_set_mapped_clock_class_no_check(
-               type, clock_class);
+       ret = bt_field_type_common_integer_set_mapped_clock_class_no_check_frozen(
+               ft, clock_class);
 
 end:
        return ret;
 }
 
+int bt_field_type_integer_set_mapped_clock_class(struct bt_field_type *ft,
+               struct bt_clock_class *clock_class)
+{
+       return bt_field_type_common_integer_set_mapped_clock_class((void *) ft,
+               clock_class);
+}
+
 static
 void bt_field_type_enum_iter_destroy(struct bt_object *obj)
 {
@@ -1169,23 +1346,21 @@ void bt_field_type_enum_iter_destroy(struct bt_object *obj)
        BT_LOGD("Destroying enumeration field type mapping iterator: addr=%p",
                obj);
        BT_LOGD_STR("Putting parent enumeration field type.");
-       bt_put(&iter->enumeration_type->parent);
+       bt_put(iter->enumeration_ft);
        g_free(iter);
 }
 
 static
 struct bt_field_type_enumeration_mapping_iterator *
-bt_field_type_enumeration_find_mappings_type(
-               struct bt_field_type *type,
+bt_field_type_common_enumeration_find_mappings_type(
+               struct bt_field_type_common *ft,
                enum bt_field_type_enumeration_mapping_iterator_type iterator_type)
 {
-       struct bt_field_type_enumeration *enumeration_type;
        struct bt_field_type_enumeration_mapping_iterator *iter = NULL;
 
-       BT_ASSERT_PRE_NON_NULL(type, "Field type");
-       BT_ASSERT_PRE_FT_HAS_ID(type, BT_FIELD_TYPE_ID_ENUM, "Field type");
-       enumeration_type = container_of(type,
-               struct bt_field_type_enumeration, parent);
+       BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+       BT_ASSERT_PRE_FT_COMMON_HAS_ID(ft, BT_FIELD_TYPE_ID_ENUM,
+               "Field type");
        iter = g_new0(struct bt_field_type_enumeration_mapping_iterator, 1);
        if (!iter) {
                BT_LOGE_STR("Failed to allocate one enumeration field type mapping.");
@@ -1193,25 +1368,26 @@ bt_field_type_enumeration_find_mappings_type(
        }
 
        bt_object_init(&iter->base, bt_field_type_enum_iter_destroy);
-       bt_get(type);
-       iter->enumeration_type = enumeration_type;
+       iter->enumeration_ft = bt_get(ft);
        iter->index = -1;
        iter->type = iterator_type;
+
 end:
        return iter;
 }
 
+BT_HIDDEN
 struct bt_field_type_enumeration_mapping_iterator *
-bt_field_type_enumeration_find_mappings_by_name(
-               struct bt_field_type *type, const char *name)
+bt_field_type_common_enumeration_find_mappings_by_name(
+               struct bt_field_type_common *ft, const char *name)
 {
        struct bt_field_type_enumeration_mapping_iterator *iter;
 
-       iter = bt_field_type_enumeration_find_mappings_type(
-                       type, ITERATOR_BY_NAME);
+       iter = bt_field_type_common_enumeration_find_mappings_type(
+                       ft, ITERATOR_BY_NAME);
        if (!iter) {
                BT_LOGW("Cannot create enumeration field type mapping iterator: "
-                       "ft-addr=%p, mapping-name=\"%s\"", type, name);
+                       "ft-addr=%p, mapping-name=\"%s\"", ft, name);
                goto error;
        }
 
@@ -1221,28 +1397,36 @@ bt_field_type_enumeration_find_mappings_by_name(
                 * No results are possible, set the iterator's position at the
                 * end.
                 */
-               iter->index = iter->enumeration_type->entries->len;
+               iter->index = iter->enumeration_ft->entries->len;
        }
+
        return iter;
+
 error:
        bt_put(iter);
        return NULL;
 }
 
+struct bt_field_type_enumeration_mapping_iterator *
+bt_field_type_enumeration_find_mappings_by_name(
+               struct bt_field_type *ft, const char *name)
+{
+       return bt_field_type_common_enumeration_find_mappings_by_name(
+               (void *) ft, name);
+}
+
 int bt_field_type_enumeration_mapping_iterator_next(
                struct bt_field_type_enumeration_mapping_iterator *iter)
 {
-       struct bt_field_type_enumeration *enumeration;
-       struct bt_field_type *type;
+       struct bt_field_type_common_enumeration *enum_ft = iter->enumeration_ft;
        int i, ret = 0, len;
 
        BT_ASSERT_PRE_NON_NULL(iter, "Enumeration field type mapping iterator");
-       enumeration = iter->enumeration_type;
-       type = &enumeration->parent;
-       len = enumeration->entries->len;
+       len = enum_ft->entries->len;
        for (i = iter->index + 1; i < len; i++) {
                struct enumeration_mapping *mapping =
-                       get_enumeration_mapping(type, i);
+                       bt_field_type_common_enumeration_get_mapping_by_index(
+                               BT_TO_COMMON(enum_ft), i);
 
                switch (iter->type) {
                case ITERATOR_BY_NAME:
@@ -1281,68 +1465,90 @@ int bt_field_type_enumeration_mapping_iterator_next(
        }
 
        ret = -1;
+
 end:
        return ret;
 }
 
+BT_HIDDEN
 struct bt_field_type_enumeration_mapping_iterator *
-bt_field_type_enumeration_find_mappings_by_signed_value(
-               struct bt_field_type *type, int64_t value)
+bt_field_type_common_enumeration_signed_find_mappings_by_value(
+               struct bt_field_type_common *ft, int64_t value)
 {
        struct bt_field_type_enumeration_mapping_iterator *iter;
 
-       iter = bt_field_type_enumeration_find_mappings_type(
-                       type, ITERATOR_BY_SIGNED_VALUE);
+       iter = bt_field_type_common_enumeration_find_mappings_type(
+                       ft, ITERATOR_BY_SIGNED_VALUE);
        if (!iter) {
                BT_LOGW("Cannot create enumeration field type mapping iterator: "
-                       "ft-addr=%p, value=%" PRId64, type, value);
+                       "ft-addr=%p, value=%" PRId64, ft, value);
                goto error;
        }
 
-       if (bt_ctf_field_type_integer_get_signed(
-                       iter->enumeration_type->container) != 1) {
+       if (bt_field_type_common_integer_is_signed(
+                       BT_TO_COMMON(iter->enumeration_ft->container_ft)) != 1) {
                BT_LOGW("Invalid parameter: enumeration field type is unsigned: "
                        "enum-ft-addr=%p, int-ft-addr=%p",
-                       type, iter->enumeration_type->container);
+                       ft, iter->enumeration_ft->container_ft);
                goto error;
        }
 
        iter->u.signed_value = value;
        return iter;
+
 error:
        bt_put(iter);
        return NULL;
 }
 
 struct bt_field_type_enumeration_mapping_iterator *
-bt_field_type_enumeration_find_mappings_by_unsigned_value(
-               struct bt_field_type *type, uint64_t value)
+bt_field_type_enumeration_signed_find_mappings_by_value(
+               struct bt_field_type *ft, int64_t value)
+{
+       return bt_field_type_common_enumeration_signed_find_mappings_by_value(
+               (void *) ft, value);
+}
+
+BT_HIDDEN
+struct bt_field_type_enumeration_mapping_iterator *
+bt_field_type_common_enumeration_unsigned_find_mappings_by_value(
+               struct bt_field_type_common *ft, uint64_t value)
 {
        struct bt_field_type_enumeration_mapping_iterator *iter;
 
-       iter = bt_field_type_enumeration_find_mappings_type(
-                       type, ITERATOR_BY_UNSIGNED_VALUE);
+       iter = bt_field_type_common_enumeration_find_mappings_type(
+                       ft, ITERATOR_BY_UNSIGNED_VALUE);
        if (!iter) {
                BT_LOGW("Cannot create enumeration field type mapping iterator: "
-                       "ft-addr=%p, value=%" PRIu64, type, value);
+                       "ft-addr=%p, value=%" PRIu64, ft, value);
                goto error;
        }
 
-       if (bt_ctf_field_type_integer_get_signed(
-                       iter->enumeration_type->container) != 0) {
+       if (bt_field_type_common_integer_is_signed(
+                       BT_TO_COMMON(iter->enumeration_ft->container_ft)) != 0) {
                BT_LOGW("Invalid parameter: enumeration field type is signed: "
                        "enum-ft-addr=%p, int-ft-addr=%p",
-                       type, iter->enumeration_type->container);
+                       ft, iter->enumeration_ft->container_ft);
                goto error;
        }
+
        iter->u.unsigned_value = value;
        return iter;
+
 error:
        bt_put(iter);
        return NULL;
 }
 
-int bt_field_type_enumeration_mapping_iterator_get_signed(
+struct bt_field_type_enumeration_mapping_iterator *
+bt_field_type_enumeration_unsigned_find_mappings_by_value(
+               struct bt_field_type *ft, uint64_t value)
+{
+       return bt_field_type_common_enumeration_unsigned_find_mappings_by_value(
+               (void *) ft, value);
+}
+
+int bt_field_type_enumeration_mapping_iterator_signed_get(
                struct bt_field_type_enumeration_mapping_iterator *iter,
                const char **mapping_name, int64_t *range_begin,
                int64_t *range_end)
@@ -1351,12 +1557,12 @@ int bt_field_type_enumeration_mapping_iterator_get_signed(
        BT_ASSERT_PRE(iter->index != -1,
                "Invalid enumeration field type mapping iterator access: "
                "addr=%p, position=-1", iter);
-       return bt_field_type_enumeration_get_mapping_signed(
-                       &iter->enumeration_type->parent, iter->index,
+       return bt_field_type_common_enumeration_signed_get_mapping_by_index(
+                       (void *) iter->enumeration_ft, iter->index,
                        mapping_name, range_begin, range_end);
 }
 
-int bt_field_type_enumeration_mapping_iterator_get_unsigned(
+int bt_field_type_enumeration_mapping_iterator_unsigned_get(
                struct bt_field_type_enumeration_mapping_iterator *iter,
                const char **mapping_name, uint64_t *range_begin,
                uint64_t *range_end)
@@ -1365,25 +1571,27 @@ int bt_field_type_enumeration_mapping_iterator_get_unsigned(
        BT_ASSERT_PRE(iter->index != -1,
                "Invalid enumeration field type mapping iterator access: "
                "addr=%p, position=-1", iter);
-       return bt_field_type_enumeration_get_mapping_unsigned(
-                       &iter->enumeration_type->parent, iter->index,
+       return bt_field_type_common_enumeration_unsigned_get_mapping_by_index(
+                       (void *) iter->enumeration_ft, iter->index,
                        mapping_name, range_begin, range_end);
 }
 
-int bt_field_type_enumeration_get_mapping_signed(
-               struct bt_field_type *enum_field_type,
-               uint64_t index, const char **mapping_name, int64_t *range_begin,
+BT_HIDDEN
+int bt_field_type_common_enumeration_signed_get_mapping_by_index(
+               struct bt_field_type_common *ft, uint64_t index,
+               const char **mapping_name, int64_t *range_begin,
                int64_t *range_end)
 {
        int ret = 0;
        struct enumeration_mapping *mapping;
 
-       BT_ASSERT_PRE_NON_NULL(enum_field_type, "Field type");
-       BT_ASSERT_PRE_FT_HAS_ID(enum_field_type,
+       BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+       BT_ASSERT_PRE_FT_COMMON_HAS_ID(ft,
                BT_FIELD_TYPE_ID_ENUM, "Field type");
-       mapping = get_enumeration_mapping(enum_field_type, index);
+       mapping = bt_field_type_common_enumeration_get_mapping_by_index(ft,
+               index);
        if (!mapping) {
-               /* get_enumeration_mapping() reports any error */
+               /* bt_field_type_common_enumeration_get_mapping_by_index() logs errors */
                ret = -1;
                goto end;
        }
@@ -1405,21 +1613,30 @@ end:
        return ret;
 }
 
-int bt_field_type_enumeration_get_mapping_unsigned(
-               struct bt_field_type *enum_field_type,
-               uint64_t index,
+int bt_field_type_enumeration_signed_get_mapping_by_index(
+               struct bt_field_type *ft, uint64_t index,
+               const char **mapping_name, int64_t *range_begin,
+               int64_t *range_end)
+{
+       return bt_field_type_common_enumeration_signed_get_mapping_by_index(
+               (void *) ft, index, mapping_name, range_begin, range_end);
+}
+
+BT_HIDDEN
+int bt_field_type_common_enumeration_unsigned_get_mapping_by_index(
+               struct bt_field_type_common *ft, uint64_t index,
                const char **mapping_name, uint64_t *range_begin,
                uint64_t *range_end)
 {
        int ret = 0;
        struct enumeration_mapping *mapping;
 
-       BT_ASSERT_PRE_NON_NULL(enum_field_type, "Field type");
-       BT_ASSERT_PRE_FT_HAS_ID(enum_field_type,
-               BT_FIELD_TYPE_ID_ENUM, "Field type");
-       mapping = get_enumeration_mapping(enum_field_type, index);
+       BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+       BT_ASSERT_PRE_FT_COMMON_HAS_ID(ft, BT_FIELD_TYPE_ID_ENUM, "Field type");
+       mapping = bt_field_type_common_enumeration_get_mapping_by_index(
+               ft, index);
        if (!mapping) {
-               /* get_enumeration_mapping() reports any error */
+               /* bt_field_type_common_enumeration_get_mapping_by_index() reports any error */
                ret = -1;
                goto end;
        }
@@ -1441,72 +1658,88 @@ end:
        return ret;
 }
 
+int bt_field_type_enumeration_unsigned_get_mapping_by_index(
+               struct bt_field_type *ft, uint64_t index,
+               const char **mapping_name, uint64_t *range_begin,
+               uint64_t *range_end)
+{
+       return bt_field_type_common_enumeration_unsigned_get_mapping_by_index(
+               (void *) ft, index, mapping_name, range_begin, range_end);
+}
+
 struct bt_field_type *bt_field_type_enumeration_create(
-               struct bt_field_type *integer_container_type)
+               struct bt_field_type *container_ft)
 {
-       struct bt_field_type_enumeration *enumeration = NULL;
+       struct bt_field_type_common_enumeration *enumeration = NULL;
+       struct bt_field_type_common *int_ft = (void *) container_ft;
 
        BT_LOGD("Creating enumeration field type object: int-ft-addr=%p",
-               integer_container_type);
+               container_ft);
 
-       if (!integer_container_type) {
+       if (!container_ft) {
                BT_LOGW_STR("Invalid parameter: field type is NULL.");
                goto error;
        }
 
-       if (integer_container_type->id != BT_FIELD_TYPE_ID_INTEGER) {
+       if (int_ft->id != BT_FIELD_TYPE_ID_INTEGER) {
                BT_LOGW("Invalid parameter: container field type is not an integer field type: "
                        "container-ft-addr=%p, container-ft-id=%s",
-                       integer_container_type,
-                       bt_field_type_id_string(integer_container_type->id));
+                       container_ft, bt_common_field_type_id_string(int_ft->id));
                goto error;
        }
 
-       enumeration = g_new0(struct bt_field_type_enumeration, 1);
+       enumeration = g_new0(struct bt_field_type_common_enumeration, 1);
        if (!enumeration) {
                BT_LOGE_STR("Failed to allocate one enumeration field type.");
                goto error;
        }
 
-       enumeration->parent.id = BT_FIELD_TYPE_ID_ENUM;
-       bt_get(integer_container_type);
-       enumeration->container = integer_container_type;
-       enumeration->entries = g_ptr_array_new_with_free_func(
-               (GDestroyNotify)destroy_enumeration_mapping);
-       bt_field_type_init(&enumeration->parent, FALSE);
+       bt_field_type_common_enumeration_initialize(BT_TO_COMMON(enumeration),
+               int_ft, bt_field_type_common_enumeration_destroy_recursive,
+               &bt_field_type_enumeration_methods);
        BT_LOGD("Created enumeration field type object: addr=%p, "
                "int-ft-addr=%p, int-ft-size=%u",
-               &enumeration->parent, integer_container_type,
-               bt_field_type_integer_get_size(integer_container_type));
-       return &enumeration->parent;
+               enumeration, container_ft,
+               bt_field_type_integer_get_size(container_ft));
+       goto end;
+
 error:
-       g_free(enumeration);
-       return NULL;
+       BT_PUT(enumeration);
+
+end:
+       return (void *) enumeration;
 }
 
-struct bt_field_type *bt_field_type_enumeration_get_container_type(
-               struct bt_field_type *type)
+BT_HIDDEN
+struct bt_field_type_common *bt_field_type_common_enumeration_get_container_field_type(
+               struct bt_field_type_common *ft)
 {
-       struct bt_field_type_enumeration *enumeration_type;
+       struct bt_field_type_common_enumeration *enum_ft = BT_FROM_COMMON(ft);
+
+       BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+       BT_ASSERT_PRE_FT_COMMON_HAS_ID(ft, BT_FIELD_TYPE_ID_ENUM, "Field type");
+       return bt_get(enum_ft->container_ft);
+}
 
-       BT_ASSERT_PRE_NON_NULL(type, "Field type");
-       BT_ASSERT_PRE_FT_HAS_ID(type, BT_FIELD_TYPE_ID_ENUM, "Field type");
-       enumeration_type = container_of(type,
-               struct bt_field_type_enumeration, parent);
-       return bt_get(enumeration_type->container);
+struct bt_field_type *bt_field_type_enumeration_get_container_field_type(
+               struct bt_field_type *ft)
+{
+       return (void *) bt_field_type_common_enumeration_get_container_field_type(
+               (void *) ft);
 }
 
-int bt_field_type_enumeration_add_mapping_signed(
-               struct bt_field_type *type, const char *string,
+BT_HIDDEN
+int bt_field_type_common_enumeration_signed_add_mapping(
+               struct bt_field_type_common *ft, const char *string,
                int64_t range_start, int64_t range_end)
 {
        int ret = 0;
        GQuark mapping_name;
        struct enumeration_mapping *mapping;
-       struct bt_field_type_enumeration *enumeration;
+       struct bt_field_type_common_enumeration *enum_ft = BT_FROM_COMMON(ft);
        char *escaped_string;
 
-       if (!type) {
+       if (!ft) {
                BT_LOGW_STR("Invalid parameter: field type is NULL.");
                ret = -1;
                goto end;
@@ -1518,17 +1751,17 @@ int bt_field_type_enumeration_add_mapping_signed(
                goto end;
        }
 
-       if (type->frozen) {
+       if (ft->frozen) {
                BT_LOGW("Invalid parameter: field type is frozen: addr=%p",
-                       type);
+                       ft);
                ret = -1;
                goto end;
        }
 
-       if (type->id != BT_FIELD_TYPE_ID_ENUM) {
+       if (ft->id != BT_FIELD_TYPE_ID_ENUM) {
                BT_LOGW("Invalid parameter: field type is not an enumeration field type: "
-                       "addr=%p, ft-id=%s", type,
-                       bt_field_type_id_string(type->id));
+                       "addr=%p, ft-id=%s", ft,
+                       bt_common_field_type_id_string(ft->id));
                ret = -1;
                goto end;
        }
@@ -1536,14 +1769,14 @@ int bt_field_type_enumeration_add_mapping_signed(
        if (range_end < range_start) {
                BT_LOGW("Invalid parameter: range's end is lesser than range's start: "
                        "addr=%p, range-start=%" PRId64 ", range-end=%" PRId64,
-                       type, range_start, range_end);
+                       ft, range_start, range_end);
                ret = -1;
                goto end;
        }
 
        if (strlen(string) == 0) {
                BT_LOGW("Invalid parameter: mapping name is an empty string: "
-                       "enum-ft-addr=%p, mapping-name-addr=%p", type,
+                       "enum-ft-addr=%p, mapping-name-addr=%p", ft,
                        string);
                ret = -1;
                goto end;
@@ -1553,7 +1786,7 @@ int bt_field_type_enumeration_add_mapping_signed(
        if (!escaped_string) {
                BT_LOGE("Cannot escape mapping name: enum-ft-addr=%p, "
                        "mapping-name-addr=%p, mapping-name=\"%s\"",
-                       type, string, string);
+                       ft, string, string);
                ret = -1;
                goto end;
        }
@@ -1570,32 +1803,41 @@ int bt_field_type_enumeration_add_mapping_signed(
                .range_end._signed = range_end,
                .string =  mapping_name,
        };
-       enumeration = container_of(type, struct bt_field_type_enumeration,
-               parent);
-       g_ptr_array_add(enumeration->entries, mapping);
-       g_ptr_array_sort(enumeration->entries,
-               (GCompareFunc)compare_enumeration_mappings_signed);
+       g_ptr_array_add(enum_ft->entries, mapping);
+       g_ptr_array_sort(enum_ft->entries,
+               (GCompareFunc) compare_enumeration_mappings_signed);
        BT_LOGV("Added mapping to signed enumeration field type: addr=%p, "
                "name=\"%s\", range-start=%" PRId64 ", "
                "range-end=%" PRId64,
-               type, string, range_start, range_end);
+               ft, string, range_start, range_end);
+
 error_free:
        free(escaped_string);
+
 end:
        return ret;
 }
 
-int bt_field_type_enumeration_add_mapping_unsigned(
-               struct bt_field_type *type, const char *string,
+int bt_field_type_enumeration_signed_add_mapping(
+               struct bt_field_type *ft, const char *string,
+               int64_t range_start, int64_t range_end)
+{
+       return bt_field_type_common_enumeration_signed_add_mapping(
+               (void *) ft, string, range_start, range_end);
+}
+
+BT_HIDDEN
+int bt_field_type_common_enumeration_unsigned_add_mapping(
+               struct bt_field_type_common *ft, const char *string,
                uint64_t range_start, uint64_t range_end)
 {
        int ret = 0;
        GQuark mapping_name;
        struct enumeration_mapping *mapping;
-       struct bt_field_type_enumeration *enumeration;
+       struct bt_field_type_common_enumeration *enum_ft = BT_FROM_COMMON(ft);
        char *escaped_string;
 
-       if (!type) {
+       if (!ft) {
                BT_LOGW_STR("Invalid parameter: field type is NULL.");
                ret = -1;
                goto end;
@@ -1607,17 +1849,17 @@ int bt_field_type_enumeration_add_mapping_unsigned(
                goto end;
        }
 
-       if (type->frozen) {
+       if (ft->frozen) {
                BT_LOGW("Invalid parameter: field type is frozen: addr=%p",
-                       type);
+                       ft);
                ret = -1;
                goto end;
        }
 
-       if (type->id != BT_FIELD_TYPE_ID_ENUM) {
+       if (ft->id != BT_FIELD_TYPE_ID_ENUM) {
                BT_LOGW("Invalid parameter: field type is not an enumeration field type: "
-                       "addr=%p, ft-id=%s", type,
-                       bt_field_type_id_string(type->id));
+                       "addr=%p, ft-id=%s", ft,
+                       bt_common_field_type_id_string(ft->id));
                ret = -1;
                goto end;
        }
@@ -1625,14 +1867,14 @@ int bt_field_type_enumeration_add_mapping_unsigned(
        if (range_end < range_start) {
                BT_LOGW("Invalid parameter: range's end is lesser than range's start: "
                        "addr=%p, range-start=%" PRIu64 ", range-end=%" PRIu64,
-                       type, range_start, range_end);
+                       ft, range_start, range_end);
                ret = -1;
                goto end;
        }
 
        if (strlen(string) == 0) {
                BT_LOGW("Invalid parameter: mapping name is an empty string: "
-                       "enum-ft-addr=%p, mapping-name-addr=%p", type,
+                       "enum-ft-addr=%p, mapping-name-addr=%p", ft,
                        string);
                ret = -1;
                goto end;
@@ -1642,7 +1884,7 @@ int bt_field_type_enumeration_add_mapping_unsigned(
        if (!escaped_string) {
                BT_LOGE("Cannot escape mapping name: enum-ft-addr=%p, "
                        "mapping-name-addr=%p, mapping-name=\"%s\"",
-                       type, string, string);
+                       ft, string, string);
                ret = -1;
                goto end;
        }
@@ -1659,37 +1901,50 @@ int bt_field_type_enumeration_add_mapping_unsigned(
                .range_end._unsigned = range_end,
                .string = mapping_name,
        };
-       enumeration = container_of(type, struct bt_field_type_enumeration,
-               parent);
-       g_ptr_array_add(enumeration->entries, mapping);
-       g_ptr_array_sort(enumeration->entries,
-               (GCompareFunc)compare_enumeration_mappings_unsigned);
+       g_ptr_array_add(enum_ft->entries, mapping);
+       g_ptr_array_sort(enum_ft->entries,
+               (GCompareFunc) compare_enumeration_mappings_unsigned);
        BT_LOGV("Added mapping to unsigned enumeration field type: addr=%p, "
                "name=\"%s\", range-start=%" PRIu64 ", "
                "range-end=%" PRIu64,
-               type, string, range_start, range_end);
+               ft, string, range_start, range_end);
+
 error_free:
        free(escaped_string);
+
 end:
        return ret;
 }
 
-int64_t bt_field_type_enumeration_get_mapping_count(
-               struct bt_field_type *type)
+int bt_field_type_enumeration_unsigned_add_mapping(
+               struct bt_field_type *ft, const char *string,
+               uint64_t range_start, uint64_t range_end)
 {
-       struct bt_field_type_enumeration *enumeration;
+       return bt_field_type_common_enumeration_unsigned_add_mapping(
+               (void *) ft, string, range_start, range_end);
+}
+
+BT_HIDDEN
+int64_t bt_field_type_common_enumeration_get_mapping_count(
+               struct bt_field_type_common *ft)
+{
+       struct bt_field_type_common_enumeration *enum_ft = BT_FROM_COMMON(ft);
 
-       BT_ASSERT_PRE_NON_NULL(type, "Field type");
-       BT_ASSERT_PRE_FT_HAS_ID(type, BT_FIELD_TYPE_ID_ENUM, "Field type");
-       enumeration = container_of(type, struct bt_field_type_enumeration,
-               parent);
-       return (int64_t) enumeration->entries->len;
+       BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+       BT_ASSERT_PRE_FT_COMMON_HAS_ID(ft, BT_FIELD_TYPE_ID_ENUM, "Field type");
+       return (int64_t) enum_ft->entries->len;
+}
+
+int64_t bt_field_type_enumeration_get_mapping_count(
+               struct bt_field_type *ft)
+{
+       return bt_field_type_common_enumeration_get_mapping_count((void *) ft);
 }
 
 struct bt_field_type *bt_field_type_floating_point_create(void)
 {
-       struct bt_field_type_floating_point *floating_point =
-               g_new0(struct bt_field_type_floating_point, 1);
+       struct bt_field_type_common_floating_point *floating_point =
+               g_new0(struct bt_field_type_common_floating_point, 1);
 
        BT_LOGD_STR("Creating floating point number field type object.");
 
@@ -1698,137 +1953,166 @@ struct bt_field_type *bt_field_type_floating_point_create(void)
                goto end;
        }
 
-       floating_point->parent.id = BT_FIELD_TYPE_ID_FLOAT;
-       floating_point->exp_dig = sizeof(float) * CHAR_BIT - FLT_MANT_DIG;
-       floating_point->mant_dig = FLT_MANT_DIG;
-       bt_field_type_init(&floating_point->parent, TRUE);
+       bt_field_type_common_floating_point_initialize(
+               BT_TO_COMMON(floating_point),
+               bt_field_type_common_floating_point_destroy,
+               &bt_field_type_floating_point_methods);
        BT_LOGD("Created floating point number field type object: addr=%p, "
-               "exp-size=%u, mant-size=%u", &floating_point->parent,
+               "exp-size=%u, mant-size=%u", floating_point,
                floating_point->exp_dig, floating_point->mant_dig);
+
 end:
-       return floating_point ? &floating_point->parent : NULL;
+       return (void *) floating_point;
 }
 
-int bt_field_type_floating_point_get_exponent_digits(
-               struct bt_field_type *type)
+BT_HIDDEN
+int bt_field_type_common_floating_point_get_exponent_digits(
+               struct bt_field_type_common *ft)
 {
-       struct bt_field_type_floating_point *floating_point;
+       struct bt_field_type_common_floating_point *flt_ft = BT_FROM_COMMON(ft);
 
-       BT_ASSERT_PRE_NON_NULL(type, "Field type");
-       BT_ASSERT_PRE_FT_HAS_ID(type, BT_FIELD_TYPE_ID_FLOAT, "Field type");
-       floating_point = container_of(type,
-               struct bt_field_type_floating_point, parent);
-       return (int) floating_point->exp_dig;
+       BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+       BT_ASSERT_PRE_FT_COMMON_HAS_ID(ft, BT_FIELD_TYPE_ID_FLOAT,
+               "Field type");
+       return (int) flt_ft->exp_dig;
 }
 
-int bt_field_type_floating_point_set_exponent_digits(
-               struct bt_field_type *type, unsigned int exponent_digits)
+int bt_field_type_floating_point_get_exponent_digits(
+               struct bt_field_type *ft)
+{
+       return bt_field_type_common_floating_point_get_exponent_digits(
+               (void *) ft);
+}
+
+BT_HIDDEN
+int bt_field_type_common_floating_point_set_exponent_digits(
+               struct bt_field_type_common *ft,
+               unsigned int exponent_digits)
 {
        int ret = 0;
-       struct bt_field_type_floating_point *floating_point;
+       struct bt_field_type_common_floating_point *flt_ft = BT_FROM_COMMON(ft);
 
-       if (!type) {
+       if (!ft) {
                BT_LOGW_STR("Invalid parameter: field type is NULL.");
                ret = -1;
                goto end;
        }
 
-       if (type->frozen) {
+       if (ft->frozen) {
                BT_LOGW("Invalid parameter: field type is frozen: addr=%p",
-                       type);
+                       ft);
                ret = -1;
                goto end;
        }
 
-       if (type->id != BT_FIELD_TYPE_ID_FLOAT) {
+       if (ft->id != BT_FIELD_TYPE_ID_FLOAT) {
                BT_LOGW("Invalid parameter: field type is not a floating point number field type: "
-                       "addr=%p, ft-id=%s", type,
-                       bt_field_type_id_string(type->id));
+                       "addr=%p, ft-id=%s", ft,
+                       bt_common_field_type_id_string(ft->id));
                ret = -1;
                goto end;
        }
 
-       floating_point = container_of(type,
-               struct bt_field_type_floating_point, parent);
        if ((exponent_digits != sizeof(float) * CHAR_BIT - FLT_MANT_DIG) &&
                (exponent_digits != sizeof(double) * CHAR_BIT - DBL_MANT_DIG) &&
                (exponent_digits !=
                        sizeof(long double) * CHAR_BIT - LDBL_MANT_DIG)) {
                BT_LOGW("Invalid parameter: invalid exponent size: "
-                       "addr=%p, exp-size=%u", type, exponent_digits);
+                       "addr=%p, exp-size=%u", ft, exponent_digits);
                ret = -1;
                goto end;
        }
 
-       floating_point->exp_dig = exponent_digits;
+       flt_ft->exp_dig = exponent_digits;
        BT_LOGV("Set floating point number field type's exponent size: addr=%p, "
-               "exp-size=%u", type, exponent_digits);
+               "exp-size=%u", ft, exponent_digits);
+
 end:
        return ret;
 }
 
-int bt_field_type_floating_point_get_mantissa_digits(
-               struct bt_field_type *type)
+int bt_field_type_floating_point_set_exponent_digits(
+               struct bt_field_type *ft, unsigned int exponent_digits)
+{
+       return bt_field_type_common_floating_point_set_exponent_digits(
+               (void *) ft, exponent_digits);
+}
+
+BT_HIDDEN
+int bt_field_type_common_floating_point_get_mantissa_digits(
+               struct bt_field_type_common *ft)
 {
-       struct bt_field_type_floating_point *floating_point;
+       struct bt_field_type_common_floating_point *flt_ft = BT_FROM_COMMON(ft);
 
-       BT_ASSERT_PRE_NON_NULL(type, "Field type");
-       BT_ASSERT_PRE_FT_HAS_ID(type, BT_FIELD_TYPE_ID_FLOAT, "Field type");
-       floating_point = container_of(type,
-               struct bt_field_type_floating_point, parent);
-       return (int) floating_point->mant_dig;
+       BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+       BT_ASSERT_PRE_FT_COMMON_HAS_ID(ft, BT_FIELD_TYPE_ID_FLOAT,
+               "Field type");
+       return (int) flt_ft->mant_dig;
 }
 
-int bt_field_type_floating_point_set_mantissa_digits(
-               struct bt_field_type *type, unsigned int mantissa_digits)
+int bt_field_type_floating_point_get_mantissa_digits(
+               struct bt_field_type *ft)
+{
+       return bt_field_type_common_floating_point_get_mantissa_digits(
+               (void *) ft);
+}
+
+BT_HIDDEN
+int bt_field_type_common_floating_point_set_mantissa_digits(
+               struct bt_field_type_common *ft, unsigned int mantissa_digits)
 {
        int ret = 0;
-       struct bt_field_type_floating_point *floating_point;
+       struct bt_field_type_common_floating_point *flt_ft = BT_FROM_COMMON(ft);
 
-       if (!type) {
+       if (!ft) {
                BT_LOGW_STR("Invalid parameter: field type is NULL.");
                ret = -1;
                goto end;
        }
 
-       if (type->frozen) {
+       if (ft->frozen) {
                BT_LOGW("Invalid parameter: field type is frozen: addr=%p",
-                       type);
+                       ft);
                ret = -1;
                goto end;
        }
 
-       if (type->id != BT_FIELD_TYPE_ID_FLOAT) {
+       if (ft->id != BT_FIELD_TYPE_ID_FLOAT) {
                BT_LOGW("Invalid parameter: field type is not a floating point number field type: "
-                       "addr=%p, ft-id=%s", type,
-                       bt_field_type_id_string(type->id));
+                       "addr=%p, ft-id=%s", ft,
+                       bt_common_field_type_id_string(ft->id));
                ret = -1;
                goto end;
        }
 
-       floating_point = container_of(type,
-               struct bt_field_type_floating_point, parent);
-
        if ((mantissa_digits != FLT_MANT_DIG) &&
                (mantissa_digits != DBL_MANT_DIG) &&
                (mantissa_digits != LDBL_MANT_DIG)) {
                BT_LOGW("Invalid parameter: invalid mantissa size: "
-                       "addr=%p, mant-size=%u", type, mantissa_digits);
+                       "addr=%p, mant-size=%u", ft, mantissa_digits);
                ret = -1;
                goto end;
        }
 
-       floating_point->mant_dig = mantissa_digits;
+       flt_ft->mant_dig = mantissa_digits;
        BT_LOGV("Set floating point number field type's mantissa size: addr=%p, "
-               "mant-size=%u", type, mantissa_digits);
+               "mant-size=%u", ft, mantissa_digits);
+
 end:
        return ret;
 }
 
+int bt_field_type_floating_point_set_mantissa_digits(
+               struct bt_field_type *ft, unsigned int mantissa_digits)
+{
+       return bt_field_type_common_floating_point_set_mantissa_digits(
+               (void *) ft, mantissa_digits);
+}
+
 struct bt_field_type *bt_field_type_structure_create(void)
 {
-       struct bt_field_type_structure *structure =
-               g_new0(struct bt_field_type_structure, 1);
+       struct bt_field_type_common_structure *structure =
+               g_new0(struct bt_field_type_common_structure, 1);
 
        BT_LOGD_STR("Creating structure field type object.");
 
@@ -1837,37 +2121,40 @@ struct bt_field_type *bt_field_type_structure_create(void)
                goto error;
        }
 
-       structure->parent.id = BT_FIELD_TYPE_ID_STRUCT;
-       structure->fields = g_ptr_array_new_with_free_func(
-               (GDestroyNotify)destroy_structure_field);
-       structure->field_name_to_index = g_hash_table_new(NULL, NULL);
-       bt_field_type_init(&structure->parent, TRUE);
+       bt_field_type_common_structure_initialize(BT_TO_COMMON(structure),
+               bt_field_type_common_structure_destroy_recursive,
+               &bt_field_type_structure_methods);
        BT_LOGD("Created structure field type object: addr=%p",
-               &structure->parent);
-       return &structure->parent;
+               structure);
+       goto end;
+
 error:
-       return NULL;
+       BT_PUT(structure);
+
+end:
+       return (void *) structure;
 }
 
 BT_HIDDEN
-int bt_field_type_structure_replace_field(struct bt_field_type *type,
-               const char *field_name, struct bt_field_type *field_type)
+int bt_field_type_common_structure_replace_field(
+               struct bt_field_type_common *ft,
+               const char *field_name,
+               struct bt_field_type_common *field_type)
 {
        int ret = 0;
-       struct bt_field_type_structure *structure;
+       struct bt_field_type_common_structure *struct_ft = BT_FROM_COMMON(ft);
        GQuark name_quark;
        uint64_t i;
 
-       BT_ASSERT(type);
+       BT_ASSERT(ft);
        BT_ASSERT(field_name);
        BT_ASSERT(field_type);
-       BT_ASSERT(type->id == BT_FIELD_TYPE_ID_STRUCT);
-       structure = container_of(type, struct bt_field_type_structure, parent);
+       BT_ASSERT(ft->id == BT_FIELD_TYPE_ID_STRUCT);
        name_quark = g_quark_from_string(field_name);
 
-       for (i = 0; i < structure->fields->len; i++) {
-               struct structure_field *field = g_ptr_array_index(
-                       structure->fields, i);
+       for (i = 0; i < struct_ft->fields->len; i++) {
+               struct structure_field_common *field = g_ptr_array_index(
+                       struct_ft->fields, i);
 
                if (field->name == name_quark) {
                        bt_put(field->type);
@@ -1878,18 +2165,19 @@ int bt_field_type_structure_replace_field(struct bt_field_type *type,
        return ret;
 }
 
-int bt_field_type_structure_add_field(struct bt_field_type *type,
-               struct bt_field_type *field_type,
+BT_HIDDEN
+int bt_field_type_common_structure_add_field(struct bt_field_type_common *ft,
+               struct bt_field_type_common *field_type,
                const char *field_name)
 {
        int ret = 0;
-       struct bt_field_type_structure *structure;
+       struct bt_field_type_common_structure *struct_ft = BT_FROM_COMMON(ft);
 
        /*
         * TODO: check that `field_type` does not contain `type`,
         *       recursively.
         */
-       if (!type) {
+       if (!ft) {
                BT_LOGW_STR("Invalid parameter: field type is NULL.");
                ret = -1;
                goto end;
@@ -1901,75 +2189,87 @@ int bt_field_type_structure_add_field(struct bt_field_type *type,
                goto end;
        }
 
-       if (type->frozen) {
+       if (ft->frozen) {
                BT_LOGW("Invalid parameter: field type is frozen: addr=%p",
-                       type);
+                       ft);
                ret = -1;
                goto end;
        }
 
-       if (type->id != BT_FIELD_TYPE_ID_STRUCT) {
+       if (ft->id != BT_FIELD_TYPE_ID_STRUCT) {
                BT_LOGW("Invalid parameter: field type is not a structure field type: "
-                       "addr=%p, ft-id=%s", type,
-                       bt_field_type_id_string(type->id));
+                       "addr=%p, ft-id=%s", ft,
+                       bt_common_field_type_id_string(ft->id));
                ret = -1;
                goto end;
        }
 
-       if (type == field_type) {
+       if (ft == field_type) {
                BT_LOGW("Invalid parameter: structure field type and field type to add are the same: "
-                       "addr=%p", type);
+                       "addr=%p", ft);
                ret = -1;
                goto end;
        }
 
-       structure = container_of(type,
-               struct bt_field_type_structure, parent);
-       if (add_structure_field(structure->fields,
-                       structure->field_name_to_index, field_type, field_name)) {
+       if (add_structure_field(struct_ft->fields,
+                       struct_ft->field_name_to_index, field_type, field_name)) {
                BT_LOGW("Cannot add field to structure field type: "
                        "struct-ft-addr=%p, field-ft-addr=%p, field-name=\"%s\"",
-                       type, field_type, field_name);
+                       ft, field_type, field_name);
                ret = -1;
                goto end;
        }
 
        BT_LOGV("Added structure field type field: struct-ft-addr=%p, "
-               "field-ft-addr=%p, field-name=\"%s\"", type,
+               "field-ft-addr=%p, field-name=\"%s\"", ft,
                field_type, field_name);
+
 end:
        return ret;
 }
 
-int64_t bt_field_type_structure_get_field_count(
-               struct bt_field_type *type)
+int bt_field_type_structure_add_field(struct bt_field_type *ft,
+               struct bt_field_type *field_type,
+               const char *field_name)
+{
+       return bt_field_type_common_structure_add_field((void *) ft,
+               (void *) field_type, field_name);
+}
+
+BT_HIDDEN
+int64_t bt_field_type_common_structure_get_field_count(
+               struct bt_field_type_common *ft)
 {
-       struct bt_field_type_structure *structure;
+       struct bt_field_type_common_structure *struct_ft = BT_FROM_COMMON(ft);
 
-       BT_ASSERT_PRE_NON_NULL(type, "Field type");
-       BT_ASSERT_PRE_FT_HAS_ID(type, BT_FIELD_TYPE_ID_STRUCT, "Field type");
-       structure = container_of(type, struct bt_field_type_structure,
-               parent);
-       return (int64_t) structure->fields->len;
+       BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+       BT_ASSERT_PRE_FT_COMMON_HAS_ID(ft, BT_FIELD_TYPE_ID_STRUCT,
+               "Field type");
+       return (int64_t) struct_ft->fields->len;
 }
 
-int bt_field_type_structure_get_field_by_index(
-               struct bt_field_type *type,
-               const char **field_name, struct bt_field_type **field_type,
-               uint64_t index)
+int64_t bt_field_type_structure_get_field_count(struct bt_field_type *ft)
 {
-       struct bt_field_type_structure *structure;
-       struct structure_field *field;
+       return bt_field_type_common_structure_get_field_count((void *) ft);
+}
 
-       BT_ASSERT_PRE_NON_NULL(type, "Field type");
-       BT_ASSERT_PRE_FT_HAS_ID(type, BT_FIELD_TYPE_ID_STRUCT, "Field type");
-       structure = container_of(type, struct bt_field_type_structure,
-               parent);
-       BT_ASSERT_PRE(index < structure->fields->len,
+BT_HIDDEN
+int bt_field_type_common_structure_get_field_by_index(
+               struct bt_field_type_common *ft,
+               const char **field_name,
+               struct bt_field_type_common **field_type, uint64_t index)
+{
+       struct bt_field_type_common_structure *struct_ft = BT_FROM_COMMON(ft);
+       struct structure_field_common *field;
+
+       BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+       BT_ASSERT_PRE_FT_COMMON_HAS_ID(ft, BT_FIELD_TYPE_ID_STRUCT,
+               "Field type");
+       BT_ASSERT_PRE(index < struct_ft->fields->len,
                "Index is out of bounds: index=%" PRIu64 ", "
-               "count=%u, %![ft-]+F",
-               index, structure->fields->len, type);
-       field = g_ptr_array_index(structure->fields, index);
+               "count=%u, %![ft-]+_F",
+               index, struct_ft->fields->len, ft);
+       field = g_ptr_array_index(struct_ft->fields, index);
 
        if (field_type) {
                *field_type = field->type;
@@ -1984,37 +2284,46 @@ int bt_field_type_structure_get_field_by_index(
        return 0;
 }
 
-struct bt_field_type *bt_field_type_structure_get_field_type_by_name(
-               struct bt_field_type *type, const char *name)
+int bt_field_type_structure_get_field_by_index(
+               struct bt_field_type *ft,
+               const char **field_name,
+               struct bt_field_type **field_type, uint64_t index)
+{
+       return bt_field_type_common_structure_get_field_by_index(
+               (void *) ft, field_name, (void *) field_type, index);
+}
+
+BT_HIDDEN
+struct bt_field_type_common *bt_field_type_common_structure_get_field_type_by_name(
+               struct bt_field_type_common *ft, const char *name)
 {
        size_t index;
        GQuark name_quark;
-       struct structure_field *field;
-       struct bt_field_type_structure *structure;
-       struct bt_field_type *field_type = NULL;
+       struct structure_field_common *field;
+       struct bt_field_type_common_structure *struct_ft = BT_FROM_COMMON(ft);
+       struct bt_field_type_common *field_type = NULL;
 
-       BT_ASSERT_PRE_NON_NULL(type, "Field type");
+       BT_ASSERT_PRE_NON_NULL(ft, "Field type");
        BT_ASSERT_PRE_NON_NULL(name, "Name");
-       BT_ASSERT_PRE_FT_HAS_ID(type, BT_FIELD_TYPE_ID_STRUCT, "Field type");
+       BT_ASSERT_PRE_FT_COMMON_HAS_ID(ft, BT_FIELD_TYPE_ID_STRUCT,
+               "Field type");
        name_quark = g_quark_try_string(name);
        if (!name_quark) {
                BT_LOGV("No such structure field type field name: "
                        "ft-addr=%p, field-name=\"%s\"",
-                       type, name);
+                       ft, name);
                goto end;
        }
 
-       structure = container_of(type, struct bt_field_type_structure,
-               parent);
-       if (!g_hash_table_lookup_extended(structure->field_name_to_index,
-                       GUINT_TO_POINTER(name_quark), NULL, (gpointer *)&index)) {
+       if (!g_hash_table_lookup_extended(struct_ft->field_name_to_index,
+                       GUINT_TO_POINTER(name_quark), NULL, (gpointer *) &index)) {
                BT_LOGV("No such structure field type field name: "
                        "ft-addr=%p, field-name=\"%s\"",
-                       type, name);
+                       ft, name);
                goto end;
        }
 
-       field = structure->fields->pdata[index];
+       field = struct_ft->fields->pdata[index];
        field_type = field->type;
        bt_get(field_type);
 
@@ -2022,114 +2331,132 @@ end:
        return field_type;
 }
 
+struct bt_field_type *bt_field_type_structure_get_field_type_by_name(
+               struct bt_field_type *ft, const char *name)
+{
+       return (void *) bt_field_type_common_structure_get_field_type_by_name(
+               (void *) ft, name);
+}
+
 struct bt_field_type *bt_field_type_variant_create(
-       struct bt_field_type *enum_tag, const char *tag_name)
+       struct bt_field_type *tag_ft, const char *tag_name)
 {
-       struct bt_field_type_variant *variant = NULL;
+       struct bt_field_type_common_variant *var_ft = NULL;
 
        BT_LOGD("Creating variant field type object: "
                "tag-ft-addr=%p, tag-field-name=\"%s\"",
-               enum_tag, tag_name);
+               tag_ft, tag_name);
 
        if (tag_name && !bt_identifier_is_valid(tag_name)) {
                BT_LOGW("Invalid parameter: tag field name is not a valid CTF identifier: "
                        "tag-ft-addr=%p, tag-field-name=\"%s\"",
-                       enum_tag, tag_name);
+                       tag_ft, tag_name);
                goto error;
        }
 
-       variant = g_new0(struct bt_field_type_variant, 1);
-       if (!variant) {
+       var_ft = g_new0(struct bt_field_type_common_variant, 1);
+       if (!var_ft) {
                BT_LOGE_STR("Failed to allocate one variant field type.");
                goto error;
        }
 
-       variant->parent.id = BT_FIELD_TYPE_ID_VARIANT;
-       variant->tag_name = g_string_new(tag_name);
-       variant->field_name_to_index = g_hash_table_new(NULL, NULL);
-       variant->fields = g_ptr_array_new_with_free_func(
-               (GDestroyNotify) destroy_structure_field);
-       if (enum_tag) {
-               bt_get(enum_tag);
-               variant->tag = container_of(enum_tag,
-                       struct bt_field_type_enumeration, parent);
-       }
-
-       bt_field_type_init(&variant->parent, TRUE);
-       /* A variant's alignment is undefined */
-       variant->parent.alignment = 0;
+       bt_field_type_common_variant_initialize(BT_TO_COMMON(var_ft),
+               (void *) tag_ft, tag_name,
+               bt_field_type_common_variant_destroy_recursive,
+               &bt_field_type_variant_methods);
        BT_LOGD("Created variant field type object: addr=%p, "
                "tag-ft-addr=%p, tag-field-name=\"%s\"",
-               &variant->parent, enum_tag, tag_name);
-       return &variant->parent;
+               var_ft, tag_ft, tag_name);
+       goto end;
+
 error:
-       return NULL;
+       BT_PUT(var_ft);
+
+end:
+       return (void *) var_ft;
 }
 
-struct bt_field_type *bt_field_type_variant_get_tag_type(
-               struct bt_field_type *type)
+BT_HIDDEN
+struct bt_field_type_common *bt_field_type_common_variant_get_tag_field_type(
+               struct bt_field_type_common *ft)
 {
-       struct bt_field_type_variant *variant;
-       struct bt_field_type *tag_type = NULL;
+       struct bt_field_type_common_variant *var_ft = BT_FROM_COMMON(ft);
+       struct bt_field_type_common *tag_ft = NULL;
 
-       BT_ASSERT_PRE_NON_NULL(type, "Field type");
-       BT_ASSERT_PRE_FT_HAS_ID(type, BT_FIELD_TYPE_ID_VARIANT, "Field type");
-       variant = container_of(type, struct bt_field_type_variant, parent);
-       if (!variant->tag) {
+       BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+       BT_ASSERT_PRE_FT_COMMON_HAS_ID(ft, BT_FIELD_TYPE_ID_VARIANT,
+               "Field type");
+
+       if (!var_ft->tag_ft) {
                BT_LOGV("Variant field type has no tag field type: "
-                       "addr=%p", type);
+                       "addr=%p", ft);
                goto end;
        }
 
-       tag_type = &variant->tag->parent;
-       bt_get(tag_type);
+       tag_ft = bt_get(var_ft->tag_ft);
 
 end:
-       return tag_type;
+       return tag_ft;
+}
+
+struct bt_field_type *bt_field_type_variant_get_tag_field_type(
+               struct bt_field_type *ft)
+{
+       return (void *) bt_field_type_common_variant_get_tag_field_type(
+               (void *) ft);
 }
 
-const char *bt_field_type_variant_get_tag_name(struct bt_field_type *type)
+BT_HIDDEN
+const char *bt_field_type_common_variant_get_tag_name(
+               struct bt_field_type_common *ft)
 {
-       struct bt_field_type_variant *variant;
+       struct bt_field_type_common_variant *var_ft = BT_FROM_COMMON(ft);
        const char *tag_name = NULL;
 
-       BT_ASSERT_PRE_NON_NULL(type, "Field type");
-       BT_ASSERT_PRE_FT_HAS_ID(type, BT_FIELD_TYPE_ID_VARIANT, "Field type");
-       variant = container_of(type, struct bt_field_type_variant, parent);
-       if (variant->tag_name->len == 0) {
+       BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+       BT_ASSERT_PRE_FT_COMMON_HAS_ID(ft, BT_FIELD_TYPE_ID_VARIANT,
+               "Field type");
+
+       if (var_ft->tag_name->len == 0) {
                BT_LOGV("Variant field type has no tag field name: "
-                       "addr=%p", type);
+                       "addr=%p", ft);
                goto end;
        }
 
-       tag_name = variant->tag_name->str;
+       tag_name = var_ft->tag_name->str;
+
 end:
        return tag_name;
 }
 
-int bt_field_type_variant_set_tag_name(
-               struct bt_field_type *type, const char *name)
+const char *bt_field_type_variant_get_tag_name(struct bt_field_type *ft)
+{
+       return bt_field_type_common_variant_get_tag_name((void *) ft);
+}
+
+BT_HIDDEN
+int bt_field_type_common_variant_set_tag_name(
+               struct bt_field_type_common *ft, const char *name)
 {
        int ret = 0;
-       struct bt_field_type_variant *variant;
+       struct bt_field_type_common_variant *var_ft = BT_FROM_COMMON(ft);
 
-       if (!type) {
+       if (!ft) {
                BT_LOGW_STR("Invalid parameter: field type is NULL.");
                ret = -1;
                goto end;
        }
 
-       if (type->frozen) {
+       if (ft->frozen) {
                BT_LOGW("Invalid parameter: field type is frozen: addr=%p",
-                       type);
+                       ft);
                ret = -1;
                goto end;
        }
 
-       if (type->id != BT_FIELD_TYPE_ID_VARIANT) {
+       if (ft->id != BT_FIELD_TYPE_ID_VARIANT) {
                BT_LOGW("Invalid parameter: field type is not a variant field type: "
-                       "addr=%p, ft-id=%s", type,
-                       bt_field_type_id_string(type->id));
+                       "addr=%p, ft-id=%s", ft, bt_common_field_type_id_string(ft->id));
                ret = -1;
                goto end;
        }
@@ -2137,70 +2464,75 @@ int bt_field_type_variant_set_tag_name(
        if (!bt_identifier_is_valid(name)) {
                BT_LOGW("Invalid parameter: tag field name is not a valid CTF identifier: "
                        "variant-ft-addr=%p, tag-field-name=\"%s\"",
-                       type, name);
+                       ft, name);
                ret = -1;
                goto end;
        }
 
-       variant = container_of(type, struct bt_field_type_variant, parent);
-       g_string_assign(variant->tag_name, name);
+       g_string_assign(var_ft->tag_name, name);
        BT_LOGV("Set variant field type's tag field name: addr=%p, "
-               "tag-field-name=\"%s\"", type, name);
+               "tag-field-name=\"%s\"", ft, name);
+
 end:
        return ret;
 }
 
-int bt_field_type_variant_add_field(struct bt_field_type *type,
-               struct bt_field_type *field_type,
+int bt_field_type_variant_set_tag_name(
+               struct bt_field_type *ft, const char *name)
+{
+       return bt_field_type_common_variant_set_tag_name((void *) ft, name);
+}
+
+BT_HIDDEN
+int bt_field_type_common_variant_add_field(struct bt_field_type_common *ft,
+               struct bt_field_type_common *field_type,
                const char *field_name)
 {
        size_t i;
        int ret = 0;
-       struct bt_field_type_variant *variant;
+       struct bt_field_type_common_variant *var_ft = BT_FROM_COMMON(ft);
        GQuark field_name_quark = g_quark_from_string(field_name);
 
        /*
         * TODO: check that `field_type` does not contain `type`,
         *       recursively.
         */
-       if (!type) {
+       if (!ft) {
                BT_LOGW_STR("Invalid parameter: field type is NULL.");
                ret = -1;
                goto end;
        }
 
-       if (type->frozen) {
+       if (ft->frozen) {
                BT_LOGW("Invalid parameter: field type is frozen: addr=%p",
-                       type);
+                       ft);
                ret = -1;
                goto end;
        }
 
-       if (type->id != BT_FIELD_TYPE_ID_VARIANT) {
+       if (ft->id != BT_FIELD_TYPE_ID_VARIANT) {
                BT_LOGW("Invalid parameter: field type is not a variant field type: "
-                       "addr=%p, ft-id=%s", type,
-                       bt_field_type_id_string(type->id));
+                       "addr=%p, ft-id=%s", ft,
+                       bt_common_field_type_id_string(ft->id));
                ret = -1;
                goto end;
        }
 
-       if (type == field_type) {
+       if (ft == field_type) {
                BT_LOGW("Invalid parameter: variant field type and field type to add are the same: "
-                       "addr=%p", type);
+                       "addr=%p", ft);
                ret = -1;
                goto end;
        }
 
-       variant = container_of(type, struct bt_field_type_variant, parent);
-
        /* The user has explicitly provided a tag; validate against it. */
-       if (variant->tag) {
+       if (var_ft->tag_ft) {
                int name_found = 0;
 
                /* Make sure this name is present in the enum tag */
-               for (i = 0; i < variant->tag->entries->len; i++) {
+               for (i = 0; i < var_ft->tag_ft->entries->len; i++) {
                        struct enumeration_mapping *mapping =
-                               g_ptr_array_index(variant->tag->entries, i);
+                               g_ptr_array_index(var_ft->tag_ft->entries, i);
 
                        if (mapping->string == field_name_quark) {
                                name_found = 1;
@@ -2214,61 +2546,70 @@ int bt_field_type_variant_add_field(struct bt_field_type *type,
                                "variant-ft-addr=%p, tag-ft-addr=%p, "
                                "tag-field-name=\"%s\""
                                "field-ft-addr=%p, field-name=\"%s\"",
-                               type, variant->tag, variant->tag_name->str,
+                               ft, var_ft->tag_ft, var_ft->tag_name->str,
                                field_type, field_name);
                        ret = -1;
                        goto end;
                }
        }
 
-       if (add_structure_field(variant->fields, variant->field_name_to_index,
+       if (add_structure_field(var_ft->fields, var_ft->field_name_to_index,
                        field_type, field_name)) {
                BT_LOGW("Cannot add field to variant field type: "
                        "variant-ft-addr=%p, field-ft-addr=%p, field-name=\"%s\"",
-                       type, field_type, field_name);
+                       ft, field_type, field_name);
                ret = -1;
                goto end;
        }
 
        BT_LOGV("Added variant field type field: variant-ft-addr=%p, "
-               "field-ft-addr=%p, field-name=\"%s\"", type,
+               "field-ft-addr=%p, field-name=\"%s\"", ft,
                field_type, field_name);
 
 end:
        return ret;
 }
 
-struct bt_field_type *bt_field_type_variant_get_field_type_by_name(
-               struct bt_field_type *type,
+int bt_field_type_variant_add_field(struct bt_field_type *ft,
+               struct bt_field_type *field_type,
+               const char *field_name)
+{
+       return bt_field_type_common_variant_add_field((void *) ft,
+               (void *) field_type, field_name);
+}
+
+BT_HIDDEN
+struct bt_field_type_common *bt_field_type_common_variant_get_field_type_by_name(
+               struct bt_field_type_common *ft,
                const char *field_name)
 {
        size_t index;
        GQuark name_quark;
-       struct structure_field *field;
-       struct bt_field_type_variant *variant;
-       struct bt_field_type *field_type = NULL;
+       struct structure_field_common *field;
+       struct bt_field_type_common_variant *var_ft = BT_FROM_COMMON(ft);
+       struct bt_field_type_common *field_type = NULL;
 
-       BT_ASSERT_PRE_NON_NULL(type, "Field type");
+       BT_ASSERT_PRE_NON_NULL(ft, "Field type");
        BT_ASSERT_PRE_NON_NULL(field_name, "Name");
-       BT_ASSERT_PRE_FT_HAS_ID(type, BT_FIELD_TYPE_ID_VARIANT, "Field type");
+       BT_ASSERT_PRE_FT_COMMON_HAS_ID(ft, BT_FIELD_TYPE_ID_VARIANT,
+               "Field type");
        name_quark = g_quark_try_string(field_name);
        if (!name_quark) {
                BT_LOGV("No such variant field type field name: "
                        "ft-addr=%p, field-name=\"%s\"",
-                       type, field_name);
+                       ft, field_name);
                goto end;
        }
 
-       variant = container_of(type, struct bt_field_type_variant, parent);
-       if (!g_hash_table_lookup_extended(variant->field_name_to_index,
-                       GUINT_TO_POINTER(name_quark), NULL, (gpointer *)&index)) {
+       if (!g_hash_table_lookup_extended(var_ft->field_name_to_index,
+                       GUINT_TO_POINTER(name_quark), NULL, (gpointer *) &index)) {
                BT_LOGV("No such variant field type field name: "
                        "ft-addr=%p, field-name=\"%s\"",
-                       type, field_name);
+                       ft, field_name);
                goto end;
        }
 
-       field = g_ptr_array_index(variant->fields, index);
+       field = g_ptr_array_index(var_ft->fields, index);
        field_type = field->type;
        bt_get(field_type);
 
@@ -2276,27 +2617,39 @@ end:
        return field_type;
 }
 
-struct bt_field_type *bt_field_type_variant_get_field_type_from_tag(
-               struct bt_field_type *type,
-               struct bt_field *tag)
+struct bt_field_type *bt_field_type_variant_get_field_type_by_name(
+               struct bt_field_type *ft,
+               const char *field_name)
+{
+       return (void *) bt_field_type_common_variant_get_field_type_by_name(
+               (void *) ft, field_name);
+}
+
+BT_HIDDEN
+struct bt_field_type_common *bt_field_type_common_variant_get_field_type_from_tag(
+               struct bt_field_type_common *ft,
+               struct bt_field_common *tag_field,
+               bt_field_common_create_func field_create_func)
 {
        int ret;
        const char *enum_value;
-       struct bt_field_type *field_type = NULL;
+       struct bt_field_type_common *field_type = NULL;
        struct bt_field_type_enumeration_mapping_iterator *iter = NULL;
 
-       BT_ASSERT_PRE_NON_NULL(type, "Variant field type");
-       BT_ASSERT_PRE_NON_NULL(tag, "Tag field type");
-       BT_ASSERT_PRE_FT_HAS_ID(type, BT_FIELD_TYPE_ID_VARIANT, "Field type");
-       iter = bt_field_enumeration_get_mappings(tag);
+       BT_ASSERT_PRE_NON_NULL(ft, "Variant field type");
+       BT_ASSERT_PRE_NON_NULL(tag_field, "Tag field");
+       BT_ASSERT_PRE_FT_COMMON_HAS_ID(ft, BT_FIELD_TYPE_ID_VARIANT,
+               "Field type");
+       iter = bt_field_common_enumeration_get_mappings(tag_field,
+               field_create_func);
        ret = bt_field_type_enumeration_mapping_iterator_next(iter);
        if (!iter || ret) {
                BT_LOGW("Cannot get enumeration field type mapping iterator from enumeration field: "
-                       "enum-field-addr=%p", tag);
+                       "enum-field-addr=%p", tag_field);
                goto end;
        }
 
-       ret = bt_field_type_enumeration_mapping_iterator_get_signed(iter,
+       ret = bt_field_type_enumeration_mapping_iterator_signed_get(iter,
                &enum_value, NULL, NULL);
        if (ret) {
                BT_LOGW("Cannot get enumeration field type mapping iterator's current mapping: "
@@ -2304,40 +2657,57 @@ struct bt_field_type *bt_field_type_variant_get_field_type_from_tag(
                goto end;
        }
 
-       field_type = bt_field_type_variant_get_field_type_by_name(
-               type, enum_value);
+       field_type = bt_field_type_common_variant_get_field_type_by_name(
+               ft, enum_value);
+
 end:
        bt_put(iter);
        return field_type;
 }
 
-int64_t bt_field_type_variant_get_field_count(struct bt_field_type *type)
+struct bt_field_type *bt_field_type_variant_get_field_type_from_tag(
+               struct bt_field_type *ft,
+               struct bt_field *tag_field)
 {
-       struct bt_field_type_variant *variant;
-
-       BT_ASSERT_PRE_NON_NULL(type, "Variant field type");
-       BT_ASSERT_PRE_FT_HAS_ID(type, BT_FIELD_TYPE_ID_VARIANT, "Field type");
-       variant = container_of(type, struct bt_field_type_variant,
-               parent);
-       return (int64_t) variant->fields->len;
+       return (void *) bt_field_type_common_variant_get_field_type_from_tag(
+               (void *) ft, (void *) tag_field,
+               (bt_field_common_create_func) bt_field_create);
 }
 
-int bt_field_type_variant_get_field_by_index(struct bt_field_type *type,
-               const char **field_name, struct bt_field_type **field_type,
-               uint64_t index)
+BT_HIDDEN
+int64_t bt_field_type_common_variant_get_field_count(
+               struct bt_field_type_common *ft)
+{
+       struct bt_field_type_common_variant *var_ft = BT_FROM_COMMON(ft);
+
+       BT_ASSERT_PRE_NON_NULL(ft, "Variant field type");
+       BT_ASSERT_PRE_FT_COMMON_HAS_ID(ft, BT_FIELD_TYPE_ID_VARIANT,
+               "Field type");
+       return (int64_t) var_ft->fields->len;
+}
+
+int64_t bt_field_type_variant_get_field_count(struct bt_field_type *ft)
 {
-       struct bt_field_type_variant *variant;
-       struct structure_field *field;
+       return bt_field_type_common_variant_get_field_count((void *) ft);
+}
 
-       BT_ASSERT_PRE_NON_NULL(type, "Field type");
-       BT_ASSERT_PRE_FT_HAS_ID(type, BT_FIELD_TYPE_ID_VARIANT, "Field type");
-       variant = container_of(type, struct bt_field_type_variant,
-               parent);
-       BT_ASSERT_PRE(index < variant->fields->len,
+BT_HIDDEN
+int bt_field_type_common_variant_get_field_by_index(
+               struct bt_field_type_common *ft,
+               const char **field_name,
+               struct bt_field_type_common **field_type, uint64_t index)
+{
+       struct bt_field_type_common_variant *var_ft = BT_FROM_COMMON(ft);
+       struct structure_field_common *field;
+
+       BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+       BT_ASSERT_PRE_FT_COMMON_HAS_ID(ft, BT_FIELD_TYPE_ID_VARIANT,
+               "Field type");
+       BT_ASSERT_PRE(index < var_ft->fields->len,
                "Index is out of bounds: index=%" PRIu64 ", "
-               "count=%u, %![ft-]+F",
-               index, variant->fields->len, type);
-       field = g_ptr_array_index(variant->fields, index);
+               "count=%u, %![ft-]+_F",
+               index, var_ft->fields->len, ft);
+       field = g_ptr_array_index(var_ft->fields, index);
 
        if (field_type) {
                *field_type = field->type;
@@ -2352,16 +2722,23 @@ int bt_field_type_variant_get_field_by_index(struct bt_field_type *type,
        return 0;
 }
 
+int bt_field_type_variant_get_field_by_index(struct bt_field_type *ft,
+               const char **field_name, struct bt_field_type **field_type,
+               uint64_t index)
+{
+       return bt_field_type_common_variant_get_field_by_index((void *) ft,
+               field_name, (void *) field_type, index);
+}
+
 struct bt_field_type *bt_field_type_array_create(
-               struct bt_field_type *element_type,
-               unsigned int length)
+               struct bt_field_type *element_ft, unsigned int length)
 {
-       struct bt_field_type_array *array = NULL;
+       struct bt_field_type_common_array *array = NULL;
 
        BT_LOGD("Creating array field type object: element-ft-addr=%p, "
-               "length=%u", element_type, length);
+               "length=%u", element_ft, length);
 
-       if (!element_type) {
+       if (!element_ft) {
                BT_LOGW_STR("Invalid parameter: element field type is NULL.");
                goto error;
        }
@@ -2371,98 +2748,114 @@ struct bt_field_type *bt_field_type_array_create(
                goto error;
        }
 
-       array = g_new0(struct bt_field_type_array, 1);
+       array = g_new0(struct bt_field_type_common_array, 1);
        if (!array) {
                BT_LOGE_STR("Failed to allocate one array field type.");
                goto error;
        }
 
-       array->parent.id = BT_FIELD_TYPE_ID_ARRAY;
-       bt_get(element_type);
-       array->element_type = element_type;
-       array->length = length;
-       bt_field_type_init(&array->parent, FALSE);
+       bt_field_type_common_array_initialize(BT_TO_COMMON(array),
+               (void *) element_ft, length,
+               bt_field_type_common_array_destroy_recursive,
+               &bt_field_type_array_methods);
        BT_LOGD("Created array field type object: addr=%p, "
                "element-ft-addr=%p, length=%u",
-               &array->parent, element_type, length);
-       return &array->parent;
+               array, element_ft, length);
+       goto end;
+
 error:
-       return NULL;
+       BT_PUT(array);
+
+end:
+       return (void *) array;
 }
 
-struct bt_field_type *bt_field_type_array_get_element_type(
-               struct bt_field_type *type)
+BT_HIDDEN
+struct bt_field_type_common *bt_field_type_common_array_get_element_field_type(
+               struct bt_field_type_common *ft)
 {
-       struct bt_field_type_array *array;
+       struct bt_field_type_common_array *array_ft = BT_FROM_COMMON(ft);
+
+       BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+       BT_ASSERT_PRE_FT_COMMON_HAS_ID(ft, BT_FIELD_TYPE_ID_ARRAY,
+               "Field type");
+       BT_ASSERT(array_ft && array_ft->element_ft);
+       return bt_get(array_ft->element_ft);
+}
 
-       BT_ASSERT_PRE_NON_NULL(type, "Field type");
-       BT_ASSERT_PRE_FT_HAS_ID(type, BT_FIELD_TYPE_ID_ARRAY, "Field type");
-       array = container_of(type, struct bt_field_type_array, parent);
-       return bt_get(array->element_type);
+struct bt_field_type *bt_field_type_array_get_element_field_type(
+               struct bt_field_type *ft)
+{
+       return (void *) bt_field_type_common_array_get_element_field_type(
+               (void *) ft);
 }
 
 BT_HIDDEN
-int bt_field_type_array_set_element_type(struct bt_field_type *type,
-               struct bt_field_type *element_type)
+int bt_field_type_common_array_set_element_field_type(
+               struct bt_field_type_common *ft,
+               struct bt_field_type_common *element_ft)
 {
        int ret = 0;
-       struct bt_field_type_array *array;
+       struct bt_field_type_common_array *array_ft = BT_FROM_COMMON(ft);
 
-       if (!type) {
+       if (!ft) {
                BT_LOGW_STR("Invalid parameter: array field type is NULL.");
                ret = -1;
                goto end;
        }
 
-       if (!element_type) {
+       if (!element_ft) {
                BT_LOGW_STR("Invalid parameter: element field type is NULL.");
                ret = -1;
                goto end;
        }
 
-       if (type->id != BT_FIELD_TYPE_ID_ARRAY) {
+       if (ft->id != BT_FIELD_TYPE_ID_ARRAY) {
                BT_LOGW("Invalid parameter: field type is not an array field type: "
-                       "addr=%p, ft-id=%s", type,
-                       bt_field_type_id_string(type->id));
+                       "addr=%p, ft-id=%s", ft,
+                       bt_common_field_type_id_string(ft->id));
                ret = -1;
                goto end;
        }
 
-       array = container_of(type, struct bt_field_type_array, parent);
-
-       if (array->element_type) {
-               BT_PUT(array->element_type);
+       if (array_ft->element_ft) {
+               BT_PUT(array_ft->element_ft);
        }
 
-       array->element_type = element_type;
-       bt_get(array->element_type);
+       array_ft->element_ft = bt_get(element_ft);
        BT_LOGV("Set array field type's element field type: array-ft-addr=%p, "
-               "element-ft-addr=%p", type, element_type);
+               "element-ft-addr=%p", ft, element_ft);
 
 end:
        return ret;
 }
 
-int64_t bt_field_type_array_get_length(struct bt_field_type *type)
+BT_HIDDEN
+int64_t bt_field_type_common_array_get_length(struct bt_field_type_common *ft)
 {
-       struct bt_field_type_array *array;
+       struct bt_field_type_common_array *array_ft = BT_FROM_COMMON(ft);
 
-       BT_ASSERT_PRE_NON_NULL(type, "Field type");
-       BT_ASSERT_PRE_FT_HAS_ID(type, BT_FIELD_TYPE_ID_ARRAY, "Field type");
-       array = container_of(type, struct bt_field_type_array, parent);
-       return (int64_t) array->length;
+       BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+       BT_ASSERT_PRE_FT_COMMON_HAS_ID(ft, BT_FIELD_TYPE_ID_ARRAY,
+               "Field type");
+       return (int64_t) array_ft->length;
+}
+
+int64_t bt_field_type_array_get_length(struct bt_field_type *ft)
+{
+       return bt_field_type_common_array_get_length((void *) ft);
 }
 
 struct bt_field_type *bt_field_type_sequence_create(
-               struct bt_field_type *element_type,
+               struct bt_field_type *element_ft,
                const char *length_field_name)
 {
-       struct bt_field_type_sequence *sequence = NULL;
+       struct bt_field_type_common_sequence *sequence = NULL;
 
        BT_LOGD("Creating sequence field type object: element-ft-addr=%p, "
-               "length-field-name=\"%s\"", element_type, length_field_name);
+               "length-field-name=\"%s\"", element_ft, length_field_name);
 
-       if (!element_type) {
+       if (!element_ft) {
                BT_LOGW_STR("Invalid parameter: element field type is NULL.");
                goto error;
        }
@@ -2473,95 +2866,111 @@ struct bt_field_type *bt_field_type_sequence_create(
                goto error;
        }
 
-       sequence = g_new0(struct bt_field_type_sequence, 1);
+       sequence = g_new0(struct bt_field_type_common_sequence, 1);
        if (!sequence) {
                BT_LOGE_STR("Failed to allocate one sequence field type.");
                goto error;
        }
 
-       sequence->parent.id = BT_FIELD_TYPE_ID_SEQUENCE;
-       bt_get(element_type);
-       sequence->element_type = element_type;
-       sequence->length_field_name = g_string_new(length_field_name);
-       bt_field_type_init(&sequence->parent, FALSE);
+       bt_field_type_common_sequence_initialize(BT_TO_COMMON(sequence),
+               (void *) element_ft, length_field_name,
+               bt_field_type_common_sequence_destroy_recursive,
+               &bt_field_type_sequence_methods);
        BT_LOGD("Created sequence field type object: addr=%p, "
                "element-ft-addr=%p, length-field-name=\"%s\"",
-               &sequence->parent, element_type, length_field_name);
-       return &sequence->parent;
+               sequence, element_ft, length_field_name);
+       goto end;
+
 error:
-       return NULL;
+       BT_PUT(sequence);
+
+end:
+       return (void *) sequence;
 }
 
-struct bt_field_type *bt_field_type_sequence_get_element_type(
-               struct bt_field_type *type)
+BT_HIDDEN
+struct bt_field_type_common *bt_field_type_common_sequence_get_element_field_type(
+               struct bt_field_type_common *ft)
 {
-       struct bt_field_type_sequence *sequence;
+       struct bt_field_type_common_sequence *seq_ft = BT_FROM_COMMON(ft);
+
+       BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+       BT_ASSERT_PRE_FT_COMMON_HAS_ID(ft, BT_FIELD_TYPE_ID_SEQUENCE,
+               "Field type");
+       return bt_get(seq_ft->element_ft);
+}
 
-       BT_ASSERT_PRE_NON_NULL(type, "Field type");
-       BT_ASSERT_PRE_FT_HAS_ID(type, BT_FIELD_TYPE_ID_SEQUENCE, "Field type");
-       sequence = container_of(type, struct bt_field_type_sequence,
-               parent);
-       return bt_get(sequence->element_type);
+struct bt_field_type *bt_field_type_sequence_get_element_field_type(
+               struct bt_field_type *ft)
+{
+       return (void *) bt_field_type_common_sequence_get_element_field_type(
+               (void *) ft);
 }
 
 BT_HIDDEN
-int bt_field_type_sequence_set_element_type(struct bt_field_type *type,
-               struct bt_field_type *element_type)
+int bt_field_type_common_sequence_set_element_field_type(
+               struct bt_field_type_common *ft,
+               struct bt_field_type_common *element_ft)
 {
        int ret = 0;
-       struct bt_field_type_sequence *sequence;
+       struct bt_field_type_common_sequence *seq_ft = BT_FROM_COMMON(ft);
 
-       if (!type) {
+       if (!ft) {
                BT_LOGW_STR("Invalid parameter: sequence field type is NULL.");
                ret = -1;
                goto end;
        }
 
-       if (!element_type) {
+       if (!element_ft) {
                BT_LOGW_STR("Invalid parameter: element field type is NULL.");
                ret = -1;
                goto end;
        }
 
-       if (type->id != BT_FIELD_TYPE_ID_SEQUENCE) {
+       if (ft->id != BT_FIELD_TYPE_ID_SEQUENCE) {
                BT_LOGW("Invalid parameter: field type is not a sequence field type: "
-                       "addr=%p, ft-id=%s", type,
-                       bt_field_type_id_string(type->id));
+                       "addr=%p, ft-id=%s", ft,
+                       bt_common_field_type_id_string(ft->id));
                ret = -1;
                goto end;
        }
 
-       sequence = container_of(type, struct bt_field_type_sequence, parent);
-       if (sequence->element_type) {
-               BT_PUT(sequence->element_type);
+       if (seq_ft->element_ft) {
+               BT_PUT(seq_ft->element_ft);
        }
 
-       sequence->element_type = element_type;
-       bt_get(sequence->element_type);
+       seq_ft->element_ft = element_ft;
+       bt_get(seq_ft->element_ft);
        BT_LOGV("Set sequence field type's element field type: sequence-ft-addr=%p, "
-               "element-ft-addr=%p", type, element_type);
+               "element-ft-addr=%p", ft, element_ft);
 
 end:
        return ret;
 }
 
-const char *bt_field_type_sequence_get_length_field_name(
-               struct bt_field_type *type)
+BT_HIDDEN
+const char *bt_field_type_common_sequence_get_length_field_name(
+               struct bt_field_type_common *ft)
 {
-       struct bt_field_type_sequence *sequence;
+       struct bt_field_type_common_sequence *seq_ft = BT_FROM_COMMON(ft);
+
+       BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+       BT_ASSERT_PRE_FT_COMMON_HAS_ID(ft, BT_FIELD_TYPE_ID_SEQUENCE,
+               "Field type");
+       return seq_ft->length_field_name ?
+               seq_ft->length_field_name->str : NULL;
+}
 
-       BT_ASSERT_PRE_NON_NULL(type, "Field type");
-       BT_ASSERT_PRE_FT_HAS_ID(type, BT_FIELD_TYPE_ID_SEQUENCE, "Field type");
-       sequence = container_of(type, struct bt_field_type_sequence,
-               parent);
-       return sequence->length_field_name ?
-               sequence->length_field_name->str : NULL;
+const char *bt_field_type_sequence_get_length_field_name(
+               struct bt_field_type *ft)
+{
+       return bt_field_type_common_sequence_get_length_field_name((void *) ft);
 }
 
 struct bt_field_type *bt_field_type_string_create(void)
 {
-       struct bt_field_type_string *string =
-               g_new0(struct bt_field_type_string, 1);
+       struct bt_field_type_common_string *string =
+               g_new0(struct bt_field_type_common_string, 1);
 
        BT_LOGD_STR("Creating string field type object.");
 
@@ -2570,42 +2979,48 @@ struct bt_field_type *bt_field_type_string_create(void)
                return NULL;
        }
 
-       string->parent.id = BT_FIELD_TYPE_ID_STRING;
-       bt_field_type_init(&string->parent, TRUE);
-       string->encoding = BT_STRING_ENCODING_UTF8;
-       string->parent.alignment = CHAR_BIT;
-       BT_LOGD("Created string field type object: addr=%p", &string->parent);
-       return &string->parent;
+       bt_field_type_common_string_initialize(BT_TO_COMMON(string),
+               bt_field_type_common_string_destroy,
+               &bt_field_type_string_methods);
+       BT_LOGD("Created string field type object: addr=%p", string);
+       return (void *) string;
 }
 
-enum bt_string_encoding bt_field_type_string_get_encoding(
-               struct bt_field_type *type)
+BT_HIDDEN
+enum bt_string_encoding bt_field_type_common_string_get_encoding(
+               struct bt_field_type_common *ft)
 {
-       struct bt_field_type_string *string;
+       struct bt_field_type_common_string *string_ft = BT_FROM_COMMON(ft);
 
-       BT_ASSERT_PRE_NON_NULL(type, "Field type");
-       BT_ASSERT_PRE_FT_HAS_ID(type, BT_FIELD_TYPE_ID_STRING, "Field type");
-       string = container_of(type, struct bt_field_type_string,
-               parent);
-       return string->encoding;
+       BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+       BT_ASSERT_PRE_FT_COMMON_HAS_ID(ft, BT_FIELD_TYPE_ID_STRING,
+               "Field type");
+       return string_ft->encoding;
+}
+
+enum bt_string_encoding bt_field_type_string_get_encoding(
+               struct bt_field_type *ft)
+{
+       return bt_field_type_common_string_get_encoding((void *) ft);
 }
 
-int bt_field_type_string_set_encoding(struct bt_field_type *type,
+BT_HIDDEN
+int bt_field_type_common_string_set_encoding(struct bt_field_type_common *ft,
                enum bt_string_encoding encoding)
 {
        int ret = 0;
-       struct bt_field_type_string *string;
+       struct bt_field_type_common_string *string_ft = BT_FROM_COMMON(ft);
 
-       if (!type) {
+       if (!ft) {
                BT_LOGW_STR("Invalid parameter: field type is NULL.");
                ret = -1;
                goto end;
        }
 
-       if (type->id != BT_FIELD_TYPE_ID_STRING) {
+       if (ft->id != BT_FIELD_TYPE_ID_STRING) {
                BT_LOGW("Invalid parameter: field type is not a string field type: "
-                       "addr=%p, ft-id=%s", type,
-                       bt_field_type_id_string(type->id));
+                       "addr=%p, ft-id=%s", ft,
+                       bt_common_field_type_id_string(ft->id));
                ret = -1;
                goto end;
        }
@@ -2613,70 +3028,77 @@ int bt_field_type_string_set_encoding(struct bt_field_type *type,
        if (encoding != BT_STRING_ENCODING_UTF8 &&
                        encoding != BT_STRING_ENCODING_ASCII) {
                BT_LOGW("Invalid parameter: unknown string encoding: "
-                       "addr=%p, encoding=%d", type, encoding);
+                       "addr=%p, encoding=%d", ft, encoding);
                ret = -1;
                goto end;
        }
 
-       string = container_of(type, struct bt_field_type_string, parent);
-       string->encoding = encoding;
+       string_ft->encoding = encoding;
        BT_LOGV("Set string field type's encoding: addr=%p, encoding=%s",
-               type, bt_string_encoding_string(encoding));
+               ft, bt_common_string_encoding_string(encoding));
+
 end:
        return ret;
 }
 
-int bt_field_type_get_alignment(struct bt_field_type *type)
+int bt_field_type_string_set_encoding(struct bt_field_type *ft,
+               enum bt_string_encoding encoding)
+{
+       return bt_field_type_common_string_set_encoding((void *) ft, encoding);
+}
+
+BT_HIDDEN
+int bt_field_type_common_get_alignment(struct bt_field_type_common *ft)
 {
        int ret;
        enum bt_field_type_id type_id;
 
-       BT_ASSERT_PRE_NON_NULL(type, "Field type");
+       BT_ASSERT_PRE_NON_NULL(ft, "Field type");
 
-       if (type->frozen) {
-               ret = (int) type->alignment;
+       if (ft->frozen) {
+               ret = (int) ft->alignment;
                goto end;
        }
 
-       type_id = bt_field_type_get_type_id(type);
+       type_id = bt_field_type_common_get_type_id(ft);
        switch (type_id) {
        case BT_FIELD_TYPE_ID_SEQUENCE:
        {
-               struct bt_field_type *element =
-                       bt_field_type_sequence_get_element_type(type);
+               struct bt_field_type_common *element_ft =
+                       bt_field_type_common_sequence_get_element_field_type(ft);
 
-               BT_ASSERT(element);
-               ret = bt_field_type_get_alignment(element);
-               bt_put(element);
+               BT_ASSERT(element_ft);
+               ret = bt_field_type_common_get_alignment(element_ft);
+               bt_put(element_ft);
                break;
        }
        case BT_FIELD_TYPE_ID_ARRAY:
        {
-               struct bt_field_type *element =
-                       bt_field_type_array_get_element_type(type);
+               struct bt_field_type_common *element_ft =
+                       bt_field_type_common_array_get_element_field_type(ft);
 
-               BT_ASSERT(element);
-               ret = bt_field_type_get_alignment(element);
-               bt_put(element);
+               BT_ASSERT(element_ft);
+               ret = bt_field_type_common_get_alignment(element_ft);
+               bt_put(element_ft);
                break;
        }
        case BT_FIELD_TYPE_ID_STRUCT:
        {
                int64_t i, element_count;
 
-               element_count = bt_field_type_structure_get_field_count(
-                       type);
+               element_count = bt_field_type_common_structure_get_field_count(
+                       ft);
                BT_ASSERT(element_count >= 0);
 
                for (i = 0; i < element_count; i++) {
-                       struct bt_field_type *field = NULL;
+                       struct bt_field_type_common *field = NULL;
                        int field_alignment;
 
-                       ret = bt_field_type_structure_get_field_by_index(
-                               type, NULL, &field, i);
+                       ret = bt_field_type_common_structure_get_field_by_index(
+                               ft, NULL, &field, i);
                        BT_ASSERT(ret == 0);
                        BT_ASSERT(field);
-                       field_alignment = bt_field_type_get_alignment(
+                       field_alignment = bt_field_type_common_get_alignment(
                                field);
                        bt_put(field);
                        if (field_alignment < 0) {
@@ -2684,78 +3106,75 @@ int bt_field_type_get_alignment(struct bt_field_type *type)
                                goto end;
                        }
 
-                       type->alignment = MAX(field_alignment, type->alignment);
+                       ft->alignment = MAX(field_alignment, ft->alignment);
                }
-               ret = (int) type->alignment;
-               break;
-       }
-       case BT_FIELD_TYPE_ID_ENUM:
-       {
-               struct bt_field_type *container =
-                       bt_field_type_enumeration_get_container_type(type);
-
-               ret = bt_field_type_get_alignment(container);
-               bt_put(container);
+               ret = (int) ft->alignment;
                break;
        }
        case BT_FIELD_TYPE_ID_UNKNOWN:
                BT_LOGW("Invalid parameter: unknown field type ID: "
-                       "addr=%p, ft-id=%d", type, type_id);
+                       "addr=%p, ft-id=%d", ft, type_id);
                ret = -1;
                break;
        default:
-               ret = (int) type->alignment;
+               ret = (int) ft->alignment;
                break;
        }
+
 end:
        return ret;
 }
 
+int bt_field_type_get_alignment(struct bt_field_type *ft)
+{
+       return bt_field_type_common_get_alignment((void *) ft);
+}
+
 static inline
 int is_power_of_two(unsigned int value)
 {
        return ((value & (value - 1)) == 0) && value > 0;
 }
 
-int bt_field_type_set_alignment(struct bt_field_type *type,
+BT_HIDDEN
+int bt_field_type_common_set_alignment(struct bt_field_type_common *ft,
                unsigned int alignment)
 {
        int ret = 0;
        enum bt_field_type_id type_id;
 
        /* Alignment must be a power of two */
-       if (!type) {
+       if (!ft) {
                BT_LOGW_STR("Invalid parameter: field type is NULL.");
                ret = -1;
                goto end;
        }
 
-       if (type->frozen) {
+       if (ft->frozen) {
                BT_LOGW("Invalid parameter: field type is frozen: addr=%p",
-                       type);
+                       ft);
                ret = -1;
                goto end;
        }
 
        if (!is_power_of_two(alignment)) {
                BT_LOGW("Invalid parameter: alignment is not a power of two: "
-                       "addr=%p, align=%u", type, alignment);
+                       "addr=%p, align=%u", ft, alignment);
                ret = -1;
                goto end;
        }
 
-       type_id = bt_field_type_get_type_id(type);
+       type_id = bt_field_type_common_get_type_id(ft);
        if (type_id == BT_FIELD_TYPE_ID_UNKNOWN) {
                BT_LOGW("Invalid parameter: unknown field type ID: "
-                       "addr=%p, ft-id=%d", type, type_id);
+                       "addr=%p, ft-id=%d", ft, type_id);
                ret = -1;
                goto end;
        }
 
-       if (type->id == BT_FIELD_TYPE_ID_STRING &&
-                       alignment != CHAR_BIT) {
+       if (ft->id == BT_FIELD_TYPE_ID_STRING && alignment != CHAR_BIT) {
                BT_LOGW("Invalid parameter: alignment must be %u for a string field type: "
-                       "addr=%p, align=%u", CHAR_BIT, type, alignment);
+                       "addr=%p, align=%u", CHAR_BIT, ft, alignment);
                ret = -1;
                goto end;
        }
@@ -2765,55 +3184,64 @@ int bt_field_type_set_alignment(struct bt_field_type *type,
                        type_id == BT_FIELD_TYPE_ID_ARRAY) {
                /* Setting an alignment on these types makes no sense */
                BT_LOGW("Invalid parameter: cannot set the alignment of this field type: "
-                       "addr=%p, ft-id=%s", type,
-                       bt_field_type_id_string(type->id));
+                       "addr=%p, ft-id=%s", ft,
+                       bt_common_field_type_id_string(ft->id));
                ret = -1;
                goto end;
        }
 
-       type->alignment = alignment;
+       ft->alignment = alignment;
        ret = 0;
        BT_LOGV("Set field type's alignment: addr=%p, align=%u",
-               type, alignment);
+               ft, alignment);
+
 end:
        return ret;
 }
 
-enum bt_byte_order bt_field_type_get_byte_order(
-               struct bt_field_type *type)
+int bt_field_type_set_alignment(struct bt_field_type *ft,
+               unsigned int alignment)
+{
+       return bt_field_type_common_set_alignment((void *) ft, alignment);
+}
+
+BT_HIDDEN
+enum bt_byte_order bt_field_type_common_get_byte_order(
+               struct bt_field_type_common *ft)
 {
        enum bt_byte_order ret = BT_BYTE_ORDER_UNKNOWN;
 
-       BT_ASSERT_PRE_NON_NULL(type, "Field type");
+       BT_ASSERT_PRE_NON_NULL(ft, "Field type");
 
-       switch (type->id) {
+       switch (ft->id) {
        case BT_FIELD_TYPE_ID_INTEGER:
        {
-               struct bt_field_type_integer *integer = container_of(
-                       type, struct bt_field_type_integer, parent);
+               struct bt_field_type_common_integer *integer =
+                       BT_FROM_COMMON(ft);
+
                ret = integer->user_byte_order;
                break;
        }
        case BT_FIELD_TYPE_ID_ENUM:
        {
-               struct bt_field_type_enumeration *enum_ft = container_of(
-                       type, struct bt_field_type_enumeration, parent);
-               ret = bt_field_type_get_byte_order(enum_ft->container);
+               struct bt_field_type_common_enumeration *enum_ft =
+                       BT_FROM_COMMON(ft);
+
+               ret = bt_field_type_common_get_byte_order(
+                       BT_TO_COMMON(enum_ft->container_ft));
                break;
        }
        case BT_FIELD_TYPE_ID_FLOAT:
        {
-               struct bt_field_type_floating_point *floating_point =
-                       container_of(type,
-                               struct bt_field_type_floating_point,
-                               parent);
+               struct bt_field_type_common_floating_point *floating_point =
+                       BT_FROM_COMMON(ft);
                ret = floating_point->user_byte_order;
                break;
        }
        default:
                BT_LOGW("Invalid parameter: cannot get the byte order of this field type: "
-                       "addr=%p, ft-id=%s", type,
-                       bt_field_type_id_string(type->id));
+                       "addr=%p, ft-id=%s", ft,
+                       bt_common_field_type_id_string(ft->id));
                goto end;
        }
 
@@ -2826,20 +3254,26 @@ end:
        return ret;
 }
 
-int bt_field_type_set_byte_order(struct bt_field_type *type,
+enum bt_byte_order bt_field_type_get_byte_order(struct bt_field_type *ft)
+{
+       return bt_field_type_common_get_byte_order((void *) ft);
+}
+
+BT_HIDDEN
+int bt_field_type_common_set_byte_order(struct bt_field_type_common *ft,
                enum bt_byte_order byte_order)
 {
        int ret = 0;
 
-       if (!type) {
+       if (!ft) {
                BT_LOGW_STR("Invalid parameter: field type is NULL.");
                ret = -1;
                goto end;
        }
 
-       if (type->frozen) {
+       if (ft->frozen) {
                BT_LOGW("Invalid parameter: field type is frozen: addr=%p",
-                       type);
+                       ft);
                ret = -1;
                goto end;
        }
@@ -2849,28 +3283,40 @@ int bt_field_type_set_byte_order(struct bt_field_type *type,
                        byte_order != BT_BYTE_ORDER_BIG_ENDIAN &&
                        byte_order != BT_BYTE_ORDER_NETWORK) {
                BT_LOGW("Invalid parameter: invalid byte order: "
-                       "addr=%p, bo=%s", type,
-                       bt_byte_order_string(byte_order));
+                       "addr=%p, bo=%s", ft,
+                       bt_common_byte_order_string(byte_order));
                ret = -1;
                goto end;
        }
 
-       if (set_byte_order_funcs[type->id]) {
-               set_byte_order_funcs[type->id](type, byte_order);
+       if (ft->methods->set_byte_order) {
+               ft->methods->set_byte_order(ft, byte_order);
        }
 
        BT_LOGV("Set field type's byte order: addr=%p, bo=%s",
-               type, bt_byte_order_string(byte_order));
+               ft, bt_common_byte_order_string(byte_order));
 
 end:
        return ret;
 }
 
-enum bt_field_type_id bt_field_type_get_type_id(
-               struct bt_field_type *type)
+int bt_field_type_set_byte_order(struct bt_field_type *ft,
+               enum bt_byte_order byte_order)
+{
+       return bt_field_type_common_set_byte_order((void *) ft, byte_order);
+}
+
+BT_HIDDEN
+enum bt_field_type_id bt_field_type_common_get_type_id(
+               struct bt_field_type_common *ft)
+{
+       BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+       return ft->id;
+}
+
+enum bt_field_type_id bt_field_type_get_type_id(struct bt_field_type *ft)
 {
-       BT_ASSERT_PRE_NON_NULL(type, "Field type");
-       return type->id;
+       return bt_field_type_common_get_type_id((void *) ft);
 }
 
 int bt_field_type_is_integer(struct bt_field_type *type)
@@ -2913,37 +3359,32 @@ int bt_field_type_is_variant(struct bt_field_type *type)
        return bt_field_type_get_type_id(type) == BT_FIELD_TYPE_ID_VARIANT;
 }
 
-/* Pre-2.0 CTF writer backward compatibility */
-void bt_ctf_field_type_get(struct bt_field_type *type)
+BT_HIDDEN
+void _bt_field_type_common_freeze(struct bt_field_type_common *ft)
 {
-       bt_get(type);
-}
+       if (!ft || ft->frozen) {
+               return;
+       }
 
-/* Pre-2.0 CTF writer backward compatibility */
-void bt_ctf_field_type_put(struct bt_field_type *type)
-{
-       bt_put(type);
+       BT_ASSERT(ft->methods->freeze);
+       ft->methods->freeze(ft);
 }
 
 BT_HIDDEN
-void _bt_field_type_freeze(struct bt_field_type *type)
+void _bt_field_type_freeze(struct bt_field_type *ft)
 {
-       if (!type || type->frozen) {
-               return;
-       }
-
-       type->freeze(type);
+       _bt_field_type_common_freeze((void *) ft);
 }
 
 BT_HIDDEN
-struct bt_field_type *bt_field_type_variant_get_field_type_signed(
-               struct bt_field_type_variant *variant,
+struct bt_field_type_common *bt_field_type_common_variant_get_field_type_signed(
+               struct bt_field_type_common_variant *var_ft,
                int64_t tag_value)
 {
-       struct bt_field_type *type = NULL;
+       struct bt_field_type_common *field_type = NULL;
        GQuark field_name_quark;
        gpointer index;
-       struct structure_field *field_entry;
+       struct structure_field_common *field_entry;
        struct range_overlap_query query = {
                .range_start._signed = tag_value,
                .range_end._signed = tag_value,
@@ -2951,33 +3392,34 @@ struct bt_field_type *bt_field_type_variant_get_field_type_signed(
                .overlaps = 0,
        };
 
-       g_ptr_array_foreach(variant->tag->entries, check_ranges_overlap,
+       g_ptr_array_foreach(var_ft->tag_ft->entries, check_ranges_overlap,
                &query);
        if (!query.overlaps) {
                goto end;
        }
 
        field_name_quark = query.mapping_name;
-       if (!g_hash_table_lookup_extended(variant->field_name_to_index,
+       if (!g_hash_table_lookup_extended(var_ft->field_name_to_index,
                        GUINT_TO_POINTER(field_name_quark), NULL, &index)) {
                goto end;
        }
 
-       field_entry = g_ptr_array_index(variant->fields, (size_t) index);
-       type = field_entry->type;
+       field_entry = g_ptr_array_index(var_ft->fields, (size_t) index);
+       field_type = field_entry->type;
+
 end:
-       return type;
+       return field_type;
 }
 
 BT_HIDDEN
-struct bt_field_type *bt_field_type_variant_get_field_type_unsigned(
-               struct bt_field_type_variant *variant,
+struct bt_field_type_common *bt_field_type_common_variant_get_field_type_unsigned(
+               struct bt_field_type_common_variant *var_ft,
                uint64_t tag_value)
 {
-       struct bt_field_type *type = NULL;
+       struct bt_field_type_common *field_type = NULL;
        GQuark field_name_quark;
        gpointer index;
-       struct structure_field *field_entry;
+       struct structure_field_common *field_entry;
        struct range_overlap_query query = {
                .range_start._unsigned = tag_value,
                .range_end._unsigned = tag_value,
@@ -2985,1996 +3427,1530 @@ struct bt_field_type *bt_field_type_variant_get_field_type_unsigned(
                .overlaps = 0,
        };
 
-       g_ptr_array_foreach(variant->tag->entries,
-               check_ranges_overlap_unsigned,
-               &query);
+       g_ptr_array_foreach(var_ft->tag_ft->entries,
+               check_ranges_overlap_unsigned, &query);
        if (!query.overlaps) {
                goto end;
        }
 
        field_name_quark = query.mapping_name;
-       if (!g_hash_table_lookup_extended(variant->field_name_to_index,
+       if (!g_hash_table_lookup_extended(var_ft->field_name_to_index,
                GUINT_TO_POINTER(field_name_quark), NULL, &index)) {
                goto end;
        }
 
-       field_entry = g_ptr_array_index(variant->fields, (size_t)index);
-       type = field_entry->type;
+       field_entry = g_ptr_array_index(var_ft->fields, (size_t) index);
+       field_type = field_entry->type;
 end:
-       return type;
+       return field_type;
 }
 
 BT_HIDDEN
-int bt_field_type_serialize(struct bt_field_type *type,
-               struct metadata_context *context)
+struct bt_field_type_common *bt_field_type_common_copy(
+               struct bt_field_type_common *ft)
 {
-       int ret;
+       struct bt_field_type_common *ft_copy = NULL;
 
-       BT_ASSERT(type);
-       BT_ASSERT(context);
-
-       /* Make sure field type is valid before serializing it */
-       ret = bt_field_type_validate(type);
-       if (ret) {
-               BT_LOGW("Cannot serialize field type's metadata: field type is invalid: "
-                       "addr=%p", type);
+       BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+       BT_ASSERT(ft->methods->copy);
+       ft_copy = ft->methods->copy(ft);
+       if (!ft_copy) {
+               BT_LOGE_STR("Cannot copy field type.");
                goto end;
        }
 
-       ret = type->serialize(type, context);
+       ft_copy->alignment = ft->alignment;
+
 end:
-       return ret;
+       return ft_copy;
 }
 
-struct bt_field_type *bt_field_type_copy(struct bt_field_type *type)
+struct bt_field_type *bt_field_type_copy(struct bt_field_type *ft)
 {
-       struct bt_field_type *copy = NULL;
-
-       BT_ASSERT_PRE_NON_NULL(type, "Field type");
-       copy = type_copy_funcs[type->id](type);
-       if (!copy) {
-               BT_LOGE_STR("Cannot copy field type.");
-               goto end;
-       }
-
-       copy->alignment = type->alignment;
-
-end:
-       return copy;
+       return (void *) bt_field_type_common_copy((void *) ft);
 }
 
 BT_HIDDEN
-int bt_field_type_structure_get_field_name_index(
-               struct bt_field_type *type, const char *name)
+int bt_field_type_common_structure_get_field_name_index(
+               struct bt_field_type_common *ft, const char *name)
 {
        int ret;
        size_t index;
        GQuark name_quark;
-       struct bt_field_type_structure *structure;
+       struct bt_field_type_common_structure *struct_ft = BT_FROM_COMMON(ft);
 
-       BT_ASSERT_PRE_NON_NULL(type, "Field type");
+       BT_ASSERT_PRE_NON_NULL(ft, "Field type");
        BT_ASSERT_PRE_NON_NULL(name, "Name");
-       BT_ASSERT_PRE_FT_HAS_ID(type, BT_FIELD_TYPE_ID_STRUCT, "Field type");
+       BT_ASSERT_PRE_FT_COMMON_HAS_ID(ft, BT_FIELD_TYPE_ID_STRUCT,
+               "Field type");
 
        name_quark = g_quark_try_string(name);
        if (!name_quark) {
                BT_LOGV("No such structure field type field name: "
                        "ft-addr=%p, field-name=\"%s\"",
-                       type, name);
+                       ft, name);
                ret = -1;
                goto end;
        }
 
-       structure = container_of(type, struct bt_field_type_structure,
-               parent);
-       if (!g_hash_table_lookup_extended(structure->field_name_to_index,
+       if (!g_hash_table_lookup_extended(struct_ft->field_name_to_index,
                        GUINT_TO_POINTER(name_quark),
-                       NULL, (gpointer *)&index)) {
+                       NULL, (gpointer *) &index)) {
                BT_LOGV("No such structure field type field name: "
                        "ft-addr=%p, field-name=\"%s\"",
-                       type, name);
+                       ft, name);
                ret = -1;
                goto end;
        }
+
        ret = (int) index;
+
 end:
        return ret;
 }
 
 BT_HIDDEN
-int bt_field_type_variant_get_field_name_index(
-               struct bt_field_type *type, const char *name)
+int bt_field_type_common_variant_get_field_name_index(
+               struct bt_field_type_common *ft, const char *name)
 {
        int ret;
        size_t index;
        GQuark name_quark;
-       struct bt_field_type_variant *variant;
+       struct bt_field_type_common_variant *var_ft = BT_FROM_COMMON(ft);
 
-       BT_ASSERT_PRE_NON_NULL(type, "Field type");
+       BT_ASSERT_PRE_NON_NULL(ft, "Field type");
        BT_ASSERT_PRE_NON_NULL(name, "Name");
-       BT_ASSERT_PRE_FT_HAS_ID(type, BT_FIELD_TYPE_ID_VARIANT, "Field type");
+       BT_ASSERT_PRE_FT_COMMON_HAS_ID(ft, BT_FIELD_TYPE_ID_VARIANT,
+               "Field type");
        name_quark = g_quark_try_string(name);
        if (!name_quark) {
                BT_LOGV("No such variant field type field name: "
                        "ft-addr=%p, field-name=\"%s\"",
-                       type, name);
+                       ft, name);
                ret = -1;
                goto end;
        }
 
-       variant = container_of(type, struct bt_field_type_variant,
-               parent);
-       if (!g_hash_table_lookup_extended(variant->field_name_to_index,
+       if (!g_hash_table_lookup_extended(var_ft->field_name_to_index,
                        GUINT_TO_POINTER(name_quark),
-                       NULL, (gpointer *)&index)) {
+                       NULL, (gpointer *) &index)) {
                BT_LOGV("No such variant field type field name: "
                        "ft-addr=%p, field-name=\"%s\"",
-                       type, name);
+                       ft, name);
                ret = -1;
                goto end;
        }
+
        ret = (int) index;
+
 end:
        return ret;
 }
 
 BT_HIDDEN
-int bt_field_type_sequence_set_length_field_path(
-               struct bt_field_type *type, struct bt_field_path *path)
+int bt_field_type_common_sequence_set_length_field_path(
+               struct bt_field_type_common *ft, struct bt_field_path *path)
 {
        int ret = 0;
-       struct bt_field_type_sequence *sequence;
+       struct bt_field_type_common_sequence *seq_ft = BT_FROM_COMMON(ft);
 
-       if (!type) {
+       if (!ft) {
                BT_LOGW_STR("Invalid parameter: field type is NULL.");
                ret = -1;
                goto end;
        }
 
-       if (bt_field_type_get_type_id(type) != BT_FIELD_TYPE_ID_SEQUENCE) {
+       if (ft->id != BT_FIELD_TYPE_ID_SEQUENCE) {
                BT_LOGW("Invalid parameter: field type is not a sequence field type: "
-                       "addr=%p, ft-id=%s", type,
-                       bt_field_type_id_string(type->id));
+                       "addr=%p, ft-id=%s", ft,
+                       bt_common_field_type_id_string(ft->id));
                ret = -1;
                goto end;
        }
 
-       sequence = container_of(type, struct bt_field_type_sequence,
-               parent);
        bt_get(path);
-       BT_MOVE(sequence->length_field_path, path);
+       BT_MOVE(seq_ft->length_field_path, path);
        BT_LOGV("Set sequence field type's length field path: ft-addr=%p, "
-               "field-path-addr=%p", type, path);
+               "field-path-addr=%p", ft, path);
+
 end:
        return ret;
 }
 
 BT_HIDDEN
-int bt_field_type_variant_set_tag_field_path(struct bt_field_type *type,
+int bt_field_type_common_variant_set_tag_field_path(
+               struct bt_field_type_common *ft,
                struct bt_field_path *path)
 {
        int ret = 0;
-       struct bt_field_type_variant *variant;
+       struct bt_field_type_common_variant *var_ft = BT_FROM_COMMON(ft);
 
-       if (!type) {
+       if (!ft) {
                BT_LOGW_STR("Invalid parameter: field type is NULL.");
                ret = -1;
                goto end;
        }
 
-       if (bt_field_type_get_type_id(type) != BT_FIELD_TYPE_ID_VARIANT) {
+       if (ft->id != BT_FIELD_TYPE_ID_VARIANT) {
                BT_LOGW("Invalid parameter: field type is not a variant field type: "
-                       "addr=%p, ft-id=%s", type,
-                       bt_field_type_id_string(type->id));
+                       "addr=%p, ft-id=%s", ft,
+                       bt_common_field_type_id_string(ft->id));
                ret = -1;
                goto end;
        }
 
-       variant = container_of(type, struct bt_field_type_variant,
-               parent);
        bt_get(path);
-       BT_MOVE(variant->tag_field_path, path);
+       BT_MOVE(var_ft->tag_field_path, path);
        BT_LOGV("Set variant field type's tag field path: ft-addr=%p, "
-               "field-path-addr=%p", type, path);
+               "field-path-addr=%p", ft, path);
+
 end:
        return ret;
 }
 
 BT_HIDDEN
-int bt_field_type_variant_set_tag_field_type(struct bt_field_type *type,
-               struct bt_field_type *tag)
+int bt_field_type_common_variant_set_tag_field_type(
+               struct bt_field_type_common *ft,
+               struct bt_field_type_common *tag_ft)
 {
        int ret = 0;
-       struct bt_field_type_variant *variant;
+       struct bt_field_type_common_variant *var_ft = BT_FROM_COMMON(ft);
 
-       if (!type) {
+       if (!ft) {
                BT_LOGW_STR("Invalid parameter: variant field type is NULL.");
                ret = -1;
                goto end;
        }
 
-       if (!tag) {
+       if (!tag_ft) {
                BT_LOGW_STR("Invalid parameter: tag field type is NULL.");
                ret = -1;
                goto end;
        }
 
-       if (bt_field_type_get_type_id(tag) != BT_FIELD_TYPE_ID_ENUM) {
-               BT_LOGW("Invalid parameter: field type is not an enumeration field type: "
-                       "addr=%p, ft-id=%s", type,
-                       bt_field_type_id_string(type->id));
+       if (tag_ft->id != BT_FIELD_TYPE_ID_ENUM) {
+               BT_LOGW("Invalid parameter: tag field type is not an enumeration field type: "
+                       "addr=%p, ft-id=%s", tag_ft,
+                       bt_common_field_type_id_string(tag_ft->id));
                ret = -1;
                goto end;
        }
 
-       variant = container_of(type, struct bt_field_type_variant,
-               parent);
-       bt_get(tag);
-       if (variant->tag) {
-               bt_put(&variant->tag->parent);
-       }
-       variant->tag = container_of(tag, struct bt_field_type_enumeration,
-               parent);
+       bt_put(var_ft->tag_ft);
+       var_ft->tag_ft = bt_get(tag_ft);
        BT_LOGV("Set variant field type's tag field type: variant-ft-addr=%p, "
-               "tag-ft-addr=%p", type, tag);
+               "tag-ft-addr=%p", ft, tag_ft);
+
 end:
        return ret;
 }
 
-static
-void bt_field_type_integer_destroy(struct bt_field_type *type)
+BT_HIDDEN
+void bt_field_type_common_generic_freeze(struct bt_field_type_common *ft)
 {
-       struct bt_field_type_integer *integer =
-               (struct bt_field_type_integer *) type;
-
-       if (!type) {
-               return;
-       }
-
-       BT_LOGD("Destroying integer field type object: addr=%p", type);
-       BT_LOGD_STR("Putting mapped clock class.");
-       bt_put(integer->mapped_clock);
-       g_free(integer);
+       ft->frozen = 1;
 }
 
-static
-void bt_field_type_enumeration_destroy(struct bt_field_type *type)
+BT_HIDDEN
+void bt_field_type_common_enumeration_freeze_recursive(
+               struct bt_field_type_common *ft)
 {
-       struct bt_field_type_enumeration *enumeration =
-               (struct bt_field_type_enumeration *) type;
+       struct bt_field_type_common_enumeration *enum_ft = BT_FROM_COMMON(ft);
 
-       if (!type) {
-               return;
-       }
-
-       BT_LOGD("Destroying enumeration field type object: addr=%p", type);
-       g_ptr_array_free(enumeration->entries, TRUE);
-       BT_LOGD_STR("Putting container field type.");
-       bt_put(enumeration->container);
-       g_free(enumeration);
+       BT_LOGD("Freezing enumeration field type object: addr=%p", ft);
+       bt_field_type_common_enumeration_set_range_overlap(enum_ft);
+       bt_field_type_common_generic_freeze(ft);
+       BT_LOGD("Freezing enumeration field type object's container field type: int-ft-addr=%p",
+               enum_ft->container_ft);
+       bt_field_type_common_freeze(BT_TO_COMMON(enum_ft->container_ft));
 }
 
 static
-void bt_field_type_floating_point_destroy(struct bt_field_type *type)
+void freeze_structure_field(struct structure_field_common *field)
 {
-       struct bt_field_type_floating_point *floating_point =
-               (struct bt_field_type_floating_point *) type;
+       BT_LOGD("Freezing structure/variant field type field: field-addr=%p, "
+               "field-ft-addr=%p, field-name=\"%s\"", field,
+               field->type, g_quark_to_string(field->name));
+       bt_field_type_common_freeze(field->type);
+}
 
-       if (!type) {
-               return;
-       }
+BT_HIDDEN
+void bt_field_type_common_structure_freeze_recursive(
+               struct bt_field_type_common *ft)
+{
+       struct bt_field_type_common_structure *struct_ft = BT_FROM_COMMON(ft);
 
-       BT_LOGD("Destroying floating point number field type object: addr=%p", type);
-       g_free(floating_point);
+       /* Cache the alignment */
+       BT_LOGD("Freezing structure field type object: addr=%p", ft);
+       ft->alignment = bt_field_type_common_get_alignment(ft);
+       bt_field_type_common_generic_freeze(ft);
+       g_ptr_array_foreach(struct_ft->fields,
+               (GFunc) freeze_structure_field, NULL);
 }
 
-static
-void bt_field_type_structure_destroy(struct bt_field_type *type)
+BT_HIDDEN
+void bt_field_type_common_variant_freeze_recursive(
+               struct bt_field_type_common *ft)
 {
-       struct bt_field_type_structure *structure =
-               (struct bt_field_type_structure *) type;
-
-       if (!type) {
-               return;
-       }
+       struct bt_field_type_common_variant *var_ft = BT_FROM_COMMON(ft);
 
-       BT_LOGD("Destroying structure field type object: addr=%p", type);
-       g_ptr_array_free(structure->fields, TRUE);
-       g_hash_table_destroy(structure->field_name_to_index);
-       g_free(structure);
+       BT_LOGD("Freezing variant field type object: addr=%p", ft);
+       bt_field_type_common_generic_freeze(ft);
+       g_ptr_array_foreach(var_ft->fields,
+               (GFunc) freeze_structure_field, NULL);
 }
 
-static
-void bt_field_type_variant_destroy(struct bt_field_type *type)
+BT_HIDDEN
+void bt_field_type_common_array_freeze_recursive(
+               struct bt_field_type_common *ft)
 {
-       struct bt_field_type_variant *variant =
-               (struct bt_field_type_variant *) type;
-
-       if (!type) {
-               return;
-       }
+       struct bt_field_type_common_array *array_ft = BT_FROM_COMMON(ft);
 
-       BT_LOGD("Destroying variant field type object: addr=%p", type);
-       g_ptr_array_free(variant->fields, TRUE);
-       g_hash_table_destroy(variant->field_name_to_index);
-       g_string_free(variant->tag_name, TRUE);
-       BT_LOGD_STR("Putting tag field type.");
-       bt_put(&variant->tag->parent);
-       BT_PUT(variant->tag_field_path);
-       g_free(variant);
+       /* Cache the alignment */
+       BT_LOGD("Freezing array field type object: addr=%p", ft);
+       ft->alignment = bt_field_type_common_get_alignment(ft);
+       bt_field_type_common_generic_freeze(ft);
+       BT_LOGD("Freezing array field type object's element field type: element-ft-addr=%p",
+               array_ft->element_ft);
+       bt_field_type_common_freeze(array_ft->element_ft);
 }
 
-static
-void bt_field_type_array_destroy(struct bt_field_type *type)
+BT_HIDDEN
+void bt_field_type_common_sequence_freeze_recursive(
+               struct bt_field_type_common *ft)
 {
-       struct bt_field_type_array *array =
-               (struct bt_field_type_array *) type;
-
-       if (!type) {
-               return;
-       }
+       struct bt_field_type_common_sequence *seq_ft = BT_FROM_COMMON(ft);
 
-       BT_LOGD("Destroying array field type object: addr=%p", type);
-       BT_LOGD_STR("Putting element field type.");
-       bt_put(array->element_type);
-       g_free(array);
+       /* Cache the alignment */
+       BT_LOGD("Freezing sequence field type object: addr=%p", ft);
+       ft->alignment = bt_field_type_common_get_alignment(ft);
+       bt_field_type_common_generic_freeze(ft);
+       BT_LOGD("Freezing sequence field type object's element field type: element-ft-addr=%p",
+               seq_ft->element_ft);
+       bt_field_type_common_freeze(seq_ft->element_ft);
 }
 
-static
-void bt_field_type_sequence_destroy(struct bt_field_type *type)
+BT_HIDDEN
+void bt_field_type_common_integer_set_byte_order(
+               struct bt_field_type_common *ft, enum bt_byte_order byte_order)
 {
-       struct bt_field_type_sequence *sequence =
-               (struct bt_field_type_sequence *) type;
-
-       if (!type) {
-               return;
-       }
+       struct bt_field_type_common_integer *int_ft = BT_FROM_COMMON(ft);
 
-       BT_LOGD("Destroying sequence field type object: addr=%p", type);
-       BT_LOGD_STR("Putting element field type.");
-       bt_put(sequence->element_type);
-       g_string_free(sequence->length_field_name, TRUE);
-       BT_LOGD_STR("Putting length field path.");
-       BT_PUT(sequence->length_field_path);
-       g_free(sequence);
+       int_ft->user_byte_order = byte_order;
 }
 
-static
-void bt_field_type_string_destroy(struct bt_field_type *type)
+BT_HIDDEN
+void bt_field_type_common_enumeration_set_byte_order_recursive(
+               struct bt_field_type_common *ft, enum bt_byte_order byte_order)
 {
-       struct bt_field_type_string *string =
-               (struct bt_field_type_string *) type;
-
-       if (!type) {
-               return;
-       }
+       struct bt_field_type_common_enumeration *enum_ft = BT_FROM_COMMON(ft);
 
-       BT_LOGD("Destroying string field type object: addr=%p", type);
-       g_free(string);
+       bt_field_type_common_set_byte_order(BT_TO_COMMON(enum_ft->container_ft),
+               byte_order);
 }
 
-static
-void generic_field_type_freeze(struct bt_field_type *type)
+BT_HIDDEN
+void bt_field_type_common_floating_point_set_byte_order(
+               struct bt_field_type_common *ft, enum bt_byte_order byte_order)
 {
-       type->frozen = 1;
+       struct bt_field_type_common_floating_point *flt_ft = BT_FROM_COMMON(ft);
+
+       flt_ft->user_byte_order = byte_order;
 }
 
-static
-void bt_field_type_integer_freeze(struct bt_field_type *type)
+BT_HIDDEN
+void bt_field_type_common_structure_set_byte_order_recursive(
+               struct bt_field_type_common *ft,
+               enum bt_byte_order byte_order)
 {
-       struct bt_field_type_integer *integer_type = container_of(
-               type, struct bt_field_type_integer, parent);
+       int i;
+       struct bt_field_type_common_structure *struct_ft = BT_FROM_COMMON(ft);
 
-       BT_LOGD("Freezing integer field type object: addr=%p", type);
+       for (i = 0; i < struct_ft->fields->len; i++) {
+               struct structure_field_common *field = g_ptr_array_index(
+                       struct_ft->fields, i);
+               struct bt_field_type_common *field_type = field->type;
 
-       if (integer_type->mapped_clock) {
-               BT_LOGD_STR("Freezing integer field type's mapped clock class.");
-               bt_clock_class_freeze(integer_type->mapped_clock);
+               bt_field_type_common_set_byte_order(field_type, byte_order);
        }
-
-       generic_field_type_freeze(type);
 }
 
-static
-void bt_field_type_enumeration_freeze(struct bt_field_type *type)
+BT_HIDDEN
+void bt_field_type_common_variant_set_byte_order_recursive(
+               struct bt_field_type_common *ft,
+               enum bt_byte_order byte_order)
 {
-       struct bt_field_type_enumeration *enumeration_type = container_of(
-               type, struct bt_field_type_enumeration, parent);
+       int i;
+       struct bt_field_type_common_variant *var_ft = BT_FROM_COMMON(ft);
 
-       BT_LOGD("Freezing enumeration field type object: addr=%p", type);
-       type->alignment = bt_field_type_get_alignment(type);
-       set_enumeration_range_overlap(type);
-       generic_field_type_freeze(type);
-       BT_LOGD("Freezing enumeration field type object's container field type: int-ft-addr=%p",
-               enumeration_type->container);
-       bt_field_type_freeze(enumeration_type->container);
-}
+       for (i = 0; i < var_ft->fields->len; i++) {
+               struct structure_field_common *field = g_ptr_array_index(
+                       var_ft->fields, i);
+               struct bt_field_type_common *field_type = field->type;
 
-static
-void freeze_structure_field(struct structure_field *field)
-{
-       BT_LOGD("Freezing structure/variant field type field: field-addr=%p, "
-               "field-ft-addr=%p, field-name=\"%s\"", field,
-               field->type, g_quark_to_string(field->name));
-       bt_field_type_freeze(field->type);
+               bt_field_type_common_set_byte_order(field_type, byte_order);
+       }
 }
 
-static
-void bt_field_type_structure_freeze(struct bt_field_type *type)
+BT_HIDDEN
+void bt_field_type_common_array_set_byte_order_recursive(
+               struct bt_field_type_common *ft,
+               enum bt_byte_order byte_order)
 {
-       struct bt_field_type_structure *structure_type = container_of(
-               type, struct bt_field_type_structure, parent);
+       struct bt_field_type_common_array *array_ft = BT_FROM_COMMON(ft);
 
-       /* Cache the alignment */
-       BT_LOGD("Freezing structure field type object: addr=%p", type);
-       type->alignment = bt_field_type_get_alignment(type);
-       generic_field_type_freeze(type);
-       g_ptr_array_foreach(structure_type->fields,
-               (GFunc) freeze_structure_field, NULL);
+       bt_field_type_common_set_byte_order(array_ft->element_ft, byte_order);
 }
 
-static
-void bt_field_type_variant_freeze(struct bt_field_type *type)
+BT_HIDDEN
+void bt_field_type_common_sequence_set_byte_order_recursive(
+               struct bt_field_type_common *ft,
+               enum bt_byte_order byte_order)
 {
-       struct bt_field_type_variant *variant_type = container_of(
-               type, struct bt_field_type_variant, parent);
+       struct bt_field_type_common_sequence *seq_ft = BT_FROM_COMMON(ft);
 
-       BT_LOGD("Freezing variant field type object: addr=%p", type);
-       generic_field_type_freeze(type);
-       g_ptr_array_foreach(variant_type->fields,
-               (GFunc) freeze_structure_field, NULL);
+       bt_field_type_common_set_byte_order(seq_ft->element_ft, byte_order);
 }
 
-static
-void bt_field_type_array_freeze(struct bt_field_type *type)
-{
-       struct bt_field_type_array *array_type = container_of(
-               type, struct bt_field_type_array, parent);
-
-       /* Cache the alignment */
-       BT_LOGD("Freezing array field type object: addr=%p", type);
-       type->alignment = bt_field_type_get_alignment(type);
-       generic_field_type_freeze(type);
-       BT_LOGD("Freezing array field type object's element field type: element-ft-addr=%p",
-               array_type->element_type);
-       bt_field_type_freeze(array_type->element_type);
-}
 
-static
-void bt_field_type_sequence_freeze(struct bt_field_type *type)
+BT_HIDDEN
+int bt_field_type_common_integer_compare(struct bt_field_type_common *ft_a,
+               struct bt_field_type_common *ft_b)
 {
-       struct bt_field_type_sequence *sequence_type = container_of(
-               type, struct bt_field_type_sequence, parent);
+       int ret = 1;
+       struct bt_field_type_common_integer *int_ft_a = BT_FROM_COMMON(ft_a);
+       struct bt_field_type_common_integer *int_ft_b = BT_FROM_COMMON(ft_b);
 
-       /* Cache the alignment */
-       BT_LOGD("Freezing sequence field type object: addr=%p", type);
-       type->alignment = bt_field_type_get_alignment(type);
-       generic_field_type_freeze(type);
-       BT_LOGD("Freezing sequence field type object's element field type: element-ft-addr=%p",
-               sequence_type->element_type);
-       bt_field_type_freeze(sequence_type->element_type);
-}
+       /* Length */
+       if (int_ft_a->size != int_ft_b->size) {
+               BT_LOGV("Integer field types differ: different sizes: "
+                       "ft-a-size=%u, ft-b-size=%u",
+                       int_ft_a->size, int_ft_b->size);
+               goto end;
+       }
 
-static
-const char *get_encoding_string(enum bt_string_encoding encoding)
-{
-       const char *encoding_string;
+       /* Byte order */
+       if (int_ft_a->user_byte_order != int_ft_b->user_byte_order) {
+               BT_LOGV("Integer field types differ: different byte orders: "
+                       "ft-a-bo=%s, ft-b-bo=%s",
+                       bt_common_byte_order_string(int_ft_a->user_byte_order),
+                       bt_common_byte_order_string(int_ft_b->user_byte_order));
+               goto end;
+       }
 
-       switch (encoding) {
-       case BT_STRING_ENCODING_NONE:
-               encoding_string = "none";
-               break;
-       case BT_STRING_ENCODING_ASCII:
-               encoding_string = "ASCII";
-               break;
-       case BT_STRING_ENCODING_UTF8:
-               encoding_string = "UTF8";
-               break;
-       default:
-               encoding_string = "unknown";
-               break;
+       /* Signedness */
+       if (int_ft_a->is_signed != int_ft_b->is_signed) {
+               BT_LOGV("Integer field types differ: different signedness: "
+                       "ft-a-is-signed=%d, ft-b-is-signed=%d",
+                       int_ft_a->is_signed,
+                       int_ft_b->is_signed);
+               goto end;
        }
 
-       return encoding_string;
-}
+       /* Base */
+       if (int_ft_a->base != int_ft_b->base) {
+               BT_LOGV("Integer field types differ: different bases: "
+                       "ft-a-base=%s, ft-b-base=%s",
+                       bt_common_integer_base_string(int_ft_a->base),
+                       bt_common_integer_base_string(int_ft_b->base));
+               goto end;
+       }
 
-static
-const char *get_integer_base_string(enum bt_integer_base base)
-{
-       const char *base_string;
+       /* Encoding */
+       if (int_ft_a->encoding != int_ft_b->encoding) {
+               BT_LOGV("Integer field types differ: different encodings: "
+                       "ft-a-encoding=%s, ft-b-encoding=%s",
+                       bt_common_string_encoding_string(int_ft_a->encoding),
+                       bt_common_string_encoding_string(int_ft_b->encoding));
+               goto end;
+       }
 
-       switch (base) {
-       case BT_INTEGER_BASE_DECIMAL:
-       case BT_INTEGER_BASE_UNSPECIFIED:
-               base_string = "decimal";
-               break;
-       case BT_INTEGER_BASE_HEXADECIMAL:
-               base_string = "hexadecimal";
-               break;
-       case BT_INTEGER_BASE_OCTAL:
-               base_string = "octal";
-               break;
-       case BT_INTEGER_BASE_BINARY:
-               base_string = "binary";
-               break;
-       default:
-               base_string = "unknown";
-               break;
-       }
-
-       return base_string;
-}
-
-static
-void append_field_name(struct metadata_context *context,
-               const char *name)
-{
-       g_string_append_c(context->string, ' ');
+       /* Mapped clock class */
+       if (int_ft_a->mapped_clock_class) {
+               if (!int_ft_b->mapped_clock_class) {
+                       BT_LOGV_STR("Integer field types differ: field type A "
+                               "has a mapped clock class, but field type B "
+                               "does not.");
+                       goto end;
+               }
 
-       if (!bt_identifier_is_valid(name) || *name == '_') {
-               g_string_append_c(context->string, '_');
+               if (bt_clock_class_compare(int_ft_a->mapped_clock_class,
+                               int_ft_b->mapped_clock_class) != 0) {
+                       BT_LOGV_STR("Integer field types differ: different "
+                               "mapped clock classes.");
+               }
+       } else {
+               if (int_ft_b->mapped_clock_class) {
+                       BT_LOGV_STR("Integer field types differ: field type A "
+                               "has no description, but field type B has one.");
+                       goto end;
+               }
        }
 
-       g_string_append(context->string, name);
-}
-
-static
-int bt_field_type_integer_serialize(struct bt_field_type *type,
-               struct metadata_context *context)
-{
-       struct bt_field_type_integer *integer = container_of(type,
-               struct bt_field_type_integer, parent);
-       int ret = 0;
+       /* Equal */
+       ret = 0;
 
-       BT_LOGD("Serializing integer field type's metadata: "
-               "ft-addr=%p, metadata-context-addr=%p", type, context);
-       g_string_append_printf(context->string,
-               "integer { size = %u; align = %u; signed = %s; encoding = %s; base = %s; byte_order = %s",
-               integer->size, type->alignment,
-               (integer->is_signed ? "true" : "false"),
-               get_encoding_string(integer->encoding),
-               get_integer_base_string(integer->base),
-               get_byte_order_string(integer->user_byte_order));
-       if (integer->mapped_clock) {
-               const char *clock_name = bt_clock_class_get_name(
-                       integer->mapped_clock);
-
-               BT_ASSERT(clock_name);
-               g_string_append_printf(context->string,
-                       "; map = clock.%s.value", clock_name);
-       }
-
-       g_string_append(context->string, "; }");
+end:
        return ret;
 }
 
-static
-int bt_field_type_enumeration_serialize(struct bt_field_type *type,
-               struct metadata_context *context)
+BT_HIDDEN
+int bt_field_type_common_floating_point_compare(
+               struct bt_field_type_common *ft_a,
+               struct bt_field_type_common *ft_b)
 {
-       size_t entry;
-       int ret;
-       struct bt_field_type_enumeration *enumeration = container_of(type,
-               struct bt_field_type_enumeration, parent);
-       struct bt_field_type *container_type;
-       int container_signed;
-
-       BT_LOGD("Serializing enumeration field type's metadata: "
-               "ft-addr=%p, metadata-context-addr=%p", type, context);
-       container_type = bt_field_type_enumeration_get_container_type(type);
-       BT_ASSERT(container_type);
-       container_signed = bt_ctf_field_type_integer_get_signed(container_type);
-       BT_ASSERT(container_signed >= 0);
-       g_string_append(context->string, "enum : ");
-       BT_LOGD_STR("Serializing enumeration field type's container field type's metadata.");
-       ret = bt_field_type_serialize(enumeration->container, context);
-       if (ret) {
-               BT_LOGW("Cannot serialize enumeration field type's container field type's metadata: "
-                       "container-ft-addr=%p", enumeration->container);
+       int ret = 1;
+       struct bt_field_type_common_floating_point *flt_ft_a =
+               BT_FROM_COMMON(ft_a);
+       struct bt_field_type_common_floating_point *flt_ft_b =
+               BT_FROM_COMMON(ft_b);
+
+       /* Byte order */
+       if (flt_ft_a->user_byte_order != flt_ft_b->user_byte_order) {
+               BT_LOGV("Floating point number field types differ: different byte orders: "
+                       "ft-a-bo=%s, ft-b-bo=%s",
+                       bt_common_byte_order_string(flt_ft_a->user_byte_order),
+                       bt_common_byte_order_string(flt_ft_b->user_byte_order));
                goto end;
        }
 
-       g_string_append(context->string, " { ");
-       for (entry = 0; entry < enumeration->entries->len; entry++) {
-               struct enumeration_mapping *mapping =
-                       enumeration->entries->pdata[entry];
-               const char *label = g_quark_to_string(mapping->string);
-
-               g_string_append(context->string, "\"");
-
-               if (!bt_identifier_is_valid(label) || label[0] == '_') {
-                       g_string_append(context->string, "_");
-               }
-
-               g_string_append_printf(context->string, "%s\" = ", label);
-
-               if (container_signed) {
-                       if (mapping->range_start._signed ==
-                               mapping->range_end._signed) {
-                               g_string_append_printf(context->string,
-                                       "%" PRId64,
-                                       mapping->range_start._signed);
-                       } else {
-                               g_string_append_printf(context->string,
-                                       "%" PRId64 " ... %" PRId64,
-                                       mapping->range_start._signed,
-                                       mapping->range_end._signed);
-                       }
-               } else {
-                       if (mapping->range_start._unsigned ==
-                               mapping->range_end._unsigned) {
-                               g_string_append_printf(context->string,
-                                       "%" PRIu64,
-                                       mapping->range_start._unsigned);
-                       } else {
-                               g_string_append_printf(context->string,
-                                       "%" PRIu64 " ... %" PRIu64,
-                                       mapping->range_start._unsigned,
-                                       mapping->range_end._unsigned);
-                       }
-               }
-
-               g_string_append(context->string,
-                       ((entry != (enumeration->entries->len - 1)) ?
-                       ", " : " }"));
+       /* Exponent length */
+       if (flt_ft_a->exp_dig != flt_ft_b->exp_dig) {
+               BT_LOGV("Floating point number field types differ: different exponent sizes: "
+                       "ft-a-exp-size=%u, ft-b-exp-size=%u",
+                       flt_ft_a->exp_dig, flt_ft_b->exp_dig);
+               goto end;
        }
 
-       if (context->field_name->len) {
-               append_field_name(context,
-                       context->field_name->str);
-               g_string_assign(context->field_name, "");
+       /* Mantissa length */
+       if (flt_ft_a->mant_dig != flt_ft_b->mant_dig) {
+               BT_LOGV("Floating point number field types differ: different mantissa sizes: "
+                       "ft-a-mant-size=%u, ft-b-mant-size=%u",
+                       flt_ft_a->mant_dig, flt_ft_b->mant_dig);
+               goto end;
        }
+
+       /* Equal */
+       ret = 0;
+
 end:
-       bt_put(container_type);
        return ret;
 }
 
 static
-int bt_field_type_floating_point_serialize(struct bt_field_type *type,
-               struct metadata_context *context)
-{
-       struct bt_field_type_floating_point *floating_point = container_of(
-               type, struct bt_field_type_floating_point, parent);
-
-       BT_LOGD("Serializing floating point number field type's metadata: "
-               "ft-addr=%p, metadata-context-addr=%p", type, context);
-       g_string_append_printf(context->string,
-               "floating_point { exp_dig = %u; mant_dig = %u; byte_order = %s; align = %u; }",
-               floating_point->exp_dig,
-               floating_point->mant_dig,
-               get_byte_order_string(floating_point->user_byte_order),
-               type->alignment);
-       return 0;
-}
-
-static
-int bt_field_type_structure_serialize(struct bt_field_type *type,
-               struct metadata_context *context)
+int compare_enumeration_mappings(struct enumeration_mapping *mapping_a,
+               struct enumeration_mapping *mapping_b)
 {
-       size_t i;
-       unsigned int indent;
-       int ret = 0;
-       struct bt_field_type_structure *structure = container_of(type,
-               struct bt_field_type_structure, parent);
-       GString *structure_field_name = context->field_name;
-
-       BT_LOGD("Serializing structure field type's metadata: "
-               "ft-addr=%p, metadata-context-addr=%p", type, context);
-       context->field_name = g_string_new("");
-
-       context->current_indentation_level++;
-       g_string_append(context->string, "struct {\n");
-
-       for (i = 0; i < structure->fields->len; i++) {
-               struct structure_field *field = structure->fields->pdata[i];
-
-               BT_LOGD("Serializing structure field type's field metadata: "
-                       "index=%zu, "
-                       "field-ft-addr=%p, field-name=\"%s\"",
-                       i, field, g_quark_to_string(field->name));
-
-               for (indent = 0; indent < context->current_indentation_level;
-                       indent++) {
-                       g_string_append_c(context->string, '\t');
-               }
+       int ret = 1;
 
-               g_string_assign(context->field_name,
-                       g_quark_to_string(field->name));
-               ret = bt_field_type_serialize(field->type, context);
-               if (ret) {
-                       BT_LOGW("Cannot serialize structure field type's field's metadata: "
-                               "index=%zu, "
-                               "field-ft-addr=%p, field-name=\"%s\"",
-                               i, field->type,
-                               g_quark_to_string(field->name));
-                       goto end;
-               }
+       /* Label */
+       if (mapping_a->string != mapping_b->string) {
+               BT_LOGV("Enumeration field type mappings differ: different names: "
+                       "mapping-a-name=\"%s\", mapping-b-name=\"%s\"",
+                       g_quark_to_string(mapping_a->string),
+                       g_quark_to_string(mapping_b->string));
+               goto end;
+       }
 
-               if (context->field_name->len) {
-                       append_field_name(context,
-                               context->field_name->str);
-               }
-               g_string_append(context->string, ";\n");
+       /* Range start */
+       if (mapping_a->range_start._unsigned !=
+                       mapping_b->range_start._unsigned) {
+               BT_LOGV("Enumeration field type mappings differ: different starts of range: "
+                       "mapping-a-range-start-unsigned=%" PRIu64 ", "
+                       "mapping-b-range-start-unsigned=%" PRIu64,
+                       mapping_a->range_start._unsigned,
+                       mapping_b->range_start._unsigned);
+               goto end;
        }
 
-       context->current_indentation_level--;
-       for (indent = 0; indent < context->current_indentation_level;
-               indent++) {
-               g_string_append_c(context->string, '\t');
+       /* Range end */
+       if (mapping_a->range_end._unsigned !=
+                       mapping_b->range_end._unsigned) {
+               BT_LOGV("Enumeration field type mappings differ: different ends of range: "
+                       "mapping-a-range-end-unsigned=%" PRIu64 ", "
+                       "mapping-b-range-end-unsigned=%" PRIu64,
+                       mapping_a->range_end._unsigned,
+                       mapping_b->range_end._unsigned);
+               goto end;
        }
 
-       g_string_append_printf(context->string, "} align(%u)",
-                type->alignment);
+       /* Equal */
+       ret = 0;
+
 end:
-       g_string_free(context->field_name, TRUE);
-       context->field_name = structure_field_name;
        return ret;
 }
 
-static
-int bt_field_type_variant_serialize(struct bt_field_type *type,
-               struct metadata_context *context)
+BT_HIDDEN
+int bt_field_type_common_enumeration_compare_recursive(
+               struct bt_field_type_common *ft_a,
+               struct bt_field_type_common *ft_b)
 {
-       size_t i;
-       unsigned int indent;
-       int ret = 0;
-       struct bt_field_type_variant *variant = container_of(
-               type, struct bt_field_type_variant, parent);
-       GString *variant_field_name = context->field_name;
-
-       BT_LOGD("Serializing variant field type's metadata: "
-               "ft-addr=%p, metadata-context-addr=%p", type, context);
-       context->field_name = g_string_new("");
-       if (variant->tag_name->len > 0) {
-               g_string_append(context->string, "variant <");
-               append_field_name(context, variant->tag_name->str);
-               g_string_append(context->string, "> {\n");
-       } else {
-               g_string_append(context->string, "variant {\n");
+       int ret = 1;
+       int i;
+       struct bt_field_type_common_enumeration *enum_ft_a =
+               BT_FROM_COMMON(ft_a);
+       struct bt_field_type_common_enumeration *enum_ft_b =
+               BT_FROM_COMMON(ft_b);
+
+       /* Container field type */
+       ret = bt_field_type_common_compare(
+               BT_TO_COMMON(enum_ft_a->container_ft),
+               BT_TO_COMMON(enum_ft_b->container_ft));
+       if (ret) {
+               BT_LOGV("Enumeration field types differ: different container field types: "
+                       "ft-a-container-ft-addr=%p, ft-b-container-ft-addr=%p",
+                       enum_ft_a->container_ft, enum_ft_b->container_ft);
+               goto end;
        }
 
-       context->current_indentation_level++;
-       for (i = 0; i < variant->fields->len; i++) {
-               struct structure_field *field = variant->fields->pdata[i];
+       ret = 1;
 
-               BT_LOGD("Serializing variant field type's field metadata: "
-                       "index=%zu, "
-                       "field-ft-addr=%p, field-name=\"%s\"",
-                       i, field, g_quark_to_string(field->name));
+       /* Entries */
+       if (enum_ft_a->entries->len != enum_ft_b->entries->len) {
+               goto end;
+       }
 
-               g_string_assign(context->field_name,
-                       g_quark_to_string(field->name));
-               for (indent = 0; indent < context->current_indentation_level;
-                       indent++) {
-                       g_string_append_c(context->string, '\t');
-               }
+       for (i = 0; i < enum_ft_a->entries->len; ++i) {
+               struct enumeration_mapping *mapping_a =
+                       g_ptr_array_index(enum_ft_a->entries, i);
+               struct enumeration_mapping *mapping_b =
+                       g_ptr_array_index(enum_ft_b->entries, i);
 
-               g_string_assign(context->field_name,
-                       g_quark_to_string(field->name));
-               ret = bt_field_type_serialize(field->type, context);
-               if (ret) {
-                       BT_LOGW("Cannot serialize variant field type's field's metadata: "
-                               "index=%zu, "
-                               "field-ft-addr=%p, field-name=\"%s\"",
-                               i, field->type,
-                               g_quark_to_string(field->name));
+               if (compare_enumeration_mappings(mapping_a, mapping_b)) {
+                       BT_LOGV("Enumeration field types differ: different mappings: "
+                               "ft-a-mapping-addr=%p, ft-b-mapping-addr=%p, "
+                               "ft-a-mapping-name=\"%s\", ft-b-mapping-name=\"%s\"",
+                               mapping_a, mapping_b,
+                               g_quark_to_string(mapping_a->string),
+                               g_quark_to_string(mapping_b->string));
                        goto end;
                }
-
-               if (context->field_name->len) {
-                       append_field_name(context,
-                               context->field_name->str);
-                       g_string_append_c(context->string, ';');
-               }
-
-               g_string_append_c(context->string, '\n');
        }
 
-       context->current_indentation_level--;
-       for (indent = 0; indent < context->current_indentation_level;
-               indent++) {
-               g_string_append_c(context->string, '\t');
-       }
+       /* Equal */
+       ret = 0;
 
-       g_string_append(context->string, "}");
 end:
-       g_string_free(context->field_name, TRUE);
-       context->field_name = variant_field_name;
        return ret;
 }
 
-static
-int bt_field_type_array_serialize(struct bt_field_type *type,
-               struct metadata_context *context)
+BT_HIDDEN
+int bt_field_type_common_string_compare(struct bt_field_type_common *ft_a,
+               struct bt_field_type_common *ft_b)
 {
-       int ret = 0;
-       struct bt_field_type_array *array = container_of(type,
-               struct bt_field_type_array, parent);
+       int ret = 1;
+       struct bt_field_type_common_string *string_ft_a = BT_FROM_COMMON(ft_a);
+       struct bt_field_type_common_string *string_ft_b = BT_FROM_COMMON(ft_b);
 
-       BT_LOGD("Serializing array field type's metadata: "
-               "ft-addr=%p, metadata-context-addr=%p", type, context);
-       BT_LOGD_STR("Serializing array field type's element field type's metadata.");
-       ret = bt_field_type_serialize(array->element_type, context);
-       if (ret) {
-               BT_LOGW("Cannot serialize array field type's element field type's metadata: "
-                       "element-ft-addr=%p", array->element_type);
+       /* Encoding */
+       if (string_ft_a->encoding != string_ft_b->encoding) {
+               BT_LOGV("String field types differ: different encodings: "
+                       "ft-a-encoding=%s, ft-b-encoding=%s",
+                       bt_common_string_encoding_string(string_ft_a->encoding),
+                       bt_common_string_encoding_string(string_ft_b->encoding));
                goto end;
        }
 
-       if (context->field_name->len) {
-               append_field_name(context,
-                       context->field_name->str);
+       /* Equal */
+       ret = 0;
 
-               g_string_append_printf(context->string, "[%u]", array->length);
-               g_string_assign(context->field_name, "");
-       } else {
-               g_string_append_printf(context->string, "[%u]", array->length);
-       }
 end:
        return ret;
 }
 
 static
-int bt_field_type_sequence_serialize(struct bt_field_type *type,
-               struct metadata_context *context)
+int compare_structure_fields(struct structure_field_common *field_a,
+               struct structure_field_common *field_b)
 {
-       int ret = 0;
-       struct bt_field_type_sequence *sequence = container_of(
-               type, struct bt_field_type_sequence, parent);
+       int ret = 1;
 
-       BT_LOGD("Serializing sequence field type's metadata: "
-               "ft-addr=%p, metadata-context-addr=%p", type, context);
-       BT_LOGD_STR("Serializing sequence field type's element field type's metadata.");
-       ret = bt_field_type_serialize(sequence->element_type, context);
-       if (ret) {
-               BT_LOGW("Cannot serialize sequence field type's element field type's metadata: "
-                       "element-ft-addr=%p", sequence->element_type);
+       /* Label */
+       if (field_a->name != field_b->name) {
+               BT_LOGV("Structure/variant field type fields differ: different names: "
+                       "field-a-name=%s, field-b-name=%s",
+                       g_quark_to_string(field_a->name),
+                       g_quark_to_string(field_b->name));
                goto end;
        }
 
-       if (context->field_name->len) {
-               append_field_name(context, context->field_name->str);
-               g_string_assign(context->field_name, "");
+       /* Type */
+       ret = bt_field_type_common_compare(field_a->type, field_b->type);
+       if (ret == 1) {
+               BT_LOGV("Structure/variant field type fields differ: different field types: "
+                       "field-name=\"%s\", field-a-ft-addr=%p, field-b-ft-addr=%p",
+                       g_quark_to_string(field_a->name),
+                       field_a->type, field_b->type);
        }
-       g_string_append(context->string, "[");
-       append_field_name(context, sequence->length_field_name->str);
-       g_string_append(context->string, "]");
+
 end:
        return ret;
 }
 
-static
-int bt_field_type_string_serialize(struct bt_field_type *type,
-               struct metadata_context *context)
+BT_HIDDEN
+int bt_field_type_common_structure_compare_recursive(
+               struct bt_field_type_common *ft_a,
+               struct bt_field_type_common *ft_b)
 {
-       struct bt_field_type_string *string = container_of(
-               type, struct bt_field_type_string, parent);
-
-       BT_LOGD("Serializing string field type's metadata: "
-               "ft-addr=%p, metadata-context-addr=%p", type, context);
-       g_string_append_printf(context->string,
-               "string { encoding = %s; }",
-               get_encoding_string(string->encoding));
-       return 0;
-}
+       int ret = 1;
+       int i;
+       struct bt_field_type_common_structure *struct_ft_a =
+               BT_FROM_COMMON(ft_a);
+       struct bt_field_type_common_structure *struct_ft_b =
+               BT_FROM_COMMON(ft_b);
 
-static
-void bt_field_type_integer_set_byte_order(struct bt_field_type *type,
-               enum bt_byte_order byte_order)
-{
-       struct bt_field_type_integer *integer_type = container_of(type,
-               struct bt_field_type_integer, parent);
+       /* Alignment */
+       if (bt_field_type_common_get_alignment(ft_a) !=
+                       bt_field_type_common_get_alignment(ft_b)) {
+               BT_LOGV("Structure field types differ: different alignments: "
+                       "ft-a-align=%u, ft-b-align=%u",
+                       bt_field_type_common_get_alignment(ft_a),
+                       bt_field_type_common_get_alignment(ft_b));
+               goto end;
+       }
 
-       integer_type->user_byte_order = byte_order;
-}
+       /* Fields */
+       if (struct_ft_a->fields->len != struct_ft_b->fields->len) {
+               BT_LOGV("Structure field types differ: different field counts: "
+                       "ft-a-field-count=%u, ft-b-field-count=%u",
+                       struct_ft_a->fields->len, struct_ft_b->fields->len);
+               goto end;
+       }
 
-static
-void bt_field_type_enumeration_set_byte_order(
-               struct bt_field_type *type, enum bt_byte_order byte_order)
-{
-       struct bt_field_type_enumeration *enum_type = container_of(type,
-               struct bt_field_type_enumeration, parent);
+       for (i = 0; i < struct_ft_a->fields->len; ++i) {
+               struct structure_field_common *field_a =
+                       g_ptr_array_index(struct_ft_a->fields, i);
+               struct structure_field_common *field_b =
+                       g_ptr_array_index(struct_ft_b->fields, i);
 
-       /* Safe to assume that container is an integer */
-       bt_field_type_integer_set_byte_order(enum_type->container,
-               byte_order);
-}
+               ret = compare_structure_fields(field_a, field_b);
+               if (ret) {
+                       /* compare_structure_fields() logs what differs */
+                       BT_LOGV_STR("Structure field types differ: different fields.");
+                       goto end;
+               }
+       }
 
-static
-void bt_field_type_floating_point_set_byte_order(
-               struct bt_field_type *type, enum bt_byte_order byte_order)
-{
-       struct bt_field_type_floating_point *floating_point_type =
-               container_of(type, struct bt_field_type_floating_point,
-               parent);
+       /* Equal */
+       ret = 0;
 
-       floating_point_type->user_byte_order = byte_order;
+end:
+       return ret;
 }
 
-static
-void bt_field_type_structure_set_byte_order(struct bt_field_type *type,
-               enum bt_byte_order byte_order)
+BT_HIDDEN
+int bt_field_type_common_variant_compare_recursive(
+               struct bt_field_type_common *ft_a,
+               struct bt_field_type_common *ft_b)
 {
+       int ret = 1;
        int i;
-       struct bt_field_type_structure *structure_type =
-               container_of(type, struct bt_field_type_structure,
-               parent);
-
-       for (i = 0; i < structure_type->fields->len; i++) {
-               struct structure_field *field = g_ptr_array_index(
-                       structure_type->fields, i);
-               struct bt_field_type *field_type = field->type;
-
-               if (set_byte_order_funcs[field_type->id]) {
-                       set_byte_order_funcs[field_type->id](
-                               field_type, byte_order);
-               }
+       struct bt_field_type_common_variant *var_ft_a = BT_FROM_COMMON(ft_a);
+       struct bt_field_type_common_variant *var_ft_b = BT_FROM_COMMON(ft_b);
+
+       /* Tag name */
+       if (strcmp(var_ft_a->tag_name->str, var_ft_b->tag_name->str)) {
+               BT_LOGV("Variant field types differ: different tag field names: "
+                       "ft-a-tag-field-name=\"%s\", ft-b-tag-field-name=\"%s\"",
+                       var_ft_a->tag_name->str, var_ft_b->tag_name->str);
+               goto end;
        }
-}
 
-static
-void bt_field_type_variant_set_byte_order(struct bt_field_type *type,
-               enum bt_byte_order byte_order)
-{
-       int i;
-       struct bt_field_type_variant *variant_type =
-               container_of(type, struct bt_field_type_variant,
-               parent);
-
-       for (i = 0; i < variant_type->fields->len; i++) {
-               struct structure_field *field = g_ptr_array_index(
-                       variant_type->fields, i);
-               struct bt_field_type *field_type = field->type;
-
-               if (set_byte_order_funcs[field_type->id]) {
-                       set_byte_order_funcs[field_type->id](
-                               field_type, byte_order);
-               }
+       /* Tag type */
+       ret = bt_field_type_common_compare(BT_TO_COMMON(var_ft_a->tag_ft),
+               BT_TO_COMMON(var_ft_b->tag_ft));
+       if (ret) {
+               BT_LOGV("Variant field types differ: different tag field types: "
+                       "ft-a-tag-ft-addr=%p, ft-b-tag-ft-addr=%p",
+                       var_ft_a->tag_ft, var_ft_b->tag_ft);
+               goto end;
        }
-}
 
-static
-void bt_field_type_array_set_byte_order(struct bt_field_type *type,
-               enum bt_byte_order byte_order)
-{
-       struct bt_field_type_array *array_type =
-               container_of(type, struct bt_field_type_array,
-               parent);
+       ret = 1;
 
-       if (set_byte_order_funcs[array_type->element_type->id]) {
-               set_byte_order_funcs[array_type->element_type->id](
-                       array_type->element_type, byte_order);
+       /* Fields */
+       if (var_ft_a->fields->len != var_ft_b->fields->len) {
+               BT_LOGV("Structure field types differ: different field counts: "
+                       "ft-a-field-count=%u, ft-b-field-count=%u",
+                       var_ft_a->fields->len, var_ft_b->fields->len);
+               goto end;
        }
-}
 
-static
-void bt_field_type_sequence_set_byte_order(struct bt_field_type *type,
-               enum bt_byte_order byte_order)
-{
-       struct bt_field_type_sequence *sequence_type =
-               container_of(type, struct bt_field_type_sequence,
-               parent);
+       for (i = 0; i < var_ft_a->fields->len; ++i) {
+               struct structure_field_common *field_a =
+                       g_ptr_array_index(var_ft_a->fields, i);
+               struct structure_field_common *field_b =
+                       g_ptr_array_index(var_ft_b->fields, i);
 
-       if (set_byte_order_funcs[
-               sequence_type->element_type->id]) {
-               set_byte_order_funcs[
-                       sequence_type->element_type->id](
-                       sequence_type->element_type, byte_order);
-       }
-}
-
-static
-struct bt_field_type *bt_field_type_integer_copy(
-               struct bt_field_type *type)
-{
-       struct bt_field_type *copy;
-       struct bt_field_type_integer *integer, *copy_integer;
-
-       BT_LOGD("Copying integer field type's: addr=%p", type);
-       integer = container_of(type, struct bt_field_type_integer, parent);
-       copy = bt_field_type_integer_create(integer->size);
-       if (!copy) {
-               BT_LOGE_STR("Cannot create integer field type.");
-               goto end;
+               ret = compare_structure_fields(field_a, field_b);
+               if (ret) {
+                       /* compare_structure_fields() logs what differs */
+                       BT_LOGV_STR("Variant field types differ: different fields.");
+                       goto end;
+               }
        }
 
-       copy_integer = container_of(copy, struct bt_field_type_integer,
-               parent);
-       copy_integer->mapped_clock = bt_get(integer->mapped_clock);
-       copy_integer->user_byte_order = integer->user_byte_order;
-       copy_integer->is_signed = integer->is_signed;
-       copy_integer->size = integer->size;
-       copy_integer->base = integer->base;
-       copy_integer->encoding = integer->encoding;
-       BT_LOGD("Copied integer field type: original-ft-addr=%p, copy-ft-addr=%p",
-               type, copy);
+       /* Equal */
+       ret = 0;
 
 end:
-       return copy;
+       return ret;
 }
 
-static
-struct bt_field_type *bt_field_type_enumeration_copy(
-               struct bt_field_type *type)
+BT_HIDDEN
+int bt_field_type_common_array_compare_recursive(
+               struct bt_field_type_common *ft_a,
+               struct bt_field_type_common *ft_b)
 {
-       size_t i;
-       struct bt_field_type *copy = NULL, *copy_container;
-       struct bt_field_type_enumeration *enumeration, *copy_enumeration;
-
-       BT_LOGD("Copying enumeration field type's: addr=%p", type);
-       enumeration = container_of(type, struct bt_field_type_enumeration,
-               parent);
-
-       /* Copy the source enumeration's container */
-       BT_LOGD_STR("Copying enumeration field type's container field type.");
-       copy_container = bt_field_type_copy(enumeration->container);
-       if (!copy_container) {
-               BT_LOGE_STR("Cannot copy enumeration field type's container field type.");
-               goto end;
-       }
+       int ret = 1;
+       struct bt_field_type_common_array *array_ft_a = BT_FROM_COMMON(ft_a);
+       struct bt_field_type_common_array *array_ft_b = BT_FROM_COMMON(ft_b);
 
-       copy = bt_field_type_enumeration_create(copy_container);
-       if (!copy) {
-               BT_LOGE_STR("Cannot create enumeration field type.");
+       /* Length */
+       if (array_ft_a->length != array_ft_b->length) {
+               BT_LOGV("Structure field types differ: different lengths: "
+                       "ft-a-length=%u, ft-b-length=%u",
+                       array_ft_a->length, array_ft_b->length);
                goto end;
        }
-       copy_enumeration = container_of(copy,
-               struct bt_field_type_enumeration, parent);
-
-       /* Copy all enumaration entries */
-       for (i = 0; i < enumeration->entries->len; i++) {
-               struct enumeration_mapping *mapping = g_ptr_array_index(
-                       enumeration->entries, i);
-               struct enumeration_mapping *copy_mapping = g_new0(
-                       struct enumeration_mapping, 1);
-
-               if (!copy_mapping) {
-                       BT_LOGE_STR("Failed to allocate one enumeration mapping.");
-                       goto error;
-               }
-
-               *copy_mapping = *mapping;
-               g_ptr_array_add(copy_enumeration->entries, copy_mapping);
-       }
-
-       BT_LOGD("Copied enumeration field type: original-ft-addr=%p, copy-ft-addr=%p",
-               type, copy);
-
-end:
-       bt_put(copy_container);
-       return copy;
-error:
-       bt_put(copy_container);
-        BT_PUT(copy);
-       return copy;
-}
-
-static
-struct bt_field_type *bt_field_type_floating_point_copy(
-               struct bt_field_type *type)
-{
-       struct bt_field_type *copy;
-       struct bt_field_type_floating_point *floating_point, *copy_float;
 
-       BT_LOGD("Copying floating point number field type's: addr=%p", type);
-       floating_point = container_of(type,
-               struct bt_field_type_floating_point, parent);
-       copy = bt_field_type_floating_point_create();
-       if (!copy) {
-               BT_LOGE_STR("Cannot create floating point number field type.");
-               goto end;
+       /* Element type */
+       ret = bt_field_type_common_compare(array_ft_a->element_ft,
+               array_ft_b->element_ft);
+       if (ret == 1) {
+               BT_LOGV("Array field types differ: different element field types: "
+                       "ft-a-element-ft-addr=%p, ft-b-element-ft-addr=%p",
+                       array_ft_a->element_ft, array_ft_b->element_ft);
        }
 
-       copy_float = container_of(copy,
-               struct bt_field_type_floating_point, parent);
-       copy_float->user_byte_order = floating_point->user_byte_order;
-       copy_float->exp_dig = floating_point->exp_dig;
-       copy_float->mant_dig = floating_point->mant_dig;
-       BT_LOGD("Copied floating point number field type: original-ft-addr=%p, copy-ft-addr=%p",
-               type, copy);
 end:
-       return copy;
+       return ret;
 }
 
-static
-struct bt_field_type *bt_field_type_structure_copy(
-               struct bt_field_type *type)
+BT_HIDDEN
+int bt_field_type_common_sequence_compare_recursive(
+               struct bt_field_type_common *ft_a,
+               struct bt_field_type_common *ft_b)
 {
-       int64_t i;
-       GHashTableIter iter;
-       gpointer key, value;
-       struct bt_field_type *copy;
-       struct bt_field_type_structure *structure, *copy_structure;
+       int ret = -1;
+       struct bt_field_type_common_sequence *seq_ft_a = BT_FROM_COMMON(ft_a);
+       struct bt_field_type_common_sequence *seq_ft_b = BT_FROM_COMMON(ft_b);
 
-       BT_LOGD("Copying structure field type's: addr=%p", type);
-       structure = container_of(type, struct bt_field_type_structure,
-               parent);
-       copy = bt_field_type_structure_create();
-       if (!copy) {
-               BT_LOGE_STR("Cannot create structure field type.");
+       /* Length name */
+       if (strcmp(seq_ft_a->length_field_name->str,
+                       seq_ft_b->length_field_name->str)) {
+               BT_LOGV("Sequence field types differ: different length field names: "
+                       "ft-a-length-field-name=\"%s\", "
+                       "ft-b-length-field-name=\"%s\"",
+                       seq_ft_a->length_field_name->str,
+                       seq_ft_b->length_field_name->str);
                goto end;
        }
 
-       copy_structure = container_of(copy,
-               struct bt_field_type_structure, parent);
-
-       /* Copy field_name_to_index */
-       g_hash_table_iter_init(&iter, structure->field_name_to_index);
-       while (g_hash_table_iter_next (&iter, &key, &value)) {
-               g_hash_table_insert(copy_structure->field_name_to_index,
-                       key, value);
-       }
-
-       for (i = 0; i < structure->fields->len; i++) {
-               struct structure_field *entry, *copy_entry;
-               struct bt_field_type *copy_field;
-
-               entry = g_ptr_array_index(structure->fields, i);
-               BT_LOGD("Copying structure field type's field: "
-                       "index=%" PRId64 ", "
-                       "field-ft-addr=%p, field-name=\"%s\"",
-                       i, entry, g_quark_to_string(entry->name));
-               copy_entry = g_new0(struct structure_field, 1);
-               if (!copy_entry) {
-                       BT_LOGE_STR("Failed to allocate one structure field type field.");
-                       goto error;
-               }
-
-               copy_field = bt_field_type_copy(entry->type);
-               if (!copy_field) {
-                       BT_LOGE("Cannot copy structure field type's field: "
-                               "index=%" PRId64 ", "
-                               "field-ft-addr=%p, field-name=\"%s\"",
-                               i, entry, g_quark_to_string(entry->name));
-                       g_free(copy_entry);
-                       goto error;
-               }
-
-               copy_entry->name = entry->name;
-               copy_entry->type = copy_field;
-               g_ptr_array_add(copy_structure->fields, copy_entry);
+       /* Element type */
+       ret = bt_field_type_common_compare(seq_ft_a->element_ft,
+                       seq_ft_b->element_ft);
+       if (ret == 1) {
+               BT_LOGV("Sequence field types differ: different element field types: "
+                       "ft-a-element-ft-addr=%p, ft-b-element-ft-addr=%p",
+                       seq_ft_a->element_ft, seq_ft_b->element_ft);
        }
 
-       BT_LOGD("Copied structure field type: original-ft-addr=%p, copy-ft-addr=%p",
-               type, copy);
-
 end:
-       return copy;
-error:
-        BT_PUT(copy);
-       return copy;
+       return ret;
 }
 
-static
-struct bt_field_type *bt_field_type_variant_copy(
-               struct bt_field_type *type)
+BT_HIDDEN
+int bt_field_type_common_compare(struct bt_field_type_common *ft_a,
+               struct bt_field_type_common *ft_b)
 {
-       int64_t i;
-       GHashTableIter iter;
-       gpointer key, value;
-       struct bt_field_type *copy = NULL, *copy_tag = NULL;
-       struct bt_field_type_variant *variant, *copy_variant;
-
-       BT_LOGD("Copying variant field type's: addr=%p", type);
-       variant = container_of(type, struct bt_field_type_variant,
-               parent);
-       if (variant->tag) {
-               BT_LOGD_STR("Copying variant field type's tag field type.");
-               copy_tag = bt_field_type_copy(&variant->tag->parent);
-               if (!copy_tag) {
-                       BT_LOGE_STR("Cannot copy variant field type's tag field type.");
-                       goto end;
-               }
-       }
-
-       copy = bt_field_type_variant_create(copy_tag,
-               variant->tag_name->len ? variant->tag_name->str : NULL);
-       if (!copy) {
-               BT_LOGE_STR("Cannot create variant field type.");
-               goto end;
-       }
-
-       copy_variant = container_of(copy, struct bt_field_type_variant,
-               parent);
-
-       /* Copy field_name_to_index */
-       g_hash_table_iter_init(&iter, variant->field_name_to_index);
-       while (g_hash_table_iter_next (&iter, &key, &value)) {
-               g_hash_table_insert(copy_variant->field_name_to_index,
-                       key, value);
-       }
-
-       for (i = 0; i < variant->fields->len; i++) {
-               struct structure_field *entry, *copy_entry;
-               struct bt_field_type *copy_field;
-
-               entry = g_ptr_array_index(variant->fields, i);
-               BT_LOGD("Copying variant field type's field: "
-                       "index=%" PRId64 ", "
-                       "field-ft-addr=%p, field-name=\"%s\"",
-                       i, entry, g_quark_to_string(entry->name));
-               copy_entry = g_new0(struct structure_field, 1);
-               if (!copy_entry) {
-                       BT_LOGE_STR("Failed to allocate one variant field type field.");
-                       goto error;
-               }
-
-               copy_field = bt_field_type_copy(entry->type);
-               if (!copy_field) {
-                       BT_LOGE("Cannot copy variant field type's field: "
-                               "index=%" PRId64 ", "
-                               "field-ft-addr=%p, field-name=\"%s\"",
-                               i, entry, g_quark_to_string(entry->name));
-                       g_free(copy_entry);
-                       goto error;
-               }
+       int ret = 1;
 
-               copy_entry->name = entry->name;
-               copy_entry->type = copy_field;
-               g_ptr_array_add(copy_variant->fields, copy_entry);
-       }
+       BT_ASSERT_PRE_NON_NULL(ft_a, "Field type A");
+       BT_ASSERT_PRE_NON_NULL(ft_b, "Field type B");
 
-       if (variant->tag_field_path) {
-               BT_LOGD_STR("Copying variant field type's tag field path.");
-               copy_variant->tag_field_path = bt_field_path_copy(
-                       variant->tag_field_path);
-               if (!copy_variant->tag_field_path) {
-                       BT_LOGE_STR("Cannot copy variant field type's tag field path.");
-                       goto error;
-               }
+       if (ft_a == ft_b) {
+               /* Same reference: equal (even if both are NULL) */
+               ret = 0;
+               goto end;
        }
 
-       BT_LOGD("Copied variant field type: original-ft-addr=%p, copy-ft-addr=%p",
-               type, copy);
-
-end:
-       bt_put(copy_tag);
-       return copy;
-error:
-       bt_put(copy_tag);
-        BT_PUT(copy);
-       return copy;
-}
-
-static
-struct bt_field_type *bt_field_type_array_copy(
-               struct bt_field_type *type)
-{
-       struct bt_field_type *copy = NULL, *copy_element;
-       struct bt_field_type_array *array;
-
-       BT_LOGD("Copying array field type's: addr=%p", type);
-       array = container_of(type, struct bt_field_type_array,
-               parent);
-       BT_LOGD_STR("Copying array field type's element field type.");
-       copy_element = bt_field_type_copy(array->element_type);
-       if (!copy_element) {
-               BT_LOGE_STR("Cannot copy array field type's element field type.");
+       if (!ft_a) {
+               BT_LOGW_STR("Invalid parameter: field type A is NULL.");
+               ret = -1;
                goto end;
        }
 
-       copy = bt_field_type_array_create(copy_element, array->length);
-       if (!copy) {
-               BT_LOGE_STR("Cannot create array field type.");
+       if (!ft_b) {
+               BT_LOGW_STR("Invalid parameter: field type B is NULL.");
+               ret = -1;
                goto end;
        }
 
-       BT_LOGD("Copied array field type: original-ft-addr=%p, copy-ft-addr=%p",
-               type, copy);
-
-end:
-       bt_put(copy_element);
-       return copy;
-}
-
-static
-struct bt_field_type *bt_field_type_sequence_copy(
-               struct bt_field_type *type)
-{
-       struct bt_field_type *copy = NULL, *copy_element;
-       struct bt_field_type_sequence *sequence, *copy_sequence;
-
-       BT_LOGD("Copying sequence field type's: addr=%p", type);
-       sequence = container_of(type, struct bt_field_type_sequence,
-               parent);
-       BT_LOGD_STR("Copying sequence field type's element field type.");
-       copy_element = bt_field_type_copy(sequence->element_type);
-       if (!copy_element) {
-               BT_LOGE_STR("Cannot copy sequence field type's element field type.");
+       if (ft_a->id != ft_b->id) {
+               /* Different type IDs */
+               BT_LOGV("Field types differ: different IDs: "
+                       "ft-a-addr=%p, ft-b-addr=%p, "
+                       "ft-a-id=%s, ft-b-id=%s",
+                       ft_a, ft_b,
+                       bt_common_field_type_id_string(ft_a->id),
+                       bt_common_field_type_id_string(ft_b->id));
                goto end;
        }
 
-       copy = bt_field_type_sequence_create(copy_element,
-               sequence->length_field_name->len ?
-                       sequence->length_field_name->str : NULL);
-       if (!copy) {
-               BT_LOGE_STR("Cannot create sequence field type.");
+       if (ft_a->id == BT_FIELD_TYPE_ID_UNKNOWN) {
+               /* Both have unknown type IDs */
+               BT_LOGW_STR("Invalid parameter: field type IDs are unknown.");
                goto end;
        }
 
-       copy_sequence = container_of(copy, struct bt_field_type_sequence,
-               parent);
-       if (sequence->length_field_path) {
-               BT_LOGD_STR("Copying sequence field type's length field path.");
-               copy_sequence->length_field_path = bt_field_path_copy(
-                       sequence->length_field_path);
-               if (!copy_sequence->length_field_path) {
-                       BT_LOGE_STR("Cannot copy sequence field type's length field path.");
-                       goto error;
-               }
+       BT_ASSERT(ft_a->methods->compare);
+       ret = ft_a->methods->compare(ft_a, ft_b);
+       if (ret == 1) {
+               BT_LOGV("Field types differ: ft-a-addr=%p, ft-b-addr=%p",
+                       ft_a, ft_b);
        }
 
-       BT_LOGD("Copied sequence field type: original-ft-addr=%p, copy-ft-addr=%p",
-               type, copy);
-
 end:
-       bt_put(copy_element);
-       return copy;
-error:
-       BT_PUT(copy);
-       goto end;
+       return ret;
 }
 
-static
-struct bt_field_type *bt_field_type_string_copy(
-               struct bt_field_type *type)
+int bt_field_type_compare(struct bt_field_type *ft_a,
+               struct bt_field_type *ft_b)
 {
-       struct bt_field_type *copy;
-
-       BT_LOGD("Copying string field type's: addr=%p", type);
-       copy = bt_field_type_string_create();
-       if (!copy) {
-               BT_LOGE_STR("Cannot create string field type.");
-               goto end;
-       }
-
-       BT_LOGD("Copied string field type: original-ft-addr=%p, copy-ft-addr=%p",
-               type, copy);
-end:
-       return copy;
+       return bt_field_type_common_compare((void *) ft_a, (void *) ft_b);
 }
 
-static
-int bt_field_type_integer_compare(struct bt_field_type *type_a,
-               struct bt_field_type *type_b)
+BT_HIDDEN
+int64_t bt_field_type_common_get_field_count(struct bt_field_type_common *ft)
 {
-       int ret = 1;
-       struct bt_field_type_integer *int_type_a;
-       struct bt_field_type_integer *int_type_b;
-
-       int_type_a = container_of(type_a, struct bt_field_type_integer,
-               parent);
-       int_type_b = container_of(type_b, struct bt_field_type_integer,
-               parent);
-
-       /* Length */
-       if (int_type_a->size != int_type_b->size) {
-               BT_LOGV("Integer field types differ: different sizes: "
-                       "ft-a-size=%u, ft-b-size=%u",
-                       int_type_a->size, int_type_b->size);
-               goto end;
-       }
-
-       /* Byte order */
-       if (int_type_a->user_byte_order != int_type_b->user_byte_order) {
-               BT_LOGV("Integer field types differ: different byte orders: "
-                       "ft-a-bo=%s, ft-b-bo=%s",
-                       bt_byte_order_string(int_type_a->user_byte_order),
-                       bt_byte_order_string(int_type_b->user_byte_order));
-               goto end;
-       }
+       int64_t field_count = -1;
 
-       /* Signedness */
-       if (int_type_a->is_signed != int_type_b->is_signed) {
-               BT_LOGV("Integer field types differ: different signedness: "
-                       "ft-a-is-signed=%d, ft-b-is-signed=%d",
-                       int_type_a->is_signed,
-                       int_type_b->is_signed);
-               goto end;
+       switch (ft->id) {
+       case BT_FIELD_TYPE_ID_STRUCT:
+               field_count =
+                       bt_field_type_common_structure_get_field_count(ft);
+               break;
+       case BT_FIELD_TYPE_ID_VARIANT:
+               field_count =
+                       bt_field_type_common_variant_get_field_count(ft);
+               break;
+       case BT_FIELD_TYPE_ID_ARRAY:
+       case BT_FIELD_TYPE_ID_SEQUENCE:
+               /*
+                * Array and sequence types always contain a single member
+                * (the element type).
+                */
+               field_count = 1;
+               break;
+       default:
+               break;
        }
 
-       /* Base */
-       if (int_type_a->base != int_type_b->base) {
-               BT_LOGV("Integer field types differ: different bases: "
-                       "ft-a-base=%s, ft-b-base=%s",
-                       bt_integer_base_string(int_type_a->base),
-                       bt_integer_base_string(int_type_b->base));
-               goto end;
-       }
+       return field_count;
+}
 
-       /* Encoding */
-       if (int_type_a->encoding != int_type_b->encoding) {
-               BT_LOGV("Integer field types differ: different encodings: "
-                       "ft-a-encoding=%s, ft-b-encoding=%s",
-                       bt_string_encoding_string(int_type_a->encoding),
-                       bt_string_encoding_string(int_type_b->encoding));
-               goto end;
-       }
+BT_HIDDEN
+struct bt_field_type_common *bt_field_type_common_get_field_at_index(
+               struct bt_field_type_common *ft, int index)
+{
+       struct bt_field_type_common *field_type = NULL;
 
-       /* Mapped clock class */
-       if (int_type_a->mapped_clock) {
-               if (!int_type_b->mapped_clock) {
-                       BT_LOGV_STR("Integer field types differ: field type A "
-                               "has a mapped clock class, but field type B "
-                               "does not.");
+       switch (ft->id) {
+       case BT_FIELD_TYPE_ID_STRUCT:
+       {
+               int ret = bt_field_type_common_structure_get_field_by_index(
+                       ft, NULL, &field_type, index);
+               if (ret) {
+                       field_type = NULL;
                        goto end;
                }
-
-               if (bt_clock_class_compare(int_type_a->mapped_clock,
-                               int_type_b->mapped_clock) != 0) {
-                       BT_LOGV_STR("Integer field types differ: different "
-                               "mapped clock classes.");
-               }
-       } else {
-               if (int_type_b->mapped_clock) {
-                       BT_LOGV_STR("Integer field types differ: field type A "
-                               "has no description, but field type B has one.");
+               break;
+       }
+       case BT_FIELD_TYPE_ID_VARIANT:
+       {
+               int ret = bt_field_type_common_variant_get_field_by_index(
+                       ft, NULL, &field_type, index);
+               if (ret) {
+                       field_type = NULL;
                        goto end;
                }
+               break;
+       }
+       case BT_FIELD_TYPE_ID_ARRAY:
+               field_type = bt_field_type_common_array_get_element_field_type(ft);
+               break;
+       case BT_FIELD_TYPE_ID_SEQUENCE:
+               field_type = bt_field_type_common_sequence_get_element_field_type(ft);
+               break;
+       default:
+               break;
        }
-
-       /* Equal */
-       ret = 0;
 
 end:
-       return ret;
+       return field_type;
 }
 
-static
-int bt_field_type_floating_point_compare(struct bt_field_type *type_a,
-               struct bt_field_type *type_b)
+BT_HIDDEN
+int bt_field_type_common_get_field_index(struct bt_field_type_common *ft,
+               const char *name)
 {
-       int ret = 1;
-       struct bt_field_type_floating_point *float_a;
-       struct bt_field_type_floating_point *float_b;
-
-       float_a = container_of(type_a,
-               struct bt_field_type_floating_point, parent);
-       float_b = container_of(type_b,
-               struct bt_field_type_floating_point, parent);
+       int field_index = -1;
 
-       /* Byte order */
-       if (float_a->user_byte_order != float_b->user_byte_order) {
-               BT_LOGV("Floating point number field types differ: different byte orders: "
-                       "ft-a-bo=%s, ft-b-bo=%s",
-                       bt_byte_order_string(float_a->user_byte_order),
-                       bt_byte_order_string(float_b->user_byte_order));
-               goto end;
+       switch (ft->id) {
+       case BT_FIELD_TYPE_ID_STRUCT:
+               field_index = bt_field_type_common_structure_get_field_name_index(
+                       ft, name);
+               break;
+       case BT_FIELD_TYPE_ID_VARIANT:
+               field_index = bt_field_type_common_variant_get_field_name_index(
+                       ft, name);
+               break;
+       default:
+               break;
        }
 
-       /* Exponent length */
-       if (float_a->exp_dig != float_b->exp_dig) {
-               BT_LOGV("Floating point number field types differ: different exponent sizes: "
-                       "ft-a-exp-size=%u, ft-b-exp-size=%u",
-                       float_a->exp_dig, float_b->exp_dig);
-               goto end;
-       }
+       return field_index;
+}
 
-       /* Mantissa length */
-       if (float_a->mant_dig != float_b->mant_dig) {
-               BT_LOGV("Floating point number field types differ: different mantissa sizes: "
-                       "ft-a-mant-size=%u, ft-b-mant-size=%u",
-                       float_a->mant_dig, float_b->mant_dig);
-               goto end;
-       }
+BT_HIDDEN
+struct bt_field_path *bt_field_type_common_variant_get_tag_field_path(
+               struct bt_field_type_common *ft)
+{
+       struct bt_field_type_common_variant *var_ft = BT_FROM_COMMON(ft);
 
-       /* Equal */
-       ret = 0;
+       BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+       BT_ASSERT_PRE_FT_COMMON_HAS_ID(ft, BT_FIELD_TYPE_ID_VARIANT,
+               "Field type");
+       return bt_get(var_ft->tag_field_path);
+}
 
-end:
-       return ret;
+struct bt_field_path *bt_field_type_variant_get_tag_field_path(
+               struct bt_field_type *ft)
+{
+       return bt_field_type_common_variant_get_tag_field_path((void *) ft);
 }
 
-static
-int compare_enumeration_mappings(struct enumeration_mapping *mapping_a,
-               struct enumeration_mapping *mapping_b)
+BT_HIDDEN
+struct bt_field_path *bt_field_type_common_sequence_get_length_field_path(
+               struct bt_field_type_common *ft)
 {
-       int ret = 1;
+       struct bt_field_type_common_sequence *seq_ft = BT_FROM_COMMON(ft);
 
-       /* Label */
-       if (mapping_a->string != mapping_b->string) {
-               BT_LOGV("Enumeration field type mappings differ: different names: "
-                       "mapping-a-name=\"%s\", mapping-b-name=\"%s\"",
-                       g_quark_to_string(mapping_a->string),
-                       g_quark_to_string(mapping_b->string));
-               goto end;
-       }
+       BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+       BT_ASSERT_PRE_FT_COMMON_HAS_ID(ft, BT_FIELD_TYPE_ID_SEQUENCE,
+               "Field type");
+       return bt_get(seq_ft->length_field_path);
+}
 
-       /* Range start */
-       if (mapping_a->range_start._unsigned !=
-                       mapping_b->range_start._unsigned) {
-               BT_LOGV("Enumeration field type mappings differ: different starts of range: "
-                       "mapping-a-range-start-unsigned=%" PRIu64 ", "
-                       "mapping-b-range-start-unsigned=%" PRIu64,
-                       mapping_a->range_start._unsigned,
-                       mapping_b->range_start._unsigned);
-               goto end;
-       }
+struct bt_field_path *bt_field_type_sequence_get_length_field_path(
+               struct bt_field_type *ft)
+{
+       return bt_field_type_common_sequence_get_length_field_path((void *) ft);
+}
 
-       /* Range end */
-       if (mapping_a->range_end._unsigned !=
-                       mapping_b->range_end._unsigned) {
-               BT_LOGV("Enumeration field type mappings differ: different ends of range: "
-                       "mapping-a-range-end-unsigned=%" PRIu64 ", "
-                       "mapping-b-range-end-unsigned=%" PRIu64,
-                       mapping_a->range_end._unsigned,
-                       mapping_b->range_end._unsigned);
+BT_HIDDEN
+int bt_field_type_common_validate_single_clock_class(
+               struct bt_field_type_common *ft,
+               struct bt_clock_class **expected_clock_class)
+{
+       int ret = 0;
+
+       if (!ft) {
                goto end;
        }
 
-       /* Equal */
-       ret = 0;
+       BT_ASSERT(expected_clock_class);
 
-end:
-       return ret;
-}
+       switch (ft->id) {
+       case BT_FIELD_TYPE_ID_INTEGER:
+       {
+               struct bt_clock_class *mapped_clock_class =
+                       bt_field_type_common_integer_get_mapped_clock_class(ft);
 
-static
-int bt_field_type_enumeration_compare(struct bt_field_type *type_a,
-               struct bt_field_type *type_b)
-{
-       int ret = 1;
-       int i;
-       struct bt_field_type_enumeration *enum_a;
-       struct bt_field_type_enumeration *enum_b;
+               if (!mapped_clock_class) {
+                       goto end;
+               }
 
-       enum_a = container_of(type_a,
-               struct bt_field_type_enumeration, parent);
-       enum_b = container_of(type_b,
-               struct bt_field_type_enumeration, parent);
+               if (!*expected_clock_class) {
+                       /* Move reference to output parameter */
+                       *expected_clock_class = mapped_clock_class;
+                       mapped_clock_class = NULL;
+                       BT_LOGV("Setting expected clock class: "
+                               "expected-clock-class-addr=%p",
+                               *expected_clock_class);
+               } else {
+                       if (mapped_clock_class != *expected_clock_class) {
+                               BT_LOGW("Integer field type is not mapped to "
+                                       "the expected clock class: "
+                                       "mapped-clock-class-addr=%p, "
+                                       "mapped-clock-class-name=\"%s\", "
+                                       "expected-clock-class-addr=%p, "
+                                       "expected-clock-class-name=\"%s\"",
+                                       mapped_clock_class,
+                                       bt_clock_class_get_name(mapped_clock_class),
+                                       *expected_clock_class,
+                                       bt_clock_class_get_name(*expected_clock_class));
+                               bt_put(mapped_clock_class);
+                               ret = -1;
+                               goto end;
+                       }
+               }
 
-       /* Container field type */
-       ret = bt_field_type_compare(enum_a->container, enum_b->container);
-       if (ret) {
-               BT_LOGV("Enumeration field types differ: different container field types: "
-                       "ft-a-container-ft-addr=%p, ft-b-container-ft-addr=%p",
-                       enum_a->container, enum_b->container);
-               goto end;
+               bt_put(mapped_clock_class);
+               break;
        }
+       case BT_FIELD_TYPE_ID_ENUM:
+       case BT_FIELD_TYPE_ID_ARRAY:
+       case BT_FIELD_TYPE_ID_SEQUENCE:
+       {
+               struct bt_field_type_common *sub_ft = NULL;
 
-       ret = 1;
+               switch (ft->id) {
+               case BT_FIELD_TYPE_ID_ENUM:
+                       sub_ft = bt_field_type_common_enumeration_get_container_field_type(
+                               ft);
+                       break;
+               case BT_FIELD_TYPE_ID_ARRAY:
+                       sub_ft = bt_field_type_common_array_get_element_field_type(
+                               ft);
+                       break;
+               case BT_FIELD_TYPE_ID_SEQUENCE:
+                       sub_ft = bt_field_type_common_sequence_get_element_field_type(
+                               ft);
+                       break;
+               default:
+                       BT_LOGF("Unexpected field type ID: id=%d", ft->id);
+                       abort();
+               }
 
-       /* Entries */
-       if (enum_a->entries->len != enum_b->entries->len) {
-               goto end;
+               BT_ASSERT(sub_ft);
+               ret = bt_field_type_common_validate_single_clock_class(sub_ft,
+                       expected_clock_class);
+               bt_put(sub_ft);
+               break;
        }
+       case BT_FIELD_TYPE_ID_STRUCT:
+       {
+               uint64_t i;
+               int64_t count = bt_field_type_common_structure_get_field_count(
+                       ft);
 
-       for (i = 0; i < enum_a->entries->len; ++i) {
-               struct enumeration_mapping *mapping_a =
-                       g_ptr_array_index(enum_a->entries, i);
-               struct enumeration_mapping *mapping_b =
-                       g_ptr_array_index(enum_b->entries, i);
+               for (i = 0; i < count; i++) {
+                       const char *name;
+                       struct bt_field_type_common *member_type;
 
-               if (compare_enumeration_mappings(mapping_a, mapping_b)) {
-                       BT_LOGV("Enumeration field types differ: different mappings: "
-                               "ft-a-mapping-addr=%p, ft-b-mapping-addr=%p, "
-                               "ft-a-mapping-name=\"%s\", ft-b-mapping-name=\"%s\"",
-                               mapping_a, mapping_b,
-                               g_quark_to_string(mapping_a->string),
-                               g_quark_to_string(mapping_b->string));
-                       goto end;
+                       ret = bt_field_type_common_structure_get_field_by_index(
+                               ft, &name, &member_type, i);
+                       BT_ASSERT(ret == 0);
+                       ret = bt_field_type_common_validate_single_clock_class(
+                               member_type, expected_clock_class);
+                       bt_put(member_type);
+                       if (ret) {
+                               BT_LOGW("Structure field type's field's type "
+                                       "is not recursively mapped to the "
+                                       "expected clock class: "
+                                       "field-ft-addr=%p, field-name=\"%s\"",
+                                       member_type, name);
+                               goto end;
+                       }
                }
+               break;
        }
+       case BT_FIELD_TYPE_ID_VARIANT:
+       {
+               uint64_t i;
+               int64_t count = bt_field_type_common_variant_get_field_count(
+                       ft);
 
-       /* Equal */
-       ret = 0;
-
-end:
-       return ret;
-}
-
-static
-int bt_field_type_string_compare(struct bt_field_type *type_a,
-               struct bt_field_type *type_b)
-{
-       int ret = 1;
-       struct bt_field_type_string *string_a;
-       struct bt_field_type_string *string_b;
-
-       string_a = container_of(type_a,
-               struct bt_field_type_string, parent);
-       string_b = container_of(type_b,
-               struct bt_field_type_string, parent);
+               for (i = 0; i < count; i++) {
+                       const char *name;
+                       struct bt_field_type_common *member_type;
 
-       /* Encoding */
-       if (string_a->encoding != string_b->encoding) {
-               BT_LOGV("String field types differ: different encodings: "
-                       "ft-a-encoding=%s, ft-b-encoding=%s",
-                       bt_string_encoding_string(string_a->encoding),
-                       bt_string_encoding_string(string_b->encoding));
-               goto end;
+                       ret = bt_field_type_common_variant_get_field_by_index(
+                               ft, &name, &member_type, i);
+                       BT_ASSERT(ret == 0);
+                       ret = bt_field_type_common_validate_single_clock_class(
+                               member_type, expected_clock_class);
+                       bt_put(member_type);
+                       if (ret) {
+                               BT_LOGW("Variant field type's field's type "
+                                       "is not recursively mapped to the "
+                                       "expected clock class: "
+                                       "field-ft-addr=%p, field-name=\"%s\"",
+                                       member_type, name);
+                               goto end;
+                       }
+               }
+               break;
+       }
+       default:
+               break;
        }
-
-       /* Equal */
-       ret = 0;
 
 end:
        return ret;
 }
 
 static
-int compare_structure_fields(struct structure_field *field_a,
-               struct structure_field *field_b)
+struct bt_field_type *bt_field_type_integer_copy(
+               struct bt_field_type *ft)
 {
-       int ret = 1;
+       struct bt_field_type_common_integer *int_ft = (void *) ft;
+       struct bt_field_type_common_integer *copy_ft;
 
-       /* Label */
-       if (field_a->name != field_b->name) {
-               BT_LOGV("Structure/variant field type fields differ: different names: "
-                       "field-a-name=%s, field-b-name=%s",
-                       g_quark_to_string(field_a->name),
-                       g_quark_to_string(field_b->name));
+       BT_LOGD("Copying CTF writer integer field type's: addr=%p", ft);
+       copy_ft = (void *) bt_field_type_integer_create(int_ft->size);
+       if (!copy_ft) {
+               BT_LOGE_STR("Cannot create CTF writer integer field type.");
                goto end;
        }
 
-       /* Type */
-       ret = bt_field_type_compare(field_a->type, field_b->type);
-       if (ret == 1) {
-               BT_LOGV("Structure/variant field type fields differ: different field types: "
-                       "field-name=\"%s\", field-a-ft-addr=%p, field-b-ft-addr=%p",
-                       g_quark_to_string(field_a->name),
-                       field_a->type, field_b->type);
-       }
+       copy_ft->mapped_clock_class = bt_get(int_ft->mapped_clock_class);
+       copy_ft->user_byte_order = int_ft->user_byte_order;
+       copy_ft->is_signed = int_ft->is_signed;
+       copy_ft->size = int_ft->size;
+       copy_ft->base = int_ft->base;
+       copy_ft->encoding = int_ft->encoding;
+       BT_LOGD("Copied CTF writer integer field type: original-ft-addr=%p, copy-ft-addr=%p",
+               ft, copy_ft);
 
 end:
-       return ret;
+       return (void *) copy_ft;
 }
 
 static
-int bt_field_type_structure_compare(struct bt_field_type *type_a,
-               struct bt_field_type *type_b)
+struct bt_field_type *bt_field_type_enumeration_copy_recursive(
+               struct bt_field_type *ft)
 {
-       int ret = 1;
-       int i;
-       struct bt_field_type_structure *struct_a;
-       struct bt_field_type_structure *struct_b;
+       size_t i;
+       struct bt_field_type_common_enumeration *enum_ft = (void *) ft;
+       struct bt_field_type_common_enumeration *copy_ft = NULL;
+       struct bt_field_type_common_enumeration *container_copy_ft;
 
-       struct_a = container_of(type_a,
-               struct bt_field_type_structure, parent);
-       struct_b = container_of(type_b,
-               struct bt_field_type_structure, parent);
+       BT_LOGD("Copying CTF writer enumeration field type's: addr=%p", ft);
 
-       /* Alignment */
-       if (bt_field_type_get_alignment(type_a) !=
-                       bt_field_type_get_alignment(type_b)) {
-               BT_LOGV("Structure field types differ: different alignments: "
-                       "ft-a-align=%u, ft-b-align=%u",
-                       bt_field_type_get_alignment(type_a),
-                       bt_field_type_get_alignment(type_b));
+       /* Copy the source enumeration's container */
+       BT_LOGD_STR("Copying CTF writer enumeration field type's container field type.");
+       container_copy_ft = BT_FROM_COMMON(bt_field_type_common_copy(
+               BT_TO_COMMON(enum_ft->container_ft)));
+       if (!container_copy_ft) {
+               BT_LOGE_STR("Cannot copy CTF writer enumeration field type's container field type.");
                goto end;
        }
 
-       /* Fields */
-       if (struct_a->fields->len != struct_b->fields->len) {
-               BT_LOGV("Structure field types differ: different field counts: "
-                       "ft-a-field-count=%u, ft-b-field-count=%u",
-                       struct_a->fields->len, struct_b->fields->len);
+       copy_ft = (void *) bt_field_type_enumeration_create(
+               (void *) container_copy_ft);
+       if (!copy_ft) {
+               BT_LOGE_STR("Cannot create CTF writer enumeration field type.");
                goto end;
        }
 
-       for (i = 0; i < struct_a->fields->len; ++i) {
-               struct structure_field *field_a =
-                       g_ptr_array_index(struct_a->fields, i);
-               struct structure_field *field_b =
-                       g_ptr_array_index(struct_b->fields, i);
+       /* Copy all enumaration entries */
+       for (i = 0; i < enum_ft->entries->len; i++) {
+               struct enumeration_mapping *mapping = g_ptr_array_index(
+                       enum_ft->entries, i);
+               struct enumeration_mapping *copy_mapping = g_new0(
+                       struct enumeration_mapping, 1);
 
-               ret = compare_structure_fields(field_a, field_b);
-               if (ret) {
-                       /* compare_structure_fields() logs what differs */
-                       BT_LOGV_STR("Structure field types differ: different fields.");
-                       goto end;
+               if (!copy_mapping) {
+                       BT_LOGE_STR("Failed to allocate one enumeration mapping.");
+                       goto error;
                }
+
+               *copy_mapping = *mapping;
+               g_ptr_array_add(copy_ft->entries, copy_mapping);
        }
 
-       /* Equal */
-       ret = 0;
+       BT_LOGD("Copied CTF writer enumeration field type: original-ft-addr=%p, copy-ft-addr=%p",
+               ft, copy_ft);
 
 end:
-       return ret;
+       bt_put(container_copy_ft);
+       return (void *) copy_ft;
+
+error:
+       bt_put(container_copy_ft);
+        BT_PUT(copy_ft);
+       return (void *) copy_ft;
 }
 
 static
-int bt_field_type_variant_compare(struct bt_field_type *type_a,
-               struct bt_field_type *type_b)
+struct bt_field_type *bt_field_type_floating_point_copy(
+               struct bt_field_type *ft)
 {
-       int ret = 1;
-       int i;
-       struct bt_field_type_variant *variant_a;
-       struct bt_field_type_variant *variant_b;
+       struct bt_field_type_common_floating_point *flt_ft = BT_FROM_COMMON(ft);
+       struct bt_field_type_common_floating_point *copy_ft;
 
-       variant_a = container_of(type_a,
-               struct bt_field_type_variant, parent);
-       variant_b = container_of(type_b,
-               struct bt_field_type_variant, parent);
-
-       /* Tag name */
-       if (strcmp(variant_a->tag_name->str, variant_b->tag_name->str)) {
-               BT_LOGV("Variant field types differ: different tag field names: "
-                       "ft-a-tag-field-name=\"%s\", ft-b-tag-field-name=\"%s\"",
-                       variant_a->tag_name->str, variant_b->tag_name->str);
+       BT_LOGD("Copying CTF writer floating point number field type's: addr=%p", ft);
+       copy_ft = (void *) bt_field_type_floating_point_create();
+       if (!copy_ft) {
+               BT_LOGE_STR("Cannot create CTF writer floating point number field type.");
                goto end;
        }
 
-       /* Tag type */
-       ret = bt_field_type_compare(
-               (struct bt_field_type *) variant_a->tag,
-               (struct bt_field_type *) variant_b->tag);
-       if (ret) {
-               BT_LOGV("Variant field types differ: different tag field types: "
-                       "ft-a-tag-ft-addr=%p, ft-b-tag-ft-addr=%p",
-                       variant_a->tag, variant_b->tag);
-               goto end;
-       }
+       copy_ft->user_byte_order = flt_ft->user_byte_order;
+       copy_ft->exp_dig = flt_ft->exp_dig;
+       copy_ft->mant_dig = flt_ft->mant_dig;
+       BT_LOGD("Copied CTF writer floating point number field type: original-ft-addr=%p, copy-ft-addr=%p",
+               ft, copy_ft);
 
-       ret = 1;
+end:
+       return (void *) copy_ft;
+}
 
-       /* Fields */
-       if (variant_a->fields->len != variant_b->fields->len) {
-               BT_LOGV("Structure field types differ: different field counts: "
-                       "ft-a-field-count=%u, ft-b-field-count=%u",
-                       variant_a->fields->len, variant_b->fields->len);
+static
+struct bt_field_type *bt_field_type_structure_copy_recursive(
+               struct bt_field_type *ft)
+{
+       int64_t i;
+       GHashTableIter iter;
+       gpointer key, value;
+       struct bt_field_type_common_structure *struct_ft = (void *) ft;
+       struct bt_field_type_common_structure *copy_ft;
+
+       BT_LOGD("Copying CTF writer structure field type's: addr=%p", ft);
+       copy_ft = (void *) bt_field_type_structure_create();
+       if (!copy_ft) {
+               BT_LOGE_STR("Cannot create CTF writer structure field type.");
                goto end;
        }
 
-       for (i = 0; i < variant_a->fields->len; ++i) {
-               struct structure_field *field_a =
-                       g_ptr_array_index(variant_a->fields, i);
-               struct structure_field *field_b =
-                       g_ptr_array_index(variant_b->fields, i);
+       /* Copy field_name_to_index */
+       g_hash_table_iter_init(&iter, struct_ft->field_name_to_index);
+       while (g_hash_table_iter_next(&iter, &key, &value)) {
+               g_hash_table_insert(copy_ft->field_name_to_index,
+                       key, value);
+       }
+
+       for (i = 0; i < struct_ft->fields->len; i++) {
+               struct structure_field_common *entry, *copy_entry;
+               struct bt_field_type_common *field_ft_copy;
 
-               ret = compare_structure_fields(field_a, field_b);
-               if (ret) {
-                       /* compare_structure_fields() logs what differs */
-                       BT_LOGV_STR("Variant field types differ: different fields.");
-                       goto end;
+               entry = g_ptr_array_index(struct_ft->fields, i);
+               BT_LOGD("Copying CTF writer structure field type's field: "
+                       "index=%" PRId64 ", "
+                       "field-ft-addr=%p, field-name=\"%s\"",
+                       i, entry, g_quark_to_string(entry->name));
+               copy_entry = g_new0(struct structure_field_common, 1);
+               if (!copy_entry) {
+                       BT_LOGE_STR("Failed to allocate one structure field type field.");
+                       goto error;
+               }
+
+               field_ft_copy = (void *) bt_field_type_copy(
+                       (void *) entry->type);
+               if (!field_ft_copy) {
+                       BT_LOGE("Cannot copy CTF writer structure field type's field: "
+                               "index=%" PRId64 ", "
+                               "field-ft-addr=%p, field-name=\"%s\"",
+                               i, entry, g_quark_to_string(entry->name));
+                       g_free(copy_entry);
+                       goto error;
                }
+
+               copy_entry->name = entry->name;
+               copy_entry->type = field_ft_copy;
+               g_ptr_array_add(copy_ft->fields, copy_entry);
        }
 
-       /* Equal */
-       ret = 0;
+       BT_LOGD("Copied CTF writer structure field type: original-ft-addr=%p, copy-ft-addr=%p",
+               ft, copy_ft);
 
 end:
-       return ret;
+       return (void *) copy_ft;
+
+error:
+        BT_PUT(copy_ft);
+       return NULL;
 }
 
 static
-int bt_field_type_array_compare(struct bt_field_type *type_a,
-               struct bt_field_type *type_b)
+struct bt_field_type *bt_field_type_variant_copy_recursive(
+               struct bt_field_type *ft)
 {
-       int ret = 1;
-       struct bt_field_type_array *array_a;
-       struct bt_field_type_array *array_b;
-
-       array_a = container_of(type_a,
-               struct bt_field_type_array, parent);
-       array_b = container_of(type_b,
-               struct bt_field_type_array, parent);
+       int64_t i;
+       GHashTableIter iter;
+       gpointer key, value;
+       struct bt_field_type_common *tag_ft_copy = NULL;
+       struct bt_field_type_common_variant *var_ft = (void *) ft;
+       struct bt_field_type_common_variant *copy_ft = NULL;
+
+       BT_LOGD("Copying CTF writer variant field type's: addr=%p", ft);
+       if (var_ft->tag_ft) {
+               BT_LOGD_STR("Copying CTF writer variant field type's tag field type.");
+               tag_ft_copy = bt_field_type_common_copy(
+                       BT_TO_COMMON(var_ft->tag_ft));
+               if (!tag_ft_copy) {
+                       BT_LOGE_STR("Cannot copy CTF writer variant field type's tag field type.");
+                       goto end;
+               }
+       }
 
-       /* Length */
-       if (array_a->length != array_b->length) {
-               BT_LOGV("Structure field types differ: different lengths: "
-                       "ft-a-length=%u, ft-b-length=%u",
-                       array_a->length, array_b->length);
+       copy_ft = (void *) bt_field_type_variant_create(
+               (void *) tag_ft_copy,
+               var_ft->tag_name->len ? var_ft->tag_name->str : NULL);
+       if (!copy_ft) {
+               BT_LOGE_STR("Cannot create CTF writer variant field type.");
                goto end;
        }
 
-       /* Element type */
-       ret = bt_field_type_compare(array_a->element_type,
-               array_b->element_type);
-       if (ret == 1) {
-               BT_LOGV("Array field types differ: different element field types: "
-                       "ft-a-element-ft-addr=%p, ft-b-element-ft-addr=%p",
-                       array_a->element_type, array_b->element_type);
+       /* Copy field_name_to_index */
+       g_hash_table_iter_init(&iter, var_ft->field_name_to_index);
+       while (g_hash_table_iter_next(&iter, &key, &value)) {
+               g_hash_table_insert(copy_ft->field_name_to_index,
+                       key, value);
        }
 
-end:
-       return ret;
-}
+       for (i = 0; i < var_ft->fields->len; i++) {
+               struct structure_field_common *entry, *copy_entry;
+               struct bt_field_type_common *field_ft_copy;
 
-static
-int bt_field_type_sequence_compare(struct bt_field_type *type_a,
-               struct bt_field_type *type_b)
-{
-       int ret = -1;
-       struct bt_field_type_sequence *sequence_a;
-       struct bt_field_type_sequence *sequence_b;
+               entry = g_ptr_array_index(var_ft->fields, i);
+               BT_LOGD("Copying CTF writer variant field type's field: "
+                       "index=%" PRId64 ", "
+                       "field-ft-addr=%p, field-name=\"%s\"",
+                       i, entry, g_quark_to_string(entry->name));
+               copy_entry = g_new0(struct structure_field_common, 1);
+               if (!copy_entry) {
+                       BT_LOGE_STR("Failed to allocate one variant field type field.");
+                       goto error;
+               }
 
-       sequence_a = container_of(type_a,
-               struct bt_field_type_sequence, parent);
-       sequence_b = container_of(type_b,
-               struct bt_field_type_sequence, parent);
+               field_ft_copy = (void *) bt_field_type_copy(
+                       (void *) entry->type);
+               if (!field_ft_copy) {
+                       BT_LOGE("Cannot copy CTF writer variant field type's field: "
+                               "index=%" PRId64 ", "
+                               "field-ft-addr=%p, field-name=\"%s\"",
+                               i, entry, g_quark_to_string(entry->name));
+                       g_free(copy_entry);
+                       goto error;
+               }
 
-       /* Length name */
-       if (strcmp(sequence_a->length_field_name->str,
-                       sequence_b->length_field_name->str)) {
-               BT_LOGV("Sequence field types differ: different length field names: "
-                       "ft-a-length-field-name=\"%s\", "
-                       "ft-b-length-field-name=\"%s\"",
-                       sequence_a->length_field_name->str,
-                       sequence_b->length_field_name->str);
-               goto end;
+               copy_entry->name = entry->name;
+               copy_entry->type = field_ft_copy;
+               g_ptr_array_add(copy_ft->fields, copy_entry);
        }
 
-       /* Element type */
-       ret = bt_field_type_compare(sequence_a->element_type,
-                       sequence_b->element_type);
-       if (ret == 1) {
-               BT_LOGV("Sequence field types differ: different element field types: "
-                       "ft-a-element-ft-addr=%p, ft-b-element-ft-addr=%p",
-                       sequence_a->element_type, sequence_b->element_type);
+       if (var_ft->tag_field_path) {
+               BT_LOGD_STR("Copying CTF writer variant field type's tag field path.");
+               copy_ft->tag_field_path = bt_field_path_copy(
+                       var_ft->tag_field_path);
+               if (!copy_ft->tag_field_path) {
+                       BT_LOGE_STR("Cannot copy CTF writer variant field type's tag field path.");
+                       goto error;
+               }
        }
 
+       BT_LOGD("Copied variant field type: original-ft-addr=%p, copy-ft-addr=%p",
+               ft, copy_ft);
+
 end:
-       return ret;
+       bt_put(tag_ft_copy);
+       return (void *) copy_ft;
+
+error:
+       bt_put(tag_ft_copy);
+        BT_PUT(copy_ft);
+       return NULL;
 }
 
-int bt_field_type_compare(struct bt_field_type *type_a,
-               struct bt_field_type *type_b)
+static
+struct bt_field_type *bt_field_type_array_copy_recursive(
+               struct bt_field_type *ft)
 {
-       int ret = 1;
-
-       BT_ASSERT_PRE_NON_NULL(type_a, "Field type A");
-       BT_ASSERT_PRE_NON_NULL(type_b, "Field type B");
-
-       if (type_a == type_b) {
-               /* Same reference: equal (even if both are NULL) */
-               ret = 0;
-               goto end;
-       }
-
-       if (!type_a) {
-               BT_LOGW_STR("Invalid parameter: field type A is NULL.");
-               ret = -1;
-               goto end;
-       }
-
-       if (!type_b) {
-               BT_LOGW_STR("Invalid parameter: field type B is NULL.");
-               ret = -1;
-               goto end;
-       }
+       struct bt_field_type_common *container_ft_copy = NULL;
+       struct bt_field_type_common_array *array_ft = (void *) ft;
+       struct bt_field_type_common_array *copy_ft = NULL;
 
-       if (type_a->id != type_b->id) {
-               /* Different type IDs */
-               BT_LOGV("Field types differ: different IDs: "
-                       "ft-a-addr=%p, ft-b-addr=%p, "
-                       "ft-a-id=%s, ft-b-id=%s",
-                       type_a, type_b,
-                       bt_field_type_id_string(type_a->id),
-                       bt_field_type_id_string(type_b->id));
+       BT_LOGD("Copying CTF writer array field type's: addr=%p", ft);
+       BT_LOGD_STR("Copying CTF writer array field type's element field type.");
+       container_ft_copy = bt_field_type_common_copy(array_ft->element_ft);
+       if (!container_ft_copy) {
+               BT_LOGE_STR("Cannot copy CTF writer array field type's element field type.");
                goto end;
        }
 
-       if (type_a->id == BT_FIELD_TYPE_ID_UNKNOWN) {
-               /* Both have unknown type IDs */
-               BT_LOGW_STR("Invalid parameter: field type IDs are unknown.");
+       copy_ft = (void *) bt_field_type_array_create(
+               (void *) container_ft_copy, array_ft->length);
+       if (!copy_ft) {
+               BT_LOGE_STR("Cannot create CTF writer array field type.");
                goto end;
        }
 
-       ret = type_compare_funcs[type_a->id](type_a, type_b);
-       if (ret == 1) {
-               BT_LOGV("Field types differ: ft-a-addr=%p, ft-b-addr=%p",
-                       type_a, type_b);
-       }
+       BT_LOGD("Copied CTF writer array field type: original-ft-addr=%p, copy-ft-addr=%p",
+               ft, copy_ft);
 
 end:
-       return ret;
+       bt_put(container_ft_copy);
+       return (void *) copy_ft;
 }
 
-BT_HIDDEN
-int64_t bt_field_type_get_field_count(struct bt_field_type *field_type)
+static
+struct bt_field_type *bt_field_type_sequence_copy_recursive(
+               struct bt_field_type *ft)
 {
-       int64_t field_count = -1;
-       enum bt_field_type_id type_id = bt_field_type_get_type_id(field_type);
+       struct bt_field_type_common *container_ft_copy = NULL;
+       struct bt_field_type_common_sequence *seq_ft = (void *) ft;
+       struct bt_field_type_common_sequence *copy_ft = NULL;
 
-       switch (type_id) {
-       case CTF_TYPE_STRUCT:
-               field_count =
-                       bt_field_type_structure_get_field_count(field_type);
-               break;
-       case CTF_TYPE_VARIANT:
-               field_count =
-                       bt_field_type_variant_get_field_count(field_type);
-               break;
-       case CTF_TYPE_ARRAY:
-       case CTF_TYPE_SEQUENCE:
-               /*
-                * Array and sequence types always contain a single member
-                * (the element type).
-                */
-               field_count = 1;
-               break;
-       default:
-               break;
+       BT_LOGD("Copying CTF writer sequence field type's: addr=%p", ft);
+       BT_LOGD_STR("Copying CTF writer sequence field type's element field type.");
+       container_ft_copy = bt_field_type_common_copy(seq_ft->element_ft);
+       if (!container_ft_copy) {
+               BT_LOGE_STR("Cannot copy CTF writer sequence field type's element field type.");
+               goto end;
        }
 
-       return field_count;
-}
-
-BT_HIDDEN
-struct bt_field_type *bt_field_type_get_field_at_index(
-               struct bt_field_type *field_type, int index)
-{
-       struct bt_field_type *field = NULL;
-       enum bt_field_type_id type_id = bt_field_type_get_type_id(field_type);
-
-       switch (type_id) {
-       case CTF_TYPE_STRUCT:
-       {
-               int ret = bt_field_type_structure_get_field_by_index(
-                       field_type, NULL, &field, index);
-               if (ret) {
-                       field = NULL;
-                       goto end;
-               }
-               break;
+       copy_ft = (void *) bt_field_type_sequence_create(
+               (void *) container_ft_copy,
+               seq_ft->length_field_name->len ?
+                       seq_ft->length_field_name->str : NULL);
+       if (!copy_ft) {
+               BT_LOGE_STR("Cannot create CTF writer sequence field type.");
+               goto end;
        }
-       case CTF_TYPE_VARIANT:
-       {
-               int ret = bt_field_type_variant_get_field_by_index(
-                       field_type, NULL, &field, index);
-               if (ret) {
-                       field = NULL;
-                       goto end;
+
+       if (seq_ft->length_field_path) {
+               BT_LOGD_STR("Copying CTF writer sequence field type's length field path.");
+               copy_ft->length_field_path = bt_field_path_copy(
+                       seq_ft->length_field_path);
+               if (!copy_ft->length_field_path) {
+                       BT_LOGE_STR("Cannot copy CTF writer sequence field type's length field path.");
+                       goto error;
                }
-               break;
-       }
-       case CTF_TYPE_ARRAY:
-               field = bt_field_type_array_get_element_type(field_type);
-               break;
-       case CTF_TYPE_SEQUENCE:
-               field = bt_field_type_sequence_get_element_type(field_type);
-               break;
-       default:
-               break;
        }
-end:
-       return field;
-}
-
-BT_HIDDEN
-int bt_field_type_get_field_index(struct bt_field_type *field_type,
-               const char *name)
-{
-       int field_index = -1;
-       enum bt_field_type_id type_id = bt_field_type_get_type_id(field_type);
 
-       switch (type_id) {
-       case CTF_TYPE_STRUCT:
-               field_index = bt_field_type_structure_get_field_name_index(
-                       field_type, name);
-               break;
-       case CTF_TYPE_VARIANT:
-               field_index = bt_field_type_variant_get_field_name_index(
-                       field_type, name);
-               break;
-       default:
-               break;
-       }
+       BT_LOGD("Copied CTF writer sequence field type: original-ft-addr=%p, copy-ft-addr=%p",
+               ft, copy_ft);
 
-       return field_index;
+end:
+       bt_put(container_ft_copy);
+       return (void *) copy_ft;
+error:
+       bt_put(container_ft_copy);
+       BT_PUT(copy_ft);
+       return NULL;
 }
 
-struct bt_field_path *bt_field_type_variant_get_tag_field_path(
-               struct bt_field_type *type)
+static
+struct bt_field_type *bt_field_type_string_copy(struct bt_field_type *ft)
 {
-       struct bt_field_type_variant *variant;
+       struct bt_field_type_common_string *string_ft = (void *) ft;
+       struct bt_field_type_common_string *copy_ft = NULL;
 
-       BT_ASSERT_PRE_NON_NULL(type, "Field type");
-       BT_ASSERT_PRE_FT_HAS_ID(type, BT_FIELD_TYPE_ID_VARIANT, "Field type");
-       variant = container_of(type, struct bt_field_type_variant,
-                       parent);
-       return bt_get(variant->tag_field_path);
-}
+       BT_LOGD("Copying CTF writer string field type's: addr=%p", ft);
+       copy_ft = (void *) bt_field_type_string_create();
+       if (!copy_ft) {
+               BT_LOGE_STR("Cannot create CTF writer string field type.");
+               goto end;
+       }
 
-struct bt_field_path *bt_field_type_sequence_get_length_field_path(
-               struct bt_field_type *type)
-{
-       struct bt_field_type_sequence *sequence;
+       copy_ft->encoding = string_ft->encoding;
+       BT_LOGD("Copied CTF writer string field type: original-ft-addr=%p, copy-ft-addr=%p",
+               ft, copy_ft);
 
-       BT_ASSERT_PRE_NON_NULL(type, "Field type");
-       BT_ASSERT_PRE_FT_HAS_ID(type, BT_FIELD_TYPE_ID_SEQUENCE, "Field type");
-       sequence = container_of(type, struct bt_field_type_sequence,
-                       parent);
-       return bt_get(sequence->length_field_path);
+end:
+       return (void *) copy_ft;
 }
index 5faaaec82cfce9470a49162aa4aa32dbcb599139..b8f08cfaaaec869d9bf0f5ea18d51567b3313b8a 100644 (file)
 #define BT_LOG_TAG "FIELDS"
 #include <babeltrace/lib-logging-internal.h>
 
+#include <babeltrace/assert-pre-internal.h>
 #include <babeltrace/ctf-ir/fields-internal.h>
 #include <babeltrace/ctf-ir/field-types-internal.h>
-#include <babeltrace/ctf-writer/serialize-internal.h>
 #include <babeltrace/object-internal.h>
 #include <babeltrace/ref.h>
 #include <babeltrace/compiler-internal.h>
 #include <babeltrace/compat/fcntl-internal.h>
 #include <babeltrace/align-internal.h>
 #include <babeltrace/assert-internal.h>
-#include <babeltrace/assert-pre-internal.h>
 #include <inttypes.h>
 
 static
-struct bt_field *bt_field_integer_create(struct bt_field_type *);
-static
-struct bt_field *bt_field_enumeration_create(struct bt_field_type *);
-static
-struct bt_field *bt_field_floating_point_create(struct bt_field_type *);
-static
-struct bt_field *bt_field_structure_create(struct bt_field_type *);
-static
-struct bt_field *bt_field_variant_create(struct bt_field_type *);
-static
-struct bt_field *bt_field_array_create(struct bt_field_type *);
-static
-struct bt_field *bt_field_sequence_create(struct bt_field_type *);
-static
-struct bt_field *bt_field_string_create(struct bt_field_type *);
+struct bt_field_common *bt_field_integer_copy(struct bt_field_common *src);
 
 static
-void bt_field_destroy(struct bt_object *);
-static
-void bt_field_integer_destroy(struct bt_field *);
-static
-void bt_field_enumeration_destroy_recursive(struct bt_field *);
-static
-void bt_field_floating_point_destroy(struct bt_field *);
-static
-void bt_field_structure_destroy_recursive(struct bt_field *);
-static
-void bt_field_variant_destroy_recursive(struct bt_field *);
-static
-void bt_field_array_destroy_recursive(struct bt_field *);
-static
-void bt_field_sequence_destroy_recursive(struct bt_field *);
-static
-void bt_field_string_destroy(struct bt_field *);
+struct bt_field_common *bt_field_enumeration_copy_recursive(
+               struct bt_field_common *src);
 
 static
-int bt_field_generic_validate(struct bt_field *);
-static
-int bt_field_structure_validate_recursive(struct bt_field *);
-static
-int bt_field_variant_validate_recursive(struct bt_field *);
-static
-int bt_field_enumeration_validate_recursive(struct bt_field *);
-static
-int bt_field_array_validate_recursive(struct bt_field *);
-static
-int bt_field_sequence_validate_recursive(struct bt_field *);
+struct bt_field_common *bt_field_floating_point_copy(
+               struct bt_field_common *src);
 
 static
-void bt_field_generic_reset(struct bt_field *);
-static
-void bt_field_structure_reset_recursive(struct bt_field *);
-static
-void bt_field_variant_reset_recursive(struct bt_field *);
-static
-void bt_field_enumeration_reset_recursive(struct bt_field *);
-static
-void bt_field_array_reset_recursive(struct bt_field *);
-static
-void bt_field_sequence_reset_recursive(struct bt_field *);
-static
-void bt_field_string_reset_recursive(struct bt_field *);
+struct bt_field_common *bt_field_structure_copy_recursive(
+               struct bt_field_common *src);
 
 static
-int bt_field_integer_serialize(struct bt_field *,
-               struct bt_stream_pos *, enum bt_byte_order);
-static
-int bt_field_enumeration_serialize_recursive(struct bt_field *,
-               struct bt_stream_pos *, enum bt_byte_order);
-static
-int bt_field_floating_point_serialize(struct bt_field *,
-               struct bt_stream_pos *, enum bt_byte_order);
-static
-int bt_field_structure_serialize_recursive(struct bt_field *,
-               struct bt_stream_pos *, enum bt_byte_order);
-static
-int bt_field_variant_serialize_recursive(struct bt_field *,
-               struct bt_stream_pos *, enum bt_byte_order);
-static
-int bt_field_array_serialize_recursive(struct bt_field *,
-               struct bt_stream_pos *, enum bt_byte_order);
-static
-int bt_field_sequence_serialize_recursive(struct bt_field *,
-               struct bt_stream_pos *, enum bt_byte_order);
-static
-int bt_field_string_serialize(struct bt_field *,
-               struct bt_stream_pos *, enum bt_byte_order);
+struct bt_field_common *bt_field_variant_copy_recursive(
+               struct bt_field_common *src);
 
 static
-int bt_field_integer_copy(struct bt_field *, struct bt_field *);
-static
-int bt_field_enumeration_copy_recursive(struct bt_field *, struct bt_field *);
-static
-int bt_field_floating_point_copy(struct bt_field *, struct bt_field *);
-static
-int bt_field_structure_copy_recursive(struct bt_field *, struct bt_field *);
-static
-int bt_field_variant_copy_recursive(struct bt_field *, struct bt_field *);
-static
-int bt_field_array_copy_recursive(struct bt_field *, struct bt_field *);
-static
-int bt_field_sequence_copy_recursive(struct bt_field *, struct bt_field *);
-static
-int bt_field_string_copy_recursive(struct bt_field *, struct bt_field *);
+struct bt_field_common *bt_field_array_copy_recursive(
+               struct bt_field_common *src);
 
 static
-void generic_field_freeze(struct bt_field *);
-static
-void bt_field_enumeration_freeze_recursive(struct bt_field *);
-static
-void bt_field_structure_freeze_recursive(struct bt_field *);
-static
-void bt_field_variant_freeze_recursive(struct bt_field *);
-static
-void bt_field_array_freeze_recursive(struct bt_field *);
-static
-void bt_field_sequence_freeze_recursive(struct bt_field *);
+struct bt_field_common *bt_field_sequence_copy_recursive(
+               struct bt_field_common *src);
 
 static
-bt_bool bt_field_generic_is_set(struct bt_field *);
-static
-bt_bool bt_field_structure_is_set_recursive(struct bt_field *);
-static
-bt_bool bt_field_variant_is_set_recursive(struct bt_field *);
-static
-bt_bool bt_field_enumeration_is_set_recursive(struct bt_field *);
-static
-bt_bool bt_field_array_is_set_recursive(struct bt_field *);
-static
-bt_bool bt_field_sequence_is_set_recursive(struct bt_field *);
+struct bt_field_common *bt_field_string_copy(struct bt_field_common *src);
 
-static
-int increase_packet_size(struct bt_stream_pos *pos);
+static struct bt_field_common_methods bt_field_integer_methods = {
+       .freeze = bt_field_common_generic_freeze,
+       .validate = bt_field_common_generic_validate,
+       .copy = bt_field_integer_copy,
+       .is_set = bt_field_common_generic_is_set,
+       .reset = bt_field_common_generic_reset,
+};
 
-static
-struct bt_field *(* const field_create_funcs[])(struct bt_field_type *) = {
-       [BT_FIELD_TYPE_ID_INTEGER] = bt_field_integer_create,
-       [BT_FIELD_TYPE_ID_ENUM] = bt_field_enumeration_create,
-       [BT_FIELD_TYPE_ID_FLOAT] = bt_field_floating_point_create,
-       [BT_FIELD_TYPE_ID_STRUCT] = bt_field_structure_create,
-       [BT_FIELD_TYPE_ID_VARIANT] = bt_field_variant_create,
-       [BT_FIELD_TYPE_ID_ARRAY] = bt_field_array_create,
-       [BT_FIELD_TYPE_ID_SEQUENCE] = bt_field_sequence_create,
-       [BT_FIELD_TYPE_ID_STRING] = bt_field_string_create,
+static struct bt_field_common_methods bt_field_floating_point_methods = {
+       .freeze = bt_field_common_generic_freeze,
+       .validate = bt_field_common_generic_validate,
+       .copy = bt_field_floating_point_copy,
+       .is_set = bt_field_common_generic_is_set,
+       .reset = bt_field_common_generic_reset,
 };
 
-static
-void (* const field_destroy_funcs[])(struct bt_field *) = {
-       [BT_FIELD_TYPE_ID_INTEGER] = bt_field_integer_destroy,
-       [BT_FIELD_TYPE_ID_ENUM] = bt_field_enumeration_destroy_recursive,
-       [BT_FIELD_TYPE_ID_FLOAT] = bt_field_floating_point_destroy,
-       [BT_FIELD_TYPE_ID_STRUCT] = bt_field_structure_destroy_recursive,
-       [BT_FIELD_TYPE_ID_VARIANT] = bt_field_variant_destroy_recursive,
-       [BT_FIELD_TYPE_ID_ARRAY] = bt_field_array_destroy_recursive,
-       [BT_FIELD_TYPE_ID_SEQUENCE] = bt_field_sequence_destroy_recursive,
-       [BT_FIELD_TYPE_ID_STRING] = bt_field_string_destroy,
+static struct bt_field_common_methods bt_field_enumeration_methods = {
+       .freeze = bt_field_common_enumeration_freeze_recursive,
+       .validate = bt_field_common_enumeration_validate_recursive,
+       .copy = bt_field_enumeration_copy_recursive,
+       .is_set = bt_field_common_enumeration_is_set_recursive,
+       .reset = bt_field_common_enumeration_reset_recursive,
 };
 
-static
-int (* const field_validate_funcs[])(struct bt_field *) = {
-       [BT_FIELD_TYPE_ID_INTEGER] = bt_field_generic_validate,
-       [BT_FIELD_TYPE_ID_ENUM] = bt_field_enumeration_validate_recursive,
-       [BT_FIELD_TYPE_ID_FLOAT] = bt_field_generic_validate,
-       [BT_FIELD_TYPE_ID_STRUCT] = bt_field_structure_validate_recursive,
-       [BT_FIELD_TYPE_ID_VARIANT] = bt_field_variant_validate_recursive,
-       [BT_FIELD_TYPE_ID_ARRAY] = bt_field_array_validate_recursive,
-       [BT_FIELD_TYPE_ID_SEQUENCE] = bt_field_sequence_validate_recursive,
-       [BT_FIELD_TYPE_ID_STRING] = bt_field_generic_validate,
+static struct bt_field_common_methods bt_field_string_methods = {
+       .freeze = bt_field_common_generic_freeze,
+       .validate = bt_field_common_generic_validate,
+       .copy = bt_field_string_copy,
+       .is_set = bt_field_common_generic_is_set,
+       .reset = bt_field_common_string_reset,
 };
 
-static
-void (* const field_reset_funcs[])(struct bt_field *) = {
-       [BT_FIELD_TYPE_ID_INTEGER] = bt_field_generic_reset,
-       [BT_FIELD_TYPE_ID_ENUM] = bt_field_enumeration_reset_recursive,
-       [BT_FIELD_TYPE_ID_FLOAT] = bt_field_generic_reset,
-       [BT_FIELD_TYPE_ID_STRUCT] = bt_field_structure_reset_recursive,
-       [BT_FIELD_TYPE_ID_VARIANT] = bt_field_variant_reset_recursive,
-       [BT_FIELD_TYPE_ID_ARRAY] = bt_field_array_reset_recursive,
-       [BT_FIELD_TYPE_ID_SEQUENCE] = bt_field_sequence_reset_recursive,
-       [BT_FIELD_TYPE_ID_STRING] = bt_field_string_reset_recursive,
+static struct bt_field_common_methods bt_field_structure_methods = {
+       .freeze = bt_field_common_structure_freeze_recursive,
+       .validate = bt_field_common_structure_validate_recursive,
+       .copy = bt_field_structure_copy_recursive,
+       .is_set = bt_field_common_structure_is_set_recursive,
+       .reset = bt_field_common_structure_reset_recursive,
 };
 
-static
-int (* const field_serialize_funcs[])(struct bt_field *,
-               struct bt_stream_pos *, enum bt_byte_order) = {
-       [BT_FIELD_TYPE_ID_INTEGER] = bt_field_integer_serialize,
-       [BT_FIELD_TYPE_ID_ENUM] = bt_field_enumeration_serialize_recursive,
-       [BT_FIELD_TYPE_ID_FLOAT] = bt_field_floating_point_serialize,
-       [BT_FIELD_TYPE_ID_STRUCT] = bt_field_structure_serialize_recursive,
-       [BT_FIELD_TYPE_ID_VARIANT] = bt_field_variant_serialize_recursive,
-       [BT_FIELD_TYPE_ID_ARRAY] = bt_field_array_serialize_recursive,
-       [BT_FIELD_TYPE_ID_SEQUENCE] = bt_field_sequence_serialize_recursive,
-       [BT_FIELD_TYPE_ID_STRING] = bt_field_string_serialize,
+static struct bt_field_common_methods bt_field_sequence_methods = {
+       .freeze = bt_field_common_sequence_freeze_recursive,
+       .validate = bt_field_common_sequence_validate_recursive,
+       .copy = bt_field_sequence_copy_recursive,
+       .is_set = bt_field_common_sequence_is_set_recursive,
+       .reset = bt_field_common_sequence_reset_recursive,
 };
 
-static
-int (* const field_copy_funcs[])(struct bt_field *,
-               struct bt_field *) = {
-       [BT_FIELD_TYPE_ID_INTEGER] = bt_field_integer_copy,
-       [BT_FIELD_TYPE_ID_ENUM] = bt_field_enumeration_copy_recursive,
-       [BT_FIELD_TYPE_ID_FLOAT] = bt_field_floating_point_copy,
-       [BT_FIELD_TYPE_ID_STRUCT] = bt_field_structure_copy_recursive,
-       [BT_FIELD_TYPE_ID_VARIANT] = bt_field_variant_copy_recursive,
-       [BT_FIELD_TYPE_ID_ARRAY] = bt_field_array_copy_recursive,
-       [BT_FIELD_TYPE_ID_SEQUENCE] = bt_field_sequence_copy_recursive,
-       [BT_FIELD_TYPE_ID_STRING] = bt_field_string_copy_recursive,
+static struct bt_field_common_methods bt_field_array_methods = {
+       .freeze = bt_field_common_array_freeze_recursive,
+       .validate = bt_field_common_array_validate_recursive,
+       .copy = bt_field_array_copy_recursive,
+       .is_set = bt_field_common_array_is_set_recursive,
+       .reset = bt_field_common_array_reset_recursive,
 };
 
-static
-void (* const field_freeze_funcs[])(struct bt_field *) = {
-       [BT_FIELD_TYPE_ID_INTEGER] = generic_field_freeze,
-       [BT_FIELD_TYPE_ID_FLOAT] = generic_field_freeze,
-       [BT_FIELD_TYPE_ID_STRING] = generic_field_freeze,
-       [BT_FIELD_TYPE_ID_ENUM] = bt_field_enumeration_freeze_recursive,
-       [BT_FIELD_TYPE_ID_STRUCT] = bt_field_structure_freeze_recursive,
-       [BT_FIELD_TYPE_ID_VARIANT] = bt_field_variant_freeze_recursive,
-       [BT_FIELD_TYPE_ID_ARRAY] = bt_field_array_freeze_recursive,
-       [BT_FIELD_TYPE_ID_SEQUENCE] = bt_field_sequence_freeze_recursive,
+static struct bt_field_common_methods bt_field_variant_methods = {
+       .freeze = bt_field_common_variant_freeze_recursive,
+       .validate = bt_field_common_variant_validate_recursive,
+       .copy = bt_field_variant_copy_recursive,
+       .is_set = bt_field_common_variant_is_set_recursive,
+       .reset = bt_field_common_variant_reset_recursive,
 };
 
 static
-bt_bool (* const field_is_set_funcs[])(struct bt_field *) = {
-       [BT_FIELD_TYPE_ID_INTEGER] = bt_field_generic_is_set,
-       [BT_FIELD_TYPE_ID_ENUM] = bt_field_enumeration_is_set_recursive,
-       [BT_FIELD_TYPE_ID_FLOAT] = bt_field_generic_is_set,
-       [BT_FIELD_TYPE_ID_STRUCT] = bt_field_structure_is_set_recursive,
-       [BT_FIELD_TYPE_ID_VARIANT] = bt_field_variant_is_set_recursive,
-       [BT_FIELD_TYPE_ID_ARRAY] = bt_field_array_is_set_recursive,
-       [BT_FIELD_TYPE_ID_SEQUENCE] = bt_field_sequence_is_set_recursive,
-       [BT_FIELD_TYPE_ID_STRING] = bt_field_generic_is_set,
-};
+struct bt_field *bt_field_integer_create(struct bt_field_type *);
 
-BT_ASSERT_FUNC
-static inline bool field_type_has_known_id(struct bt_field_type *ft)
-{
-       return ft->id > BT_FIELD_TYPE_ID_UNKNOWN ||
-               ft->id < BT_FIELD_TYPE_ID_NR;
-}
+static
+struct bt_field *bt_field_enumeration_create(struct bt_field_type *);
+
+static
+struct bt_field *bt_field_floating_point_create(struct bt_field_type *);
+
+static
+struct bt_field *bt_field_structure_create(struct bt_field_type *);
+
+static
+struct bt_field *bt_field_variant_create(struct bt_field_type *);
+
+static
+struct bt_field *bt_field_array_create(struct bt_field_type *);
 
-#define BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(_field, _type_id, _name)               \
-       BT_ASSERT_PRE((_field)->type->id == (_type_id),                 \
-               _name " has the wrong type ID: expected-type-id=%s, "   \
-               "%![field-]+f", bt_field_type_id_string(_type_id),      \
-               (_field))
+static
+struct bt_field *bt_field_sequence_create(struct bt_field_type *);
 
-#define BT_ASSERT_PRE_FIELD_IS_SET(_field, _name)                      \
-       BT_ASSERT_PRE(bt_field_is_set_recursive(_field),                \
-               _name " is not set: %!+f", (_field))
+static
+struct bt_field *bt_field_string_create(struct bt_field_type *);
 
-#define BT_ASSERT_PRE_FIELD_HOT(_field, _name)                         \
-       BT_ASSERT_PRE_HOT((_field), (_name), ": +%!+f", (_field))
+static
+struct bt_field *(* const field_create_funcs[])(struct bt_field_type *) = {
+       [BT_FIELD_TYPE_ID_INTEGER] =    bt_field_integer_create,
+       [BT_FIELD_TYPE_ID_ENUM] =       bt_field_enumeration_create,
+       [BT_FIELD_TYPE_ID_FLOAT] =      bt_field_floating_point_create,
+       [BT_FIELD_TYPE_ID_STRUCT] =     bt_field_structure_create,
+       [BT_FIELD_TYPE_ID_VARIANT] =    bt_field_variant_create,
+       [BT_FIELD_TYPE_ID_ARRAY] =      bt_field_array_create,
+       [BT_FIELD_TYPE_ID_SEQUENCE] =   bt_field_sequence_create,
+       [BT_FIELD_TYPE_ID_STRING] =     bt_field_string_create,
+};
 
 struct bt_field *bt_field_create(struct bt_field_type *type)
 {
@@ -300,51 +176,32 @@ struct bt_field *bt_field_create(struct bt_field_type *type)
        enum bt_field_type_id type_id;
 
        BT_ASSERT_PRE_NON_NULL(type, "Field type");
-       BT_ASSERT(field_type_has_known_id(type));
-       BT_ASSERT_PRE(bt_field_type_validate(type) == 0,
+       BT_ASSERT(field_type_common_has_known_id((void *) type));
+       BT_ASSERT_PRE(bt_field_type_common_validate((void *) type) == 0,
                "Field type is invalid: %!+F", type);
-
        type_id = bt_field_type_get_type_id(type);
        field = field_create_funcs[type_id](type);
        if (!field) {
-               goto error;
+               goto end;
        }
 
-       /* The type's declaration can't change after this point */
        bt_field_type_freeze(type);
-       bt_get(type);
-       bt_object_init(field, bt_field_destroy);
-       field->type = type;
-error:
-       return field;
-}
 
-/* Pre-2.0 CTF writer backward compatibility */
-void bt_ctf_field_get(struct bt_field *field)
-{
-       bt_get(field);
-}
-
-/* Pre-2.0 CTF writer backward compatibility */
-void bt_ctf_field_put(struct bt_field *field)
-{
-       bt_put(field);
+end:
+       return field;
 }
 
 struct bt_field_type *bt_field_get_type(struct bt_field *field)
 {
-       struct bt_field_type *ret = NULL;
-
-       BT_ASSERT_PRE_NON_NULL(field, "Field");
-       ret = field->type;
-       bt_get(ret);
-       return ret;
+       return (void *) bt_field_common_get_type((void *) field);
 }
 
 enum bt_field_type_id bt_field_get_type_id(struct bt_field *field)
 {
+       struct bt_field_common *field_common = (void *) field;
+
        BT_ASSERT_PRE_NON_NULL(field, "Field");
-       return bt_field_type_get_type_id(field->type);
+       return field_common->type->id;
 }
 
 bt_bool bt_field_is_integer(struct bt_field *field)
@@ -390,1107 +247,602 @@ bt_bool bt_field_is_variant(struct bt_field *field)
 BT_HIDDEN
 int64_t bt_field_sequence_get_int_length(struct bt_field *field)
 {
-       struct bt_field_sequence *sequence;
-       int64_t ret;
-
-       BT_ASSERT(field);
-       BT_ASSERT(bt_field_type_get_type_id(field->type) ==
-               BT_FIELD_TYPE_ID_SEQUENCE);
-       sequence = container_of(field, struct bt_field_sequence, parent);
-       if (!sequence->length) {
-               ret = -1;
-               goto end;
-       }
-
-       ret = (int64_t) sequence->elements->len;
-
-end:
-       return ret;
+       return bt_field_common_sequence_get_int_length((void *) field);
 }
 
-struct bt_field *bt_field_sequence_get_length(
-               struct bt_field *field)
+struct bt_field *bt_field_sequence_get_length(struct bt_field *field)
 {
-       struct bt_field *ret = NULL;
-       struct bt_field_sequence *sequence;
-
-       BT_ASSERT_PRE_NON_NULL(field, "Sequence field");
-       BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_SEQUENCE,
-               "Field");
-       sequence = container_of(field, struct bt_field_sequence, parent);
-       ret = sequence->length;
-       bt_get(ret);
-       return ret;
+       return (void *) bt_field_common_sequence_get_length((void *) field);
 }
 
 int bt_field_sequence_set_length(struct bt_field *field,
                struct bt_field *length_field)
 {
-       int ret = 0;
-       struct bt_field_integer *length;
-       struct bt_field_sequence *sequence;
-       uint64_t sequence_length;
-
-       BT_ASSERT_PRE_NON_NULL(field, "Sequence field");
-       BT_ASSERT_PRE_NON_NULL(length_field, "Length field");
-       BT_ASSERT_PRE_FIELD_HOT(field, "Sequence field");
-       BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(length_field, BT_FIELD_TYPE_ID_INTEGER,
-               "Length field");
-       BT_ASSERT_PRE(!bt_field_type_integer_is_signed(length_field->type),
-               "Length field's type is signed: %!+f", length_field);
-       BT_ASSERT_PRE_FIELD_IS_SET(length_field, "Length field");
-
-       length = container_of(length_field, struct bt_field_integer,
-               parent);
-       sequence_length = length->payload.unsignd;
-       sequence = container_of(field, struct bt_field_sequence, parent);
-       if (sequence->elements) {
-               g_ptr_array_free(sequence->elements, TRUE);
-               bt_put(sequence->length);
-       }
-
-       sequence->elements = g_ptr_array_sized_new((size_t) sequence_length);
-       if (!sequence->elements) {
-               BT_LOGE_STR("Failed to allocate a GPtrArray.");
-               ret = -1;
-               goto end;
-       }
-
-       g_ptr_array_set_free_func(sequence->elements,
-               (GDestroyNotify) bt_put);
-       g_ptr_array_set_size(sequence->elements, (size_t) sequence_length);
-       bt_get(length_field);
-       sequence->length = length_field;
-       bt_field_freeze_recursive(length_field);
-
-end:
-       return ret;
-}
-
-struct bt_field *bt_field_structure_get_field_by_name(
-               struct bt_field *field, const char *name)
-{
-       struct bt_field *ret = NULL;
-       GQuark field_quark;
-       struct bt_field_structure *structure;
-       size_t index;
-       GHashTable *field_name_to_index;
-
-       BT_ASSERT_PRE_NON_NULL(field, "Structure field");
-       BT_ASSERT_PRE_NON_NULL(name, "Field name");
-       BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_STRUCT, "Field");
-       field_name_to_index =
-               container_of(field->type, struct bt_field_type_structure,
-                       parent)->field_name_to_index;
-       field_quark = g_quark_from_string(name);
-       structure = container_of(field, struct bt_field_structure, parent);
-       if (!g_hash_table_lookup_extended(field_name_to_index,
-                       GUINT_TO_POINTER(field_quark),
-                       NULL, (gpointer *)&index)) {
-               BT_LOGV("Invalid parameter: no such field in structure field's type: "
-                       "struct-field-addr=%p, struct-ft-addr=%p, name=\"%s\"",
-                       field, field->type, name);
-               goto error;
-       }
-
-       ret = bt_get(structure->fields->pdata[index]);
-       BT_ASSERT(ret);
-
-error:
-       return ret;
+       return bt_field_common_sequence_set_length((void *) field,
+               (void *) length_field);
 }
 
 struct bt_field *bt_field_structure_get_field_by_index(
                struct bt_field *field, uint64_t index)
 {
-       struct bt_field_structure *structure;
-       struct bt_field *ret = NULL;
-
-       BT_ASSERT_PRE_NON_NULL(field, "Structure field");
-       BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_STRUCT, "Field");
-       structure = container_of(field, struct bt_field_structure, parent);
-       BT_ASSERT_PRE(index < structure->fields->len,
-               "Index is out of bound: %![struct-field-]+f, "
-               "index=%" PRIu64 ", count=%u", field, index,
-               structure->fields->len);
-       ret = bt_get(structure->fields->pdata[index]);
-       return ret;
+       return (void *) bt_field_common_structure_get_field_by_index(
+               (void *) field, index);
 }
 
-BT_ASSERT_PRE_FUNC
-static inline bool field_to_set_has_expected_type(struct bt_field *struct_field,
-               const char *name, struct bt_field *value)
+struct bt_field *bt_field_structure_get_field_by_name(
+               struct bt_field *field, const char *name)
 {
-       bool ret = true;
-       struct bt_field_type *expected_field_type = NULL;
-
-       expected_field_type =
-               bt_field_type_structure_get_field_type_by_name(
-                       struct_field->type, name);
-
-       if (bt_field_type_compare(expected_field_type, value->type)) {
-               BT_ASSERT_PRE_MSG("Value field's type is different from the expected field type: "
-                       "%![value-ft-]+F, %![expected-ft-]+F", value->type,
-                       expected_field_type);
-               ret = false;
-               goto end;
-       }
-
-end:
-       bt_put(expected_field_type);
-       return ret;
+       return (void *) bt_field_common_structure_get_field_by_name(
+               (void *) field, name);
 }
 
-int bt_field_structure_set_field_by_name(struct bt_field *field,
-               const char *name, struct bt_field *value)
+int bt_field_structure_set_field_by_name(struct bt_field_common *field,
+               const char *name, struct bt_field_common *value)
 {
-       int ret = 0;
-       GQuark field_quark;
-       struct bt_field_structure *structure;
-       size_t index;
-       GHashTable *field_name_to_index;
-
-       BT_ASSERT_PRE_NON_NULL(field, "Structure field");
-       BT_ASSERT_PRE_NON_NULL(name, "Field name");
-       BT_ASSERT_PRE_NON_NULL(value, "Value field");
-       BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_STRUCT,
-               "Parent field");
-       BT_ASSERT_PRE(field_to_set_has_expected_type(field, name, value),
-               "Value field's type is different from the expected field type.");
-       field_quark = g_quark_from_string(name);
-       structure = container_of(field, struct bt_field_structure, parent);
-       field_name_to_index =
-               container_of(field->type, struct bt_field_type_structure,
-                       parent)->field_name_to_index;
-       if (!g_hash_table_lookup_extended(field_name_to_index,
-                       GUINT_TO_POINTER(field_quark), NULL,
-                       (gpointer *) &index)) {
-               BT_LOGV("Invalid parameter: no such field in structure field's type: "
-                       "struct-field-addr=%p, struct-ft-addr=%p, "
-                       "field-ft-addr=%p, name=\"%s\"",
-                       field, field->type, value->type, name);
-               ret = -1;
-               goto end;
-       }
-       bt_get(value);
-       BT_MOVE(structure->fields->pdata[index], value);
-
-end:
-       return ret;
+       return bt_field_common_structure_set_field_by_name((void *) field,
+               name, (void *) value);
 }
 
-struct bt_field *bt_field_array_get_field(struct bt_field *field,
-               uint64_t index)
+struct bt_field *bt_field_array_get_field(
+               struct bt_field *field, uint64_t index)
 {
-       struct bt_field *new_field = NULL;
-       struct bt_field_type *field_type = NULL;
-       struct bt_field_array *array;
-
-       BT_ASSERT_PRE_NON_NULL(field, "Array field");
-       BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_ARRAY, "Field");
-       array = container_of(field, struct bt_field_array, parent);
-       BT_ASSERT_PRE(index < array->elements->len,
-               "Index is out of bound: %![array-field-]+f, "
-               "index=%" PRIu64 ", count=%u", field,
-               index, array->elements->len);
-
-       field_type = bt_field_type_array_get_element_type(field->type);
-       if (array->elements->pdata[(size_t) index]) {
-               new_field = array->elements->pdata[(size_t) index];
-               goto end;
-       }
-
-       /* We don't want to modify this field if it's frozen */
-       BT_ASSERT_PRE_FIELD_HOT(field, "Array field");
-       new_field = bt_field_create(field_type);
-       array->elements->pdata[(size_t)index] = new_field;
-
-end:
-       bt_put(field_type);
-       bt_get(new_field);
-       return new_field;
-}
-
-struct bt_field *bt_field_sequence_get_field(struct bt_field *field,
-               uint64_t index)
-{
-       struct bt_field *new_field = NULL;
-       struct bt_field_type *field_type = NULL;
-       struct bt_field_sequence *sequence;
-
-       BT_ASSERT_PRE_NON_NULL(field, "Sequence field");
-       BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_SEQUENCE,
-               "Field");
-       sequence = container_of(field, struct bt_field_sequence, parent);
-       BT_ASSERT_PRE_NON_NULL(sequence->elements, "Sequence field's element array");
-       BT_ASSERT_PRE(index < sequence->elements->len,
-               "Index is out of bound: %![seq-field-]+f, "
-               "index=%" PRIu64 ", count=%u", field, index,
-               sequence->elements->len);
-       field_type = bt_field_type_sequence_get_element_type(field->type);
-       if (sequence->elements->pdata[(size_t) index]) {
-               new_field = sequence->elements->pdata[(size_t) index];
-               goto end;
-       }
-
-       /* We don't want to modify this field if it's frozen */
-       BT_ASSERT_PRE_FIELD_HOT(field, "Sequence field");
-       new_field = bt_field_create(field_type);
-       sequence->elements->pdata[(size_t) index] = new_field;
+       return (void *) bt_field_common_array_get_field((void *) field, index,
+               (bt_field_common_create_func) bt_field_create);
+}
 
-end:
-       bt_put(field_type);
-       bt_get(new_field);
-       return new_field;
+struct bt_field *bt_field_sequence_get_field(
+               struct bt_field *field, uint64_t index)
+{
+       return (void *) bt_field_common_sequence_get_field((void *) field,
+               index, (bt_field_common_create_func) bt_field_create);
 }
 
 struct bt_field *bt_field_variant_get_field(struct bt_field *field,
                struct bt_field *tag_field)
 {
-       struct bt_field *new_field = NULL;
-       struct bt_field_variant *variant;
-       struct bt_field_type_variant *variant_type;
-       struct bt_field_type *field_type;
-       struct bt_field *tag_enum = NULL;
-       struct bt_field_integer *tag_enum_integer;
-       int64_t tag_enum_value;
-
-       BT_ASSERT_PRE_NON_NULL(field, "Variant field");
-       BT_ASSERT_PRE_NON_NULL(tag_field, "Tag field");
-       BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_VARIANT,
-               "Variant field");
-       BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(tag_field, BT_FIELD_TYPE_ID_ENUM,
-               "Tag field");
-       variant = container_of(field, struct bt_field_variant, parent);
-       variant_type = container_of(field->type,
-               struct bt_field_type_variant, parent);
-       tag_enum = bt_field_enumeration_get_container(tag_field);
-       BT_ASSERT_PRE_NON_NULL(tag_enum, "Tag field's container");
-       tag_enum_integer = container_of(tag_enum, struct bt_field_integer,
-               parent);
-       BT_ASSERT_PRE(bt_field_validate_recursive(tag_field) == 0,
-               "Tag field is invalid: %!+f", tag_field);
-       tag_enum_value = tag_enum_integer->payload.signd;
-
-       /*
-        * If the variant currently has a tag and a payload, and if the
-        * requested tag value is the same as the current one, return
-        * the current payload instead of creating a fresh one.
-        */
-       if (variant->tag && variant->payload) {
-               struct bt_field *cur_tag_container = NULL;
-               struct bt_field_integer *cur_tag_enum_integer;
-               int64_t cur_tag_value;
-
-               cur_tag_container =
-                       bt_field_enumeration_get_container(variant->tag);
-               BT_ASSERT(cur_tag_container);
-               cur_tag_enum_integer = container_of(cur_tag_container,
-                       struct bt_field_integer, parent);
-               bt_put(cur_tag_container);
-               cur_tag_value = cur_tag_enum_integer->payload.signd;
-
-               if (cur_tag_value == tag_enum_value) {
-                       new_field = variant->payload;
-                       bt_get(new_field);
-                       goto end;
-               }
-       }
-
-       /* We don't want to modify this field if it's frozen */
-       BT_ASSERT_PRE_FIELD_HOT(field, "Variant field");
-       field_type = bt_field_type_variant_get_field_type_signed(
-               variant_type, tag_enum_value);
-
-       /* It's the caller's job to make sure the tag's value is valid */
-       BT_ASSERT_PRE(field_type,
-               "Variant field's type does not contain a field type for "
-               "this tag value: tag-value-signed=%" PRId64 ", "
-               "%![var-ft-]+F, %![tag-field-]+f", tag_enum_value,
-               variant_type, tag_field);
-
-       new_field = bt_field_create(field_type);
-       if (!new_field) {
-               BT_LOGW("Cannot create field: "
-                       "variant-field-addr=%p, variant-ft-addr=%p, "
-                       "field-ft-addr=%p", field, field->type, field_type);
-               goto end;
-       }
-
-       bt_put(variant->tag);
-       bt_put(variant->payload);
-       bt_get(new_field);
-       bt_get(tag_field);
-       variant->tag = tag_field;
-       variant->payload = new_field;
-
-end:
-       bt_put(tag_enum);
-       return new_field;
+       return (void *) bt_field_common_variant_get_field((void *) field,
+               (void *) tag_field,
+               (bt_field_common_create_func) bt_field_create);
 }
 
 struct bt_field *bt_field_variant_get_current_field(
                struct bt_field *variant_field)
 {
-       struct bt_field_variant *variant;
-
-       BT_ASSERT_PRE_NON_NULL(variant_field, "Variant field");
-       BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(variant_field, BT_FIELD_TYPE_ID_VARIANT,
-               "Field");
-       variant = container_of(variant_field, struct bt_field_variant,
-               parent);
-       return bt_get(variant->payload);
+       return (void *) bt_field_common_variant_get_current_field(
+               (void *) variant_field);
 }
 
-struct bt_field *bt_field_variant_get_tag(struct bt_field *variant_field)
+struct bt_field_common *bt_field_variant_get_tag(
+               struct bt_field_common *variant_field)
 {
-       struct bt_field_variant *variant;
-
-       BT_ASSERT_PRE_NON_NULL(variant_field, "Variant field");
-       BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(variant_field, BT_FIELD_TYPE_ID_VARIANT,
-               "Field");
-       variant = container_of(variant_field, struct bt_field_variant,
-                       parent);
-       return bt_get(variant->tag);
+       return (void *) bt_field_common_variant_get_tag((void *) variant_field);
 }
 
 struct bt_field *bt_field_enumeration_get_container(struct bt_field *field)
 {
-       struct bt_field *container = NULL;
-       struct bt_field_enumeration *enumeration;
-
-       BT_ASSERT_PRE_NON_NULL(field, "Enumeration field");
-       BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_ENUM, "Field");
-       enumeration = container_of(field, struct bt_field_enumeration,
-               parent);
-       if (!enumeration->payload) {
-               struct bt_field_type_enumeration *enumeration_type;
-
-               /* We don't want to modify this field if it's frozen */
-               BT_ASSERT_PRE_FIELD_HOT(field, "Enumeration field");
-
-               enumeration_type = container_of(field->type,
-                       struct bt_field_type_enumeration, parent);
-               enumeration->payload =
-                       bt_field_create(enumeration_type->container);
-       }
-
-       container = enumeration->payload;
-       return bt_get(container);
+       return (void *) bt_field_common_enumeration_get_container(
+               (void *) field, (bt_field_common_create_func) bt_field_create);
 }
 
 struct bt_field_type_enumeration_mapping_iterator *
 bt_field_enumeration_get_mappings(struct bt_field *field)
 {
-       int ret;
-       struct bt_field *container = NULL;
-       struct bt_field_type_integer *integer_type = NULL;
-       struct bt_field_type_enumeration_mapping_iterator *iter = NULL;
-
-       BT_ASSERT_PRE_NON_NULL(field, "Enumeration field");
-       BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_ENUM, "Field");
-       container = bt_field_enumeration_get_container(field);
-       BT_ASSERT_PRE(container,
-               "Enumeration field has no container field: %!+f", field);
-       BT_ASSERT(container->type);
-       integer_type = container_of(container->type,
-               struct bt_field_type_integer, parent);
-       BT_ASSERT_PRE_FIELD_IS_SET(container,
-               "Enumeration field's payload field");
-
-       if (!integer_type->is_signed) {
-               uint64_t value;
-
-               ret = bt_field_unsigned_integer_get_value(container, &value);
-               BT_ASSERT(ret == 0);
-               iter = bt_field_type_enumeration_find_mappings_by_unsigned_value(
-                               field->type, value);
-       } else {
-               int64_t value;
-
-               ret = bt_field_signed_integer_get_value(container, &value);
-               BT_ASSERT(ret == 0);
-               iter = bt_field_type_enumeration_find_mappings_by_signed_value(
-                               field->type, value);
-       }
-
-       bt_put(container);
-       return iter;
+       return bt_field_common_enumeration_get_mappings((void *) field,
+               (bt_field_common_create_func) bt_field_create);
 }
 
-int bt_field_signed_integer_get_value(struct bt_field *field, int64_t *value)
+int bt_field_integer_signed_get_value(struct bt_field *field, int64_t *value)
 {
-       struct bt_field_integer *integer;
-       struct bt_field_type_integer *integer_type;
-
-       BT_ASSERT_PRE_NON_NULL(field, "Integer field");
-       BT_ASSERT_PRE_NON_NULL(value, "Value");
-       BT_ASSERT_PRE_FIELD_IS_SET(field, "Integer field");
-       BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_INTEGER, "Field");
-       integer_type = container_of(field->type,
-               struct bt_field_type_integer, parent);
-       BT_ASSERT_PRE(bt_field_type_integer_is_signed(field->type),
-               "Field's type is unsigned: %!+f", field);
-       integer = container_of(field,
-               struct bt_field_integer, parent);
-       *value = integer->payload.signd;
-       return 0;
+       return bt_field_common_integer_signed_get_value((void *) field, value);
 }
 
-BT_ASSERT_PRE_FUNC
-static inline bool value_is_in_range_signed(unsigned int size, int64_t value)
+int bt_field_integer_signed_set_value(struct bt_field *field,
+               int64_t value)
 {
-       bool ret = true;
-       int64_t min_value, max_value;
-
-       min_value = -(1ULL << (size - 1));
-       max_value = (1ULL << (size - 1)) - 1;
-       if (value < min_value || value > max_value) {
-               BT_LOGF("Value is out of bounds: value=%" PRId64 ", "
-                       "min-value=%" PRId64 ", max-value=%" PRId64,
-                       value, min_value, max_value);
-               ret = false;
-       }
-
-       return ret;
+       return bt_field_common_integer_signed_set_value((void *) field, value);
 }
 
-int bt_field_signed_integer_set_value(struct bt_field *field, int64_t value)
+int bt_field_integer_unsigned_get_value(struct bt_field *field,
+               uint64_t *value)
 {
-       int ret = 0;
-       struct bt_field_integer *integer;
-       struct bt_field_type_integer *integer_type;
-
-       BT_ASSERT_PRE_NON_NULL(field, "Integer field");
-       BT_ASSERT_PRE_FIELD_HOT(field, "Integer field");
-       BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_INTEGER, "Field");
-       integer = container_of(field, struct bt_field_integer, parent);
-       integer_type = container_of(field->type,
-               struct bt_field_type_integer, parent);
-       BT_ASSERT_PRE(bt_field_type_integer_is_signed(field->type),
-               "Field's type is unsigned: %!+f", field);
-       BT_ASSERT_PRE(value_is_in_range_signed(integer_type->size, value),
-               "Value is out of bounds: value=%" PRId64 ", %![field-]+f",
-               value, field);
-       integer->payload.signd = value;
-       bt_field_set(field, true);
-       return ret;
+       return bt_field_common_integer_unsigned_get_value((void *) field,
+               value);
 }
 
-int bt_field_unsigned_integer_get_value(struct bt_field *field, uint64_t *value)
+int bt_field_integer_unsigned_set_value(struct bt_field *field, uint64_t value)
 {
-       struct bt_field_integer *integer;
-       struct bt_field_type_integer *integer_type;
-
-       BT_ASSERT_PRE_NON_NULL(field, "Integer field");
-       BT_ASSERT_PRE_NON_NULL(value, "Value");
-       BT_ASSERT_PRE_FIELD_IS_SET(field, "Integer field");
-       BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_INTEGER, "Field");
-       integer_type = container_of(field->type,
-               struct bt_field_type_integer, parent);
-       BT_ASSERT_PRE(!bt_field_type_integer_is_signed(field->type),
-               "Field's type is signed: %!+f", field);
-       integer = container_of(field, struct bt_field_integer, parent);
-       *value = integer->payload.unsignd;
-       return 0;
+       return bt_field_common_integer_unsigned_set_value((void *) field, value);
 }
 
-BT_ASSERT_PRE_FUNC
-static inline bool value_is_in_range_unsigned(unsigned int size, uint64_t value)
+int bt_field_floating_point_get_value(struct bt_field *field,
+               double *value)
 {
-       bool ret = true;
-       int64_t max_value;
-
-       max_value = (size == 64) ? UINT64_MAX : ((uint64_t) 1 << size) - 1;
-       if (value > max_value) {
-               BT_LOGF("Value is out of bounds: value=%" PRIu64 ", "
-                       "max-value=%" PRIu64,
-                       value, max_value);
-               ret = false;
-       }
-
-       return ret;
+       return bt_field_common_floating_point_get_value((void *) field, value);
 }
 
-int bt_field_unsigned_integer_set_value(struct bt_field *field, uint64_t value)
+int bt_field_floating_point_set_value(struct bt_field *field,
+               double value)
 {
-       struct bt_field_integer *integer;
-       struct bt_field_type_integer *integer_type;
-
-       BT_ASSERT_PRE_NON_NULL(field, "Integer field");
-       BT_ASSERT_PRE_FIELD_HOT(field, "Integer field");
-       BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_INTEGER, "Field");
-       integer = container_of(field, struct bt_field_integer, parent);
-       integer_type = container_of(field->type,
-               struct bt_field_type_integer, parent);
-       BT_ASSERT_PRE(!bt_field_type_integer_is_signed(field->type),
-               "Field's type is signed: %!+f", field);
-       BT_ASSERT_PRE(value_is_in_range_unsigned(integer_type->size, value),
-               "Value is out of bounds: value=%" PRIu64 ", %![field-]+f",
-               value, field);
-       integer->payload.unsignd = value;
-       bt_field_set(field, true);
-       return 0;
+       return bt_field_common_floating_point_set_value((void *) field, value);
 }
 
-int bt_field_floating_point_get_value(struct bt_field *field, double *value)
+const char *bt_field_string_get_value(struct bt_field *field)
 {
-       struct bt_field_floating_point *floating_point;
-
-       BT_ASSERT_PRE_NON_NULL(field, "Floating point number field");
-       BT_ASSERT_PRE_NON_NULL(value, "Value");
-       BT_ASSERT_PRE_FIELD_IS_SET(field, "Floating point number field");
-       BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_FLOAT, "Field");
-       floating_point = container_of(field,
-               struct bt_field_floating_point, parent);
-       *value = floating_point->payload;
-       return 0;
+       return bt_field_common_string_get_value((void *) field);
 }
 
-int bt_field_floating_point_set_value(struct bt_field *field, double value)
+int bt_field_string_set_value(struct bt_field *field, const char *value)
 {
-       struct bt_field_floating_point *floating_point;
-
-       BT_ASSERT_PRE_NON_NULL(field, "Floating point number field");
-       BT_ASSERT_PRE_FIELD_HOT(field, "Floating point number field");
-       BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_FLOAT, "Field");
-       floating_point = container_of(field, struct bt_field_floating_point,
-               parent);
-       floating_point->payload = value;
-       bt_field_set(field, true);
-       return 0;
+       return bt_field_common_string_set_value((void *) field, value);
 }
 
-const char *bt_field_string_get_value(struct bt_field *field)
+int bt_field_string_append(struct bt_field *field, const char *value)
 {
-       struct bt_field_string *string;
-
-       BT_ASSERT_PRE_NON_NULL(field, "String field");
-       BT_ASSERT_PRE_FIELD_IS_SET(field, "String field");
-       BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_STRING, "Field");
-       string = container_of(field, struct bt_field_string, parent);
-       return string->payload->str;
+       return bt_field_common_string_append((void *) field, value);
 }
 
-int bt_field_string_set_value(struct bt_field *field, const char *value)
+int bt_field_string_append_len(struct bt_field *field,
+               const char *value, unsigned int length)
 {
-       struct bt_field_string *string;
-
-       BT_ASSERT_PRE_NON_NULL(field, "String field");
-       BT_ASSERT_PRE_NON_NULL(value, "Value");
-       BT_ASSERT_PRE_FIELD_HOT(field, "String field");
-       BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_STRING, "Field");
-       string = container_of(field, struct bt_field_string, parent);
-       if (string->payload) {
-               g_string_assign(string->payload, value);
-       } else {
-               string->payload = g_string_new(value);
-       }
-
-       bt_field_set(field, true);
-       return 0;
+       return bt_field_common_string_append_len((void *) field, value, length);
 }
 
-int bt_field_string_append(struct bt_field *field, const char *value)
+BT_HIDDEN
+struct bt_field_common *bt_field_common_copy(struct bt_field_common *field)
 {
-       struct bt_field_string *string_field;
+       struct bt_field_common *copy = NULL;
 
-       BT_ASSERT_PRE_NON_NULL(field, "String field");
-       BT_ASSERT_PRE_NON_NULL(value, "Value");
-       BT_ASSERT_PRE_FIELD_HOT(field, "String field");
-       BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_STRING, "Field");
-       string_field = container_of(field, struct bt_field_string, parent);
-       if (string_field->payload) {
-               g_string_append(string_field->payload, value);
-       } else {
-               string_field->payload = g_string_new(value);
+       BT_ASSERT_PRE_NON_NULL(field, "Field");
+       BT_ASSERT(field_type_common_has_known_id(field->type));
+       BT_ASSERT(field->methods->copy);
+       copy = field->methods->copy(field);
+       if (!copy) {
+               BT_LOGW("Cannot create field: ft-addr=%p", field->type);
+               goto end;
        }
 
-       bt_field_set(field, true);
-       return 0;
+       bt_field_common_set(copy, field->payload_set);
+
+end:
+       return copy;
 }
 
-int bt_field_string_append_len(struct bt_field *field, const char *value,
-               unsigned int length)
+struct bt_field *bt_field_copy(struct bt_field *field)
 {
-       struct bt_field_string *string_field;
-
-       BT_ASSERT_PRE_NON_NULL(field, "String field");
-       BT_ASSERT_PRE_NON_NULL(value, "Value");
-       BT_ASSERT_PRE_FIELD_HOT(field, "String field");
-       BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_STRING, "Field");
-       string_field = container_of(field, struct bt_field_string, parent);
+       return (void *) bt_field_common_copy((void *) field);
+}
 
-       /* make sure no null bytes are appended */
-       BT_ASSERT_PRE(memchr(value, '\0', length) == NULL,
-               "String value to append contains a null character: "
-               "partial-value=\"%.32s\", length=%u", value, length);
+static void bt_field_common_finalize(struct bt_field_common *field)
+{
+       BT_ASSERT(field);
+       BT_LOGD_STR("Putting field's type.");
+       bt_put(field->type);
+}
 
-       if (string_field->payload) {
-               g_string_append_len(string_field->payload, value, length);
-       } else {
-               string_field->payload = g_string_new_len(value, length);
-       }
+BT_HIDDEN
+void bt_field_common_integer_destroy(struct bt_object *obj)
+{
+       struct bt_field_common_integer *integer = (void *) obj;
 
-       bt_field_set(field, true);
-       return 0;
+       BT_ASSERT(obj);
+       bt_field_common_finalize(BT_TO_COMMON(integer));
+       BT_LOGD("Destroying integer field object: addr=%p", obj);
+       g_free(obj);
 }
 
 BT_HIDDEN
-int _bt_field_validate_recursive(struct bt_field *field)
+void bt_field_common_enumeration_destroy_recursive(struct bt_object *obj)
 {
-       int ret = 0;
-       enum bt_field_type_id type_id;
+       struct bt_field_common_enumeration *enumeration = (void *) obj;
 
-       if (!field) {
-               BT_ASSERT_PRE_MSG("%s", "Invalid field: field is NULL.");
-               ret = -1;
-               goto end;
-       }
+       BT_ASSERT(enumeration);
+       bt_field_common_finalize(BT_TO_COMMON(enumeration));
+       BT_LOGD("Destroying enumeration field object: addr=%p", obj);
+       BT_LOGD_STR("Putting payload field.");
+       bt_put(enumeration->payload);
+       g_free(enumeration);
+}
 
-       BT_ASSERT(field_type_has_known_id(field->type));
-       type_id = bt_field_type_get_type_id(field->type);
-       ret = field_validate_funcs[type_id](field);
+BT_HIDDEN
+void bt_field_common_floating_point_destroy(struct bt_object *obj)
+{
+       struct bt_field_common_floating_point *floating_point = (void *) obj;
 
-end:
-       return ret;
+       BT_ASSERT(obj);
+       bt_field_common_finalize(BT_TO_COMMON(floating_point));
+       BT_LOGD("Destroying floating point number field object: addr=%p", obj);
+       g_free(obj);
 }
 
 BT_HIDDEN
-void _bt_field_reset_recursive(struct bt_field *field)
-{      BT_ASSERT(field);
-       field_reset_funcs[field->type->id](field);
+void bt_field_common_structure_destroy_recursive(struct bt_object *obj)
+{
+       struct bt_field_common_structure *structure = (void *) obj;
+
+       BT_ASSERT(obj);
+       bt_field_common_finalize(BT_TO_COMMON(structure));
+       BT_LOGD("Destroying structure field object: addr=%p", obj);
+       g_ptr_array_free(structure->fields, TRUE);
+       g_free(structure);
 }
 
 BT_HIDDEN
-void _bt_field_set(struct bt_field *field, bool value)
+void bt_field_common_variant_destroy_recursive(struct bt_object *obj)
 {
-       BT_ASSERT(field);
-       field->payload_set = value;
+       struct bt_field_common_variant *variant = (void *) obj;
+
+       BT_ASSERT(obj);
+       bt_field_common_finalize(BT_TO_COMMON(variant));
+       BT_LOGD("Destroying variant field object: addr=%p", obj);
+       BT_LOGD_STR("Putting tag field.");
+       bt_put(variant->tag);
+       BT_LOGD_STR("Putting payload field.");
+       bt_put(variant->payload);
+       g_free(variant);
 }
 
 BT_HIDDEN
-int bt_field_serialize_recursive(struct bt_field *field, struct bt_stream_pos *pos,
-               enum bt_byte_order native_byte_order)
+void bt_field_common_array_destroy_recursive(struct bt_object *obj)
 {
-       enum bt_field_type_id type_id;
+       struct bt_field_common_array *array = (void *) obj;
 
-       BT_ASSERT(pos);
-       BT_ASSERT_PRE_NON_NULL(field, "Field");
-       BT_ASSERT(field_type_has_known_id(field->type));
-       type_id = bt_field_type_get_type_id(field->type);
-       return field_serialize_funcs[type_id](field, pos, native_byte_order);
+       BT_ASSERT(obj);
+       bt_field_common_finalize(BT_TO_COMMON(array));
+       BT_LOGD("Destroying array field object: addr=%p", obj);
+       g_ptr_array_free(array->elements, TRUE);
+       g_free(array);
 }
 
 BT_HIDDEN
-bt_bool _bt_field_is_set_recursive(struct bt_field *field)
+void bt_field_common_sequence_destroy_recursive(struct bt_object *obj)
 {
-       bt_bool is_set = BT_FALSE;
-       enum bt_field_type_id type_id;
+       struct bt_field_common_sequence *sequence = (void *) obj;
 
-       if (!field) {
-               goto end;
-       }
+       BT_ASSERT(obj);
+       bt_field_common_finalize(BT_TO_COMMON(sequence));
+       BT_LOGD("Destroying sequence field object: addr=%p", obj);
 
-       BT_ASSERT(field_type_has_known_id(field->type));
-       type_id = bt_field_type_get_type_id(field->type);
-       is_set = field_is_set_funcs[type_id](field);
+       if (sequence->elements) {
+               g_ptr_array_free(sequence->elements, TRUE);
+       }
 
-end:
-       return is_set;
+       BT_LOGD_STR("Putting length field.");
+       bt_put(sequence->length);
+       g_free(sequence);
 }
 
-struct bt_field *bt_field_copy(struct bt_field *field)
+BT_HIDDEN
+void bt_field_common_string_destroy(struct bt_object *obj)
 {
-       int ret;
-       struct bt_field *copy = NULL;
-       enum bt_field_type_id type_id;
+       struct bt_field_common_string *string = (void *) obj;
 
-       BT_ASSERT_PRE_NON_NULL(field, "Field");
-       BT_ASSERT(field_type_has_known_id(field->type));
-       copy = bt_field_create(field->type);
-       if (!copy) {
-               BT_LOGW("Cannot create field: ft-addr=%p", field->type);
-               goto end;
-       }
+       BT_ASSERT(obj);
+       bt_field_common_finalize(BT_TO_COMMON(string));
+       BT_LOGD("Destroying string field object: addr=%p", obj);
 
-       bt_field_set(copy, field->payload_set);
-       type_id = bt_field_type_get_type_id(field->type);
-       ret = field_copy_funcs[type_id](field, copy);
-       if (ret) {
-               BT_PUT(copy);
+       if (string->payload) {
+               g_string_free(string->payload, TRUE);
        }
 
-end:
-       return copy;
+       g_free(string);
 }
 
 static
 struct bt_field *bt_field_integer_create(struct bt_field_type *type)
 {
-       struct bt_field_integer *integer = g_new0(
-               struct bt_field_integer, 1);
+       struct bt_field_common_integer *integer =
+               g_new0(struct bt_field_common_integer, 1);
 
        BT_LOGD("Creating integer field object: ft-addr=%p", type);
 
        if (integer) {
+               bt_field_common_initialize(BT_TO_COMMON(integer), (void *) type,
+                       bt_field_common_integer_destroy,
+                       &bt_field_integer_methods);
                BT_LOGD("Created integer field object: addr=%p, ft-addr=%p",
-                       &integer->parent, type);
+                       integer, type);
        } else {
                BT_LOGE_STR("Failed to allocate one integer field.");
        }
 
-       return integer ? &integer->parent : NULL;
+       return (void *) integer;
 }
 
 static
-struct bt_field *bt_field_enumeration_create(
-       struct bt_field_type *type)
+struct bt_field *bt_field_enumeration_create(struct bt_field_type *type)
 {
-       struct bt_field_enumeration *enumeration = g_new0(
-               struct bt_field_enumeration, 1);
+       struct bt_field_common_enumeration *enumeration = g_new0(
+               struct bt_field_common_enumeration, 1);
 
        BT_LOGD("Creating enumeration field object: ft-addr=%p", type);
 
        if (enumeration) {
+               bt_field_common_initialize(BT_TO_COMMON(enumeration),
+                       (void *) type,
+                       bt_field_common_enumeration_destroy_recursive,
+                       &bt_field_enumeration_methods);
                BT_LOGD("Created enumeration field object: addr=%p, ft-addr=%p",
-                       &enumeration->parent, type);
+                       enumeration, type);
        } else {
                BT_LOGE_STR("Failed to allocate one enumeration field.");
        }
 
-       return enumeration ? &enumeration->parent : NULL;
+       return (void *) enumeration;
 }
 
 static
-struct bt_field *bt_field_floating_point_create(
-       struct bt_field_type *type)
+struct bt_field *bt_field_floating_point_create(struct bt_field_type *type)
 {
-       struct bt_field_floating_point *floating_point;
+       struct bt_field_common_floating_point *floating_point;
 
        BT_LOGD("Creating floating point number field object: ft-addr=%p", type);
-       floating_point = g_new0(struct bt_field_floating_point, 1);
+       floating_point = g_new0(struct bt_field_common_floating_point, 1);
 
        if (floating_point) {
+               bt_field_common_initialize(BT_TO_COMMON(floating_point),
+                       (void *) type,
+                       bt_field_common_floating_point_destroy,
+                       &bt_field_floating_point_methods);
                BT_LOGD("Created floating point number field object: addr=%p, ft-addr=%p",
-                       &floating_point->parent, type);
+                       floating_point, type);
        } else {
                BT_LOGE_STR("Failed to allocate one floating point number field.");
        }
 
-       return floating_point ? &floating_point->parent : NULL;
+       return (void *) floating_point;
 }
 
-static
-struct bt_field *bt_field_structure_create(
-       struct bt_field_type *type)
-{
-       struct bt_field_type_structure *structure_type = container_of(type,
-               struct bt_field_type_structure, parent);
-       struct bt_field_structure *structure = g_new0(
-               struct bt_field_structure, 1);
-       struct bt_field *ret = NULL;
+BT_HIDDEN
+int bt_field_common_structure_initialize(struct bt_field_common *field,
+               struct bt_field_type_common *type,
+               bt_object_release_func release_func,
+               struct bt_field_common_methods *methods,
+               bt_field_common_create_func field_create_func)
+{
+       int ret = 0;
+       struct bt_field_type_common_structure *structure_type =
+               BT_FROM_COMMON(type);
+       struct bt_field_common_structure *structure = BT_FROM_COMMON(field);
        size_t i;
 
-       BT_LOGD("Creating structure field object: ft-addr=%p", type);
-
-       if (!structure) {
-               BT_LOGE_STR("Failed to allocate one structure field.");
-               goto end;
-       }
-
+       BT_LOGD("Initializing common structure field object: ft-addr=%p", type);
+       bt_field_common_initialize(field, type, release_func, methods);
        structure->fields = g_ptr_array_new_with_free_func(
                (GDestroyNotify) bt_put);
-       g_ptr_array_set_size(structure->fields,
-               structure_type->fields->len);
+       g_ptr_array_set_size(structure->fields, structure_type->fields->len);
 
        /* Create all fields contained by the structure field. */
        for (i = 0; i < structure_type->fields->len; i++) {
-               struct bt_field *field;
-               struct structure_field *field_type =
+               struct bt_field_common *field;
+               struct structure_field_common *struct_field =
                        g_ptr_array_index(structure_type->fields, i);
 
-               field = bt_field_create(field_type->type);
+               field = field_create_func(struct_field->type);
                if (!field) {
                        BT_LOGE("Failed to create structure field's member: name=\"%s\", index=%zu",
-                               g_quark_to_string(field_type->name), i);
-                       bt_field_structure_destroy_recursive(&structure->parent);
+                               g_quark_to_string(struct_field->name), i);
+                       ret = -1;
                        goto end;
                }
 
                g_ptr_array_index(structure->fields, i) = field;
        }
 
-       ret = &structure->parent;
-       BT_LOGD("Created structure field object: addr=%p, ft-addr=%p", ret,
-               type);
+       BT_LOGD("Initialized common structure field object: addr=%p, ft-addr=%p",
+               field, type);
+
 end:
        return ret;
 }
 
+static
+struct bt_field *bt_field_structure_create(struct bt_field_type *type)
+{
+       struct bt_field_common_structure *structure = g_new0(
+               struct bt_field_common_structure, 1);
+       int iret;
+
+       BT_LOGD("Creating structure field object: ft-addr=%p", type);
+
+       if (!structure) {
+               BT_LOGE_STR("Failed to allocate one structure field.");
+               goto end;
+       }
+
+       iret = bt_field_common_structure_initialize(BT_TO_COMMON(structure),
+               (void *) type, bt_field_common_structure_destroy_recursive,
+               &bt_field_structure_methods,
+               (bt_field_common_create_func) bt_field_create);
+       if (iret) {
+               BT_PUT(structure);
+               goto end;
+       }
+
+       BT_LOGD("Created structure field object: addr=%p, ft-addr=%p",
+               structure, type);
+
+end:
+       return (void *) structure;
+}
+
 static
 struct bt_field *bt_field_variant_create(struct bt_field_type *type)
 {
-       struct bt_field_variant *variant = g_new0(
-               struct bt_field_variant, 1);
+       struct bt_field_common_variant *variant = g_new0(
+               struct bt_field_common_variant, 1);
 
        BT_LOGD("Creating variant field object: ft-addr=%p", type);
 
        if (variant) {
+               bt_field_common_initialize(BT_TO_COMMON(variant),
+                       (void *) type,
+                       bt_field_common_variant_destroy_recursive,
+                       &bt_field_variant_methods);
                BT_LOGD("Created variant field object: addr=%p, ft-addr=%p",
-                       &variant->parent, type);
+                       variant, type);
        } else {
                BT_LOGE_STR("Failed to allocate one variant field.");
        }
 
-       return variant ? &variant->parent : NULL;
+       return (void *) variant;
 }
 
-static
-struct bt_field *bt_field_array_create(struct bt_field_type *type)
+BT_HIDDEN
+int bt_field_common_array_initialize(struct bt_field_common *field,
+               struct bt_field_type_common *type,
+               bt_object_release_func release_func,
+               struct bt_field_common_methods *methods)
 {
-       struct bt_field_array *array = g_new0(struct bt_field_array, 1);
-       struct bt_field_type_array *array_type;
+       struct bt_field_type_common_array *array_type = BT_FROM_COMMON(type);
+       struct bt_field_common_array *array = BT_FROM_COMMON(field);
        unsigned int array_length;
+       int ret = 0;
 
-       BT_LOGD("Creating array field object: ft-addr=%p", type);
+       BT_LOGD("Initializing common array field object: ft-addr=%p", type);
        BT_ASSERT(type);
-
-       if (!array) {
-               BT_LOGE_STR("Failed to allocate one array field.");
-               goto error;
-       }
-
-       array_type = container_of(type, struct bt_field_type_array, parent);
+       bt_field_common_initialize(field, type, release_func, methods);
        array_length = array_type->length;
        array->elements = g_ptr_array_sized_new(array_length);
        if (!array->elements) {
-               goto error;
+               ret = -1;
+               goto end;
        }
 
-       g_ptr_array_set_free_func(array->elements,
-               (GDestroyNotify) bt_put);
+       g_ptr_array_set_free_func(array->elements, (GDestroyNotify) bt_put);
        g_ptr_array_set_size(array->elements, array_length);
-       BT_LOGD("Created array field object: addr=%p, ft-addr=%p",
-               &array->parent, type);
-       return &array->parent;
-error:
-       g_free(array);
-       return NULL;
-}
+       BT_LOGD("Initialized common array field object: addr=%p, ft-addr=%p",
+               field, type);
 
-static
-struct bt_field *bt_field_sequence_create(
-       struct bt_field_type *type)
-{
-       struct bt_field_sequence *sequence = g_new0(
-               struct bt_field_sequence, 1);
-
-       BT_LOGD("Creating sequence field object: ft-addr=%p", type);
-
-       if (sequence) {
-               BT_LOGD("Created sequence field object: addr=%p, ft-addr=%p",
-                       &sequence->parent, type);
-       } else {
-               BT_LOGE_STR("Failed to allocate one sequence field.");
-       }
-
-       return sequence ? &sequence->parent : NULL;
+end:
+       return ret;
 }
 
 static
-struct bt_field *bt_field_string_create(struct bt_field_type *type)
+struct bt_field *bt_field_array_create(struct bt_field_type *type)
 {
-       struct bt_field_string *string = g_new0(
-               struct bt_field_string, 1);
+       struct bt_field_common_array *array =
+               g_new0(struct bt_field_common_array, 1);
+       int ret;
 
-       BT_LOGD("Creating string field object: ft-addr=%p", type);
+       BT_LOGD("Creating array field object: ft-addr=%p", type);
+       BT_ASSERT(type);
 
-       if (string) {
-               BT_LOGD("Created string field object: addr=%p, ft-addr=%p",
-                       &string->parent, type);
-       } else {
-               BT_LOGE_STR("Failed to allocate one string field.");
+       if (!array) {
+               BT_LOGE_STR("Failed to allocate one array field.");
+               goto end;
        }
 
-       return string ? &string->parent : NULL;
-}
-
-static
-void bt_field_destroy(struct bt_object *obj)
-{
-       struct bt_field *field;
-       struct bt_field_type *type;
-       enum bt_field_type_id type_id;
-
-       BT_ASSERT(obj);
-       field = container_of(obj, struct bt_field, base);
-       type = field->type;
-       BT_ASSERT(field_type_has_known_id(type));
-       type_id = bt_field_type_get_type_id(type);
-       field_destroy_funcs[type_id](field);
-       BT_LOGD_STR("Putting field's type.");
-       bt_put(type);
-}
-
-static
-void bt_field_integer_destroy(struct bt_field *field)
-{
-       struct bt_field_integer *integer;
-
-       BT_ASSERT(field);
-       BT_LOGD("Destroying integer field object: addr=%p", field);
-       integer = container_of(field, struct bt_field_integer, parent);
-       g_free(integer);
-}
-
-static
-void bt_field_enumeration_destroy_recursive(struct bt_field *field)
-{
-       struct bt_field_enumeration *enumeration;
-
-       BT_ASSERT(field);
-       BT_LOGD("Destroying enumeration field object: addr=%p", field);
-       enumeration = container_of(field, struct bt_field_enumeration,
-               parent);
-       BT_LOGD_STR("Putting payload field.");
-       bt_put(enumeration->payload);
-       g_free(enumeration);
-}
-
-static
-void bt_field_floating_point_destroy(struct bt_field *field)
-{
-       struct bt_field_floating_point *floating_point;
-
-       BT_ASSERT(field);
-       BT_LOGD("Destroying floating point number field object: addr=%p", field);
-       floating_point = container_of(field, struct bt_field_floating_point,
-               parent);
-       g_free(floating_point);
-}
-
-static
-void bt_field_structure_destroy_recursive(struct bt_field *field)
-{
-       struct bt_field_structure *structure;
-
-       BT_ASSERT(field);
-       BT_LOGD("Destroying structure field object: addr=%p", field);
-       structure = container_of(field, struct bt_field_structure, parent);
-       g_ptr_array_free(structure->fields, TRUE);
-       g_free(structure);
-}
+       ret = bt_field_common_array_initialize(BT_TO_COMMON(array),
+               (void *) type,
+               bt_field_common_array_destroy_recursive,
+               &bt_field_array_methods);
+       if (ret) {
+               BT_PUT(array);
+               goto end;
+       }
 
-static
-void bt_field_variant_destroy_recursive(struct bt_field *field)
-{
-       struct bt_field_variant *variant;
+       BT_LOGD("Created array field object: addr=%p, ft-addr=%p",
+               array, type);
 
-       BT_ASSERT(field);
-       BT_LOGD("Destroying variant field object: addr=%p", field);
-       variant = container_of(field, struct bt_field_variant, parent);
-       BT_LOGD_STR("Putting tag field.");
-       bt_put(variant->tag);
-       BT_LOGD_STR("Putting payload field.");
-       bt_put(variant->payload);
-       g_free(variant);
+end:
+       return (void *) array;
 }
 
 static
-void bt_field_array_destroy_recursive(struct bt_field *field)
+struct bt_field *bt_field_sequence_create(struct bt_field_type *type)
 {
-       struct bt_field_array *array;
+       struct bt_field_common_sequence *sequence = g_new0(
+               struct bt_field_common_sequence, 1);
 
-       BT_ASSERT(field);
-       BT_LOGD("Destroying array field object: addr=%p", field);
-       array = container_of(field, struct bt_field_array, parent);
-       g_ptr_array_free(array->elements, TRUE);
-       g_free(array);
-}
-
-static
-void bt_field_sequence_destroy_recursive(struct bt_field *field)
-{
-       struct bt_field_sequence *sequence;
+       BT_LOGD("Creating sequence field object: ft-addr=%p", type);
 
-       BT_ASSERT(field);
-       BT_LOGD("Destroying sequence field object: addr=%p", field);
-       sequence = container_of(field, struct bt_field_sequence, parent);
-       if (sequence->elements) {
-               g_ptr_array_free(sequence->elements, TRUE);
+       if (sequence) {
+               bt_field_common_initialize(BT_TO_COMMON(sequence),
+                       (void *) type,
+                       bt_field_common_sequence_destroy_recursive,
+                       &bt_field_sequence_methods);
+               BT_LOGD("Created sequence field object: addr=%p, ft-addr=%p",
+                       sequence, type);
+       } else {
+               BT_LOGE_STR("Failed to allocate one sequence field.");
        }
-       BT_LOGD_STR("Putting length field.");
-       bt_put(sequence->length);
-       g_free(sequence);
+
+       return (void *) sequence;
 }
 
 static
-void bt_field_string_destroy(struct bt_field *field)
+struct bt_field *bt_field_string_create(struct bt_field_type *type)
 {
-       struct bt_field_string *string;
+       struct bt_field_common_string *string = g_new0(
+               struct bt_field_common_string, 1);
 
-       BT_ASSERT(field);
-       BT_LOGD("Destroying string field object: addr=%p", field);
-       string = container_of(field, struct bt_field_string, parent);
-       if (string->payload) {
-               g_string_free(string->payload, TRUE);
+       BT_LOGD("Creating string field object: ft-addr=%p", type);
+
+       if (string) {
+               bt_field_common_initialize(BT_TO_COMMON(string),
+                       (void *) type,
+                       bt_field_common_string_destroy,
+                       &bt_field_string_methods);
+               BT_LOGD("Created string field object: addr=%p, ft-addr=%p",
+                       string, type);
+       } else {
+               BT_LOGE_STR("Failed to allocate one string field.");
        }
-       g_free(string);
+
+       return (void *) string;
 }
 
-static
-int bt_field_generic_validate(struct bt_field *field)
+BT_HIDDEN
+int bt_field_common_generic_validate(struct bt_field_common *field)
 {
        return (field && field->payload_set) ? 0 : -1;
 }
 
-static
-int bt_field_enumeration_validate_recursive(struct bt_field *field)
+BT_HIDDEN
+int bt_field_common_enumeration_validate_recursive(
+               struct bt_field_common *field)
 {
        int ret;
-       struct bt_field_enumeration *enumeration;
+       struct bt_field_common_enumeration *enumeration = BT_FROM_COMMON(field);
 
        BT_ASSERT(field);
-       enumeration = container_of(field, struct bt_field_enumeration,
-               parent);
+
        if (!enumeration->payload) {
                BT_ASSERT_PRE_MSG("Invalid enumeration field: payload is not set: "
-                       "%!+f", field);
+                       "%!+_f", field);
                ret = -1;
                goto end;
        }
 
-       ret = bt_field_validate_recursive(enumeration->payload);
+       ret = bt_field_common_validate_recursive(enumeration->payload);
 
 end:
        return ret;
 }
 
-static
-int bt_field_structure_validate_recursive(struct bt_field *field)
+BT_HIDDEN
+int bt_field_common_structure_validate_recursive(struct bt_field_common *field)
 {
        int64_t i;
        int ret = 0;
-       struct bt_field_structure *structure;
+       struct bt_field_common_structure *structure = BT_FROM_COMMON(field);
 
        BT_ASSERT(field);
-       structure = container_of(field, struct bt_field_structure, parent);
 
        for (i = 0; i < structure->fields->len; i++) {
-               ret = bt_field_validate_recursive(
+               ret = bt_field_common_validate_recursive(
                        (void *) structure->fields->pdata[i]);
 
                if (ret) {
                        int this_ret;
                        const char *name;
 
-                       this_ret = bt_field_type_structure_get_field_by_index(
+                       this_ret = bt_field_type_common_structure_get_field_by_index(
                                field->type, &name, NULL, i);
                        BT_ASSERT(this_ret == 0);
                        BT_ASSERT_PRE_MSG("Invalid structure field's field: "
-                               "%![struct-field-]+f, field-name=\"%s\", "
-                               "index=%" PRId64 ", %![field-]+f",
+                               "%![struct-field-]+_f, field-name=\"%s\", "
+                               "index=%" PRId64 ", %![field-]+_f",
                                field, name, i, structure->fields->pdata[i]);
                        goto end;
                }
@@ -1500,39 +852,38 @@ end:
        return ret;
 }
 
-static
-int bt_field_variant_validate_recursive(struct bt_field *field)
+BT_HIDDEN
+int bt_field_common_variant_validate_recursive(struct bt_field_common *field)
 {
        int ret = 0;
-       struct bt_field_variant *variant;
+       struct bt_field_common_variant *variant = BT_FROM_COMMON(field);
 
        BT_ASSERT(field);
-       variant = container_of(field, struct bt_field_variant, parent);
-       ret = bt_field_validate_recursive(variant->payload);
+       ret = bt_field_common_validate_recursive(variant->payload);
        if (ret) {
                BT_ASSERT_PRE_MSG("Invalid variant field's payload field: "
-                       "%![variant-field-]+f, %![payload-field-]+f",
+                       "%![variant-field-]+_f, %![payload-field-]+_f",
                        field, variant->payload);
        }
 
        return ret;
 }
 
-static
-int bt_field_array_validate_recursive(struct bt_field *field)
+BT_HIDDEN
+int bt_field_common_array_validate_recursive(struct bt_field_common *field)
 {
        int64_t i;
        int ret = 0;
-       struct bt_field_array *array;
+       struct bt_field_common_array *array = BT_FROM_COMMON(field);
 
        BT_ASSERT(field);
-       array = container_of(field, struct bt_field_array, parent);
+
        for (i = 0; i < array->elements->len; i++) {
-               ret = bt_field_validate_recursive((void *) array->elements->pdata[i]);
+               ret = bt_field_common_validate_recursive((void *) array->elements->pdata[i]);
                if (ret) {
                        BT_ASSERT_PRE_MSG("Invalid array field's element field: "
-                               "%![array-field-]+f, " PRId64 ", "
-                               "%![elem-field-]+f",
+                               "%![array-field-]+_f, " PRId64 ", "
+                               "%![elem-field-]+_f",
                                field, i, array->elements->pdata[i]);
                        goto end;
                }
@@ -1542,22 +893,22 @@ end:
        return ret;
 }
 
-static
-int bt_field_sequence_validate_recursive(struct bt_field *field)
+BT_HIDDEN
+int bt_field_common_sequence_validate_recursive(struct bt_field_common *field)
 {
        size_t i;
        int ret = 0;
-       struct bt_field_sequence *sequence;
+       struct bt_field_common_sequence *sequence = BT_FROM_COMMON(field);
 
        BT_ASSERT(field);
-       sequence = container_of(field, struct bt_field_sequence, parent);
+
        for (i = 0; i < sequence->elements->len; i++) {
-               ret = bt_field_validate_recursive(
+               ret = bt_field_common_validate_recursive(
                        (void *) sequence->elements->pdata[i]);
                if (ret) {
                        BT_ASSERT_PRE_MSG("Invalid sequence field's element field: "
-                               "%![seq-field-]+f, " PRId64 ", "
-                               "%![elem-field-]+f",
+                               "%![seq-field-]+_f, " PRId64 ", "
+                               "%![elem-field-]+_f",
                                field, i, sequence->elements->pdata[i]);
                        goto end;
                }
@@ -1566,39 +917,37 @@ end:
        return ret;
 }
 
-static
-void bt_field_generic_reset(struct bt_field *field)
+BT_HIDDEN
+void bt_field_common_generic_reset(struct bt_field_common *field)
 {
        BT_ASSERT(field);
        field->payload_set = false;
 }
 
-static
-void bt_field_enumeration_reset_recursive(struct bt_field *field)
+BT_HIDDEN
+void bt_field_common_enumeration_reset_recursive(struct bt_field_common *field)
 {
-       struct bt_field_enumeration *enumeration;
+       struct bt_field_common_enumeration *enumeration = BT_FROM_COMMON(field);
 
        BT_ASSERT(field);
-       enumeration = container_of(field, struct bt_field_enumeration,
-               parent);
+
        if (!enumeration->payload) {
                return;
        }
 
-       bt_field_reset_recursive(enumeration->payload);
+       bt_field_common_reset_recursive(enumeration->payload);
 }
 
-static
-void bt_field_structure_reset_recursive(struct bt_field *field)
+BT_HIDDEN
+void bt_field_common_structure_reset_recursive(struct bt_field_common *field)
 {
        int64_t i;
-       struct bt_field_structure *structure;
+       struct bt_field_common_structure *structure = BT_FROM_COMMON(field);
 
        BT_ASSERT(field);
-       structure = container_of(field, struct bt_field_structure, parent);
 
        for (i = 0; i < structure->fields->len; i++) {
-               struct bt_field *member = structure->fields->pdata[i];
+               struct bt_field_common *member = structure->fields->pdata[i];
 
                if (!member) {
                        /*
@@ -1609,32 +958,30 @@ void bt_field_structure_reset_recursive(struct bt_field *field)
                        continue;
                }
 
-               bt_field_reset_recursive(member);
+               bt_field_common_reset_recursive(member);
        }
 }
 
-static
-void bt_field_variant_reset_recursive(struct bt_field *field)
+BT_HIDDEN
+void bt_field_common_variant_reset_recursive(struct bt_field_common *field)
 {
-       struct bt_field_variant *variant;
+       struct bt_field_common_variant *variant = BT_FROM_COMMON(field);
 
        BT_ASSERT(field);
-       variant = container_of(field, struct bt_field_variant, parent);
        BT_PUT(variant->tag);
        BT_PUT(variant->payload);
 }
 
-static
-void bt_field_array_reset_recursive(struct bt_field *field)
+BT_HIDDEN
+void bt_field_common_array_reset_recursive(struct bt_field_common *field)
 {
        size_t i;
-       struct bt_field_array *array;
+       struct bt_field_common_array *array = BT_FROM_COMMON(field);
 
        BT_ASSERT(field);
-       array = container_of(field, struct bt_field_array, parent);
 
        for (i = 0; i < array->elements->len; i++) {
-               struct bt_field *member = array->elements->pdata[i];
+               struct bt_field_common *member = array->elements->pdata[i];
 
                if (!member) {
                        /*
@@ -1644,17 +991,16 @@ void bt_field_array_reset_recursive(struct bt_field *field)
                        continue;
                }
 
-               bt_field_reset_recursive(member);
+               bt_field_common_reset_recursive(member);
        }
 }
 
-static
-void bt_field_sequence_reset_recursive(struct bt_field *field)
+BT_HIDDEN
+void bt_field_common_sequence_reset_recursive(struct bt_field_common *field)
 {
-       struct bt_field_sequence *sequence;
+       struct bt_field_common_sequence *sequence = BT_FROM_COMMON(field);
 
        BT_ASSERT(field);
-       sequence = container_of(field, struct bt_field_sequence, parent);
 
        if (sequence->elements) {
                g_ptr_array_free(sequence->elements, TRUE);
@@ -1664,387 +1010,121 @@ void bt_field_sequence_reset_recursive(struct bt_field *field)
        BT_PUT(sequence->length);
 }
 
-static
-void bt_field_string_reset_recursive(struct bt_field *field)
+BT_HIDDEN
+void bt_field_common_string_reset(struct bt_field_common *field)
 {
-       struct bt_field_string *string;
+       struct bt_field_common_string *string = BT_FROM_COMMON(field);
 
        BT_ASSERT(field);
-       bt_field_generic_reset(field);
-       string = container_of(field, struct bt_field_string, parent);
+       bt_field_common_generic_reset(field);
+
        if (string->payload) {
                g_string_truncate(string->payload, 0);
        }
 }
 
 static
-int bt_field_integer_serialize(struct bt_field *field,
-               struct bt_stream_pos *pos,
-               enum bt_byte_order native_byte_order)
-{
-       int ret = 0;
-       struct bt_field_integer *integer = container_of(field,
-               struct bt_field_integer, parent);
-
-       BT_ASSERT_PRE_FIELD_IS_SET(field, "Integer field");
-       BT_LOGV("Serializing integer field: addr=%p, pos-offset=%" PRId64 ", "
-               "native-bo=%s", field, pos->offset,
-               bt_byte_order_string(native_byte_order));
-
-retry:
-       ret = bt_field_integer_write(integer, pos, native_byte_order);
-       if (ret == -EFAULT) {
-               /*
-                * The field is too large to fit in the current packet's
-                * remaining space. Bump the packet size and retry.
-                */
-               ret = increase_packet_size(pos);
-               if (ret) {
-                       BT_LOGE("Cannot increase packet size: ret=%d", ret);
-                       goto end;
-               }
-               goto retry;
-       }
-
-end:
-       return ret;
-}
-
-static
-int bt_field_enumeration_serialize_recursive(struct bt_field *field,
-               struct bt_stream_pos *pos,
-               enum bt_byte_order native_byte_order)
-{
-       struct bt_field_enumeration *enumeration = container_of(
-               field, struct bt_field_enumeration, parent);
-
-       BT_LOGV("Serializing enumeration field: addr=%p, pos-offset=%" PRId64 ", "
-               "native-bo=%s", field, pos->offset,
-               bt_byte_order_string(native_byte_order));
-       BT_LOGV_STR("Serializing enumeration field's payload field.");
-       return bt_field_serialize_recursive(enumeration->payload, pos,
-               native_byte_order);
-}
-
-static
-int bt_field_floating_point_serialize(struct bt_field *field,
-               struct bt_stream_pos *pos,
-               enum bt_byte_order native_byte_order)
-{
-       int ret = 0;
-       struct bt_field_floating_point *floating_point = container_of(field,
-               struct bt_field_floating_point, parent);
-
-       BT_ASSERT_PRE_FIELD_IS_SET(field, "Floating point number field");
-       BT_LOGV("Serializing floating point number field: addr=%p, pos-offset=%" PRId64 ", "
-               "native-bo=%s", field, pos->offset,
-               bt_byte_order_string(native_byte_order));
-
-retry:
-       ret = bt_field_floating_point_write(floating_point, pos,
-               native_byte_order);
-       if (ret == -EFAULT) {
-               /*
-                * The field is too large to fit in the current packet's
-                * remaining space. Bump the packet size and retry.
-                */
-               ret = increase_packet_size(pos);
-               if (ret) {
-                       BT_LOGE("Cannot increase packet size: ret=%d", ret);
-                       goto end;
-               }
-               goto retry;
-       }
-
-end:
-       return ret;
-}
-
-static
-int bt_field_structure_serialize_recursive(struct bt_field *field,
-               struct bt_stream_pos *pos,
-               enum bt_byte_order native_byte_order)
+struct bt_field_common *bt_field_integer_copy(struct bt_field_common *src)
 {
-       int64_t i;
-       int ret = 0;
-       struct bt_field_structure *structure = container_of(
-               field, struct bt_field_structure, parent);
-
-       BT_LOGV("Serializing structure field: addr=%p, pos-offset=%" PRId64 ", "
-               "native-bo=%s", field, pos->offset,
-               bt_byte_order_string(native_byte_order));
-
-       while (!bt_stream_pos_access_ok(pos,
-               offset_align(pos->offset, field->type->alignment))) {
-               ret = increase_packet_size(pos);
-               if (ret) {
-                       BT_LOGE("Cannot increase packet size: ret=%d", ret);
-                       goto end;
-               }
-       }
+       struct bt_field_common_integer *integer_src = (void *) src;
+       struct bt_field_common_integer *integer_dst;
 
-       if (!bt_stream_pos_align(pos, field->type->alignment)) {
-               BT_LOGE("Cannot align packet's position: pos-offset=%" PRId64 ", "
-                       "align=%u", pos->offset, field->type->alignment);
-               ret = -1;
+       BT_LOGD("Copying integer field: src-field-addr=%p", src);
+       integer_dst = (void *) bt_field_create((void *) src->type);
+       if (!integer_dst) {
                goto end;
        }
 
-       for (i = 0; i < structure->fields->len; i++) {
-               struct bt_field *member = g_ptr_array_index(
-                       structure->fields, i);
-               const char *field_name = NULL;
-
-               BT_LOGV("Serializing structure field's field: pos-offset=%" PRId64 ", "
-                       "field-addr=%p, index=%" PRId64,
-                       pos->offset, member, i);
-
-               if (!member) {
-                       ret = bt_field_type_structure_get_field_by_index(
-                               field->type, &field_name, NULL, i);
-                       BT_ASSERT(ret == 0);
-                       BT_LOGW("Cannot serialize structure field's field: field is not set: "
-                               "struct-field-addr=%p, "
-                               "field-name=\"%s\", index=%" PRId64,
-                               field, field_name, i);
-                       ret = -1;
-                       goto end;
-               }
-
-               ret = bt_field_serialize_recursive(member, pos,
-                       native_byte_order);
-               if (ret) {
-                       ret = bt_field_type_structure_get_field_by_index(
-                               field->type, &field_name, NULL, i);
-                       BT_ASSERT(ret == 0);
-                       BT_LOGW("Cannot serialize structure field's field: "
-                               "struct-field-addr=%p, field-addr=%p, "
-                               "field-name=\"%s\", index=%" PRId64,
-                               field->type, member, field_name, i);
-                       break;
-               }
-       }
-
-end:
-       return ret;
-}
-
-static
-int bt_field_variant_serialize_recursive(struct bt_field *field,
-               struct bt_stream_pos *pos,
-               enum bt_byte_order native_byte_order)
-{
-       struct bt_field_variant *variant = container_of(
-               field, struct bt_field_variant, parent);
-
-       BT_LOGV("Serializing variant field: addr=%p, pos-offset=%" PRId64 ", "
-               "native-bo=%s", field, pos->offset,
-               bt_byte_order_string(native_byte_order));
-       BT_LOGV_STR("Serializing variant field's payload field.");
-       return bt_field_serialize_recursive(variant->payload, pos,
-               native_byte_order);
-}
-
-static
-int bt_field_array_serialize_recursive(struct bt_field *field,
-               struct bt_stream_pos *pos,
-               enum bt_byte_order native_byte_order)
-{
-       int64_t i;
-       int ret = 0;
-       struct bt_field_array *array = container_of(
-               field, struct bt_field_array, parent);
-
-       BT_LOGV("Serializing array field: addr=%p, pos-offset=%" PRId64 ", "
-               "native-bo=%s", field, pos->offset,
-               bt_byte_order_string(native_byte_order));
-
-       for (i = 0; i < array->elements->len; i++) {
-               struct bt_field *elem_field =
-                       g_ptr_array_index(array->elements, i);
-
-               BT_LOGV("Serializing array field's element field: "
-                       "pos-offset=%" PRId64 ", field-addr=%p, index=%" PRId64,
-                       pos->offset, elem_field, i);
-               ret = bt_field_serialize_recursive(elem_field, pos,
-                       native_byte_order);
-               if (ret) {
-                       BT_LOGW("Cannot serialize array field's element field: "
-                               "array-field-addr=%p, field-addr=%p, "
-                               "index=%" PRId64, field, elem_field, i);
-                       goto end;
-               }
-       }
+       integer_dst->payload = integer_src->payload;
+       BT_LOGD_STR("Copied integer field.");
 
 end:
-       return ret;
+       return BT_TO_COMMON(integer_dst);
 }
 
 static
-int bt_field_sequence_serialize_recursive(struct bt_field *field,
-               struct bt_stream_pos *pos,
-               enum bt_byte_order native_byte_order)
+struct bt_field_common *bt_field_enumeration_copy_recursive(
+               struct bt_field_common *src)
 {
-       int64_t i;
-       int ret = 0;
-       struct bt_field_sequence *sequence = container_of(
-               field, struct bt_field_sequence, parent);
-
-       BT_LOGV("Serializing sequence field: addr=%p, pos-offset=%" PRId64 ", "
-               "native-bo=%s", field, pos->offset,
-               bt_byte_order_string(native_byte_order));
-
-       for (i = 0; i < sequence->elements->len; i++) {
-               struct bt_field *elem_field =
-                       g_ptr_array_index(sequence->elements, i);
-
-               BT_LOGV("Serializing sequence field's element field: "
-                       "pos-offset=%" PRId64 ", field-addr=%p, index=%" PRId64,
-                       pos->offset, elem_field, i);
-               ret = bt_field_serialize_recursive(elem_field, pos,
-                       native_byte_order);
-               if (ret) {
-                       BT_LOGW("Cannot serialize sequence field's element field: "
-                               "sequence-field-addr=%p, field-addr=%p, "
-                               "index=%" PRId64, field, elem_field, i);
-                       goto end;
-               }
-       }
-
-end:
-       return ret;
-}
+       struct bt_field_common_enumeration *enum_src = BT_FROM_COMMON(src);
+       struct bt_field_common_enumeration *enum_dst;
 
-static
-int bt_field_string_serialize(struct bt_field *field, struct bt_stream_pos *pos,
-               enum bt_byte_order native_byte_order)
-{
-       int64_t i;
-       int ret = 0;
-       struct bt_field_string *string = container_of(field,
-               struct bt_field_string, parent);
-       struct bt_field_type *character_type =
-               get_field_type(FIELD_TYPE_ALIAS_UINT8_T);
-       struct bt_field *character;
-
-       BT_ASSERT_PRE_FIELD_IS_SET(field, "String field");
-       BT_LOGV("Serializing string field: addr=%p, pos-offset=%" PRId64 ", "
-               "native-bo=%s", field, pos->offset,
-               bt_byte_order_string(native_byte_order));
-
-       BT_LOGV_STR("Creating character field from string field's character field type.");
-       character = bt_field_create(character_type);
-
-       for (i = 0; i < string->payload->len + 1; i++) {
-               const uint64_t chr = (uint64_t) string->payload->str[i];
-
-               ret = bt_field_unsigned_integer_set_value(character, chr);
-               BT_ASSERT(ret == 0);
-               BT_LOGV("Serializing string field's character field: "
-                       "pos-offset=%" PRId64 ", field-addr=%p, "
-                       "index=%" PRId64 ", char-int=%" PRIu64,
-                       pos->offset, character, i, chr);
-               ret = bt_field_integer_serialize(character, pos,
-                       native_byte_order);
-               if (ret) {
-                       BT_LOGW_STR("Cannot serialize character field.");
-                       goto end;
-               }
+       BT_LOGD("Copying enumeration field: src-field-addr=%p", src);
+       enum_dst = (void *) bt_field_create((void *) src->type);
+       if (!enum_dst) {
+               goto error;
        }
 
-end:
-       bt_put(character);
-       bt_put(character_type);
-       return ret;
-}
-
-static
-int bt_field_integer_copy(struct bt_field *src, struct bt_field *dst)
-{
-       struct bt_field_integer *integer_src, *integer_dst;
-
-       BT_LOGD("Copying integer field: src-field-addr=%p, dst-field-addr=%p",
-               src, dst);
-       integer_src = container_of(src, struct bt_field_integer, parent);
-       integer_dst = container_of(dst, struct bt_field_integer, parent);
-       integer_dst->payload = integer_src->payload;
-       BT_LOGD_STR("Copied integer field.");
-       return 0;
-}
-
-static
-int bt_field_enumeration_copy_recursive(struct bt_field *src,
-               struct bt_field *dst)
-{
-       int ret = 0;
-       struct bt_field_enumeration *enum_src, *enum_dst;
-
-       BT_LOGD("Copying enumeration field: src-field-addr=%p, dst-field-addr=%p",
-               src, dst);
-       enum_src = container_of(src, struct bt_field_enumeration, parent);
-       enum_dst = container_of(dst, struct bt_field_enumeration, parent);
-
        if (enum_src->payload) {
                BT_LOGD_STR("Copying enumeration field's payload field.");
-               enum_dst->payload = bt_field_copy(enum_src->payload);
+               enum_dst->payload = (void *)
+                       bt_field_copy((void *) enum_src->payload);
                if (!enum_dst->payload) {
                        BT_LOGE_STR("Cannot copy enumeration field's payload field.");
-                       ret = -1;
-                       goto end;
+                       goto error;
                }
        }
 
        BT_LOGD_STR("Copied enumeration field.");
+       goto end;
+
+error:
+       BT_PUT(enum_dst);
+
 end:
-       return ret;
+       return BT_TO_COMMON(enum_dst);
 }
 
 static
-int bt_field_floating_point_copy(struct bt_field *src, struct bt_field *dst)
+struct bt_field_common *bt_field_floating_point_copy(
+               struct bt_field_common *src)
 {
-       struct bt_field_floating_point *float_src, *float_dst;
+       struct bt_field_common_floating_point *float_src = BT_FROM_COMMON(src);
+       struct bt_field_common_floating_point *float_dst;
+
+       BT_LOGD("Copying floating point number field: src-field-addr=%p", src);
+       float_dst = (void *) bt_field_create((void *) src->type);
+       if (!float_dst) {
+               goto end;
+       }
 
-       BT_LOGD("Copying floating point number field: src-field-addr=%p, dst-field-addr=%p",
-               src, dst);
-       float_src = container_of(src, struct bt_field_floating_point,
-               parent);
-       float_dst = container_of(dst, struct bt_field_floating_point,
-               parent);
        float_dst->payload = float_src->payload;
        BT_LOGD_STR("Copied floating point number field.");
-       return 0;
+
+end:
+       return BT_TO_COMMON(float_dst);
 }
 
 static
-int bt_field_structure_copy_recursive(struct bt_field *src,
-               struct bt_field *dst)
+struct bt_field_common *bt_field_structure_copy_recursive(
+               struct bt_field_common *src)
 {
-       int ret = 0;
        int64_t i;
-       struct bt_field_structure *struct_src, *struct_dst;
+       struct bt_field_common_structure *struct_src = BT_FROM_COMMON(src);
+       struct bt_field_common_structure *struct_dst;
 
-       BT_LOGD("Copying structure field: src-field-addr=%p, dst-field-addr=%p",
-               src, dst);
-       struct_src = container_of(src, struct bt_field_structure, parent);
-       struct_dst = container_of(dst, struct bt_field_structure, parent);
+       BT_LOGD("Copying structure field: src-field-addr=%p", src);
+       struct_dst = (void *) bt_field_create((void *) src->type);
+       if (!struct_dst) {
+               goto error;
+       }
 
        g_ptr_array_set_size(struct_dst->fields, struct_src->fields->len);
 
        for (i = 0; i < struct_src->fields->len; i++) {
-               struct bt_field *field =
+               struct bt_field_common *field =
                        g_ptr_array_index(struct_src->fields, i);
-               struct bt_field *field_copy = NULL;
+               struct bt_field_common *field_copy = NULL;
 
                if (field) {
                        BT_LOGD("Copying structure field's field: src-field-addr=%p"
                                "index=%" PRId64, field, i);
-                       field_copy = bt_field_copy(field);
+                       field_copy = (void *) bt_field_copy((void *) field);
                        if (!field_copy) {
                                BT_LOGE("Cannot copy structure field's field: "
                                        "src-field-addr=%p, index=%" PRId64,
                                        field, i);
-                               ret = -1;
-                               goto end;
+                               goto error;
                        }
                }
 
@@ -2052,77 +1132,86 @@ int bt_field_structure_copy_recursive(struct bt_field *src,
        }
 
        BT_LOGD_STR("Copied structure field.");
+       goto end;
+
+error:
+       BT_PUT(struct_dst);
 
 end:
-       return ret;
+       return BT_TO_COMMON(struct_dst);
 }
 
 static
-int bt_field_variant_copy_recursive(struct bt_field *src,
-               struct bt_field *dst)
+struct bt_field_common *bt_field_variant_copy_recursive(
+               struct bt_field_common *src)
 {
-       int ret = 0;
-       struct bt_field_variant *variant_src, *variant_dst;
+       struct bt_field_common_variant *variant_src = BT_FROM_COMMON(src);
+       struct bt_field_common_variant *variant_dst;
 
-       BT_LOGD("Copying variant field: src-field-addr=%p, dst-field-addr=%p",
-               src, dst);
-       variant_src = container_of(src, struct bt_field_variant, parent);
-       variant_dst = container_of(dst, struct bt_field_variant, parent);
+       BT_LOGD("Copying variant field: src-field-addr=%p", src);
+       variant_dst = (void *) bt_field_create((void *) src->type);
+       if (!variant_dst) {
+               goto end;
+       }
 
        if (variant_src->tag) {
                BT_LOGD_STR("Copying variant field's tag field.");
-               variant_dst->tag = bt_field_copy(variant_src->tag);
+               variant_dst->tag = (void *) bt_field_copy(
+                       (void *) variant_src->tag);
                if (!variant_dst->tag) {
                        BT_LOGE_STR("Cannot copy variant field's tag field.");
-                       ret = -1;
-                       goto end;
+                       goto error;
                }
        }
        if (variant_src->payload) {
                BT_LOGD_STR("Copying variant field's payload field.");
-               variant_dst->payload = bt_field_copy(variant_src->payload);
+               variant_dst->payload = (void *) bt_field_copy(
+                       (void *) variant_src->payload);
                if (!variant_dst->payload) {
                        BT_LOGE_STR("Cannot copy variant field's payload field.");
-                       ret = -1;
-                       goto end;
+                       goto error;
                }
        }
 
        BT_LOGD_STR("Copied variant field.");
+       goto end;
+
+error:
+       BT_PUT(variant_dst);
 
 end:
-       return ret;
+       return BT_TO_COMMON(variant_dst);
 }
 
 static
-int bt_field_array_copy_recursive(struct bt_field *src,
-               struct bt_field *dst)
+struct bt_field_common *bt_field_array_copy_recursive(
+               struct bt_field_common *src)
 {
-       int ret = 0;
        int64_t i;
-       struct bt_field_array *array_src, *array_dst;
+       struct bt_field_common_array *array_src = BT_FROM_COMMON(src);
+       struct bt_field_common_array *array_dst;
 
-       BT_LOGD("Copying array field: src-field-addr=%p, dst-field-addr=%p",
-               src, dst);
-       array_src = container_of(src, struct bt_field_array, parent);
-       array_dst = container_of(dst, struct bt_field_array, parent);
+       BT_LOGD("Copying array field: src-field-addr=%p", src);
+       array_dst = (void *) bt_field_create((void *) src->type);
+       if (!array_dst) {
+               goto error;
+       }
 
        g_ptr_array_set_size(array_dst->elements, array_src->elements->len);
        for (i = 0; i < array_src->elements->len; i++) {
-               struct bt_field *field =
+               struct bt_field_common *field =
                        g_ptr_array_index(array_src->elements, i);
-               struct bt_field *field_copy = NULL;
+               struct bt_field_common *field_copy = NULL;
 
                if (field) {
                        BT_LOGD("Copying array field's element field: field-addr=%p, "
                                "index=%" PRId64, field, i);
-                       field_copy = bt_field_copy(field);
+                       field_copy = (void *) bt_field_copy((void *) field);
                        if (!field_copy) {
                                BT_LOGE("Cannot copy array field's element field: "
                                        "src-field-addr=%p, index=%" PRId64,
                                        field, i);
-                               ret = -1;
-                               goto end;
+                               goto error;
                        }
                }
 
@@ -2130,27 +1219,33 @@ int bt_field_array_copy_recursive(struct bt_field *src,
        }
 
        BT_LOGD_STR("Copied array field.");
+       goto end;
+
+error:
+       BT_PUT(array_dst);
 
 end:
-       return ret;
+       return BT_TO_COMMON(array_dst);
 }
 
 static
-int bt_field_sequence_copy_recursive(struct bt_field *src,
-               struct bt_field *dst)
+struct bt_field_common *bt_field_sequence_copy_recursive(
+               struct bt_field_common *src)
 {
        int ret = 0;
        int64_t i;
-       struct bt_field_sequence *sequence_src, *sequence_dst;
-       struct bt_field *src_length;
-       struct bt_field *dst_length;
-
-       BT_LOGD("Copying sequence field: src-field-addr=%p, dst-field-addr=%p",
-               src, dst);
-       sequence_src = container_of(src, struct bt_field_sequence, parent);
-       sequence_dst = container_of(dst, struct bt_field_sequence, parent);
+       struct bt_field_common_sequence *sequence_src = BT_FROM_COMMON(src);
+       struct bt_field_common_sequence *sequence_dst;
+       struct bt_field_common *src_length;
+       struct bt_field_common *dst_length;
+
+       BT_LOGD("Copying sequence field: src-field-addr=%p", src);
+       sequence_dst = (void *) bt_field_create((void *) src->type);
+       if (!sequence_dst) {
+               goto error;
+       }
 
-       src_length = bt_field_sequence_get_length(src);
+       src_length = bt_field_common_sequence_get_length(src);
        if (!src_length) {
                /* no length set yet: keep destination sequence empty */
                goto end;
@@ -2158,41 +1253,39 @@ int bt_field_sequence_copy_recursive(struct bt_field *src,
 
        /* copy source length */
        BT_LOGD_STR("Copying sequence field's length field.");
-       dst_length = bt_field_copy(src_length);
+       dst_length = (void *) bt_field_copy((void *) src_length);
        BT_PUT(src_length);
        if (!dst_length) {
                BT_LOGE_STR("Cannot copy sequence field's length field.");
-               ret = -1;
-               goto end;
+               goto error;
        }
 
        /* this will initialize the destination sequence's internal array */
-       ret = bt_field_sequence_set_length(dst, dst_length);
+       ret = bt_field_common_sequence_set_length(
+               BT_TO_COMMON(sequence_dst), dst_length);
        bt_put(dst_length);
        if (ret) {
                BT_LOGE("Cannot set sequence field copy's length field: "
                        "dst-length-field-addr=%p", dst_length);
-               ret = -1;
-               goto end;
+               goto error;
        }
 
        BT_ASSERT(sequence_dst->elements->len == sequence_src->elements->len);
 
        for (i = 0; i < sequence_src->elements->len; i++) {
-               struct bt_field *field =
+               struct bt_field_common *field =
                        g_ptr_array_index(sequence_src->elements, i);
-               struct bt_field *field_copy = NULL;
+               struct bt_field_common *field_copy = NULL;
 
                if (field) {
                        BT_LOGD("Copying sequence field's element field: field-addr=%p, "
                                "index=%" PRId64, field, i);
-                       field_copy = bt_field_copy(field);
+                       field_copy = (void *) bt_field_copy((void *) field);
                        if (!field_copy) {
                                BT_LOGE("Cannot copy sequence field's element field: "
                                        "src-field-addr=%p, index=%" PRId64,
                                        field, i);
-                               ret = -1;
-                               goto end;
+                               goto error;
                        }
                }
 
@@ -2200,189 +1293,145 @@ int bt_field_sequence_copy_recursive(struct bt_field *src,
        }
 
        BT_LOGD_STR("Copied sequence field.");
+       goto end;
+
+error:
+       BT_PUT(sequence_dst);
 
 end:
-       return ret;
+       return BT_TO_COMMON(sequence_dst);
 }
 
 static
-int bt_field_string_copy_recursive(struct bt_field *src,
-               struct bt_field *dst)
+struct bt_field_common *bt_field_string_copy(struct bt_field_common *src)
 {
-       int ret = 0;
-       struct bt_field_string *string_src, *string_dst;
+       struct bt_field_common_string *string_src = BT_FROM_COMMON(src);
+       struct bt_field_common_string *string_dst;
 
-       BT_LOGD("Copying string field: src-field-addr=%p, dst-field-addr=%p",
-               src, dst);
-       string_src = container_of(src, struct bt_field_string, parent);
-       string_dst = container_of(dst, struct bt_field_string, parent);
+       BT_LOGD("Copying string field: src-field-addr=%p", src);
+       string_dst = (void *) bt_field_create((void *) src->type);
+       if (!string_dst) {
+               goto error;
+       }
 
        if (string_src->payload) {
                string_dst->payload = g_string_new(string_src->payload->str);
                if (!string_dst->payload) {
                        BT_LOGE_STR("Failed to allocate a GString.");
-                       ret = -1;
-                       goto end;
+                       goto error;
                }
        }
 
        BT_LOGD_STR("Copied string field.");
+       goto end;
 
-end:
-       return ret;
-}
-
-static
-int increase_packet_size(struct bt_stream_pos *pos)
-{
-       int ret;
-
-       BT_ASSERT(pos);
-       BT_LOGV("Increasing packet size: pos-offset=%" PRId64 ", "
-               "cur-packet-size=%" PRIu64,
-               pos->offset, pos->packet_size);
-       ret = munmap_align(pos->base_mma);
-       if (ret) {
-               BT_LOGE_ERRNO("Failed to perform an aligned memory unmapping",
-                       ": ret=%d", ret);
-               goto end;
-       }
-
-       pos->packet_size += PACKET_LEN_INCREMENT;
-       do {
-               ret = bt_posix_fallocate(pos->fd, pos->mmap_offset,
-                       pos->packet_size / CHAR_BIT);
-       } while (ret == EINTR);
-       if (ret) {
-               BT_LOGE_ERRNO("Failed to preallocate memory space",
-                       ": ret=%d", ret);
-               errno = EINTR;
-               ret = -1;
-               goto end;
-       }
-
-       pos->base_mma = mmap_align(pos->packet_size / CHAR_BIT, pos->prot,
-               pos->flags, pos->fd, pos->mmap_offset);
-       if (pos->base_mma == MAP_FAILED) {
-               BT_LOGE_ERRNO("Failed to perform an aligned memory mapping",
-                       ": ret=%d", ret);
-               ret = -1;
-       }
-
-       BT_LOGV("Increased packet size: pos-offset=%" PRId64 ", "
-               "new-packet-size=%" PRIu64,
-               pos->offset, pos->packet_size);
-       BT_ASSERT(pos->packet_size % 8 == 0);
+error:
+       BT_PUT(string_dst);
 
 end:
-       return ret;
+       return BT_TO_COMMON(string_dst);
 }
 
-static
-void generic_field_freeze(struct bt_field *field)
+BT_HIDDEN
+void bt_field_common_generic_freeze(struct bt_field_common *field)
 {
        field->frozen = true;
 }
 
-static
-void bt_field_enumeration_freeze_recursive(struct bt_field *field)
+BT_HIDDEN
+void bt_field_common_enumeration_freeze_recursive(struct bt_field_common *field)
 {
-       struct bt_field_enumeration *enum_field =
-               container_of(field, struct bt_field_enumeration, parent);
+       struct bt_field_common_enumeration *enum_field = BT_FROM_COMMON(field);
 
        BT_LOGD("Freezing enumeration field object: addr=%p", field);
        BT_LOGD("Freezing enumeration field object's contained payload field: payload-field-addr=%p", enum_field->payload);
-       bt_field_freeze_recursive(enum_field->payload);
-       generic_field_freeze(field);
+       bt_field_common_freeze_recursive(enum_field->payload);
+       bt_field_common_generic_freeze(field);
 }
 
-static
-void bt_field_structure_freeze_recursive(struct bt_field *field)
+BT_HIDDEN
+void bt_field_common_structure_freeze_recursive(struct bt_field_common *field)
 {
        int64_t i;
-       struct bt_field_structure *structure_field =
-               container_of(field, struct bt_field_structure, parent);
+       struct bt_field_common_structure *structure_field =
+               BT_FROM_COMMON(field);
 
        BT_LOGD("Freezing structure field object: addr=%p", field);
 
        for (i = 0; i < structure_field->fields->len; i++) {
-               struct bt_field *field =
+               struct bt_field_common *field =
                        g_ptr_array_index(structure_field->fields, i);
 
                BT_LOGD("Freezing structure field's field: field-addr=%p, index=%" PRId64,
                        field, i);
-               bt_field_freeze_recursive(field);
+               bt_field_common_freeze_recursive(field);
        }
 
-       generic_field_freeze(field);
+       bt_field_common_generic_freeze(field);
 }
 
-static
-void bt_field_variant_freeze_recursive(struct bt_field *field)
+BT_HIDDEN
+void bt_field_common_variant_freeze_recursive(struct bt_field_common *field)
 {
-       struct bt_field_variant *variant_field =
-               container_of(field, struct bt_field_variant, parent);
+       struct bt_field_common_variant *variant_field = BT_FROM_COMMON(field);
 
        BT_LOGD("Freezing variant field object: addr=%p", field);
        BT_LOGD("Freezing variant field object's tag field: tag-field-addr=%p", variant_field->tag);
-       bt_field_freeze_recursive(variant_field->tag);
+       bt_field_common_freeze_recursive(variant_field->tag);
        BT_LOGD("Freezing variant field object's payload field: payload-field-addr=%p", variant_field->payload);
-       bt_field_freeze_recursive(variant_field->payload);
-       generic_field_freeze(field);
+       bt_field_common_freeze_recursive(variant_field->payload);
+       bt_field_common_generic_freeze(field);
 }
 
-static
-void bt_field_array_freeze_recursive(struct bt_field *field)
+BT_HIDDEN
+void bt_field_common_array_freeze_recursive(struct bt_field_common *field)
 {
        int64_t i;
-       struct bt_field_array *array_field =
-               container_of(field, struct bt_field_array, parent);
+       struct bt_field_common_array *array_field = BT_FROM_COMMON(field);
 
        BT_LOGD("Freezing array field object: addr=%p", field);
 
        for (i = 0; i < array_field->elements->len; i++) {
-               struct bt_field *elem_field =
+               struct bt_field_common *elem_field =
                        g_ptr_array_index(array_field->elements, i);
 
                BT_LOGD("Freezing array field object's element field: "
                        "element-field-addr=%p, index=%" PRId64,
                        elem_field, i);
-               bt_field_freeze_recursive(elem_field);
+               bt_field_common_freeze_recursive(elem_field);
        }
 
-       generic_field_freeze(field);
+       bt_field_common_generic_freeze(field);
 }
 
-static
-void bt_field_sequence_freeze_recursive(struct bt_field *field)
+BT_HIDDEN
+void bt_field_common_sequence_freeze_recursive(struct bt_field_common *field)
 {
        int64_t i;
-       struct bt_field_sequence *sequence_field =
-               container_of(field, struct bt_field_sequence, parent);
+       struct bt_field_common_sequence *sequence_field =
+               BT_FROM_COMMON(field);
 
        BT_LOGD("Freezing sequence field object: addr=%p", field);
        BT_LOGD("Freezing sequence field object's length field: length-field-addr=%p",
                sequence_field->length);
-       bt_field_freeze_recursive(sequence_field->length);
+       bt_field_common_freeze_recursive(sequence_field->length);
 
        for (i = 0; i < sequence_field->elements->len; i++) {
-               struct bt_field *elem_field =
+               struct bt_field_common *elem_field =
                        g_ptr_array_index(sequence_field->elements, i);
 
                BT_LOGD("Freezing sequence field object's element field: "
                        "element-field-addr=%p, index=%" PRId64,
                        elem_field, i);
-               bt_field_freeze_recursive(elem_field);
+               bt_field_common_freeze_recursive(elem_field);
        }
 
-       generic_field_freeze(field);
+       bt_field_common_generic_freeze(field);
 }
 
 BT_HIDDEN
-void _bt_field_freeze_recursive(struct bt_field *field)
+void _bt_field_common_freeze_recursive(struct bt_field_common *field)
 {
-       enum bt_field_type_id type_id;
-
        if (!field) {
                goto end;
        }
@@ -2392,105 +1441,111 @@ void _bt_field_freeze_recursive(struct bt_field *field)
        }
 
        BT_LOGD("Freezing field object: addr=%p", field);
-       BT_ASSERT(field_type_has_known_id(field->type));
-       type_id = bt_field_get_type_id(field);
-       field_freeze_funcs[type_id](field);
+       BT_ASSERT(field_type_common_has_known_id(field->type));
+       BT_ASSERT(field->methods->freeze);
+       field->methods->freeze(field);
+
 end:
        return;
 }
 
-static
-bt_bool bt_field_generic_is_set(struct bt_field *field)
+BT_HIDDEN
+bt_bool bt_field_common_generic_is_set(struct bt_field_common *field)
 {
        return field && field->payload_set;
 }
 
-static
-bt_bool bt_field_enumeration_is_set_recursive(struct bt_field *field)
+BT_HIDDEN
+bt_bool bt_field_common_enumeration_is_set_recursive(
+               struct bt_field_common *field)
 {
        bt_bool is_set = BT_FALSE;
-       struct bt_field_enumeration *enumeration;
+       struct bt_field_common_enumeration *enumeration = BT_FROM_COMMON(field);
 
        BT_ASSERT(field);
-       enumeration = container_of(field, struct bt_field_enumeration,
-                       parent);
+
        if (!enumeration->payload) {
                goto end;
        }
 
-       is_set = bt_field_is_set_recursive(enumeration->payload);
+       is_set = bt_field_common_is_set_recursive(enumeration->payload);
+
 end:
        return is_set;
 }
 
-static
-bt_bool bt_field_structure_is_set_recursive(struct bt_field *field)
+BT_HIDDEN
+bt_bool bt_field_common_structure_is_set_recursive(
+               struct bt_field_common *field)
 {
        bt_bool is_set = BT_FALSE;
        size_t i;
-       struct bt_field_structure *structure;
+       struct bt_field_common_structure *structure = BT_FROM_COMMON(field);
 
        BT_ASSERT(field);
-       structure = container_of(field, struct bt_field_structure, parent);
+
        for (i = 0; i < structure->fields->len; i++) {
-               is_set = bt_field_is_set_recursive(
+               is_set = bt_field_common_is_set_recursive(
                        structure->fields->pdata[i]);
                if (!is_set) {
                        goto end;
                }
        }
+
 end:
        return is_set;
 }
 
-static
-bt_bool bt_field_variant_is_set_recursive(struct bt_field *field)
+BT_HIDDEN
+bt_bool bt_field_common_variant_is_set_recursive(struct bt_field_common *field)
 {
-       struct bt_field_variant *variant;
+       struct bt_field_common_variant *variant = BT_FROM_COMMON(field);
 
        BT_ASSERT(field);
-       variant = container_of(field, struct bt_field_variant, parent);
-       return bt_field_is_set_recursive(variant->payload);
+       return bt_field_common_is_set_recursive(variant->payload);
 }
 
-static
-bt_bool bt_field_array_is_set_recursive(struct bt_field *field)
+BT_HIDDEN
+bt_bool bt_field_common_array_is_set_recursive(struct bt_field_common *field)
 {
        size_t i;
        bt_bool is_set = BT_FALSE;
-       struct bt_field_array *array;
+       struct bt_field_common_array *array = BT_FROM_COMMON(field);
 
        BT_ASSERT(field);
-       array = container_of(field, struct bt_field_array, parent);
+
        for (i = 0; i < array->elements->len; i++) {
-               is_set = bt_field_is_set_recursive(array->elements->pdata[i]);
+               is_set = bt_field_common_is_set_recursive(array->elements->pdata[i]);
                if (!is_set) {
                        goto end;
                }
        }
+
 end:
        return is_set;
 }
 
-static
-bt_bool bt_field_sequence_is_set_recursive(struct bt_field *field)
+BT_HIDDEN
+bt_bool bt_field_common_sequence_is_set_recursive(struct bt_field_common *field)
 {
        size_t i;
        bt_bool is_set = BT_FALSE;
-       struct bt_field_sequence *sequence;
+       struct bt_field_common_sequence *sequence = BT_FROM_COMMON(field);
 
        BT_ASSERT(field);
-       sequence = container_of(field, struct bt_field_sequence, parent);
+
        if (!sequence->elements) {
                goto end;
        }
 
        for (i = 0; i < sequence->elements->len; i++) {
-               is_set = bt_field_is_set_recursive(sequence->elements->pdata[i]);
+               is_set = bt_field_common_is_set_recursive(
+                       sequence->elements->pdata[i]);
                if (!is_set) {
                        goto end;
                }
        }
+
 end:
        return is_set;
 }
index ac3321a994b0e87fd3e4a93ca330ccb156cd97de..0004cffd1b85d6f6309079f910380b9418765575 100644 (file)
@@ -27,6 +27,7 @@
 #define BT_LOG_TAG "PACKET"
 #include <babeltrace/lib-logging-internal.h>
 
+#include <babeltrace/assert-pre-internal.h>
 #include <babeltrace/ctf-ir/fields-internal.h>
 #include <babeltrace/ctf-ir/packet.h>
 #include <babeltrace/ctf-ir/packet-internal.h>
@@ -39,7 +40,6 @@
 #include <babeltrace/object-internal.h>
 #include <babeltrace/ref.h>
 #include <babeltrace/assert-internal.h>
-#include <babeltrace/assert-pre-internal.h>
 #include <inttypes.h>
 
 struct bt_stream *bt_packet_get_stream(struct bt_packet *packet)
@@ -57,7 +57,7 @@ struct bt_field *bt_packet_get_header(
 
 BT_ASSERT_PRE_FUNC
 static inline bool validate_field_to_set(struct bt_field *field,
-               struct bt_field_type *expected_ft)
+               struct bt_field_type_common *expected_ft)
 {
        bool ret = true;
 
@@ -74,10 +74,11 @@ static inline bool validate_field_to_set(struct bt_field *field,
                goto end;
        }
 
-       if (bt_field_type_compare(field->type, expected_ft) != 0) {
+       if (bt_field_type_compare(bt_field_borrow_type(field),
+                       BT_FROM_COMMON(expected_ft)) != 0) {
                BT_ASSERT_PRE_MSG("Field type is different from expected "
                        " field type: %![field-ft-]+F, %![expected-ft-]+F",
-                       field->type, expected_ft);
+                       bt_field_borrow_type(field), expected_ft);
                ret = false;
                goto end;
        }
@@ -92,7 +93,8 @@ int bt_packet_set_header(struct bt_packet *packet,
        BT_ASSERT_PRE_NON_NULL(packet, "Packet");
        BT_ASSERT_PRE_HOT(packet, "Packet", ": +%!+a", packet);
        BT_ASSERT_PRE(validate_field_to_set(header,
-               bt_stream_class_borrow_trace(packet->stream->stream_class)->packet_header_type),
+               bt_stream_class_borrow_trace(
+                       BT_FROM_COMMON(packet->stream->common.stream_class))->common.packet_header_field_type),
                "Invalid packet header field: "
                "%![packet-]+a, %![field-]+f", packet, header);
        bt_put(packet->header);
@@ -114,7 +116,7 @@ int bt_packet_set_context(struct bt_packet *packet,
        BT_ASSERT_PRE_NON_NULL(packet, "Packet");
        BT_ASSERT_PRE_HOT(packet, "Packet", ": +%!+a", packet);
        BT_ASSERT_PRE(validate_field_to_set(context,
-               packet->stream->stream_class->packet_context_type),
+               BT_FROM_COMMON(packet->stream->common.stream_class->packet_context_field_type)),
                "Invalid packet context field: "
                "%![packet-]+a, %![field-]+f", packet, context);
        bt_put(packet->context);
@@ -142,9 +144,8 @@ void _bt_packet_freeze(struct bt_packet *packet)
 static
 void bt_packet_destroy(struct bt_object *obj)
 {
-       struct bt_packet *packet;
+       struct bt_packet *packet = (void *) obj;
 
-       packet = container_of(obj, struct bt_packet, base);
        BT_LOGD("Destroying packet: addr=%p", packet);
        BT_LOGD_STR("Putting packet's header field.");
        bt_put(packet->header);
@@ -167,11 +168,9 @@ struct bt_packet *bt_packet_create(
                "stream-name=\"%s\", stream-class-addr=%p, "
                "stream-class-name=\"%s\", stream-class-id=%" PRId64,
                stream, bt_stream_get_name(stream),
-               stream->stream_class,
-               bt_stream_class_get_name(stream->stream_class),
-               bt_stream_class_get_id(stream->stream_class));
-       BT_ASSERT_PRE(stream->pos.fd < 0,
-               "Stream is a CTF writer stream: %!+s", stream);
+               stream->common.stream_class,
+               bt_stream_class_common_get_name(stream->common.stream_class),
+               bt_stream_class_common_get_id(stream->common.stream_class));
        stream_class = bt_stream_get_class(stream);
        BT_ASSERT(stream_class);
        trace = bt_stream_class_get_trace(stream_class);
@@ -185,10 +184,11 @@ struct bt_packet *bt_packet_create(
        bt_object_init(packet, bt_packet_destroy);
        packet->stream = bt_get(stream);
 
-       if (trace->packet_header_type) {
+       if (trace->common.packet_header_field_type) {
                BT_LOGD("Creating initial packet header field: ft-addr=%p",
-                       trace->packet_header_type);
-               packet->header = bt_field_create(trace->packet_header_type);
+                       trace->common.packet_header_field_type);
+               packet->header = bt_field_create(
+                       BT_FROM_COMMON(trace->common.packet_header_field_type));
                if (!packet->header) {
                        BT_LOGE_STR("Cannot create initial packet header field object.");
                        BT_PUT(packet);
@@ -196,11 +196,11 @@ struct bt_packet *bt_packet_create(
                }
        }
 
-       if (stream->stream_class->packet_context_type) {
+       if (stream->common.stream_class->packet_context_field_type) {
                BT_LOGD("Creating initial packet context field: ft-addr=%p",
-                       stream->stream_class->packet_context_type);
+                       stream->common.stream_class->packet_context_field_type);
                packet->context = bt_field_create(
-                       stream->stream_class->packet_context_type);
+                       BT_FROM_COMMON(stream->common.stream_class->packet_context_field_type));
                if (!packet->context) {
                        BT_LOGE_STR("Cannot create initial packet header field object.");
                        BT_PUT(packet);
index 049ddda73c391065c859b538c9d733c943d3a8e8..ce155230fdc818c949ca761d72ade489015f76ed 100644 (file)
 #define BT_LOG_TAG "RESOLVE"
 #include <babeltrace/lib-logging-internal.h>
 
-#include <babeltrace/ctf-ir/event.h>
 #include <babeltrace/ctf-ir/stream-class.h>
 #include <babeltrace/ctf-ir/resolve-internal.h>
 #include <babeltrace/ctf-ir/field-types.h>
 #include <babeltrace/ctf-ir/field-path.h>
 #include <babeltrace/ctf-ir/field-path-internal.h>
-#include <babeltrace/ctf-ir/event-internal.h>
 #include <babeltrace/ref.h>
 #include <babeltrace/babeltrace-internal.h>
 #include <babeltrace/values.h>
@@ -60,7 +58,7 @@ typedef GPtrArray type_stack;
  * `type` is owned by the stack frame.
  */
 struct type_stack_frame {
-       struct bt_field_type *type;
+       struct bt_field_type_common *type;
        int index;
 };
 
@@ -79,23 +77,23 @@ struct type_stack_frame {
  */
 struct resolve_context {
        struct bt_value *environment;
-       struct bt_field_type *scopes[6];
+       struct bt_field_type_common *scopes[6];
 
        /* Root scope being visited */
        enum bt_scope root_scope;
        type_stack *type_stack;
-       struct bt_field_type *cur_field_type;
+       struct bt_field_type_common *cur_field_type;
 };
 
 /* TSDL dynamic scope prefixes as defined in CTF Section 7.3.2 */
 static const char * const absolute_path_prefixes[] = {
-       [BT_SCOPE_ENV]                  = "env.",
-       [BT_SCOPE_TRACE_PACKET_HEADER]  = "trace.packet.header.",
+       [BT_SCOPE_ENV]                          = "env.",
+       [BT_SCOPE_TRACE_PACKET_HEADER]          = "trace.packet.header.",
        [BT_SCOPE_STREAM_PACKET_CONTEXT]        = "stream.packet.context.",
-       [BT_SCOPE_STREAM_EVENT_HEADER]  = "stream.event.header.",
-       [BT_SCOPE_STREAM_EVENT_CONTEXT] = "stream.event.context.",
+       [BT_SCOPE_STREAM_EVENT_HEADER]          = "stream.event.header.",
+       [BT_SCOPE_STREAM_EVENT_CONTEXT]         = "stream.event.context.",
        [BT_SCOPE_EVENT_CONTEXT]                = "event.context.",
-       [BT_SCOPE_EVENT_FIELDS]         = "event.fields.",
+       [BT_SCOPE_EVENT_FIELDS]                 = "event.fields.",
 };
 
 /* Number of path tokens used for the absolute prefixes */
@@ -147,7 +145,7 @@ void type_stack_destroy(type_stack *stack)
  * `type` is owned by the caller (stack frame gets a new reference).
  */
 static
-int type_stack_push(type_stack *stack, struct bt_field_type *type)
+int type_stack_push(type_stack *stack, struct bt_field_type_common *type)
 {
        int ret = 0;
        struct type_stack_frame *frame = NULL;
@@ -255,7 +253,7 @@ void type_stack_pop(type_stack *stack)
  * Return value is owned by `ctx` on success.
  */
 static
-struct bt_field_type *get_type_from_ctx(struct resolve_context *ctx,
+struct bt_field_type_common *get_type_from_ctx(struct resolve_context *ctx,
                enum bt_scope scope)
 {
        BT_ASSERT(scope >= BT_SCOPE_TRACE_PACKET_HEADER &&
@@ -290,7 +288,7 @@ enum bt_scope get_root_scope_from_absolute_pathstr(const char *pathstr)
                        BT_LOGV("Prefix does not match: trying the next one: "
                                "path=\"%s\", path-prefix=\"%s\", scope=%s",
                                pathstr, absolute_path_prefixes[scope],
-                               bt_scope_string(scope));
+                               bt_common_scope_string(scope));
                        continue;
                }
 
@@ -298,7 +296,7 @@ enum bt_scope get_root_scope_from_absolute_pathstr(const char *pathstr)
                ret = scope;
                BT_LOGV("Found root scope from absolute path: "
                        "path=\"%s\", scope=%s", pathstr,
-                       bt_scope_string(scope));
+                       bt_common_scope_string(scope));
                goto end;
        }
 
@@ -397,7 +395,7 @@ error:
  */
 static
 int ptokens_to_field_path(GList *ptokens, struct bt_field_path *field_path,
-               struct bt_field_type *type, int src_index)
+               struct bt_field_type_common *type, int src_index)
 {
        int ret = 0;
        GList *cur_ptoken = ptokens;
@@ -409,10 +407,10 @@ int ptokens_to_field_path(GList *ptokens, struct bt_field_path *field_path,
        /* Locate target */
        while (cur_ptoken) {
                int child_index;
-               struct bt_field_type *child_type;
+               struct bt_field_type_common *child_type;
                const char *field_name = ptoken_get_string(cur_ptoken);
                enum bt_field_type_id type_id =
-                       bt_field_type_get_type_id(type);
+                       bt_field_type_common_get_type_id(type);
 
                BT_LOGV("Current path token: token=\"%s\"", field_name);
 
@@ -421,7 +419,7 @@ int ptokens_to_field_path(GList *ptokens, struct bt_field_path *field_path,
                                type_id == BT_FIELD_TYPE_ID_SEQUENCE) {
                        child_index = -1;
                } else {
-                       child_index = bt_field_type_get_field_index(type,
+                       child_index = bt_field_type_common_get_field_index(type,
                                field_name);
                        if (child_index < 0) {
                                /*
@@ -451,7 +449,7 @@ int ptokens_to_field_path(GList *ptokens, struct bt_field_path *field_path,
                g_array_append_val(field_path->indexes, child_index);
 
                /* Get child field type */
-               child_type = bt_field_type_get_field_at_index(type,
+               child_type = bt_field_type_common_get_field_at_index(type,
                        child_index);
                if (!child_type) {
                        BT_LOGW("Cannot get child field type: "
@@ -484,7 +482,7 @@ int absolute_ptokens_to_field_path(GList *ptokens,
 {
        int ret = 0;
        GList *cur_ptoken;
-       struct bt_field_type *type;
+       struct bt_field_type_common *type;
 
        /* Skip absolute path tokens */
        cur_ptoken = g_list_nth(ptokens,
@@ -496,7 +494,7 @@ int absolute_ptokens_to_field_path(GList *ptokens,
                /* Error: root type is not available */
                BT_LOGW("Root field type is not available: "
                        "root-scope=%s",
-                       bt_scope_string(field_path->root));
+                       bt_common_scope_string(field_path->root));
                ret = -1;
                goto end;
        }
@@ -533,7 +531,7 @@ int relative_ptokens_to_field_path(GList *ptokens,
        parent_pos_in_stack = type_stack_size(ctx->type_stack) - 1;
 
        while (parent_pos_in_stack >= 0) {
-               struct bt_field_type *parent_type =
+               struct bt_field_type_common *parent_type =
                        type_stack_at(ctx->type_stack,
                                parent_pos_in_stack)->type;
                int cur_index = type_stack_at(ctx->type_stack,
@@ -557,7 +555,7 @@ int relative_ptokens_to_field_path(GList *ptokens,
                                tail_field_path->indexes->len;
 
                        while (BT_TRUE) {
-                               struct bt_field_type *cur_type =
+                               struct bt_field_type_common *cur_type =
                                        type_stack_at(ctx->type_stack, i)->type;
                                int index = type_stack_at(
                                        ctx->type_stack, i)->index;
@@ -590,11 +588,11 @@ int relative_ptokens_to_field_path(GList *ptokens,
                field_path->root--;
 
                while (field_path->root >= BT_SCOPE_TRACE_PACKET_HEADER) {
-                       struct bt_field_type *root_type;
+                       struct bt_field_type_common *root_type;
                        bt_field_path_clear(field_path);
 
                        BT_LOGV("Looking into potential root scope: scope=%s",
-                               bt_scope_string(field_path->root));
+                               bt_common_scope_string(field_path->root));
                        root_type = get_type_from_ctx(ctx, field_path->root);
                        if (!root_type) {
                                field_path->root--;
@@ -661,13 +659,13 @@ struct bt_field_path *pathstr_to_field_path(const char *pathstr,
                /* Relative path: start with current root scope */
                field_path->root = ctx->root_scope;
                BT_LOGV("Detected relative path: starting with current root scope: "
-                       "scope=%s", bt_scope_string(field_path->root));
+                       "scope=%s", bt_common_scope_string(field_path->root));
                ret = relative_ptokens_to_field_path(ptokens, field_path, ctx);
                if (ret) {
                        BT_LOGW("Cannot get relative field path of path string: "
                                "path=\"%s\", start-scope=%s, end-scope=%s",
-                               pathstr, bt_scope_string(ctx->root_scope),
-                               bt_scope_string(field_path->root));
+                               pathstr, bt_common_scope_string(ctx->root_scope),
+                               bt_common_scope_string(field_path->root));
                        goto end;
                }
        } else if (root_scope == BT_SCOPE_ENV) {
@@ -679,12 +677,12 @@ struct bt_field_path *pathstr_to_field_path(const char *pathstr,
                /* Absolute path: use found root scope */
                field_path->root = root_scope;
                BT_LOGV("Detected absolute path: using root scope: "
-                       "scope=%s", bt_scope_string(field_path->root));
+                       "scope=%s", bt_common_scope_string(field_path->root));
                ret = absolute_ptokens_to_field_path(ptokens, field_path, ctx);
                if (ret) {
                        BT_LOGW("Cannot get absolute field path of path string: "
                                "path=\"%s\", root-scope=%s",
-                               pathstr, bt_scope_string(root_scope));
+                               pathstr, bt_common_scope_string(root_scope));
                        goto end;
                }
        }
@@ -719,12 +717,12 @@ end:
  * Return value is owned by the caller on success.
  */
 static
-struct bt_field_type *field_path_to_field_type(
+struct bt_field_type_common *field_path_to_field_type(
                struct bt_field_path *field_path,
                struct resolve_context *ctx)
 {
        int i;
-       struct bt_field_type *type;
+       struct bt_field_type_common *type;
 
        /* Start with root type */
        type = get_type_from_ctx(ctx, field_path->root);
@@ -732,18 +730,18 @@ struct bt_field_type *field_path_to_field_type(
        if (!type) {
                /* Error: root type is not available */
                BT_LOGW("Root field type is not available: root-scope=%s",
-                       bt_scope_string(field_path->root));
+                       bt_common_scope_string(field_path->root));
                goto error;
        }
 
        /* Locate target */
        for (i = 0; i < field_path->indexes->len; i++) {
-               struct bt_field_type *child_type;
+               struct bt_field_type_common *child_type;
                int child_index =
                        g_array_index(field_path->indexes, int, i);
 
                /* Get child field type */
-               child_type = bt_field_type_get_field_at_index(type,
+               child_type = bt_field_type_common_get_field_at_index(type,
                        child_index);
                if (!child_type) {
                        BT_LOGW("Cannot get field type: "
@@ -880,7 +878,7 @@ int get_field_paths_lca_index(struct bt_field_path *field_path1,
  */
 static
 int validate_target_field_path(struct bt_field_path *target_field_path,
-               struct bt_field_type *target_type,
+               struct bt_field_type_common *target_type,
                struct resolve_context *ctx)
 {
        int ret = 0;
@@ -914,8 +912,8 @@ int validate_target_field_path(struct bt_field_path *target_field_path,
        if (target_field_path->root > ctx_field_path->root) {
                BT_LOGW("Target field type is located after source field type: "
                        "target-root=%s, source-root=%s",
-                       bt_scope_string(target_field_path->root),
-                       bt_scope_string(ctx_field_path->root));
+                       bt_common_scope_string(target_field_path->root),
+                       bt_common_scope_string(ctx_field_path->root));
                ret = -1;
                goto end;
        }
@@ -956,9 +954,9 @@ int validate_target_field_path(struct bt_field_path *target_field_path,
        /*
         * Make sure the target type has the right type and properties.
         */
-       ctx_cur_field_type_id = bt_field_type_get_type_id(
+       ctx_cur_field_type_id = bt_field_type_common_get_type_id(
                ctx->cur_field_type);
-       target_type_id = bt_field_type_get_type_id(target_type);
+       target_type_id = bt_field_type_common_get_type_id(target_type);
 
        switch (ctx_cur_field_type_id) {
        case BT_FIELD_TYPE_ID_VARIANT:
@@ -966,18 +964,18 @@ int validate_target_field_path(struct bt_field_path *target_field_path,
                        BT_LOGW("Variant field type's tag field type is not an enumeration field type: "
                                "tag-ft-addr=%p, tag-ft-id=%s",
                                target_type,
-                               bt_field_type_id_string(target_type_id));
+                               bt_common_field_type_id_string(target_type_id));
                        ret = -1;
                        goto end;
                }
                break;
        case BT_FIELD_TYPE_ID_SEQUENCE:
                if (target_type_id != BT_FIELD_TYPE_ID_INTEGER ||
-                               bt_field_type_integer_is_signed(target_type)) {
+                               bt_field_type_common_integer_is_signed(target_type)) {
                        BT_LOGW("Sequence field type's length field type is not an unsigned integer field type: "
                                "length-ft-addr=%p, length-ft-id=%s",
                                target_type,
-                               bt_field_type_id_string(target_type_id));
+                               bt_common_field_type_id_string(target_type_id));
                        ret = -1;
                        goto end;
                }
@@ -997,14 +995,14 @@ end:
  * `type` is owned by the caller.
  */
 static
-int resolve_sequence_or_variant_type(struct bt_field_type *type,
+int resolve_sequence_or_variant_type(struct bt_field_type_common *type,
                struct resolve_context *ctx)
 {
        int ret = 0;
        const char *pathstr;
-       enum bt_field_type_id type_id = bt_field_type_get_type_id(type);
+       enum bt_field_type_id type_id = bt_field_type_common_get_type_id(type);
        struct bt_field_path *target_field_path = NULL;
-       struct bt_field_type *target_type = NULL;
+       struct bt_field_type_common *target_type = NULL;
        GString *target_field_path_pretty = NULL;
        const char *target_field_path_pretty_str;
 
@@ -1013,11 +1011,11 @@ int resolve_sequence_or_variant_type(struct bt_field_type *type,
        switch (type_id) {
        case BT_FIELD_TYPE_ID_SEQUENCE:
                pathstr =
-                       bt_field_type_sequence_get_length_field_name(type);
+                       bt_field_type_common_sequence_get_length_field_name(type);
                break;
        case BT_FIELD_TYPE_ID_VARIANT:
                pathstr =
-                       bt_field_type_variant_get_tag_name(type);
+                       bt_field_type_common_variant_get_tag_name(type);
                break;
        default:
                abort();
@@ -1063,7 +1061,7 @@ int resolve_sequence_or_variant_type(struct bt_field_type *type,
        /* Set target field path and target field type */
        switch (type_id) {
        case BT_FIELD_TYPE_ID_SEQUENCE:
-               ret = bt_field_type_sequence_set_length_field_path(
+               ret = bt_field_type_common_sequence_set_length_field_path(
                        type, target_field_path);
                if (ret) {
                        BT_LOGW("Cannot set sequence field type's length field path: "
@@ -1074,7 +1072,7 @@ int resolve_sequence_or_variant_type(struct bt_field_type *type,
                }
                break;
        case BT_FIELD_TYPE_ID_VARIANT:
-               ret = bt_field_type_variant_set_tag_field_path(
+               ret = bt_field_type_common_variant_set_tag_field_path(
                        type, target_field_path);
                if (ret) {
                        BT_LOGW("Cannot set varaint field type's tag field path: "
@@ -1084,7 +1082,7 @@ int resolve_sequence_or_variant_type(struct bt_field_type *type,
                        goto end;
                }
 
-               ret = bt_field_type_variant_set_tag_field_type(
+               ret = bt_field_type_common_variant_set_tag_field_type(
                        type, target_type);
                if (ret) {
                        BT_LOGW("Cannot set varaint field type's tag field type: "
@@ -1114,7 +1112,7 @@ end:
  * `type` is owned by the caller.
  */
 static
-int resolve_type(struct bt_field_type *type, struct resolve_context *ctx)
+int resolve_type(struct bt_field_type_common *type, struct resolve_context *ctx)
 {
        int ret = 0;
        enum bt_field_type_id type_id;
@@ -1124,7 +1122,7 @@ int resolve_type(struct bt_field_type *type, struct resolve_context *ctx)
                goto end;
        }
 
-       type_id = bt_field_type_get_type_id(type);
+       type_id = bt_field_type_common_get_type_id(type);
        ctx->cur_field_type = type;
 
        /* Resolve sequence/variant field type */
@@ -1158,7 +1156,7 @@ int resolve_type(struct bt_field_type *type, struct resolve_context *ctx)
                        goto end;
                }
 
-               field_count = bt_field_type_get_field_count(type);
+               field_count = bt_field_type_common_get_field_count(type);
                if (field_count < 0) {
                        BT_LOGW("Cannot get field type's field count: "
                                "ret=%" PRId64 ", ft-addr=%p",
@@ -1168,8 +1166,8 @@ int resolve_type(struct bt_field_type *type, struct resolve_context *ctx)
                }
 
                for (f_index = 0; f_index < field_count; f_index++) {
-                       struct bt_field_type *child_type =
-                               bt_field_type_get_field_at_index(type,
+                       struct bt_field_type_common *child_type =
+                               bt_field_type_common_get_field_at_index(type,
                                        f_index);
 
                        if (!child_type) {
@@ -1230,12 +1228,12 @@ int resolve_root_type(enum bt_scope root_scope, struct resolve_context *ctx)
 BT_HIDDEN
 int bt_resolve_types(
                struct bt_value *environment,
-               struct bt_field_type *packet_header_type,
-               struct bt_field_type *packet_context_type,
-               struct bt_field_type *event_header_type,
-               struct bt_field_type *stream_event_ctx_type,
-               struct bt_field_type *event_context_type,
-               struct bt_field_type *event_payload_type,
+               struct bt_field_type_common *packet_header_type,
+               struct bt_field_type_common *packet_context_type,
+               struct bt_field_type_common *event_header_type,
+               struct bt_field_type_common *stream_event_ctx_type,
+               struct bt_field_type_common *event_context_type,
+               struct bt_field_type_common *event_payload_type,
                enum bt_resolve_flag flags)
 {
        int ret = 0;
index 9ca8ffb4df7c2c1ef46fbb4876050a785ca2a199..92d09467ee79eeb4fce6654b4a6ac343006430e8 100644 (file)
 #define BT_LOG_TAG "STREAM-CLASS"
 #include <babeltrace/lib-logging-internal.h>
 
-#include <babeltrace/ctf-writer/clock.h>
-#include <babeltrace/ctf-writer/clock-internal.h>
+#include <babeltrace/assert-pre-internal.h>
 #include <babeltrace/ctf-ir/clock-class-internal.h>
-#include <babeltrace/ctf-writer/event.h>
 #include <babeltrace/ctf-ir/event-class-internal.h>
-#include <babeltrace/ctf-ir/event-internal.h>
 #include <babeltrace/ctf-ir/field-types-internal.h>
 #include <babeltrace/ctf-ir/fields-internal.h>
-#include <babeltrace/ctf-writer/stream.h>
 #include <babeltrace/ctf-ir/stream-class-internal.h>
 #include <babeltrace/ctf-ir/validation-internal.h>
 #include <babeltrace/ctf-ir/visitor-internal.h>
-#include <babeltrace/ctf-writer/functor-internal.h>
 #include <babeltrace/ctf-ir/utils.h>
 #include <babeltrace/ctf-ir/utils-internal.h>
 #include <babeltrace/ref.h>
 #include <babeltrace/align-internal.h>
 #include <babeltrace/endian-internal.h>
 #include <babeltrace/assert-internal.h>
-#include <babeltrace/assert-pre-internal.h>
 #include <inttypes.h>
 #include <stdint.h>
 #include <stdbool.h>
 
-static
-void bt_stream_class_destroy(struct bt_object *obj);
-static
-int init_event_header(struct bt_stream_class *stream_class);
-static
-int init_packet_context(struct bt_stream_class *stream_class);
-
-struct bt_stream_class *bt_stream_class_create(const char *name)
-{
-       struct bt_stream_class *stream_class;
-       int ret;
-
-       BT_LOGD("Creating default stream class object: name=\"%s\"", name);
-       stream_class = bt_stream_class_create_empty(name);
-       if (!stream_class) {
-               BT_LOGD_STR("Cannot create empty stream class.");
-               goto error;
-       }
-
-       ret = init_event_header(stream_class);
-       if (ret) {
-               BT_LOGE_STR("Cannot initialize stream class's event header field type.");
-               goto error;
-       }
-
-       ret = init_packet_context(stream_class);
-       if (ret) {
-               BT_LOGE_STR("Cannot initialize stream class's packet context field type.");
-               goto error;
-       }
-
-       BT_LOGD("Created default stream class object: addr=%p, name=\"%s\"",
-               stream_class, name);
-       return stream_class;
-
-error:
-       BT_PUT(stream_class);
-       return stream_class;
-}
-
-struct bt_stream_class *bt_stream_class_create_empty(const char *name)
+BT_HIDDEN
+int bt_stream_class_common_initialize(struct bt_stream_class_common *stream_class,
+               const char *name, bt_object_release_func release_func)
 {
-       struct bt_stream_class *stream_class = NULL;
-
-       BT_LOGD("Creating empty stream class object: name=\"%s\"", name);
-
-       stream_class = g_new0(struct bt_stream_class, 1);
-       if (!stream_class) {
-               BT_LOGE_STR("Failed to allocate one stream class.");
-               goto error;
-       }
+       BT_LOGD("Initializing common stream class object: name=\"%s\"", name);
 
+       bt_object_init(stream_class, release_func);
        stream_class->name = g_string_new(name);
        stream_class->event_classes = g_ptr_array_new_with_free_func(
                (GDestroyNotify) bt_object_release);
@@ -121,227 +70,117 @@ struct bt_stream_class *bt_stream_class_create_empty(const char *name)
                goto error;
        }
 
-       bt_object_init(stream_class, bt_stream_class_destroy);
-       BT_LOGD("Created empty stream class object: addr=%p, name=\"%s\"",
+       BT_LOGD("Initialized common stream class object: addr=%p, name=\"%s\"",
                stream_class, name);
-       return stream_class;
+       return 0;
 
 error:
-       BT_PUT(stream_class);
-       return stream_class;
-}
-
-struct bt_trace *bt_stream_class_get_trace(
-               struct bt_stream_class *stream_class)
-{
-       BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
-       return bt_get(bt_stream_class_borrow_trace(stream_class));
+       return -1;
 }
 
-const char *bt_stream_class_get_name(
-               struct bt_stream_class *stream_class)
-{
-       BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
-       return stream_class->name->len > 0 ? stream_class->name->str : NULL;
-}
-
-int bt_stream_class_set_name(struct bt_stream_class *stream_class,
-               const char *name)
+BT_HIDDEN
+void bt_stream_class_common_finalize(struct bt_stream_class_common *stream_class)
 {
-       int ret = 0;
+       BT_LOGD("Finalizing common stream class: addr=%p, name=\"%s\", id=%" PRId64,
+               stream_class, bt_stream_class_common_get_name(stream_class),
+               bt_stream_class_common_get_id(stream_class));
+       bt_put(stream_class->clock_class);
 
-       if (!stream_class) {
-               BT_LOGW_STR("Invalid parameter: stream class is NULL.");
-               ret = -1;
-               goto end;
+       if (stream_class->event_classes_ht) {
+               g_hash_table_destroy(stream_class->event_classes_ht);
+       }
+       if (stream_class->event_classes) {
+               BT_LOGD_STR("Destroying event classes.");
+               g_ptr_array_free(stream_class->event_classes, TRUE);
        }
 
-       if (stream_class->frozen) {
-               BT_LOGW("Invalid parameter: stream class is frozen: "
-                       "addr=%p, name=\"%s\", id=%" PRId64,
-                       stream_class, bt_stream_class_get_name(stream_class),
-                       bt_stream_class_get_id(stream_class));
-               ret = -1;
-               goto end;
+       if (stream_class->name) {
+               g_string_free(stream_class->name, TRUE);
        }
 
-       if (!name) {
-               g_string_assign(stream_class->name, "");
-       } else {
-               if (strlen(name) == 0) {
-                       BT_LOGW("Invalid parameter: name is empty.");
-                       ret = -1;
-                       goto end;
-               }
+       BT_LOGD_STR("Putting event header field type.");
+       bt_put(stream_class->event_header_field_type);
+       BT_LOGD_STR("Putting packet context field type.");
+       bt_put(stream_class->packet_context_field_type);
+       BT_LOGD_STR("Putting event context field type.");
+       bt_put(stream_class->event_context_field_type);
+}
 
-               g_string_assign(stream_class->name, name);
-       }
+static
+void bt_stream_class_destroy(struct bt_object *obj)
+{
+       struct bt_stream_class *stream_class;
 
-       BT_LOGV("Set stream class's name: "
-               "addr=%p, name=\"%s\", id=%" PRId64,
+       stream_class = (void *) obj;
+       BT_LOGD("Destroying stream class: addr=%p, name=\"%s\", id=%" PRId64,
                stream_class, bt_stream_class_get_name(stream_class),
                bt_stream_class_get_id(stream_class));
-end:
-       return ret;
+       bt_stream_class_common_finalize(BT_TO_COMMON(stream_class));
+       g_free(stream_class);
 }
 
-struct bt_ctf_clock *bt_stream_class_get_clock(
-               struct bt_stream_class *stream_class)
+struct bt_stream_class *bt_stream_class_create(const char *name)
 {
-       struct bt_ctf_clock *clock = NULL;
+       struct bt_stream_class *stream_class = NULL;
+       int ret;
 
+       BT_LOGD("Creating stream class object: name=\"%s\"", name);
+       stream_class = g_new0(struct bt_stream_class, 1);
        if (!stream_class) {
-               BT_LOGW_STR("Invalid parameter: stream class is NULL.");
-               goto end;
+               BT_LOGE_STR("Failed to allocate one stream class.");
+               goto error;
        }
 
-       if (!stream_class->clock) {
-               BT_LOGV("Stream class has no clock: "
-                       "addr=%p, name=\"%s\", id=%" PRId64,
-                       stream_class, bt_stream_class_get_name(stream_class),
-                       bt_stream_class_get_id(stream_class));
-               goto end;
+       ret = bt_stream_class_common_initialize(BT_TO_COMMON(stream_class),
+               name, bt_stream_class_destroy);
+       if (ret) {
+               /* bt_stream_class_common_initialize() logs errors */
+               goto error;
        }
 
-       clock = bt_get(stream_class->clock);
-end:
-       return clock;
+       BT_LOGD("Created stream class object: addr=%p, name=\"%s\"",
+               stream_class, name);
+       return stream_class;
+
+error:
+       bt_put(stream_class);
+       return NULL;
 }
 
-int bt_stream_class_set_clock(struct bt_stream_class *stream_class,
-               struct bt_ctf_clock *clock)
+struct bt_trace *bt_stream_class_get_trace(struct bt_stream_class *stream_class)
 {
-       int ret = 0;
-       struct bt_field_type *timestamp_field = NULL;
-
-       if (!stream_class || !clock) {
-               BT_LOGW("Invalid parameter: stream class or clock is NULL: "
-                       "stream-class-addr=%p, clock-addr=%p",
-                       stream_class, clock);
-               ret = -1;
-               goto end;
-       }
-
-       if (stream_class->frozen) {
-               BT_LOGW("Invalid parameter: stream class is frozen: "
-                       "addr=%p, name=\"%s\", id=%" PRId64,
-                       stream_class, bt_stream_class_get_name(stream_class),
-                       bt_stream_class_get_id(stream_class));
-               ret = -1;
-               goto end;
-       }
-
-       /* Replace the current clock of this stream class. */
-       bt_put(stream_class->clock);
-       stream_class->clock = bt_get(clock);
-       BT_LOGV("Set stream class's clock: "
-               "addr=%p, name=\"%s\", id=%" PRId64 ", "
-               "clock-addr=%p, clock-name=\"%s\"",
-               stream_class, bt_stream_class_get_name(stream_class),
-               bt_stream_class_get_id(stream_class),
-               stream_class->clock,
-               bt_ctf_clock_get_name(stream_class->clock));
-
-end:
-       bt_put(timestamp_field);
-       return ret;
+       return BT_FROM_COMMON(bt_stream_class_common_get_trace(
+               BT_TO_COMMON(stream_class)));
 }
 
-int64_t bt_stream_class_get_id(struct bt_stream_class *stream_class)
+const char *bt_stream_class_get_name(struct bt_stream_class *stream_class)
 {
-       int64_t ret;
-
-       BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
-
-       if (!stream_class->id_set) {
-               BT_LOGV("Stream class's ID is not set: addr=%p, name=\"%s\"",
-                       stream_class,
-                       bt_stream_class_get_name(stream_class));
-               ret = (int64_t) -1;
-               goto end;
-       }
-
-       ret = stream_class->id;
-
-end:
-       return ret;
+       return bt_stream_class_common_get_name(BT_TO_COMMON(stream_class));
 }
 
-BT_HIDDEN
-void _bt_stream_class_set_id(
-               struct bt_stream_class *stream_class, int64_t id)
+int bt_stream_class_set_name(struct bt_stream_class *stream_class,
+               const char *name)
 {
-       BT_ASSERT(stream_class);
-       stream_class->id = id;
-       stream_class->id_set = 1;
-       BT_LOGV("Set stream class's ID (internal): "
-               "addr=%p, name=\"%s\", id=%" PRId64,
-               stream_class, bt_stream_class_get_name(stream_class),
-               bt_stream_class_get_id(stream_class));
+       return bt_stream_class_common_set_name(BT_TO_COMMON(stream_class),
+               name);
 }
 
-struct event_class_set_stream_class_id_data {
-       int64_t stream_class_id;
-       int ret;
-};
-
-BT_HIDDEN
-int bt_stream_class_set_id_no_check(
-               struct bt_stream_class *stream_class, int64_t id)
+int64_t bt_stream_class_get_id(struct bt_stream_class *stream_class)
 {
-       _bt_stream_class_set_id(stream_class, id);
-       return 0;
+       return bt_stream_class_common_get_id(BT_TO_COMMON(stream_class));
 }
 
-int bt_stream_class_set_id(struct bt_stream_class *stream_class,
-               uint64_t id_param)
+int bt_stream_class_set_id(struct bt_stream_class *stream_class, uint64_t id)
 {
-       int ret = 0;
-       int64_t id = (int64_t) id_param;
-
-       if (!stream_class) {
-               BT_LOGW_STR("Invalid parameter: stream class is NULL.");
-               ret = -1;
-               goto end;
-       }
-
-       if (stream_class->frozen) {
-               BT_LOGW("Invalid parameter: stream class is frozen: "
-                       "addr=%p, name=\"%s\", id=%" PRId64,
-                       stream_class, bt_stream_class_get_name(stream_class),
-                       bt_stream_class_get_id(stream_class));
-               ret = -1;
-               goto end;
-       }
-
-       if (id < 0) {
-               BT_LOGW("Invalid parameter: invalid stream class's ID: "
-                       "stream-class-addr=%p, stream-class-name=\"%s\", "
-                       "stream-class-id=%" PRId64 ", id=%" PRIu64,
-                       stream_class, bt_stream_class_get_name(stream_class),
-                       bt_stream_class_get_id(stream_class),
-                       id_param);
-               ret = -1;
-               goto end;
-       }
-
-       ret = bt_stream_class_set_id_no_check(stream_class, id);
-       if (ret == 0) {
-               BT_LOGV("Set stream class's ID: "
-                       "addr=%p, name=\"%s\", id=%" PRId64,
-                       stream_class, bt_stream_class_get_name(stream_class),
-                       bt_stream_class_get_id(stream_class));
-       }
-end:
-       return ret;
+       return bt_stream_class_common_set_id(BT_TO_COMMON(stream_class), id);
 }
 
 static
 void event_class_exists(gpointer element, gpointer query)
 {
-       struct bt_event_class *event_class_a = element;
+       struct bt_event_class_common *event_class_a = element;
        struct search_query *search_query = query;
-       struct bt_event_class *event_class_b = search_query->value;
+       struct bt_event_class_common *event_class_b = search_query->value;
        int64_t id_a, id_b;
 
        if (search_query->value == element) {
@@ -353,8 +192,8 @@ void event_class_exists(gpointer element, gpointer query)
         * Two event classes cannot share the same ID in a given
         * stream class.
         */
-       id_a = bt_event_class_get_id(event_class_a);
-       id_b = bt_event_class_get_id(event_class_b);
+       id_a = bt_event_class_common_get_id(event_class_a);
+       id_b = bt_event_class_common_get_id(event_class_b);
 
        if (id_a < 0 || id_b < 0) {
                /* at least one ID is not set: will be automatically set later */
@@ -364,7 +203,7 @@ void event_class_exists(gpointer element, gpointer query)
        if (id_a == id_b) {
                BT_LOGW("Event class with this ID already exists in the stream class: "
                        "id=%" PRId64 ", name=\"%s\"",
-                       id_a, bt_event_class_get_name(event_class_a));
+                       id_a, bt_event_class_common_get_name(event_class_a));
                search_query->found = 1;
                goto end;
        }
@@ -373,25 +212,29 @@ end:
        return;
 }
 
-int bt_stream_class_add_event_class(
-               struct bt_stream_class *stream_class,
-               struct bt_event_class *event_class)
+BT_HIDDEN
+int bt_stream_class_common_add_event_class(
+               struct bt_stream_class_common *stream_class,
+               struct bt_event_class_common *event_class,
+               bt_validation_flag_copy_field_type_func copy_field_type_func)
 {
        int ret = 0;
        int64_t *event_id = NULL;
-       struct bt_trace *trace = NULL;
-       struct bt_stream_class *old_stream_class = NULL;
+       struct bt_trace_common *trace = NULL;
+       struct bt_stream_class_common *old_stream_class = NULL;
        struct bt_validation_output validation_output = { 0 };
-       struct bt_field_type *packet_header_type = NULL;
-       struct bt_field_type *packet_context_type = NULL;
-       struct bt_field_type *event_header_type = NULL;
-       struct bt_field_type *stream_event_ctx_type = NULL;
-       struct bt_field_type *event_context_type = NULL;
-       struct bt_field_type *event_payload_type = NULL;
+       struct bt_field_type_common *packet_header_type = NULL;
+       struct bt_field_type_common *packet_context_type = NULL;
+       struct bt_field_type_common *event_header_type = NULL;
+       struct bt_field_type_common *stream_event_ctx_type = NULL;
+       struct bt_field_type_common *event_context_type = NULL;
+       struct bt_field_type_common *event_payload_type = NULL;
        const enum bt_validation_flag validation_flags =
                BT_VALIDATION_FLAG_EVENT;
        struct bt_clock_class *expected_clock_class = NULL;
 
+       BT_ASSERT(copy_field_type_func);
+
        if (!stream_class || !event_class) {
                BT_LOGW("Invalid parameter: stream class or event class is NULL: "
                        "stream-class-addr=%p, event-class-addr=%p",
@@ -404,20 +247,13 @@ int bt_stream_class_add_event_class(
                "stream-class-addr=%p, stream-class-name=\"%s\", "
                "stream-class-id=%" PRId64 ", event-class-addr=%p, "
                "event-class-name=\"%s\", event-class-id=%" PRId64,
-               stream_class, bt_stream_class_get_name(stream_class),
-               bt_stream_class_get_id(stream_class),
+               stream_class, bt_stream_class_common_get_name(stream_class),
+               bt_stream_class_common_get_id(stream_class),
                event_class,
-               bt_event_class_get_name(event_class),
-               bt_event_class_get_id(event_class));
+               bt_event_class_common_get_name(event_class),
+               bt_event_class_common_get_id(event_class));
 
-       trace = bt_stream_class_get_trace(stream_class);
-       if (trace && trace->is_static) {
-               BT_LOGW("Invalid parameter: stream class's trace is static: "
-                       "trace-addr=%p, trace-name=\"%s\"",
-                       trace, bt_trace_get_name(trace));
-               ret = -1;
-               goto end;
-       }
+       trace = bt_stream_class_common_get_trace(stream_class);
 
        if (stream_class->frozen) {
                /*
@@ -439,7 +275,7 @@ int bt_stream_class_add_event_class(
                 * and bt_event_class_validate_single_clock_class()
                 * below can set it.
                 */
-               ret = bt_event_class_validate_single_clock_class(
+               ret = bt_event_class_common_validate_single_clock_class(
                        event_class, &expected_clock_class);
                if (ret) {
                        BT_LOGW("Event class contains a field type which is not "
@@ -451,8 +287,8 @@ int bt_stream_class_add_event_class(
                                "expected-clock-class-addr=%p, "
                                "expected-clock-class-name=\"%s\"",
                                stream_class,
-                               bt_stream_class_get_id(stream_class),
-                               bt_stream_class_get_name(stream_class),
+                               bt_stream_class_common_get_id(stream_class),
+                               bt_stream_class_common_get_name(stream_class),
                                expected_clock_class,
                                expected_clock_class ?
                                        bt_clock_class_get_name(expected_clock_class) :
@@ -478,7 +314,7 @@ int bt_stream_class_add_event_class(
                goto end;
        }
 
-       old_stream_class = bt_event_class_get_stream_class(event_class);
+       old_stream_class = bt_event_class_common_borrow_stream_class(event_class);
        if (old_stream_class) {
                /* Event class is already associated to a stream class. */
                BT_LOGW("Event class is already part of another stream class: "
@@ -486,8 +322,8 @@ int bt_stream_class_add_event_class(
                        "event-class-stream-class-name=\"%s\", "
                        "event-class-stream-class-id=%" PRId64,
                        old_stream_class,
-                       bt_stream_class_get_name(old_stream_class),
-                       bt_stream_class_get_id(old_stream_class));
+                       bt_stream_class_common_get_name(old_stream_class),
+                       bt_stream_class_common_get_id(old_stream_class));
                ret = -1;
                goto end;
        }
@@ -505,26 +341,28 @@ int bt_stream_class_add_event_class(
                BT_ASSERT(trace->valid);
                BT_ASSERT(stream_class->valid);
                packet_header_type =
-                       bt_trace_get_packet_header_type(trace);
+                       bt_trace_common_get_packet_header_field_type(trace);
                packet_context_type =
-                       bt_stream_class_get_packet_context_type(
+                       bt_stream_class_common_get_packet_context_field_type(
                                stream_class);
                event_header_type =
-                       bt_stream_class_get_event_header_type(stream_class);
+                       bt_stream_class_common_get_event_header_field_type(
+                               stream_class);
                stream_event_ctx_type =
-                       bt_stream_class_get_event_context_type(
+                       bt_stream_class_common_get_event_context_field_type(
                                stream_class);
                event_context_type =
-                       bt_event_class_get_context_type(event_class);
+                       bt_event_class_common_get_context_field_type(event_class);
                event_payload_type =
-                       bt_event_class_get_payload_type(event_class);
+                       bt_event_class_common_get_payload_field_type(event_class);
                ret = bt_validate_class_types(
                        trace->environment, packet_header_type,
                        packet_context_type, event_header_type,
                        stream_event_ctx_type, event_context_type,
                        event_payload_type, trace->valid,
                        stream_class->valid, event_class->valid,
-                       &validation_output, validation_flags);
+                       &validation_output, validation_flags,
+                       copy_field_type_func);
                BT_PUT(packet_header_type);
                BT_PUT(packet_context_type);
                BT_PUT(event_header_type);
@@ -554,12 +392,12 @@ int bt_stream_class_add_event_class(
        }
 
        /* Only set an event ID if none was explicitly set before */
-       *event_id = bt_event_class_get_id(event_class);
+       *event_id = bt_event_class_common_get_id(event_class);
        if (*event_id < 0) {
                BT_LOGV("Event class has no ID: automatically setting it: "
                        "id=%" PRId64, stream_class->next_event_id);
 
-               if (bt_event_class_set_id(event_class,
+               if (bt_event_class_common_set_id(event_class,
                                stream_class->next_event_id)) {
                        BT_LOGE("Cannot set event class's ID: id=%" PRId64,
                                stream_class->next_event_id);
@@ -597,7 +435,7 @@ int bt_stream_class_add_event_class(
        event_id = NULL;
 
        /* Freeze the event class */
-       bt_event_class_freeze(event_class);
+       bt_event_class_common_freeze(event_class);
 
        /*
         * It is safe to set the stream class's unique clock class
@@ -609,27 +447,18 @@ int bt_stream_class_add_event_class(
                BT_MOVE(stream_class->clock_class, expected_clock_class);
        }
 
-       /* Notifiy listeners of the trace's schema modification. */
-       if (trace) {
-               struct bt_visitor_object obj = { .object = event_class,
-                               .type = BT_VISITOR_OBJECT_TYPE_EVENT_CLASS };
-
-               (void) bt_trace_object_modification(&obj, trace);
-       }
-
        BT_LOGD("Added event class to stream class: "
                "stream-class-addr=%p, stream-class-name=\"%s\", "
                "stream-class-id=%" PRId64 ", event-class-addr=%p, "
                "event-class-name=\"%s\", event-class-id=%" PRId64,
-               stream_class, bt_stream_class_get_name(stream_class),
-               bt_stream_class_get_id(stream_class),
+               stream_class, bt_stream_class_common_get_name(stream_class),
+               bt_stream_class_common_get_id(stream_class),
                event_class,
-               bt_event_class_get_name(event_class),
-               bt_event_class_get_id(event_class));
+               bt_event_class_common_get_name(event_class),
+               bt_event_class_common_get_id(event_class));
 
 end:
        BT_PUT(trace);
-       BT_PUT(old_stream_class);
        bt_validation_output_put_types(&validation_output);
        bt_put(expected_clock_class);
        BT_ASSERT(!packet_header_type);
@@ -639,253 +468,116 @@ end:
        BT_ASSERT(!event_context_type);
        BT_ASSERT(!event_payload_type);
        g_free(event_id);
-
        return ret;
 }
 
-int64_t bt_stream_class_get_event_class_count(
-               struct bt_stream_class *stream_class)
+int bt_stream_class_add_event_class(
+               struct bt_stream_class *stream_class,
+               struct bt_event_class *event_class)
 {
-       int64_t ret;
+       struct bt_trace *trace;
+       int ret = 0;
 
        if (!stream_class) {
-               BT_LOGW_STR("Invalid parameter: stream class is NULL.");
-               ret = (int64_t) -1;
+               BT_LOGW("Invalid parameter: stream class is NULL: "
+                       "stream-class-addr=%p", stream_class);
+               ret = -1;
+               goto end;
+       }
+
+       trace = BT_FROM_COMMON(bt_stream_class_common_borrow_trace(
+               BT_TO_COMMON(stream_class)));
+       if (trace && trace->is_static) {
+               BT_LOGW("Invalid parameter: stream class's trace is static: "
+                       "trace-addr=%p, trace-name=\"%s\"",
+                       trace, bt_trace_get_name(trace));
+               ret = -1;
+               goto end;
+       }
+
+       ret = bt_stream_class_common_add_event_class(
+               BT_TO_COMMON(stream_class), BT_TO_COMMON(event_class),
+               (bt_validation_flag_copy_field_type_func) bt_field_type_copy);
+       if (ret) {
                goto end;
        }
 
-       ret = (int64_t) stream_class->event_classes->len;
+       /* Notifiy listeners of the trace's schema modification. */
+       if (trace) {
+               struct bt_visitor_object obj = { .object = event_class,
+                               .type = BT_VISITOR_OBJECT_TYPE_EVENT_CLASS };
+
+               (void) bt_trace_object_modification(&obj, trace);
+       }
+
 end:
        return ret;
 }
 
+int64_t bt_stream_class_get_event_class_count(
+               struct bt_stream_class *stream_class)
+{
+       return bt_stream_class_common_get_event_class_count(
+               BT_TO_COMMON(stream_class));
+}
+
 struct bt_event_class *bt_stream_class_get_event_class_by_index(
                struct bt_stream_class *stream_class, uint64_t index)
 {
-       BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
-       BT_ASSERT_PRE(index < stream_class->event_classes->len,
-               "Index is out of bounds: index=%" PRIu64 ", "
-               "count=%u",
-               index, stream_class->event_classes->len);
-       return bt_get(g_ptr_array_index(stream_class->event_classes, index));
+       return BT_FROM_COMMON(bt_stream_class_common_get_event_class_by_index(
+               BT_TO_COMMON(stream_class), index));
 }
 
 struct bt_event_class *bt_stream_class_get_event_class_by_id(
                struct bt_stream_class *stream_class, uint64_t id)
 {
-       int64_t id_key = (int64_t) id;
-
-       BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
-       BT_ASSERT_PRE(id_key >= 0,
-               "Invalid event class ID: %" PRIu64, id);
-       return bt_get(g_hash_table_lookup(stream_class->event_classes_ht,
-                       &id_key));
+       return BT_FROM_COMMON(bt_stream_class_common_get_event_class_by_id(
+               BT_TO_COMMON(stream_class), id));
 }
 
-struct bt_field_type *bt_stream_class_get_packet_context_type(
+struct bt_field_type *bt_stream_class_get_packet_context_field_type(
                struct bt_stream_class *stream_class)
 {
-       BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
-       return bt_get(stream_class->packet_context_type);
+       return BT_FROM_COMMON(bt_stream_class_common_get_packet_context_field_type(
+               BT_TO_COMMON(stream_class)));
 }
 
-int bt_stream_class_set_packet_context_type(
+int bt_stream_class_set_packet_context_field_type(
                struct bt_stream_class *stream_class,
                struct bt_field_type *packet_context_type)
 {
-       int ret = 0;
-
-       if (!stream_class) {
-               BT_LOGW_STR("Invalid parameter: stream class is NULL.");
-               ret = -1;
-               goto end;
-       }
-
-       if (stream_class->frozen) {
-               BT_LOGW("Invalid parameter: stream class is frozen: "
-                       "addr=%p, name=\"%s\", id=%" PRId64,
-                       stream_class, bt_stream_class_get_name(stream_class),
-                       bt_stream_class_get_id(stream_class));
-               ret = -1;
-               goto end;
-       }
-
-       if (packet_context_type &&
-                       bt_field_type_get_type_id(packet_context_type) !=
-                               BT_FIELD_TYPE_ID_STRUCT) {
-               /* A packet context must be a structure. */
-               BT_LOGW("Invalid parameter: stream class's packet context field type must be a structure: "
-                       "addr=%p, name=\"%s\", id=%" PRId64 ", "
-                       "packet-context-ft-addr=%p, packet-context-ft-id=%s",
-                       stream_class, bt_stream_class_get_name(stream_class),
-                       bt_stream_class_get_id(stream_class),
-                       packet_context_type,
-                       bt_field_type_id_string(
-                               bt_field_type_get_type_id(packet_context_type)));
-               ret = -1;
-               goto end;
-       }
-
-       bt_put(stream_class->packet_context_type);
-       bt_get(packet_context_type);
-       stream_class->packet_context_type = packet_context_type;
-       BT_LOGV("Set stream class's packet context field type: "
-               "addr=%p, name=\"%s\", id=%" PRId64 ", "
-               "packet-context-ft-addr=%p",
-               stream_class, bt_stream_class_get_name(stream_class),
-               bt_stream_class_get_id(stream_class),
-               packet_context_type);
-
-end:
-       return ret;
+       return bt_stream_class_common_set_packet_context_field_type(
+               BT_TO_COMMON(stream_class), (void *) packet_context_type);
 }
 
-struct bt_field_type *bt_stream_class_get_event_header_type(
+struct bt_field_type *bt_stream_class_get_event_header_field_type(
                struct bt_stream_class *stream_class)
 {
-       struct bt_field_type *ret = NULL;
-
-       BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
-
-       if (!stream_class->event_header_type) {
-               BT_LOGV("Stream class has no event header field type: "
-                       "addr=%p, name=\"%s\", id=%" PRId64,
-                       stream_class, bt_stream_class_get_name(stream_class),
-                       bt_stream_class_get_id(stream_class));
-               goto end;
-       }
-
-       ret = bt_get(stream_class->event_header_type);
-
-end:
-       return ret;
+       return BT_FROM_COMMON(bt_stream_class_common_get_event_header_field_type(
+               BT_TO_COMMON(stream_class)));
 }
 
-int bt_stream_class_set_event_header_type(
+int bt_stream_class_set_event_header_field_type(
                struct bt_stream_class *stream_class,
                struct bt_field_type *event_header_type)
 {
-       int ret = 0;
-
-       if (!stream_class) {
-               BT_LOGW_STR("Invalid parameter: stream class is NULL.");
-               ret = -1;
-               goto end;
-       }
-
-       if (stream_class->frozen) {
-               BT_LOGW("Invalid parameter: stream class is frozen: "
-                       "addr=%p, name=\"%s\", id=%" PRId64,
-                       stream_class, bt_stream_class_get_name(stream_class),
-                       bt_stream_class_get_id(stream_class));
-               ret = -1;
-               goto end;
-       }
-
-       if (event_header_type &&
-                       bt_field_type_get_type_id(event_header_type) !=
-                               BT_FIELD_TYPE_ID_STRUCT) {
-               /* An event header must be a structure. */
-               BT_LOGW("Invalid parameter: stream class's event header field type must be a structure: "
-                       "addr=%p, name=\"%s\", id=%" PRId64 ", "
-                       "event-header-ft-addr=%p, event-header-ft-id=%s",
-                       stream_class, bt_stream_class_get_name(stream_class),
-                       bt_stream_class_get_id(stream_class),
-                       event_header_type,
-                       bt_field_type_id_string(
-                               bt_field_type_get_type_id(event_header_type)));
-               ret = -1;
-               goto end;
-       }
-
-       bt_put(stream_class->event_header_type);
-       stream_class->event_header_type = bt_get(event_header_type);
-       BT_LOGV("Set stream class's event header field type: "
-               "addr=%p, name=\"%s\", id=%" PRId64 ", "
-               "event-header-ft-addr=%p",
-               stream_class, bt_stream_class_get_name(stream_class),
-               bt_stream_class_get_id(stream_class),
-               event_header_type);
-end:
-       return ret;
+       return bt_stream_class_common_set_event_header_field_type(
+               BT_TO_COMMON(stream_class), (void *) event_header_type);
 }
 
-struct bt_field_type *bt_stream_class_get_event_context_type(
+struct bt_field_type *bt_stream_class_get_event_context_field_type(
                struct bt_stream_class *stream_class)
 {
-       struct bt_field_type *ret = NULL;
-
-       BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
-
-       if (!stream_class->event_context_type) {
-               goto end;
-       }
-
-       ret = bt_get(stream_class->event_context_type);
-
-end:
-       return ret;
+       return BT_FROM_COMMON(bt_stream_class_common_get_event_context_field_type(
+               BT_TO_COMMON(stream_class)));
 }
 
-int bt_stream_class_set_event_context_type(
+int bt_stream_class_set_event_context_field_type(
                struct bt_stream_class *stream_class,
                struct bt_field_type *event_context_type)
 {
-       int ret = 0;
-
-       if (!stream_class) {
-               BT_LOGW_STR("Invalid parameter: stream class is NULL.");
-               ret = -1;
-               goto end;
-       }
-
-       if (stream_class->frozen) {
-               BT_LOGW("Invalid parameter: stream class is frozen: "
-                       "addr=%p, name=\"%s\", id=%" PRId64,
-                       stream_class, bt_stream_class_get_name(stream_class),
-                       bt_stream_class_get_id(stream_class));
-               ret = -1;
-               goto end;
-       }
-
-       if (event_context_type &&
-                       bt_field_type_get_type_id(event_context_type) !=
-                               BT_FIELD_TYPE_ID_STRUCT) {
-               /* A packet context must be a structure. */
-               BT_LOGW("Invalid parameter: stream class's event context field type must be a structure: "
-                       "addr=%p, name=\"%s\", id=%" PRId64 ", "
-                       "event-context-ft-addr=%p, event-context-ft-id=%s",
-                       stream_class, bt_stream_class_get_name(stream_class),
-                       bt_stream_class_get_id(stream_class),
-                       event_context_type,
-                       bt_field_type_id_string(
-                               bt_field_type_get_type_id(event_context_type)));
-               ret = -1;
-               goto end;
-       }
-
-       bt_put(stream_class->event_context_type);
-       stream_class->event_context_type = bt_get(event_context_type);
-       BT_LOGV("Set stream class's event context field type: "
-               "addr=%p, name=\"%s\", id=%" PRId64 ", "
-               "event-context-ft-addr=%p",
-               stream_class, bt_stream_class_get_name(stream_class),
-               bt_stream_class_get_id(stream_class),
-               event_context_type);
-end:
-       return ret;
-}
-
-/* Pre-2.0 CTF writer backward compatibility */
-void bt_ctf_stream_class_get(struct bt_stream_class *stream_class)
-{
-       bt_get(stream_class);
-}
-
-/* Pre-2.0 CTF writer backward compatibility */
-void bt_ctf_stream_class_put(struct bt_stream_class *stream_class)
-{
-       bt_put(stream_class);
+       return bt_stream_class_common_set_event_context_field_type(
+               BT_TO_COMMON(stream_class), (void *) event_context_type);
 }
 
 static
@@ -905,20 +597,23 @@ void *get_event_class(void *element, int i)
 static
 int visit_event_class(void *object, bt_visitor visitor,void *data)
 {
-       struct bt_visitor_object obj =
-                       { .object = object,
-                       .type = BT_VISITOR_OBJECT_TYPE_EVENT_CLASS };
+       struct bt_visitor_object obj = {
+               .object = object,
+               .type = BT_VISITOR_OBJECT_TYPE_EVENT_CLASS
+       };
 
        return visitor(&obj, data);
 }
 
-int bt_stream_class_visit(struct bt_stream_class *stream_class,
+BT_HIDDEN
+int bt_stream_class_common_visit(struct bt_stream_class_common *stream_class,
                bt_visitor visitor, void *data)
 {
        int ret;
-       struct bt_visitor_object obj =
-                       { .object = stream_class,
-                       .type = BT_VISITOR_OBJECT_TYPE_STREAM_CLASS };
+       struct bt_visitor_object obj = {
+               .object = stream_class,
+               .type = BT_VISITOR_OBJECT_TYPE_STREAM_CLASS
+       };
 
        if (!stream_class || !visitor) {
                BT_LOGW("Invalid parameter: stream class or visitor is NULL: "
@@ -932,402 +627,43 @@ int bt_stream_class_visit(struct bt_stream_class *stream_class,
                        get_event_class,
                        visit_event_class, visitor, data);
        BT_LOGV("visitor_helper() returned: ret=%d", ret);
+
 end:
        return ret;
 }
 
+int bt_stream_class_visit(struct bt_stream_class *stream_class,
+               bt_visitor visitor, void *data)
+{
+       return bt_stream_class_common_visit(BT_FROM_COMMON(stream_class),
+               visitor, data);
+}
+
 BT_HIDDEN
-void bt_stream_class_freeze(struct bt_stream_class *stream_class)
+void bt_stream_class_common_freeze(struct bt_stream_class_common *stream_class)
 {
        if (!stream_class || stream_class->frozen) {
                return;
        }
 
        BT_LOGD("Freezing stream class: addr=%p, name=\"%s\", id=%" PRId64,
-               stream_class, bt_stream_class_get_name(stream_class),
-               bt_stream_class_get_id(stream_class));
+               stream_class, bt_stream_class_common_get_name(stream_class),
+               bt_stream_class_common_get_id(stream_class));
        stream_class->frozen = 1;
-       bt_field_type_freeze(stream_class->event_header_type);
-       bt_field_type_freeze(stream_class->packet_context_type);
-       bt_field_type_freeze(stream_class->event_context_type);
-
-       if (stream_class->clock) {
-               bt_clock_class_freeze(stream_class->clock->clock_class);
-       }
-}
-
-BT_HIDDEN
-int bt_stream_class_serialize(struct bt_stream_class *stream_class,
-               struct metadata_context *context)
-{
-       int ret = 0;
-       size_t i;
-       struct bt_trace *trace;
-       struct bt_field_type *packet_header_type = NULL;
-
-       BT_LOGD("Serializing stream class's metadata: "
-               "stream-class-addr=%p, stream-class-name=\"%s\", "
-               "stream-class-id=%" PRId64 ", metadata-context-addr=%p",
-               stream_class, bt_stream_class_get_name(stream_class),
-               bt_stream_class_get_id(stream_class), context);
-       g_string_assign(context->field_name, "");
-       context->current_indentation_level = 1;
-       if (!stream_class->id_set) {
-               BT_LOGW_STR("Stream class's ID is not set.");
-               ret = -1;
-               goto end;
-       }
-
-       g_string_append(context->string, "stream {\n");
-
-       /*
-        * The reference to the trace is only borrowed since the
-        * serialization of the stream class might have been triggered
-        * by the trace's destruction. In such a case, the trace's
-        * reference count would, unexepectedly, go through the sequence
-        * 1 -> 0 -> 1 -> 0 -> ..., provoking an endless loop of destruction
-        * and serialization.
-        */
-       trace = bt_stream_class_borrow_trace(stream_class);
-       BT_ASSERT(trace);
-       packet_header_type = bt_trace_get_packet_header_type(trace);
-       trace = NULL;
-       if (packet_header_type) {
-               struct bt_field_type *stream_id_type;
-
-               stream_id_type =
-                       bt_field_type_structure_get_field_type_by_name(
-                               packet_header_type, "stream_id");
-               if (stream_id_type) {
-                       /*
-                        * Only set the stream's id if the trace's packet header
-                        * contains a stream_id field. This field is only
-                        * needed if the trace contains only one stream
-                        * class.
-                        */
-                       g_string_append_printf(context->string,
-                               "\tid = %" PRId64 ";\n", stream_class->id);
-               }
-               bt_put(stream_id_type);
-       }
-       if (stream_class->event_header_type) {
-               BT_LOGD_STR("Serializing stream class's event header field type's metadata.");
-               g_string_append(context->string, "\tevent.header := ");
-               ret = bt_field_type_serialize(stream_class->event_header_type,
-                       context);
-               if (ret) {
-                       BT_LOGW("Cannot serialize stream class's event header field type's metadata: "
-                               "ret=%d", ret);
-                       goto end;
-               }
-               g_string_append(context->string, ";");
-       }
-
-
-       if (stream_class->packet_context_type) {
-               BT_LOGD_STR("Serializing stream class's packet context field type's metadata.");
-               g_string_append(context->string, "\n\n\tpacket.context := ");
-               ret = bt_field_type_serialize(stream_class->packet_context_type,
-                       context);
-               if (ret) {
-                       BT_LOGW("Cannot serialize stream class's packet context field type's metadata: "
-                               "ret=%d", ret);
-                       goto end;
-               }
-               g_string_append(context->string, ";");
-       }
-
-       if (stream_class->event_context_type) {
-               BT_LOGD_STR("Serializing stream class's event context field type's metadata.");
-               g_string_append(context->string, "\n\n\tevent.context := ");
-               ret = bt_field_type_serialize(
-                       stream_class->event_context_type, context);
-               if (ret) {
-                       BT_LOGW("Cannot serialize stream class's event context field type's metadata: "
-                               "ret=%d", ret);
-                       goto end;
-               }
-               g_string_append(context->string, ";");
-       }
-
-       g_string_append(context->string, "\n};\n\n");
-
-       for (i = 0; i < stream_class->event_classes->len; i++) {
-               struct bt_event_class *event_class =
-                       stream_class->event_classes->pdata[i];
-
-               ret = bt_event_class_serialize(event_class, context);
-               if (ret) {
-                       BT_LOGW("Cannot serialize event class's metadata: "
-                               "event-class-addr=%p, event-class-name=\"%s\", "
-                               "event-class-id=%" PRId64,
-                               event_class,
-                               bt_event_class_get_name(event_class),
-                               bt_event_class_get_id(event_class));
-                       goto end;
-               }
-       }
-end:
-       bt_put(packet_header_type);
-       context->current_indentation_level = 0;
-       return ret;
+       bt_field_type_common_freeze(stream_class->event_header_field_type);
+       bt_field_type_common_freeze(stream_class->packet_context_field_type);
+       bt_field_type_common_freeze(stream_class->event_context_field_type);
+       bt_clock_class_freeze(stream_class->clock_class);
 }
 
-static
-void bt_stream_class_destroy(struct bt_object *obj)
-{
-       struct bt_stream_class *stream_class;
-
-       stream_class = container_of(obj, struct bt_stream_class, base);
-       BT_LOGD("Destroying stream class: addr=%p, name=\"%s\", id=%" PRId64,
-               stream_class, bt_stream_class_get_name(stream_class),
-               bt_stream_class_get_id(stream_class));
-       bt_put(stream_class->clock);
-       bt_put(stream_class->clock_class);
-
-       if (stream_class->event_classes_ht) {
-               g_hash_table_destroy(stream_class->event_classes_ht);
-       }
-       if (stream_class->event_classes) {
-               BT_LOGD_STR("Destroying event classes.");
-               g_ptr_array_free(stream_class->event_classes, TRUE);
-       }
-
-       if (stream_class->name) {
-               g_string_free(stream_class->name, TRUE);
-       }
-
-       BT_LOGD_STR("Putting event header field type.");
-       bt_put(stream_class->event_header_type);
-       BT_LOGD_STR("Putting packet context field type.");
-       bt_put(stream_class->packet_context_type);
-       BT_LOGD_STR("Putting event context field type.");
-       bt_put(stream_class->event_context_type);
-       g_free(stream_class);
-}
-
-static
-int init_event_header(struct bt_stream_class *stream_class)
-{
-       int ret = 0;
-       struct bt_field_type *event_header_type =
-               bt_field_type_structure_create();
-       struct bt_field_type *_uint32_t =
-               get_field_type(FIELD_TYPE_ALIAS_UINT32_T);
-       struct bt_field_type *_uint64_t =
-               get_field_type(FIELD_TYPE_ALIAS_UINT64_T);
-
-       if (!event_header_type) {
-               BT_LOGE_STR("Cannot create empty structure field type.");
-               ret = -1;
-               goto end;
-       }
-
-       ret = bt_field_type_structure_add_field(event_header_type,
-               _uint32_t, "id");
-       if (ret) {
-               BT_LOGE_STR("Cannot add `id` field to event header field type.");
-               goto end;
-       }
-
-       ret = bt_field_type_structure_add_field(event_header_type,
-               _uint64_t, "timestamp");
-       if (ret) {
-               BT_LOGE_STR("Cannot add `timestamp` field to event header field type.");
-               goto end;
-       }
-
-       BT_MOVE(stream_class->event_header_type, event_header_type);
-end:
-       if (ret) {
-               bt_put(event_header_type);
-       }
-
-       bt_put(_uint32_t);
-       bt_put(_uint64_t);
-       return ret;
-}
-
-static
-int init_packet_context(struct bt_stream_class *stream_class)
-{
-       int ret = 0;
-       struct bt_field_type *packet_context_type =
-               bt_field_type_structure_create();
-       struct bt_field_type *_uint64_t =
-               get_field_type(FIELD_TYPE_ALIAS_UINT64_T);
-       struct bt_field_type *ts_begin_end_uint64_t;
-
-       if (!packet_context_type) {
-               BT_LOGE_STR("Cannot create empty structure field type.");
-               ret = -1;
-               goto end;
-       }
-
-       ts_begin_end_uint64_t = bt_field_type_copy(_uint64_t);
-       if (!ts_begin_end_uint64_t) {
-               BT_LOGE_STR("Cannot copy integer field type for `timestamp_begin` and `timestamp_end` fields.");
-               ret = -1;
-               goto end;
-       }
-
-       /*
-        * We create a stream packet context as proposed in the CTF
-        * specification.
-        */
-       ret = bt_field_type_structure_add_field(packet_context_type,
-               ts_begin_end_uint64_t, "timestamp_begin");
-       if (ret) {
-               BT_LOGE_STR("Cannot add `timestamp_begin` field to event header field type.");
-               goto end;
-       }
-
-       ret = bt_field_type_structure_add_field(packet_context_type,
-               ts_begin_end_uint64_t, "timestamp_end");
-       if (ret) {
-               BT_LOGE_STR("Cannot add `timestamp_end` field to event header field type.");
-               goto end;
-       }
-
-       ret = bt_field_type_structure_add_field(packet_context_type,
-               _uint64_t, "content_size");
-       if (ret) {
-               BT_LOGE_STR("Cannot add `content_size` field to event header field type.");
-               goto end;
-       }
-
-       ret = bt_field_type_structure_add_field(packet_context_type,
-               _uint64_t, "packet_size");
-       if (ret) {
-               BT_LOGE_STR("Cannot add `packet_size` field to event header field type.");
-               goto end;
-       }
-
-       ret = bt_field_type_structure_add_field(packet_context_type,
-               _uint64_t, "events_discarded");
-       if (ret) {
-               BT_LOGE_STR("Cannot add `events_discarded` field to event header field type.");
-               goto end;
-       }
-
-       BT_MOVE(stream_class->packet_context_type, packet_context_type);
-end:
-       if (ret) {
-               bt_put(packet_context_type);
-               goto end;
-       }
-
-       bt_put(_uint64_t);
-       bt_put(ts_begin_end_uint64_t);
-       return ret;
-}
-
-static
-int try_map_clock_class(struct bt_stream_class *stream_class,
-               struct bt_field_type *parent_ft, const char *field_name)
-{
-       struct bt_clock_class *mapped_clock_class = NULL;
-       int ret = 0;
-       struct bt_field_type *ft =
-               bt_field_type_structure_get_field_type_by_name(parent_ft,
-                       field_name);
-
-       BT_ASSERT(stream_class->clock);
-
-       if (!ft) {
-               /* Field does not exist: not an error */
-               goto end;
-       }
-
-       BT_ASSERT(bt_field_type_is_integer(ft));
-       mapped_clock_class =
-               bt_field_type_integer_get_mapped_clock_class(ft);
-       if (!mapped_clock_class) {
-               struct bt_field_type *ft_copy;
-
-               if (!stream_class->clock) {
-                       BT_LOGW("Cannot automatically set field's type mapped clock class: stream class's clock is not set: "
-                               "stream-class-addr=%p, stream-class-name=\"%s\", "
-                               "stream-class-id=%" PRId64 ", ft-addr=%p",
-                               stream_class, bt_stream_class_get_name(stream_class),
-                               bt_stream_class_get_id(stream_class), ft);
-                       ret = -1;
-                       goto end;
-               }
-
-               ft_copy = bt_field_type_copy(ft);
-               if (!ft_copy) {
-                       BT_LOGE("Failed to copy integer field type: ft-addr=%p",
-                               ft);
-               }
-
-               ret = bt_field_type_integer_set_mapped_clock_class_no_check(
-                       ft_copy, stream_class->clock->clock_class);
-               BT_ASSERT(ret == 0);
-               ret = bt_field_type_structure_replace_field(parent_ft,
-                       field_name, ft_copy);
-               bt_put(ft_copy);
-               BT_LOGV("Automatically mapped field type to stream class's clock class: "
-                       "stream-class-addr=%p, stream-class-name=\"%s\", "
-                       "stream-class-id=%" PRId64 ", ft-addr=%p, "
-                       "ft-copy-addr=%p",
-                       stream_class, bt_stream_class_get_name(stream_class),
-                       bt_stream_class_get_id(stream_class), ft, ft_copy);
-       }
-
-end:
-       bt_put(ft);
-       bt_put(mapped_clock_class);
-       return ret;
-}
-
-BT_HIDDEN
-int bt_stream_class_map_clock_class(
-               struct bt_stream_class *stream_class,
-               struct bt_field_type *packet_context_type,
-               struct bt_field_type *event_header_type)
+void bt_stream_class_freeze(struct bt_stream_class *stream_class)
 {
-       int ret = 0;
-
-       BT_ASSERT(stream_class);
-
-       if (!stream_class->clock) {
-               /* No clock class to map to */
-               goto end;
-       }
-
-       if (packet_context_type) {
-               if (try_map_clock_class(stream_class, packet_context_type,
-                               "timestamp_begin")) {
-                       BT_LOGE_STR("Cannot automatically set stream class's packet context field type's `timestamp_begin` field's mapped clock class.");
-                       ret = -1;
-                       goto end;
-               }
-
-               if (try_map_clock_class(stream_class, packet_context_type,
-                               "timestamp_end")) {
-                       BT_LOGE_STR("Cannot automatically set stream class's packet context field type's `timestamp_end` field's mapped clock class.");
-                       ret = -1;
-                       goto end;
-               }
-       }
-
-       if (event_header_type) {
-               if (try_map_clock_class(stream_class, event_header_type,
-                               "timestamp")) {
-                       BT_LOGE_STR("Cannot automatically set stream class's event header field type's `timestamp` field's mapped clock class.");
-                       ret = -1;
-                       goto end;
-               }
-       }
-
-end:
-       return ret;
+       bt_stream_class_common_freeze(BT_TO_COMMON(stream_class));
 }
 
 BT_HIDDEN
-int bt_stream_class_validate_single_clock_class(
-               struct bt_stream_class *stream_class,
+int bt_stream_class_common_validate_single_clock_class(
+               struct bt_stream_class_common *stream_class,
                struct bt_clock_class **expected_clock_class)
 {
        int ret;
@@ -1335,7 +671,8 @@ int bt_stream_class_validate_single_clock_class(
 
        BT_ASSERT(stream_class);
        BT_ASSERT(expected_clock_class);
-       ret = bt_validate_single_clock_class(stream_class->packet_context_type,
+       ret = bt_field_type_common_validate_single_clock_class(
+               stream_class->packet_context_field_type,
                expected_clock_class);
        if (ret) {
                BT_LOGW("Stream class's packet context field type "
@@ -1346,13 +683,14 @@ int bt_stream_class_validate_single_clock_class(
                        "stream-class-id=%" PRId64 ", "
                        "ft-addr=%p",
                        stream_class,
-                       bt_stream_class_get_name(stream_class),
+                       bt_stream_class_common_get_name(stream_class),
                        stream_class->id,
-                       stream_class->packet_context_type);
+                       stream_class->packet_context_field_type);
                goto end;
        }
 
-       ret = bt_validate_single_clock_class(stream_class->event_header_type,
+       ret = bt_field_type_common_validate_single_clock_class(
+               stream_class->event_header_field_type,
                expected_clock_class);
        if (ret) {
                BT_LOGW("Stream class's event header field type "
@@ -1363,13 +701,14 @@ int bt_stream_class_validate_single_clock_class(
                        "stream-class-id=%" PRId64 ", "
                        "ft-addr=%p",
                        stream_class,
-                       bt_stream_class_get_name(stream_class),
+                       bt_stream_class_common_get_name(stream_class),
                        stream_class->id,
-                       stream_class->event_header_type);
+                       stream_class->event_header_field_type);
                goto end;
        }
 
-       ret = bt_validate_single_clock_class(stream_class->event_context_type,
+       ret = bt_field_type_common_validate_single_clock_class(
+               stream_class->event_context_field_type,
                expected_clock_class);
        if (ret) {
                BT_LOGW("Stream class's event context field type "
@@ -1380,19 +719,19 @@ int bt_stream_class_validate_single_clock_class(
                        "stream-class-id=%" PRId64 ", "
                        "ft-addr=%p",
                        stream_class,
-                       bt_stream_class_get_name(stream_class),
+                       bt_stream_class_common_get_name(stream_class),
                        stream_class->id,
-                       stream_class->event_context_type);
+                       stream_class->event_context_field_type);
                goto end;
        }
 
        for (i = 0; i < stream_class->event_classes->len; i++) {
-               struct bt_event_class *event_class =
+               struct bt_event_class_common *event_class =
                        g_ptr_array_index(stream_class->event_classes, i);
 
                BT_ASSERT(event_class);
-               ret = bt_event_class_validate_single_clock_class(event_class,
-                       expected_clock_class);
+               ret = bt_event_class_common_validate_single_clock_class(
+                       event_class, expected_clock_class);
                if (ret) {
                        BT_LOGW("Stream class's event class contains a "
                                "field type which is not recursively mapped to "
@@ -1401,7 +740,7 @@ int bt_stream_class_validate_single_clock_class(
                                "stream-class-name=\"%s\", "
                                "stream-class-id=%" PRId64,
                                stream_class,
-                               bt_stream_class_get_name(stream_class),
+                               bt_stream_class_common_get_name(stream_class),
                                stream_class->id);
                        goto end;
                }
index 4c6bda2653166a2044de3ecce530083472f85efc..828b2db8676cd11e32a499fe2935b0e455f30ff2 100644 (file)
 #define BT_LOG_TAG "STREAM"
 #include <babeltrace/lib-logging-internal.h>
 
-#include <babeltrace/ctf-ir/clock-class.h>
-#include <babeltrace/ctf-writer/clock.h>
-#include <babeltrace/ctf-writer/clock-internal.h>
-#include <babeltrace/ctf-writer/event.h>
-#include <babeltrace/ctf-ir/event-internal.h>
-#include <babeltrace/ctf-ir/field-types-internal.h>
-#include <babeltrace/ctf-ir/fields-internal.h>
-#include <babeltrace/ctf-ir/stream.h>
-#include <babeltrace/ctf-ir/stream-internal.h>
-#include <babeltrace/ctf-ir/stream-class-internal.h>
-#include <babeltrace/ctf-ir/trace.h>
-#include <babeltrace/ctf-ir/trace-internal.h>
-#include <babeltrace/ctf-writer/writer-internal.h>
-#include <babeltrace/graph/component-internal.h>
-#include <babeltrace/ref.h>
-#include <babeltrace/ctf-writer/functor-internal.h>
-#include <babeltrace/compiler-internal.h>
-#include <babeltrace/align-internal.h>
-#include <babeltrace/assert-internal.h>
 #include <babeltrace/assert-pre-internal.h>
-#include <inttypes.h>
-#include <unistd.h>
-
-static
-void bt_stream_destroy(struct bt_object *obj);
-static
-int try_set_structure_field_integer(struct bt_field *, char *, uint64_t);
-
-static
-int set_integer_field_value(struct bt_field* field, uint64_t value)
-{
-       int ret = 0;
-       struct bt_field_type *field_type = NULL;
-
-       if (!field) {
-               BT_LOGW_STR("Invalid parameter: field is NULL.");
-               ret = -1;
-               goto end;
-       }
-
-       field_type = bt_field_get_type(field);
-       BT_ASSERT(field_type);
-
-       if (bt_field_type_get_type_id(field_type) !=
-                       BT_FIELD_TYPE_ID_INTEGER) {
-               /* Not an integer and the value is unset, error. */
-               BT_LOGW("Invalid parameter: field's type is not an integer field type: "
-                       "field-addr=%p, ft-addr=%p, ft-id=%s",
-                       field, field_type,
-                       bt_field_type_id_string(field_type->id));
-               ret = -1;
-               goto end;
-       }
-
-       if (bt_field_type_integer_is_signed(field_type)) {
-               ret = bt_field_signed_integer_set_value(field, (int64_t) value);
-               if (ret) {
-                       /* Value is out of range, error. */
-                       BT_LOGW("Cannot set signed integer field's value: "
-                               "addr=%p, value=%" PRId64,
-                               field, (int64_t) value);
-                       goto end;
-               }
-       } else {
-               ret = bt_field_unsigned_integer_set_value(field, value);
-               if (ret) {
-                       /* Value is out of range, error. */
-                       BT_LOGW("Cannot set unsigned integer field's value: "
-                               "addr=%p, value=%" PRIu64,
-                               field, value);
-                       goto end;
-               }
-       }
-end:
-       bt_put(field_type);
-       return ret;
-}
-
-static
-int set_packet_header_magic(struct bt_stream *stream)
-{
-       int ret = 0;
-       struct bt_field *magic_field = bt_field_structure_get_field_by_name(
-               stream->packet_header, "magic");
-       const uint32_t magic_value = 0xc1fc1fc1;
-
-       BT_ASSERT(stream);
-
-       if (!magic_field) {
-               /* No magic field found. Not an error, skip. */
-               BT_LOGV("No field named `magic` in packet header: skipping: "
-                       "stream-addr=%p, stream-name=\"%s\"",
-                       stream, bt_stream_get_name(stream));
-               goto end;
-       }
-
-       ret = bt_field_unsigned_integer_set_value(magic_field,
-               (uint64_t) magic_value);
-
-       if (ret) {
-               BT_LOGW("Cannot set packet header field's `magic` integer field's value: "
-                       "stream-addr=%p, stream-name=\"%s\", field-addr=%p, value=%" PRIu64,
-                       stream, bt_stream_get_name(stream),
-                       magic_field, (uint64_t) magic_value);
-       } else {
-               BT_LOGV("Set packet header field's `magic` field's value: "
-                       "stream-addr=%p, stream-name=\"%s\", field-addr=%p, value=%" PRIu64,
-                       stream, bt_stream_get_name(stream),
-                       magic_field, (uint64_t) magic_value);
-       }
-end:
-       bt_put(magic_field);
-       return ret;
-}
-
-static
-int set_packet_header_uuid(struct bt_stream *stream)
-{
-       int ret = 0;
-       int64_t i;
-       struct bt_trace *trace = NULL;
-       struct bt_field *uuid_field = bt_field_structure_get_field_by_name(
-               stream->packet_header, "uuid");
-
-       BT_ASSERT(stream);
-
-       if (!uuid_field) {
-               /* No uuid field found. Not an error, skip. */
-               BT_LOGV("No field named `uuid` in packet header: skipping: "
-                       "stream-addr=%p, stream-name=\"%s\"",
-                       stream, bt_stream_get_name(stream));
-               goto end;
-       }
-
-       trace = (struct bt_trace *) bt_object_get_parent(stream);
-       for (i = 0; i < 16; i++) {
-               struct bt_field *uuid_element =
-                       bt_field_array_get_field(uuid_field, i);
-
-               ret = bt_field_unsigned_integer_set_value(
-                       uuid_element, (uint64_t) trace->uuid[i]);
-               bt_put(uuid_element);
-               if (ret) {
-                       BT_LOGW("Cannot set integer field's value (for `uuid` packet header field): "
-                               "stream-addr=%p, stream-name=\"%s\", field-addr=%p, "
-                               "value=%" PRIu64 ", index=%" PRId64,
-                               stream, bt_stream_get_name(stream),
-                               uuid_element, (uint64_t) trace->uuid[i], i);
-                       goto end;
-               }
-       }
-
-       BT_LOGV("Set packet header field's `uuid` field's value: "
-               "stream-addr=%p, stream-name=\"%s\", field-addr=%p",
-               stream, bt_stream_get_name(stream), uuid_field);
-
-end:
-       bt_put(uuid_field);
-       BT_PUT(trace);
-       return ret;
-}
-static
-int set_packet_header_stream_id(struct bt_stream *stream)
-{
-       int ret = 0;
-       uint32_t stream_id;
-       struct bt_field *stream_id_field = bt_field_structure_get_field_by_name(
-               stream->packet_header, "stream_id");
-
-       if (!stream_id_field) {
-               /* No stream_id field found. Not an error, skip. */
-               BT_LOGV("No field named `stream_id` in packet header: skipping: "
-                       "stream-addr=%p, stream-name=\"%s\"",
-                       stream, bt_stream_get_name(stream));
-               goto end;
-       }
-
-       stream_id = stream->stream_class->id;
-       ret = bt_field_unsigned_integer_set_value(stream_id_field,
-               (uint64_t) stream_id);
-       if (ret) {
-               BT_LOGW("Cannot set packet header field's `stream_id` integer field's value: "
-                       "stream-addr=%p, stream-name=\"%s\", field-addr=%p, value=%" PRIu64,
-                       stream, bt_stream_get_name(stream),
-                       stream_id_field, (uint64_t) stream_id);
-       } else {
-               BT_LOGV("Set packet header field's `stream_id` field's value: "
-                       "stream-addr=%p, stream-name=\"%s\", field-addr=%p, value=%" PRIu64,
-                       stream, bt_stream_get_name(stream),
-                       stream_id_field, (uint64_t) stream_id);
-       }
-
-end:
-       bt_put(stream_id_field);
-       return ret;
-}
-
-static
-int auto_populate_packet_header(struct bt_stream *stream)
-{
-       int ret = 0;
-
-       if (!stream->packet_header) {
-               goto end;
-       }
-
-       ret = set_packet_header_magic(stream);
-       if (ret) {
-               BT_LOGW("Cannot set packet header's magic number field: "
-                       "stream-addr=%p, stream-name=\"%s\"",
-                       stream, bt_stream_get_name(stream));
-               goto end;
-       }
-
-       ret = set_packet_header_uuid(stream);
-       if (ret) {
-               BT_LOGW("Cannot set packet header's UUID field: "
-                       "stream-addr=%p, stream-name=\"%s\"",
-                       stream, bt_stream_get_name(stream));
-               goto end;
-       }
-
-       ret = set_packet_header_stream_id(stream);
-       if (ret) {
-               BT_LOGW("Cannot set packet header's stream class ID field: "
-                       "stream-addr=%p, stream-name=\"%s\"",
-                       stream, bt_stream_get_name(stream));
-               goto end;
-       }
-
-       BT_LOGV("Automatically populated stream's packet header's known fields: "
-               "stream-addr=%p, stream-name=\"%s\"",
-               stream, bt_stream_get_name(stream));
-
-end:
-       return ret;
-}
-
-static
-int set_packet_context_packet_size(struct bt_stream *stream)
-{
-       int ret = 0;
-       struct bt_field *field = bt_field_structure_get_field_by_name(
-               stream->packet_context, "packet_size");
-
-       BT_ASSERT(stream);
-
-       if (!field) {
-               /* No packet size field found. Not an error, skip. */
-               BT_LOGV("No field named `packet_size` in packet context: skipping: "
-                       "stream-addr=%p, stream-name=\"%s\"",
-                       stream, bt_stream_get_name(stream));
-               goto end;
-       }
-
-       ret = bt_field_unsigned_integer_set_value(field,
-               stream->pos.packet_size);
-       if (ret) {
-               BT_LOGW("Cannot set packet context field's `packet_size` integer field's value: "
-                       "stream-addr=%p, stream-name=\"%s\", field-addr=%p, value=%" PRIu64,
-                       stream, bt_stream_get_name(stream),
-                       field, stream->pos.packet_size);
-       } else {
-               BT_LOGV("Set packet context field's `packet_size` field's value: "
-                       "stream-addr=%p, stream-name=\"%s\", field-addr=%p, value=%" PRIu64,
-                       stream, bt_stream_get_name(stream),
-                       field, stream->pos.packet_size);
-       }
-
-end:
-       bt_put(field);
-       return ret;
-}
-
-static
-int set_packet_context_content_size(struct bt_stream *stream)
-{
-       int ret = 0;
-       struct bt_field *field = bt_field_structure_get_field_by_name(
-               stream->packet_context, "content_size");
-
-       BT_ASSERT(stream);
-
-       if (!field) {
-               /* No content size field found. Not an error, skip. */
-               BT_LOGV("No field named `content_size` in packet context: skipping: "
-                       "stream-addr=%p, stream-name=\"%s\"",
-                       stream, bt_stream_get_name(stream));
-               goto end;
-       }
-
-       ret = bt_field_unsigned_integer_set_value(field,
-               stream->pos.offset);
-       if (ret) {
-               BT_LOGW("Cannot set packet context field's `content_size` integer field's value: "
-                       "stream-addr=%p, stream-name=\"%s\", field-addr=%p, value=%" PRId64,
-                       stream, bt_stream_get_name(stream),
-                       field, stream->pos.offset);
-       } else {
-               BT_LOGV("Set packet context field's `content_size` field's value: "
-                       "stream-addr=%p, stream-name=\"%s\", field-addr=%p, value=%" PRId64,
-                       stream, bt_stream_get_name(stream),
-                       field, stream->pos.offset);
-       }
-
-end:
-       bt_put(field);
-       return ret;
-}
-
-static
-int set_packet_context_events_discarded(struct bt_stream *stream)
-{
-       int ret = 0;
-       struct bt_field *field = bt_field_structure_get_field_by_name(
-               stream->packet_context, "events_discarded");
-
-       BT_ASSERT(stream);
-
-       if (!field) {
-               /* No discarded events count field found. Not an error, skip. */
-               BT_LOGV("No field named `events_discarded` in packet context: skipping: "
-                       "stream-addr=%p, stream-name=\"%s\"",
-                       stream, bt_stream_get_name(stream));
-               goto end;
-       }
-
-       /*
-        * If the field is set by the user, make sure that the value is
-        * greater than or equal to the stream's current count of
-        * discarded events. We do not allow wrapping here. If it's
-        * valid, update the stream's current count.
-        */
-       if (bt_field_is_set_recursive(field)) {
-               uint64_t user_val;
-
-               ret = bt_field_unsigned_integer_get_value(field,
-                       &user_val);
-               if (ret) {
-                       BT_LOGW("Cannot get packet context `events_discarded` field's unsigned value: "
-                               "stream-addr=%p, stream-name=\"%s\", field-addr=%p",
-                               stream, bt_stream_get_name(stream), field);
-                       goto end;
-               }
-
-               if (user_val < stream->discarded_events) {
-                       BT_LOGW("Invalid packet context `events_discarded` field's unsigned value: "
-                               "value is lesser than the stream's current discarded events count: "
-                               "stream-addr=%p, stream-name=\"%s\", field-addr=%p, "
-                               "value=%" PRIu64 ", "
-                               "stream-discarded-events-count=%" PRIu64,
-                               stream, bt_stream_get_name(stream), field,
-                               user_val, stream->discarded_events);
-                       goto end;
-               }
-
-               stream->discarded_events = user_val;
-       } else {
-               ret = bt_field_unsigned_integer_set_value(field,
-                       stream->discarded_events);
-               if (ret) {
-                       BT_LOGW("Cannot set packet context field's `events_discarded` integer field's value: "
-                               "stream-addr=%p, stream-name=\"%s\", field-addr=%p, value=%" PRIu64,
-                               stream, bt_stream_get_name(stream),
-                               field, stream->discarded_events);
-               } else {
-                       BT_LOGV("Set packet context field's `events_discarded` field's value: "
-                               "stream-addr=%p, stream-name=\"%s\", field-addr=%p, value=%" PRIu64,
-                               stream, bt_stream_get_name(stream),
-                               field, stream->discarded_events);
-               }
-       }
-
-end:
-       bt_put(field);
-       return ret;
-}
-
-static
-void update_clock_value(uint64_t *val, uint64_t new_val,
-               unsigned int new_val_size)
-{
-       const uint64_t pow2 = 1ULL << new_val_size;
-       const uint64_t mask = pow2 - 1;
-       uint64_t val_masked;
-
-#ifdef BT_LOG_ENABLED_VERBOSE
-       uint64_t old_val = *val;
-#endif
-
-       if (new_val_size == 64) {
-               *val = new_val;
-               goto end;
-       }
-
-       val_masked = *val & mask;
-
-       if (new_val < val_masked) {
-               /* Wrapped once */
-               new_val |= pow2;
-       }
-
-       *val &= ~mask;
-       *val |= new_val;
-
-end:
-       BT_LOGV("Updated clock value: old-val=%" PRIu64 ", new-val=%" PRIu64,
-               old_val, *val);
-       return;
-}
-
-static
-int visit_field_update_clock_value(struct bt_field *field, uint64_t *val)
-{
-       int ret = 0;
-
-       if (!field) {
-               goto end;
-       }
-
-       switch (bt_field_get_type_id(field)) {
-       case BT_FIELD_TYPE_ID_INTEGER:
-       {
-               struct bt_clock_class *cc =
-                       bt_field_type_integer_get_mapped_clock_class(
-                               field->type);
-               int val_size;
-               uint64_t uval;
-
-               if (!cc) {
-                       goto end;
-               }
-
-               bt_put(cc);
-               val_size = bt_field_type_integer_get_size(field->type);
-               BT_ASSERT(val_size >= 1);
-
-               if (bt_field_type_integer_is_signed(field->type)) {
-                       int64_t ival;
-
-                       ret = bt_field_signed_integer_get_value(field, &ival);
-                       uval = (uint64_t) ival;
-               } else {
-                       ret = bt_field_unsigned_integer_get_value(field, &uval);
-               }
-
-               if (ret) {
-                       /* Not set */
-                       goto end;
-               }
-
-               update_clock_value(val, uval, val_size);
-               break;
-       }
-       case BT_FIELD_TYPE_ID_ENUM:
-       {
-               struct bt_field *int_field =
-                       bt_field_enumeration_get_container(field);
-
-               BT_ASSERT(int_field);
-               ret = visit_field_update_clock_value(int_field, val);
-               bt_put(int_field);
-               break;
-       }
-       case BT_FIELD_TYPE_ID_ARRAY:
-       {
-               uint64_t i;
-               int64_t len = bt_field_type_array_get_length(field->type);
-
-               BT_ASSERT(len >= 0);
-
-               for (i = 0; i < len; i++) {
-                       struct bt_field *elem_field =
-                               bt_field_array_get_field(field, i);
-
-                       BT_ASSERT(elem_field);
-                       ret = visit_field_update_clock_value(elem_field, val);
-                       bt_put(elem_field);
-                       if (ret) {
-                               goto end;
-                       }
-               }
-               break;
-       }
-       case BT_FIELD_TYPE_ID_SEQUENCE:
-       {
-               uint64_t i;
-               int64_t len = bt_field_sequence_get_int_length(field);
-
-               if (len < 0) {
-                       ret = -1;
-                       goto end;
-               }
-
-               for (i = 0; i < len; i++) {
-                       struct bt_field *elem_field =
-                               bt_field_sequence_get_field(field, i);
-
-                       BT_ASSERT(elem_field);
-                       ret = visit_field_update_clock_value(elem_field, val);
-                       bt_put(elem_field);
-                       if (ret) {
-                               goto end;
-                       }
-               }
-               break;
-       }
-       case BT_FIELD_TYPE_ID_STRUCT:
-       {
-               uint64_t i;
-               int64_t len = bt_field_type_structure_get_field_count(
-                       field->type);
-
-               BT_ASSERT(len >= 0);
-
-               for (i = 0; i < len; i++) {
-                       struct bt_field *member_field =
-                               bt_field_structure_get_field_by_index(field, i);
-
-                       BT_ASSERT(member_field);
-                       ret = visit_field_update_clock_value(member_field, val);
-                       bt_put(member_field);
-                       if (ret) {
-                               goto end;
-                       }
-               }
-               break;
-       }
-       case BT_FIELD_TYPE_ID_VARIANT:
-       {
-               struct bt_field *cur_field =
-                       bt_field_variant_get_current_field(field);
-
-               if (!cur_field) {
-                       ret = -1;
-                       goto end;
-               }
-
-               ret = visit_field_update_clock_value(cur_field, val);
-               bt_put(cur_field);
-               break;
-       }
-       default:
-               break;
-       }
-
-end:
-       return ret;
-}
-
-int visit_event_update_clock_value(struct bt_event *event, uint64_t *val)
-{
-       int ret = 0;
-       struct bt_field *field;
-
-       field = bt_event_get_header(event);
-       ret = visit_field_update_clock_value(field, val);
-       bt_put(field);
-       if (ret) {
-               BT_LOGW_STR("Cannot automatically update clock value in "
-                       "event's header.");
-               goto end;
-       }
-
-       field = bt_event_get_stream_event_context(event);
-       ret = visit_field_update_clock_value(field, val);
-       bt_put(field);
-       if (ret) {
-               BT_LOGW_STR("Cannot automatically update clock value in "
-                       "event's stream event context.");
-               goto end;
-       }
-
-       field = bt_event_get_event_context(event);
-       ret = visit_field_update_clock_value(field, val);
-       bt_put(field);
-       if (ret) {
-               BT_LOGW_STR("Cannot automatically update clock value in "
-                       "event's context.");
-               goto end;
-       }
-
-       field = bt_event_get_event_payload(event);
-       ret = visit_field_update_clock_value(field, val);
-       bt_put(field);
-       if (ret) {
-               BT_LOGW_STR("Cannot automatically update clock value in "
-                       "event's payload.");
-               goto end;
-       }
-
-end:
-       return ret;
-}
-
-static
-int set_packet_context_timestamps(struct bt_stream *stream)
-{
-       int ret = 0;
-       uint64_t val;
-       uint64_t cur_clock_value;
-       uint64_t init_clock_value = 0;
-       struct bt_field *ts_begin_field = bt_field_structure_get_field_by_name(
-               stream->packet_context, "timestamp_begin");
-       struct bt_field *ts_end_field = bt_field_structure_get_field_by_name(
-               stream->packet_context, "timestamp_end");
-       uint64_t i;
-       int64_t len;
-
-       if (ts_begin_field && bt_field_is_set_recursive(ts_begin_field)) {
-               /* Use provided `timestamp_begin` value as starting value */
-               ret = bt_field_unsigned_integer_get_value(ts_begin_field, &val);
-               BT_ASSERT(ret == 0);
-               init_clock_value = val;
-       } else if (stream->last_ts_end != -1ULL) {
-               /* Use last packet's ending timestamp as starting value */
-               init_clock_value = stream->last_ts_end;
-       }
-
-       cur_clock_value = init_clock_value;
-
-       if (stream->last_ts_end != -1ULL &&
-                       cur_clock_value < stream->last_ts_end) {
-               BT_LOGW("Packet's initial timestamp is less than previous "
-                       "packet's final timestamp: "
-                       "stream-addr=%p, stream-name=\"%s\", "
-                       "cur-packet-ts-begin=%" PRIu64 ", "
-                       "prev-packet-ts-end=%" PRIu64,
-                       stream, bt_stream_get_name(stream),
-                       cur_clock_value, stream->last_ts_end);
-               ret = -1;
-               goto end;
-       }
-
-       /*
-        * Visit all the packet context fields, followed by all the
-        * fields of all the events, in order, updating our current
-        * clock value as we visit.
-        *
-        * While visiting the packet context fields, do not consider
-        * `timestamp_begin` and `timestamp_end` because this function's
-        * purpose is to set them anyway. Also do not consider
-        * `packet_size`, `content_size`, `events_discarded`, and
-        * `packet_seq_num` if they are not set because those are
-        * autopopulating fields.
-        */
-       len = bt_field_type_structure_get_field_count(
-               stream->packet_context->type);
-       BT_ASSERT(len >= 0);
-
-       for (i = 0; i < len; i++) {
-               const char *member_name;
-               struct bt_field *member_field;
-
-               ret = bt_field_type_structure_get_field_by_index(
-                       stream->packet_context->type, &member_name, NULL, i);
-               BT_ASSERT(ret == 0);
-
-               if (strcmp(member_name, "timestamp_begin") == 0 ||
-                               strcmp(member_name, "timestamp_end") == 0) {
-                       continue;
-               }
-
-               member_field = bt_field_structure_get_field_by_index(
-                       stream->packet_context, i);
-               BT_ASSERT(member_field);
-
-               if (strcmp(member_name, "packet_size") == 0 &&
-                               !bt_field_is_set_recursive(member_field)) {
-                       bt_put(member_field);
-                       continue;
-               }
-
-               if (strcmp(member_name, "content_size") == 0 &&
-                               !bt_field_is_set_recursive(member_field)) {
-                       bt_put(member_field);
-                       continue;
-               }
-
-               if (strcmp(member_name, "events_discarded") == 0 &&
-                               !bt_field_is_set_recursive(member_field)) {
-                       bt_put(member_field);
-                       continue;
-               }
-
-               if (strcmp(member_name, "packet_seq_num") == 0 &&
-                               !bt_field_is_set_recursive(member_field)) {
-                       bt_put(member_field);
-                       continue;
-               }
-
-               ret = visit_field_update_clock_value(member_field,
-                       &cur_clock_value);
-               bt_put(member_field);
-               if (ret) {
-                       BT_LOGW("Cannot automatically update clock value "
-                               "in stream's packet context: "
-                               "stream-addr=%p, stream-name=\"%s\", "
-                               "field-name=\"%s\"",
-                               stream, bt_stream_get_name(stream),
-                               member_name);
-                       goto end;
-               }
-       }
-
-       for (i = 0; i < stream->events->len; i++) {
-               struct bt_event *event = g_ptr_array_index(stream->events, i);
-
-               BT_ASSERT(event);
-               ret = visit_event_update_clock_value(event, &cur_clock_value);
-               if (ret) {
-                       BT_LOGW("Cannot automatically update clock value "
-                               "in stream's packet context: "
-                               "stream-addr=%p, stream-name=\"%s\", "
-                               "index=%" PRIu64 ", event-addr=%p, "
-                               "event-class-id=%" PRId64 ", "
-                               "event-class-name=\"%s\"",
-                               stream, bt_stream_get_name(stream),
-                               i, event,
-                               bt_event_class_get_id(event->event_class),
-                               bt_event_class_get_name(event->event_class));
-                       goto end;
-               }
-       }
-
-       /*
-        * Everything is visited, thus the current clock value
-        * corresponds to the ending timestamp. Validate this value
-        * against the provided value of `timestamp_end`, if any,
-        * otherwise set it.
-        */
-       if (ts_end_field && bt_field_is_set_recursive(ts_end_field)) {
-               ret = bt_field_unsigned_integer_get_value(ts_end_field, &val);
-               BT_ASSERT(ret == 0);
-
-               if (val < cur_clock_value) {
-                       BT_LOGW("Packet's final timestamp is less than "
-                               "computed packet's final timestamp: "
-                               "stream-addr=%p, stream-name=\"%s\", "
-                               "cur-packet-ts-end=%" PRIu64 ", "
-                               "computed-packet-ts-end=%" PRIu64,
-                               stream, bt_stream_get_name(stream),
-                               val, cur_clock_value);
-                       ret = -1;
-                       goto end;
-               }
-
-               stream->last_ts_end = val;
-       }
-
-       if (ts_end_field && !bt_field_is_set_recursive(ts_end_field)) {
-               ret = set_integer_field_value(ts_end_field, cur_clock_value);
-               BT_ASSERT(ret == 0);
-               stream->last_ts_end = cur_clock_value;
-       }
-
-       if (!ts_end_field) {
-               stream->last_ts_end = cur_clock_value;
-       }
-
-       /* Set `timestamp_begin` field to initial clock value */
-       if (ts_begin_field && !bt_field_is_set_recursive(ts_begin_field)) {
-               ret = set_integer_field_value(ts_begin_field, init_clock_value);
-               BT_ASSERT(ret == 0);
-       }
-
-end:
-       bt_put(ts_begin_field);
-       bt_put(ts_end_field);
-       return ret;
-}
-
-static
-int auto_populate_packet_context(struct bt_stream *stream, bool set_ts)
-{
-       int ret = 0;
-
-       if (!stream->packet_context) {
-               goto end;
-       }
-
-       ret = set_packet_context_packet_size(stream);
-       if (ret) {
-               BT_LOGW("Cannot set packet context's packet size field: "
-                       "stream-addr=%p, stream-name=\"%s\"",
-                       stream, bt_stream_get_name(stream));
-               goto end;
-       }
-
-       ret = set_packet_context_content_size(stream);
-       if (ret) {
-               BT_LOGW("Cannot set packet context's content size field: "
-                       "stream-addr=%p, stream-name=\"%s\"",
-                       stream, bt_stream_get_name(stream));
-               goto end;
-       }
-
-       if (set_ts) {
-               ret = set_packet_context_timestamps(stream);
-               if (ret) {
-                       BT_LOGW("Cannot set packet context's timestamp fields: "
-                               "stream-addr=%p, stream-name=\"%s\"",
-                               stream, bt_stream_get_name(stream));
-                       goto end;
-               }
-       }
-
-       ret = set_packet_context_events_discarded(stream);
-       if (ret) {
-               BT_LOGW("Cannot set packet context's discarded events count field: "
-                       "stream-addr=%p, stream-name=\"%s\"",
-                       stream, bt_stream_get_name(stream));
-               goto end;
-       }
-
-       BT_LOGV("Automatically populated stream's packet context's known fields: "
-               "stream-addr=%p, stream-name=\"%s\"",
-               stream, bt_stream_get_name(stream));
-
-end:
-       return ret;
-}
-
-static
-void release_event(struct bt_event *event)
-{
-       if (bt_object_get_ref_count(event)) {
-               /*
-                * The event is being orphaned, but it must guarantee the
-                * existence of its event class for the duration of its
-                * lifetime.
-                */
-               bt_get(event->event_class);
-               BT_PUT(event->base.parent);
-       } else {
-               bt_object_release(event);
-       }
-}
-
-static
-int create_stream_file(struct bt_ctf_writer *writer,
-               struct bt_stream *stream)
-{
-       int fd;
-       GString *filename = g_string_new(NULL);
-       int64_t stream_class_id;
-       char *file_path = NULL;
-
-       BT_LOGD("Creating stream file: writer-addr=%p, stream-addr=%p, "
-               "stream-name=\"%s\", stream-class-addr=%p, stream-class-name=\"%s\"",
-               writer, stream, bt_stream_get_name(stream),
-               stream->stream_class, stream->stream_class->name->str);
-
-       if (stream->name && stream->name->len > 0) {
-               /* Use stream name's base name as prefix */
-               gchar *basename = g_path_get_basename(stream->name->str);
-
-               BT_ASSERT(basename);
-
-               if (strcmp(basename, G_DIR_SEPARATOR_S) == 0) {
-                       g_string_assign(filename, "stream");
-               } else {
-                       g_string_assign(filename, basename);
-               }
-
-               g_free(basename);
-               goto append_ids;
-       }
-
-       if (stream->stream_class->name &&
-                       stream->stream_class->name->len > 0) {
-               /* Use stream class name's base name as prefix */
-               gchar *basename =
-                       g_path_get_basename(stream->stream_class->name->str);
-
-               BT_ASSERT(basename);
-
-               if (strcmp(basename, G_DIR_SEPARATOR_S) == 0) {
-                       g_string_assign(filename, "stream");
-               } else {
-                       g_string_assign(filename, basename);
-               }
-
-               g_free(basename);
-               goto append_ids;
-       }
-
-       /* Default to using `stream-` as prefix */
-       g_string_assign(filename, "stream");
-
-append_ids:
-       stream_class_id = bt_stream_class_get_id(stream->stream_class);
-       BT_ASSERT(stream_class_id >= 0);
-       BT_ASSERT(stream->id >= 0);
-       g_string_append_printf(filename, "-%" PRId64 "-%" PRId64,
-               stream_class_id, stream->id);
-
-       file_path = g_build_filename(writer->path->str, filename->str, NULL);
-       if (file_path == NULL) {
-               fd = -1;
-               goto end;
-       }
-
-       fd = open(file_path,
-               O_RDWR | O_CREAT | O_TRUNC,
-               S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
-       g_free(file_path);
-       if (fd < 0) {
-               BT_LOGW_ERRNO("Failed to open stream file for writing",
-                       ": file_path=\"%s\", filename=\"%s\", ret=%d",
-                       file_path, filename->str, fd);
-               goto end;
-       }
-
-       BT_LOGD("Created stream file for writing: "
-               "stream-addr=%p, stream-name=\"%s\", "
-               "filename=\"%s\", fd=%d", stream, bt_stream_get_name(stream),
-               filename->str, fd);
-
-end:
-       g_string_free(filename, TRUE);
-       return fd;
-}
-
-static
-void set_stream_fd(struct bt_stream *stream, int fd)
-{
-       (void) bt_stream_pos_init(&stream->pos, fd, O_RDWR);
-       stream->pos.fd = fd;
-}
-
-static
-struct bt_stream *bt_stream_create_with_id_no_check(
-               struct bt_stream_class *stream_class,
-               const char *name, uint64_t id)
-{
-       int ret;
-       struct bt_stream *stream = NULL;
-       struct bt_trace *trace = NULL;
-       struct bt_ctf_writer *writer = NULL;
-
-       if (!stream_class) {
-               BT_LOGW_STR("Invalid parameter: stream class is NULL.");
-               goto error;
-       }
-
-       BT_LOGD("Creating stream object: stream-class-addr=%p, "
-               "stream-class-name=\"%s\", stream-name=\"%s\", "
-               "stream-id=%" PRIu64,
-               stream_class, bt_stream_class_get_name(stream_class),
-               name, id);
-       trace = bt_stream_class_borrow_trace(stream_class);
-       if (!trace) {
-               BT_LOGW("Invalid parameter: cannot create stream from a stream class which is not part of trace: "
-                       "stream-class-addr=%p, stream-class-name=\"%s\", "
-                       "stream-name=\"%s\"",
-                       stream_class, bt_stream_class_get_name(stream_class),
-                       name);
-               goto error;
-       }
-
-       if (bt_trace_is_static(trace)) {
-               /*
-                * A static trace has the property that all its stream
-                * classes, clock classes, and streams are definitive:
-                * no more can be added, and each object is also frozen.
-                */
-               BT_LOGW("Invalid parameter: cannot create stream from a stream class which is part of a static trace: "
-                       "stream-class-addr=%p, stream-class-name=\"%s\", "
-                       "stream-name=\"%s\", trace-addr=%p",
-                       stream_class, bt_stream_class_get_name(stream_class),
-                       name, trace);
-               goto error;
-       }
-
-       if (id != -1ULL) {
-               /*
-                * Validate that the given ID is unique amongst all the
-                * existing trace's streams created from the same stream
-                * class.
-                */
-               size_t i;
-
-               for (i = 0; i < trace->streams->len; i++) {
-                       struct bt_stream *trace_stream =
-                               g_ptr_array_index(trace->streams, i);
-
-                       if (trace_stream->stream_class != stream_class) {
-                               continue;
-                       }
-
-                       if (trace_stream->id == id) {
-                               BT_LOGW_STR("Invalid parameter: another stream in the same trace already has this ID.");
-                               goto error;
-                       }
-               }
-       }
-
-       stream = g_new0(struct bt_stream, 1);
-       if (!stream) {
-               BT_LOGE_STR("Failed to allocate one stream.");
-               goto error;
-       }
-
-       bt_object_init(stream, bt_stream_destroy);
-       /*
-        * Acquire reference to parent since stream will become publicly
-        * reachable; it needs its parent to remain valid.
-        */
-       bt_object_set_parent(stream, trace);
-       stream->stream_class = stream_class;
-       stream->pos.fd = -1;
-       stream->id = (int64_t) id;
-
-       stream->destroy_listeners = g_array_new(FALSE, TRUE,
-               sizeof(struct bt_stream_destroy_listener));
-       if (!stream->destroy_listeners) {
-               BT_LOGE_STR("Failed to allocate a GArray.");
-               goto error;
-       }
-
-       if (name) {
-               stream->name = g_string_new(name);
-               if (!stream->name) {
-                       BT_LOGE_STR("Failed to allocate a GString.");
-                       goto error;
-               }
-       }
-
-       BT_LOGD("Set stream's trace parent: trace-addr=%p", trace);
-
-       if (trace->is_created_by_writer) {
-               int fd;
-
-               writer = (struct bt_ctf_writer *) bt_object_get_parent(trace);
-               stream->id = (int64_t) stream_class->next_stream_id++;
-               stream->last_ts_end = -1ULL;
-
-               BT_LOGD("Stream object belongs to a writer's trace: "
-                       "writer-addr=%p", writer);
-               BT_ASSERT(writer);
-
-               if (stream_class->packet_context_type) {
-                       BT_LOGD("Creating stream's packet context field: "
-                               "ft-addr=%p", stream_class->packet_context_type);
-                       stream->packet_context = bt_field_create(
-                               stream_class->packet_context_type);
-                       if (!stream->packet_context) {
-                               BT_LOGW_STR("Cannot create stream's packet context field.");
-                               goto error;
-                       }
-
-                       /* Initialize events_discarded */
-                       ret = try_set_structure_field_integer(
-                               stream->packet_context, "events_discarded", 0);
-                       if (ret < 0) {
-                               BT_LOGW("Cannot set `events_discarded` field in packet context: "
-                                       "ret=%d, packet-context-field-addr=%p",
-                                       ret, stream->packet_context);
-                               goto error;
-                       }
-               }
-
-               stream->events = g_ptr_array_new_with_free_func(
-                       (GDestroyNotify) release_event);
-               if (!stream->events) {
-                       BT_LOGE_STR("Failed to allocate a GPtrArray.");
-                       goto error;
-               }
-
-               if (trace->packet_header_type) {
-                       BT_LOGD("Creating stream's packet header field: "
-                               "ft-addr=%p", trace->packet_header_type);
-                       stream->packet_header =
-                               bt_field_create(trace->packet_header_type);
-                       if (!stream->packet_header) {
-                               BT_LOGW_STR("Cannot create stream's packet header field.");
-                               goto error;
-                       }
-               }
-
-               /*
-                * Attempt to populate the default trace packet header fields
-                * (magic, uuid and stream_id). This will _not_ fail shall the
-                * fields not be found or be of an incompatible type; they will
-                * simply not be populated automatically. The user will have to
-                * make sure to set the trace packet header fields himself
-                * before flushing.
-                */
-               ret = auto_populate_packet_header(stream);
-               if (ret) {
-                       BT_LOGW_STR("Cannot automatically populate the stream's packet header.");
-                       goto error;
-               }
-
-               /* Create file associated with this stream */
-               fd = create_stream_file(writer, stream);
-               if (fd < 0) {
-                       BT_LOGW_STR("Cannot create stream file.");
-                       goto error;
-               }
-
-               set_stream_fd(stream, fd);
-
-               /* Freeze the writer */
-               BT_LOGD_STR("Freezing stream's CTF writer.");
-               bt_ctf_writer_freeze(writer);
-       } else {
-               /* Non-writer stream indicated by a negative FD */
-               set_stream_fd(stream, -1);
-       }
-
-       /* Add this stream to the trace's streams */
-       g_ptr_array_add(trace->streams, stream);
-       BT_LOGD("Created stream object: addr=%p", stream);
-       goto end;
-
-error:
-       BT_PUT(stream);
-
-end:
-       bt_put(writer);
-       return stream;
-}
-
-struct bt_stream *bt_stream_create_with_id(
-               struct bt_stream_class *stream_class,
-               const char *name, uint64_t id_param)
-{
-       struct bt_trace *trace;
-       struct bt_stream *stream = NULL;
-       int64_t id = (int64_t) id_param;
-
-       if (!stream_class) {
-               BT_LOGW_STR("Invalid parameter: stream class is NULL.");
-               goto end;
-       }
-
-       if (id < 0) {
-               BT_LOGW("Invalid parameter: invalid stream's ID: "
-                       "name=\"%s\", id=%" PRIu64,
-                       name, id_param);
-               goto end;
-       }
-
-       trace = bt_stream_class_borrow_trace(stream_class);
-       if (!trace) {
-               BT_LOGW("Invalid parameter: cannot create stream from a stream class which is not part of trace: "
-                       "stream-class-addr=%p, stream-class-name=\"%s\", "
-                       "stream-name=\"%s\", stream-id=%" PRIu64,
-                       stream_class, bt_stream_class_get_name(stream_class),
-                       name, id_param);
-               goto end;
-       }
-
-       if (trace->is_created_by_writer) {
-               BT_LOGW("Invalid parameter: cannot create a CTF writer stream with this function; use bt_stream_create(): "
-                       "stream-class-addr=%p, stream-class-name=\"%s\", "
-                       "stream-name=\"%s\", stream-id=%" PRIu64,
-                       stream_class, bt_stream_class_get_name(stream_class),
-                       name, id_param);
-               goto end;
-       }
-
-       stream = bt_stream_create_with_id_no_check(stream_class,
-               name, id_param);
-
-end:
-       return stream;
-}
-
-struct bt_stream *bt_stream_create(
-               struct bt_stream_class *stream_class,
-               const char *name)
-{
-       return bt_stream_create_with_id_no_check(stream_class,
-               name, -1ULL);
-}
-
-struct bt_stream_class *bt_stream_get_class(
-               struct bt_stream *stream)
-{
-       BT_ASSERT_PRE_NON_NULL(stream, "Stream");
-       return bt_get(stream->stream_class);
-}
-
-int bt_stream_get_discarded_events_count(
-               struct bt_stream *stream, uint64_t *count)
-{
-       int ret = 0;
-
-       if (!stream) {
-               BT_LOGW_STR("Invalid parameter: stream is NULL.");
-               ret = -1;
-               goto end;
-       }
-
-       if (!count) {
-               BT_LOGW_STR("Invalid parameter: count is NULL.");
-               ret = -1;
-               goto end;
-       }
-
-       if (stream->pos.fd < 0) {
-               BT_LOGW("Invalid parameter: stream is not a CTF writer stream: "
-                       "stream-addr=%p, stream-name=\"%s\"",
-                       stream, bt_stream_get_name(stream));
-               ret = -1;
-               goto end;
-       }
-
-       *count = (uint64_t) stream->discarded_events;
-
-end:
-       return ret;
-}
-
-static
-int set_packet_context_events_discarded_field(struct bt_stream *stream,
-       uint64_t count)
-{
-       int ret = 0;
-       struct bt_field *events_discarded_field = NULL;
-
-       if (!stream->packet_context) {
-               goto end;
-       }
-
-       events_discarded_field = bt_field_structure_get_field_by_name(
-               stream->packet_context, "events_discarded");
-       if (!events_discarded_field) {
-               goto end;
-       }
-
-       ret = bt_field_unsigned_integer_set_value(
-               events_discarded_field, count);
-       if (ret) {
-               BT_LOGW("Cannot set packet context's `events_discarded` field: "
-                       "field-addr=%p, value=%" PRIu64,
-                       events_discarded_field, count);
-               goto end;
-       }
-
-end:
-       bt_put(events_discarded_field);
-       return ret;
-}
-
-void bt_stream_append_discarded_events(struct bt_stream *stream,
-               uint64_t event_count)
-{
-       int ret;
-       uint64_t new_count;
-       struct bt_field *events_discarded_field = NULL;
-
-       if (!stream) {
-               BT_LOGW_STR("Invalid parameter: stream is NULL.");
-               goto end;
-       }
-
-       BT_LOGV("Appending discarded events to stream: "
-               "stream-addr=%p, stream-name=\"%s\", append-count=%" PRIu64,
-               stream, bt_stream_get_name(stream), event_count);
-
-       if (!stream->packet_context) {
-               BT_LOGW_STR("Invalid parameter: stream has no packet context field.");
-               goto end;
-       }
-
-       if (stream->pos.fd < 0) {
-               BT_LOGW_STR("Invalid parameter: stream is not a CTF writer stream.");
-               goto end;
-       }
-
-       events_discarded_field = bt_field_structure_get_field_by_name(
-               stream->packet_context, "events_discarded");
-       if (!events_discarded_field) {
-               BT_LOGW_STR("No field named `events_discarded` in stream's packet context.");
-               goto end;
-       }
-
-       new_count = stream->discarded_events + event_count;
-       if (new_count < stream->discarded_events) {
-               BT_LOGW("New discarded events count is less than the stream's current discarded events count: "
-                       "cur-count=%" PRIu64 ", new-count=%" PRIu64,
-                       stream->discarded_events, new_count);
-               goto end;
-       }
-
-       ret = set_packet_context_events_discarded_field(stream, new_count);
-       if (ret) {
-               /* set_packet_context_events_discarded_field() logs errors */
-               goto end;
-       }
-
-       stream->discarded_events = new_count;
-       BT_LOGV("Appended discarded events to stream: "
-               "stream-addr=%p, stream-name=\"%s\", append-count=%" PRIu64,
-               stream, bt_stream_get_name(stream), event_count);
-
-end:
-       bt_put(events_discarded_field);
-}
-
-static int auto_populate_event_header(struct bt_stream *stream,
-               struct bt_event *event)
-{
-       int ret = 0;
-       struct bt_field *id_field = NULL, *timestamp_field = NULL;
-       struct bt_clock_class *mapped_clock_class = NULL;
-       int64_t event_class_id;
-
-       BT_ASSERT(event);
-
-       if (!event->event_header) {
-               goto end;
-       }
-
-       if (event->frozen) {
-               BT_LOGW_STR("Cannot populate event header field: event is frozen.");
-               ret = -1;
-               goto end;
-       }
-
-       BT_LOGV("Automatically populating event's header field: "
-               "stream-addr=%p, stream-name=\"%s\", event-addr=%p",
-               stream, bt_stream_get_name(stream), event);
-
-       id_field = bt_field_structure_get_field_by_name(event->event_header, "id");
-       event_class_id = bt_event_class_get_id(event->event_class);
-       BT_ASSERT(event_class_id >= 0);
-
-       if (id_field && bt_field_type_is_integer(id_field->type)) {
-               ret = set_integer_field_value(id_field, event_class_id);
-               if (ret) {
-                       BT_LOGW("Cannot set event header's `id` field's value: "
-                               "addr=%p, value=%" PRIu64, id_field,
-                               event_class_id);
-                       goto end;
-               }
-       }
-
-       /*
-        * The conditions to automatically set the timestamp are:
-        *
-        * 1. The event header field "timestamp" exists and is an
-        *    integer field.
-        * 2. This stream's class has a registered clock (set with
-        *    bt_stream_class_set_clock()).
-        * 3. The "timestamp" field is not set.
-        */
-       timestamp_field = bt_field_structure_get_field_by_name(
-                       event->event_header, "timestamp");
-       if (timestamp_field && stream->stream_class->clock &&
-                       bt_field_type_is_integer(timestamp_field->type) &&
-                       !bt_field_is_set_recursive(timestamp_field)) {
-               mapped_clock_class =
-                       bt_field_type_integer_get_mapped_clock_class(
-                               timestamp_field->type);
-               if (mapped_clock_class) {
-                       uint64_t timestamp;
-
-                       BT_ASSERT(mapped_clock_class ==
-                               stream->stream_class->clock->clock_class);
-                       ret = bt_ctf_clock_get_value(
-                               stream->stream_class->clock,
-                               &timestamp);
-                       BT_ASSERT(ret == 0);
-                       ret = set_integer_field_value(timestamp_field,
-                                       timestamp);
-                       if (ret) {
-                               BT_LOGW("Cannot set event header's `timestamp` field's value: "
-                                       "addr=%p, value=%" PRIu64,
-                                       timestamp_field, timestamp);
-                               goto end;
-                       }
-               }
-       }
-
-       BT_LOGV("Automatically populated event's header field: "
-               "stream-addr=%p, stream-name=\"%s\", event-addr=%p",
-               stream, bt_stream_get_name(stream), event);
-
-end:
-       bt_put(id_field);
-       bt_put(timestamp_field);
-       bt_put(mapped_clock_class);
-       return ret;
-}
-
-int bt_stream_append_event(struct bt_stream *stream,
-               struct bt_event *event)
-{
-       int ret = 0;
-
-       if (!stream) {
-               BT_LOGW_STR("Invalid parameter: stream is NULL.");
-               ret = -1;
-               goto end;
-       }
-
-       if (!event) {
-               BT_LOGW_STR("Invalid parameter: event is NULL.");
-               ret = -1;
-               goto end;
-       }
-
-       if (stream->pos.fd < 0) {
-               BT_LOGW_STR("Invalid parameter: stream is not a CTF writer stream.");
-               ret = -1;
-               goto end;
-       }
-
-       BT_LOGV("Appending event to stream: "
-               "stream-addr=%p, stream-name=\"%s\", event-addr=%p, "
-               "event-class-name=\"%s\", event-class-id=%" PRId64,
-               stream, bt_stream_get_name(stream), event,
-               bt_event_class_get_name(bt_event_borrow_event_class(event)),
-               bt_event_class_get_id(bt_event_borrow_event_class(event)));
-
-       /*
-        * The event is not supposed to have a parent stream at this
-        * point. The only other way an event can have a parent stream
-        * is if it was assigned when setting a packet to the event,
-        * in which case the packet's stream is not a writer stream,
-        * and thus the user is trying to append an event which belongs
-        * to another stream.
-        */
-       if (event->base.parent) {
-               ret = -1;
-               goto end;
-       }
-
-       bt_object_set_parent(event, stream);
-       BT_LOGV_STR("Automatically populating the header of the event to append.");
-       ret = auto_populate_event_header(stream, event);
-       if (ret) {
-               /* auto_populate_event_header() reports errors */
-               goto error;
-       }
-
-       /* Make sure the various scopes of the event are set */
-       BT_LOGV_STR("Validating event to append.");
-       ret = bt_event_validate(event);
-       if (ret) {
-               goto error;
-       }
-
-       /* Save the new event and freeze it */
-       BT_LOGV_STR("Freezing the event to append.");
-       bt_event_freeze(event);
-       g_ptr_array_add(stream->events, event);
-
-       /*
-        * Event had to hold a reference to its event class as long as it wasn't
-        * part of the same trace hierarchy. From now on, the event and its
-        * class share the same lifetime guarantees and the reference is no
-        * longer needed.
-        */
-       BT_LOGV_STR("Putting the event's class.");
-       bt_put(event->event_class);
-       BT_LOGV("Appended event to stream: "
-               "stream-addr=%p, stream-name=\"%s\", event-addr=%p, "
-               "event-class-name=\"%s\", event-class-id=%" PRId64,
-               stream, bt_stream_get_name(stream), event,
-               bt_event_class_get_name(bt_event_borrow_event_class(event)),
-               bt_event_class_get_id(bt_event_borrow_event_class(event)));
-
-end:
-       return ret;
-
-error:
-       /*
-        * Orphan the event; we were not successful in associating it to
-        * a stream.
-        */
-       bt_object_set_parent(event, NULL);
-
-       return ret;
-}
-
-struct bt_field *bt_stream_get_packet_context(struct bt_stream *stream)
-{
-       struct bt_field *packet_context = NULL;
-
-       if (!stream) {
-               BT_LOGW_STR("Invalid parameter: stream is NULL.");
-               goto end;
-       }
-
-       if (stream->pos.fd < 0) {
-               BT_LOGW("Invalid parameter: stream is not a CTF writer stream: "
-                       "stream-addr=%p, stream-name=\"%s\"", stream,
-                       bt_stream_get_name(stream));
-               goto end;
-       }
-
-       packet_context = stream->packet_context;
-       if (packet_context) {
-               bt_get(packet_context);
-       }
-end:
-       return packet_context;
-}
-
-int bt_stream_set_packet_context(struct bt_stream *stream,
-               struct bt_field *field)
-{
-       int ret = 0;
-       struct bt_field_type *field_type;
-
-       if (!stream) {
-               BT_LOGW_STR("Invalid parameter: stream is NULL.");
-               ret = -1;
-               goto end;
-       }
-
-       if (stream->pos.fd < 0) {
-               BT_LOGW_STR("Invalid parameter: stream is not a CTF writer stream.");
-               ret = -1;
-               goto end;
-       }
-
-       field_type = bt_field_get_type(field);
-       if (bt_field_type_compare(field_type,
-                       stream->stream_class->packet_context_type)) {
-               BT_LOGW("Invalid parameter: packet context's field type is different from the stream's packet context field type: "
-                       "stream-addr=%p, stream-name=\"%s\", "
-                       "packet-context-field-addr=%p, "
-                       "packet-context-ft-addr=%p",
-                       stream, bt_stream_get_name(stream),
-                       field, field_type);
-               ret = -1;
-               goto end;
-       }
-
-       bt_put(field_type);
-       bt_put(stream->packet_context);
-       stream->packet_context = bt_get(field);
-       BT_LOGV("Set stream's packet context field: "
-               "stream-addr=%p, stream-name=\"%s\", "
-               "packet-context-field-addr=%p",
-               stream, bt_stream_get_name(stream), field);
-end:
-       return ret;
-}
+#include <babeltrace/ctf-ir/stream.h>
+#include <babeltrace/ctf-ir/stream-internal.h>
+#include <babeltrace/ctf-ir/stream-class.h>
+#include <babeltrace/ctf-ir/stream-class-internal.h>
+#include <babeltrace/ctf-ir/trace.h>
+#include <babeltrace/ctf-ir/trace-internal.h>
+#include <babeltrace/ref.h>
+#include <babeltrace/compiler-internal.h>
+#include <babeltrace/align-internal.h>
+#include <babeltrace/assert-internal.h>
+#include <inttypes.h>
+#include <unistd.h>
 
-struct bt_field *bt_stream_get_packet_header(struct bt_stream *stream)
+BT_HIDDEN
+void bt_stream_common_finalize(struct bt_stream_common *stream)
 {
-       struct bt_field *packet_header = NULL;
-
-       if (!stream) {
-               BT_LOGW_STR("Invalid parameter: stream is NULL.");
-               goto end;
-       }
-
-       if (stream->pos.fd < 0) {
-               BT_LOGW("Invalid parameter: stream is not a CTF writer stream: "
-                       "stream-addr=%p, stream-name=\"%s\"", stream,
-                       bt_stream_get_name(stream));
-               goto end;
-       }
-
-       packet_header = stream->packet_header;
-       if (packet_header) {
-               bt_get(packet_header);
-       }
-end:
-       return packet_header;
-}
+       int i;
 
-int bt_stream_set_packet_header(struct bt_stream *stream,
-               struct bt_field *field)
-{
-       int ret = 0;
-       struct bt_trace *trace = NULL;
-       struct bt_field_type *field_type = NULL;
+       BT_LOGD("Finalizing common stream object: addr=%p, name=\"%s\"",
+               stream, bt_stream_common_get_name(stream));
 
-       if (!stream) {
-               BT_LOGW_STR("Invalid parameter: stream is NULL.");
-               ret = -1;
-               goto end;
-       }
+       /* Call destroy listeners in reverse registration order */
+       for (i = stream->destroy_listeners->len - 1; i >= 0; i--) {
+               struct bt_stream_common_destroy_listener *listener =
+                       &g_array_index(stream->destroy_listeners,
+                               struct bt_stream_common_destroy_listener, i);
 
-       if (stream->pos.fd < 0) {
-               BT_LOGW_STR("Invalid parameter: stream is not a CTF writer stream.");
-               ret = -1;
-               goto end;
+               BT_LOGD("Calling destroy listener: func=%p, data=%p, index=%d",
+                       listener->func, listener->data, i);
+               listener->func(stream, listener->data);
        }
 
-       trace = (struct bt_trace *) bt_object_get_parent(stream);
-
-       if (!field) {
-               if (trace->packet_header_type) {
-                       BT_LOGW("Invalid parameter: setting no packet header but packet header field type is not NULL: "
-                               "stream-addr=%p, stream-name=\"%s\", "
-                               "packet-header-field-addr=%p, "
-                               "expected-ft-addr=%p",
-                               stream, bt_stream_get_name(stream),
-                               field, trace->packet_header_type);
-                       ret = -1;
-                       goto end;
-               }
-
-               goto skip_validation;
+       if (stream->name) {
+               g_string_free(stream->name, TRUE);
        }
 
-       field_type = bt_field_get_type(field);
-       BT_ASSERT(field_type);
-
-       if (bt_field_type_compare(field_type, trace->packet_header_type)) {
-               BT_LOGW("Invalid parameter: packet header's field type is different from the stream's packet header field type: "
-                       "stream-addr=%p, stream-name=\"%s\", "
-                       "packet-header-field-addr=%p, "
-                       "packet-header-ft-addr=%p",
-                       stream, bt_stream_get_name(stream),
-                       field, field_type);
-               ret = -1;
-               goto end;
+       if (stream->destroy_listeners) {
+               g_array_free(stream->destroy_listeners, TRUE);
        }
-
-skip_validation:
-       bt_put(stream->packet_header);
-       stream->packet_header = bt_get(field);
-       BT_LOGV("Set stream's packet header field: "
-               "stream-addr=%p, stream-name=\"%s\", "
-               "packet-header-field-addr=%p",
-               stream, bt_stream_get_name(stream), field);
-end:
-       BT_PUT(trace);
-       bt_put(field_type);
-       return ret;
 }
 
 static
-void reset_structure_field(struct bt_field *structure, const char *name)
+void bt_stream_destroy(struct bt_object *obj)
 {
-       struct bt_field *member;
+       struct bt_stream *stream = (void *) obj;
 
-       member = bt_field_structure_get_field_by_name(structure, name);
-       if (member) {
-               (void) bt_field_reset_recursive(member);
-               bt_put(member);
-       }
+       BT_LOGD("Destroying stream object: addr=%p, name=\"%s\"",
+               stream, bt_stream_get_name(stream));
+       bt_stream_common_finalize((void *) obj);
+       g_free(stream);
 }
 
-int bt_stream_flush(struct bt_stream *stream)
+BT_HIDDEN
+int bt_stream_common_initialize(
+               struct bt_stream_common *stream,
+               struct bt_stream_class_common *stream_class, const char *name,
+               uint64_t id, bt_object_release_func release_func)
 {
        int ret = 0;
-       size_t i;
-       struct bt_stream_pos packet_context_pos;
-       struct bt_trace *trace;
-       enum bt_byte_order native_byte_order;
-       bool has_packet_size = false;
-
-       if (!stream) {
-               BT_LOGW_STR("Invalid parameter: stream is NULL.");
-               ret = -1;
-               goto end_no_stream;
-       }
-
-       if (stream->pos.fd < 0) {
-               BT_LOGW_STR("Invalid parameter: stream is not a CTF writer stream.");
-               ret = -1;
-               goto end;
-       }
-
-       if (stream->packet_context) {
-               struct bt_field *packet_size_field;
-
-               packet_size_field = bt_field_structure_get_field_by_name(
-                               stream->packet_context, "packet_size");
-               has_packet_size = (packet_size_field != NULL);
-               bt_put(packet_size_field);
-       }
-
-       if (stream->flushed_packet_count == 1) {
-               if (!stream->packet_context) {
-                       BT_LOGW_STR("Cannot flush a stream which has no packet context field more than once.");
-                       ret = -1;
-                       goto end;
-               }
-
-               if (!has_packet_size) {
-                       BT_LOGW_STR("Cannot flush a stream which has no packet context's `packet_size` field more than once.");
-                       ret = -1;
-                       goto end;
-               }
-       }
-
-       BT_LOGV("Flushing stream's current packet: stream-addr=%p, "
-               "stream-name=\"%s\", packet-index=%u", stream,
-               bt_stream_get_name(stream), stream->flushed_packet_count);
-       trace = bt_stream_class_borrow_trace(stream->stream_class);
-       BT_ASSERT(trace);
-       native_byte_order = bt_trace_get_native_byte_order(trace);
-
-       ret = auto_populate_packet_header(stream);
-       if (ret) {
-               BT_LOGW_STR("Cannot automatically populate the stream's packet header field.");
-               ret = -1;
-               goto end;
-       }
-
-       ret = auto_populate_packet_context(stream, true);
-       if (ret) {
-               BT_LOGW_STR("Cannot automatically populate the stream's packet context field.");
-               ret = -1;
-               goto end;
-       }
+       struct bt_trace_common *trace = NULL;
 
-       /* mmap the next packet */
-       BT_LOGV("Seeking to the next packet: pos-offset=%" PRId64,
-               stream->pos.offset);
-       bt_stream_pos_packet_seek(&stream->pos, 0, SEEK_CUR);
-       BT_ASSERT(stream->pos.packet_size % 8 == 0);
+       bt_object_init(stream, release_func);
 
-       if (stream->packet_header) {
-               BT_LOGV_STR("Serializing packet header field.");
-               ret = bt_field_serialize_recursive(stream->packet_header,
-                       &stream->pos, native_byte_order);
-               if (ret) {
-                       BT_LOGW("Cannot serialize stream's packet header field: "
-                               "field-addr=%p", stream->packet_header);
-                       goto end;
-               }
+       if (!stream_class) {
+               BT_LOGW_STR("Invalid parameter: stream class is NULL.");
+               goto error;
        }
 
-       if (stream->packet_context) {
-               /* Write packet context */
-               memcpy(&packet_context_pos, &stream->pos,
-                       sizeof(packet_context_pos));
-               BT_LOGV_STR("Serializing packet context field.");
-               ret = bt_field_serialize_recursive(stream->packet_context,
-                       &stream->pos, native_byte_order);
-               if (ret) {
-                       BT_LOGW("Cannot serialize stream's packet context field: "
-                               "field-addr=%p", stream->packet_context);
-                       goto end;
-               }
+       BT_LOGD("Initializing common stream object: stream-class-addr=%p, "
+               "stream-class-name=\"%s\", stream-name=\"%s\", "
+               "stream-id=%" PRIu64,
+               stream_class, bt_stream_class_common_get_name(stream_class),
+               name, id);
+       trace = bt_stream_class_common_borrow_trace(stream_class);
+       if (!trace) {
+               BT_LOGW("Invalid parameter: cannot create stream from a stream class which is not part of trace: "
+                       "stream-class-addr=%p, stream-class-name=\"%s\", "
+                       "stream-name=\"%s\"",
+                       stream_class,
+                       bt_stream_class_common_get_name(stream_class), name);
+               goto error;
        }
 
-       BT_LOGV("Serializing events: count=%u", stream->events->len);
-
-       for (i = 0; i < stream->events->len; i++) {
-               struct bt_event *event = g_ptr_array_index(
-                       stream->events, i);
-               struct bt_event_class *event_class =
-                       bt_event_borrow_event_class(event);
+       if (id != -1ULL) {
+               /*
+                * Validate that the given ID is unique amongst all the
+                * existing trace's streams created from the same stream
+                * class.
+                */
+               size_t i;
 
-               BT_LOGV("Serializing event: index=%zu, event-addr=%p, "
-                       "event-class-name=\"%s\", event-class-id=%" PRId64 ", "
-                       "pos-offset=%" PRId64 ", packet-size=%" PRIu64,
-                       i, event, bt_event_class_get_name(event_class),
-                       bt_event_class_get_id(event_class),
-                       stream->pos.offset, stream->pos.packet_size);
+               for (i = 0; i < trace->streams->len; i++) {
+                       struct bt_stream_common *trace_stream =
+                               g_ptr_array_index(trace->streams, i);
 
-               /* Write event header */
-               if (event->event_header) {
-                       BT_LOGV_STR("Serializing event's header field.");
-                       ret = bt_field_serialize_recursive(event->event_header,
-                                       &stream->pos, native_byte_order);
-                       if (ret) {
-                               BT_LOGW("Cannot serialize event's header field: "
-                                               "field-addr=%p", event->event_header);
-                               goto end;
+                       if (trace_stream->stream_class != (void *) stream_class) {
+                               continue;
                        }
-               }
 
-               /* Write stream event context */
-               if (event->stream_event_context) {
-                       BT_LOGV_STR("Serializing event's stream event context field.");
-                       ret = bt_field_serialize_recursive(
-                               event->stream_event_context, &stream->pos,
-                               native_byte_order);
-                       if (ret) {
-                               BT_LOGW("Cannot serialize event's stream event context field: "
-                                       "field-addr=%p", event->stream_event_context);
-                               goto end;
+                       if (trace_stream->id == id) {
+                               BT_LOGW_STR("Invalid parameter: another stream in the same trace already has this ID.");
+                               goto error;
                        }
                }
-
-               /* Write event content */
-               ret = bt_event_serialize(event, &stream->pos,
-                       native_byte_order);
-               if (ret) {
-                       /* bt_event_serialize() logs errors */
-                       goto end;
-               }
-       }
-
-       if (!has_packet_size && stream->pos.offset % 8 != 0) {
-               BT_LOGW("Stream's packet context field type has no `packet_size` field, "
-                       "but current content size is not a multiple of 8 bits: "
-                       "content-size=%" PRId64 ", "
-                       "packet-size=%" PRIu64,
-                       stream->pos.offset,
-                       stream->pos.packet_size);
-               ret = -1;
-               goto end;
        }
 
-       BT_ASSERT(stream->pos.packet_size % 8 == 0);
-
        /*
-        * Remove extra padding bytes.
+        * Acquire reference to parent since stream will become publicly
+        * reachable; it needs its parent to remain valid.
         */
-       stream->pos.packet_size = (stream->pos.offset + 7) & ~7;
-
-       if (stream->packet_context) {
-               /*
-                * The whole packet is serialized at this point. Make sure that,
-                * if `packet_size` is missing, the current content size is
-                * equal to the current packet size.
-                */
-               struct bt_field *field = bt_field_structure_get_field_by_name(
-                       stream->packet_context, "content_size");
-
-               bt_put(field);
-               if (!field) {
-                       if (stream->pos.offset != stream->pos.packet_size) {
-                               BT_LOGW("Stream's packet context's `content_size` field is missing, "
-                                       "but current packet's content size is not equal to its packet size: "
-                                       "content-size=%" PRId64 ", "
-                                       "packet-size=%" PRIu64,
-                                       stream->pos.offset,
-                                       stream->pos.packet_size);
-                               ret = -1;
-                               goto end;
-                       }
-               }
-
-               /*
-                * Overwrite the packet context now that the stream
-                * position's packet and content sizes have the correct
-                * values.
-                *
-                * Copy base_mma as the packet may have been remapped
-                * (e.g. when a packet is resized).
-                */
-               packet_context_pos.base_mma = stream->pos.base_mma;
-               ret = auto_populate_packet_context(stream, false);
-               if (ret) {
-                       BT_LOGW_STR("Cannot automatically populate the stream's packet context field.");
-                       ret = -1;
-                       goto end;
-               }
+       bt_object_set_parent(stream, trace);
+       stream->stream_class = stream_class;
+       stream->id = (int64_t) id;
+       stream->destroy_listeners = g_array_new(FALSE, TRUE,
+               sizeof(struct bt_stream_common_destroy_listener));
+       if (!stream->destroy_listeners) {
+               BT_LOGE_STR("Failed to allocate a GArray.");
+               goto error;
+       }
 
-               BT_LOGV("Rewriting (serializing) packet context field.");
-               ret = bt_field_serialize_recursive(stream->packet_context,
-                       &packet_context_pos, native_byte_order);
-               if (ret) {
-                       BT_LOGW("Cannot serialize stream's packet context field: "
-                               "field-addr=%p", stream->packet_context);
-                       goto end;
+       if (name) {
+               stream->name = g_string_new(name);
+               if (!stream->name) {
+                       BT_LOGE_STR("Failed to allocate a GString.");
+                       goto error;
                }
        }
 
-       g_ptr_array_set_size(stream->events, 0);
-       stream->flushed_packet_count++;
-       stream->size += stream->pos.packet_size / CHAR_BIT;
+       BT_LOGD("Set common stream's trace parent: trace-addr=%p", trace);
 
-end:
-       /* Reset automatically-set fields. */
-       if (stream->packet_context) {
-               reset_structure_field(stream->packet_context, "timestamp_begin");
-               reset_structure_field(stream->packet_context, "timestamp_end");
-               reset_structure_field(stream->packet_context, "packet_size");
-               reset_structure_field(stream->packet_context, "content_size");
-               reset_structure_field(stream->packet_context, "events_discarded");
-       }
+       /* Add this stream to the trace's streams */
+       BT_LOGD("Created common stream object: addr=%p", stream);
+       goto end;
 
-       if (ret < 0) {
-               /*
-                * We failed to write the packet. Its size is therefore set to 0
-                * to ensure the next mapping is done in the same place rather
-                * than advancing by "stream->pos.packet_size", which would
-                * leave a corrupted packet in the trace.
-                */
-               stream->pos.packet_size = 0;
-       } else {
-               BT_LOGV("Flushed stream's current packet: content-size=%" PRId64 ", "
-                       "packet-size=%" PRIu64,
-                       stream->pos.offset, stream->pos.packet_size);
-       }
+error:
+       ret = -1;
 
-end_no_stream:
+end:
        return ret;
 }
 
-/* Pre-2.0 CTF writer backward compatibility */
-void bt_ctf_stream_get(struct bt_stream *stream)
-{
-       bt_get(stream);
-}
-
-/* Pre-2.0 CTF writer backward compatibility */
-void bt_ctf_stream_put(struct bt_stream *stream)
-{
-       bt_put(stream);
-}
-
 static
-void bt_stream_destroy(struct bt_object *obj)
+struct bt_stream *bt_stream_create_with_id_no_check(
+               struct bt_stream_class *stream_class,
+               const char *name, uint64_t id)
 {
-       struct bt_stream *stream;
-       int i;
-
-       stream = container_of(obj, struct bt_stream, base);
-       BT_LOGD("Destroying stream object: addr=%p, name=\"%s\"",
-               stream, bt_stream_get_name(stream));
+       int ret;
+       struct bt_stream *stream = NULL;
+       struct bt_trace *trace = NULL;
 
-       /* Call destroy listeners in reverse registration order */
-       for (i = stream->destroy_listeners->len - 1; i >= 0; i--) {
-               struct bt_stream_destroy_listener *listener =
-                       &g_array_index(stream->destroy_listeners,
-                               struct bt_stream_destroy_listener, i);
+       BT_LOGD("Creating stream object: stream-class-addr=%p, "
+               "stream-class-name=\"%s\", stream-name=\"%s\", "
+               "stream-id=%" PRIu64,
+               stream_class, bt_stream_class_get_name(stream_class),
+               name, id);
 
-               BT_LOGD("Calling destroy listener: func=%p, data=%p, index=%d",
-                       listener->func, listener->data, i);
-               listener->func(stream, listener->data);
+       trace = BT_FROM_COMMON(bt_stream_class_common_borrow_trace(
+               BT_TO_COMMON(stream_class)));
+       if (!trace) {
+               BT_LOGW("Invalid parameter: cannot create stream from a stream class which is not part of trace: "
+                       "stream-class-addr=%p, stream-class-name=\"%s\", "
+                       "stream-name=\"%s\"",
+                       stream_class, bt_stream_class_get_name(stream_class),
+                       name);
+               goto error;
        }
 
-       (void) bt_stream_pos_fini(&stream->pos);
-       if (stream->pos.fd >= 0) {
-               int ret;
-
+       if (bt_trace_is_static(trace)) {
                /*
-                * Truncate the file's size to the minimum required to fit the
-                * last packet as we might have grown it too much on the last
-                * mmap.
+                * A static trace has the property that all its stream
+                * classes, clock classes, and streams are definitive:
+                * no more can be added, and each object is also frozen.
                 */
-               do {
-                       ret = ftruncate(stream->pos.fd, stream->size);
-               } while (ret == -1 && errno == EINTR);
-               if (ret) {
-                       BT_LOGE_ERRNO("Failed to truncate stream file",
-                               ": ret=%d, size=%" PRIu64,
-                               ret, (uint64_t) stream->size);
-               }
-
-               if (close(stream->pos.fd)) {
-                       BT_LOGE_ERRNO("Failed to close stream file",
-                               ": ret=%d", ret);
-               }
+               BT_LOGW("Invalid parameter: cannot create stream from a stream class which is part of a static trace: "
+                       "stream-class-addr=%p, stream-class-name=\"%s\", "
+                       "stream-name=\"%s\", trace-addr=%p",
+                       stream_class, bt_stream_class_get_name(stream_class),
+                       name, trace);
+               goto error;
        }
 
-       if (stream->events) {
-               BT_LOGD_STR("Putting events.");
-               g_ptr_array_free(stream->events, TRUE);
+       stream = g_new0(struct bt_stream, 1);
+       if (!stream) {
+               BT_LOGE_STR("Failed to allocate one stream.");
+               goto error;
        }
 
-       if (stream->name) {
-               g_string_free(stream->name, TRUE);
+       ret = bt_stream_common_initialize(BT_TO_COMMON(stream),
+               BT_TO_COMMON(stream_class), name, id, bt_stream_destroy);
+       if (ret) {
+               /* bt_stream_common_initialize() logs errors */
+               goto error;
        }
 
-       if (stream->destroy_listeners) {
-               g_array_free(stream->destroy_listeners, TRUE);
-       }
+       g_ptr_array_add(trace->common.streams, stream);
+       BT_LOGD("Created stream object: addr=%p", stream);
+       goto end;
 
-       BT_LOGD_STR("Putting packet header field.");
-       bt_put(stream->packet_header);
-       BT_LOGD_STR("Putting packet context field.");
-       bt_put(stream->packet_context);
-       g_free(stream);
+error:
+       BT_PUT(stream);
+
+end:
+       return stream;
 }
 
-static
-int _set_structure_field_integer(struct bt_field *structure, char *name,
-               uint64_t value, bt_bool force)
+struct bt_stream *bt_stream_create(struct bt_stream_class *stream_class,
+               const char *name, uint64_t id_param)
 {
-       int ret = 0;
-       struct bt_field_type *field_type = NULL;
-       struct bt_field *integer;
-
-       BT_ASSERT(structure);
-       BT_ASSERT(name);
+       struct bt_stream *stream = NULL;
+       int64_t id = (int64_t) id_param;
 
-       integer = bt_field_structure_get_field_by_name(structure, name);
-       if (!integer) {
-               /* Field not found, not an error. */
-               BT_LOGV("Field not found: struct-field-addr=%p, "
-                       "name=\"%s\", force=%d", structure, name, force);
+       if (!stream_class) {
+               BT_LOGW_STR("Invalid parameter: stream class is NULL.");
                goto end;
        }
 
-       /* Make sure the payload has not already been set. */
-       if (!force && bt_field_is_set_recursive(integer)) {
-               /* Payload already set, not an error */
-               BT_LOGV("Field's payload is already set: struct-field-addr=%p, "
-                       "name=\"%s\", force=%d", structure, name, force);
+       if (id < 0) {
+               BT_LOGW("Invalid parameter: invalid stream's ID: "
+                       "name=\"%s\", id=%" PRIu64,
+                       name, id_param);
                goto end;
        }
 
-       field_type = bt_field_get_type(integer);
-       BT_ASSERT(field_type);
-       if (bt_field_type_get_type_id(field_type) != BT_FIELD_TYPE_ID_INTEGER) {
-               /*
-                * The user most likely meant for us to populate this field
-                * automatically. However, we can only do this if the field
-                * is an integer. Return an error.
-                */
-               BT_LOGW("Invalid parameter: field's type is not an integer field type: "
-                       "field-addr=%p, ft-addr=%p, ft-id=%s",
-                       integer, field_type,
-                       bt_field_type_id_string(field_type->id));
-               ret = -1;
-               goto end;
-       }
+       stream = bt_stream_create_with_id_no_check(stream_class,
+               name, id_param);
 
-       if (bt_field_type_integer_is_signed(field_type)) {
-               ret = bt_field_signed_integer_set_value(integer,
-                       (int64_t) value);
-       } else {
-               ret = bt_field_unsigned_integer_set_value(integer, value);
-       }
-       ret = !ret ? 1 : ret;
 end:
-       bt_put(integer);
-       bt_put(field_type);
-       return ret;
+       return stream;
 }
 
-/*
- * Returns the following codes:
- * 1 if the field was found and set,
- * 0 if nothing was done (field not found, or was already set),
- * <0 if an error was encoutered
- */
-static
-int try_set_structure_field_integer(struct bt_field *structure, char *name,
-               uint64_t value)
+struct bt_stream_class *bt_stream_get_class(struct bt_stream *stream)
 {
-       return _set_structure_field_integer(structure, name, value, BT_FALSE);
+       return BT_FROM_COMMON(bt_stream_common_get_class(BT_TO_COMMON(stream)));
 }
 
 const char *bt_stream_get_name(struct bt_stream *stream)
 {
-       BT_ASSERT_PRE_NON_NULL(stream, "Stream");
-       return stream->name ? stream->name->str : NULL;
+       return bt_stream_common_get_name(BT_TO_COMMON(stream));
 }
 
-int bt_stream_is_writer(struct bt_stream *stream)
+int64_t bt_stream_get_id(struct bt_stream *stream)
 {
-       int ret = -1;
-
-       if (!stream) {
-               BT_LOGW_STR("Invalid parameter: stream is NULL.");
-               goto end;
-       }
-
-       ret = (stream->pos.fd >= 0);
-
-end:
-       return ret;
+       return bt_stream_common_get_id(BT_TO_COMMON(stream));
 }
 
 BT_HIDDEN
-void bt_stream_add_destroy_listener(struct bt_stream *stream,
-               bt_stream_destroy_listener_func func, void *data)
+void bt_stream_common_add_destroy_listener(struct bt_stream_common *stream,
+               bt_stream_common_destroy_listener_func func, void *data)
 {
-       struct bt_stream_destroy_listener listener;
+       struct bt_stream_common_destroy_listener listener;
 
        BT_ASSERT(stream);
        BT_ASSERT(func);
@@ -2099,12 +288,12 @@ void bt_stream_add_destroy_listener(struct bt_stream *stream,
        g_array_append_val(stream->destroy_listeners, listener);
        BT_LOGV("Added stream destroy listener: stream-addr=%p, "
                "stream-name=\"%s\", func=%p, data=%p",
-               stream, bt_stream_get_name(stream), func, data);
+               stream, bt_stream_common_get_name(stream), func, data);
 }
 
 BT_HIDDEN
-void bt_stream_remove_destroy_listener(struct bt_stream *stream,
-               bt_stream_destroy_listener_func func, void *data)
+void bt_stream_common_remove_destroy_listener(struct bt_stream_common *stream,
+               bt_stream_common_destroy_listener_func func, void *data)
 {
        size_t i;
 
@@ -2112,31 +301,17 @@ void bt_stream_remove_destroy_listener(struct bt_stream *stream,
        BT_ASSERT(func);
 
        for (i = 0; i < stream->destroy_listeners->len; i++) {
-               struct bt_stream_destroy_listener *listener =
+               struct bt_stream_common_destroy_listener *listener =
                        &g_array_index(stream->destroy_listeners,
-                               struct bt_stream_destroy_listener, i);
+                               struct bt_stream_common_destroy_listener, i);
 
                if (listener->func == func && listener->data == data) {
                        g_array_remove_index(stream->destroy_listeners, i);
                        i--;
                        BT_LOGV("Removed stream destroy listener: stream-addr=%p, "
                                "stream-name=\"%s\", func=%p, data=%p",
-                               stream, bt_stream_get_name(stream),
+                               stream, bt_stream_common_get_name(stream),
                                func, data);
                }
        }
 }
-
-int64_t bt_stream_get_id(struct bt_stream *stream)
-{
-       int64_t ret;
-
-       BT_ASSERT_PRE_NON_NULL(stream, "Stream");
-       ret = stream->id;
-       if (ret < 0) {
-               BT_LOGV("Stream's ID is not set: addr=%p, name=\"%s\"",
-                       stream, bt_stream_get_name(stream));
-       }
-
-       return ret;
-}
index bc754f5dab762074f98662ad2b34f1d1b8000653..ff026011f5cca4a389c46eb90e2c70775e1f25d4 100644 (file)
@@ -29,6 +29,7 @@
 #define BT_LOG_TAG "TRACE"
 #include <babeltrace/lib-logging-internal.h>
 
+#include <babeltrace/assert-pre-internal.h>
 #include <babeltrace/ctf-ir/trace-internal.h>
 #include <babeltrace/ctf-ir/clock-class-internal.h>
 #include <babeltrace/ctf-ir/stream-internal.h>
@@ -51,7 +52,6 @@
 #include <babeltrace/types.h>
 #include <babeltrace/endian-internal.h>
 #include <babeltrace/assert-internal.h>
-#include <babeltrace/assert-pre-internal.h>
 #include <inttypes.h>
 #include <stdint.h>
 #include <string.h>
@@ -72,44 +72,53 @@ struct bt_trace_is_static_listener_elem {
 };
 
 static
-void bt_trace_destroy(struct bt_object *obj);
-static
-void bt_trace_freeze(struct bt_trace *trace);
+void bt_trace_destroy(struct bt_object *obj)
+{
+       struct bt_trace *trace = (void *) obj;
 
-static
-const unsigned int field_type_aliases_alignments[] = {
-       [FIELD_TYPE_ALIAS_UINT5_T] = 1,
-       [FIELD_TYPE_ALIAS_UINT8_T ... FIELD_TYPE_ALIAS_UINT16_T] = 8,
-       [FIELD_TYPE_ALIAS_UINT27_T] = 1,
-       [FIELD_TYPE_ALIAS_UINT32_T ... FIELD_TYPE_ALIAS_UINT64_T] = 8,
-};
+       BT_LOGD("Destroying trace object: addr=%p, name=\"%s\"",
+               trace, bt_trace_get_name(trace));
 
-static
-const unsigned int field_type_aliases_sizes[] = {
-       [FIELD_TYPE_ALIAS_UINT5_T] = 5,
-       [FIELD_TYPE_ALIAS_UINT8_T] = 8,
-       [FIELD_TYPE_ALIAS_UINT16_T] = 16,
-       [FIELD_TYPE_ALIAS_UINT27_T] = 27,
-       [FIELD_TYPE_ALIAS_UINT32_T] = 32,
-       [FIELD_TYPE_ALIAS_UINT64_T] = 64,
-};
+       /*
+        * Call remove listeners first so that everything else still
+        * exists in the trace.
+        */
+       if (trace->is_static_listeners) {
+               size_t i;
 
-struct bt_trace *bt_trace_create(void)
-{
-       struct bt_trace *trace = NULL;
+               for (i = 0; i < trace->is_static_listeners->len; i++) {
+                       struct bt_trace_is_static_listener_elem elem =
+                               g_array_index(trace->is_static_listeners,
+                                       struct bt_trace_is_static_listener_elem, i);
 
-       trace = g_new0(struct bt_trace, 1);
-       if (!trace) {
-               BT_LOGE_STR("Failed to allocate one trace.");
-               goto error;
+                       if (elem.removed) {
+                               elem.removed(trace, elem.data);
+                       }
+               }
+
+               g_array_free(trace->is_static_listeners, TRUE);
        }
 
-       BT_LOGD_STR("Creating trace object.");
+       if (trace->listeners) {
+               g_ptr_array_free(trace->listeners, TRUE);
+       }
+
+       bt_trace_common_finalize(BT_TO_COMMON(trace));
+       g_free(trace);
+}
+
+BT_HIDDEN
+int bt_trace_common_initialize(struct bt_trace_common *trace,
+               bt_object_release_func release_func)
+{
+       int ret = 0;
+
+       BT_LOGD_STR("Initializing common trace object.");
        trace->native_byte_order = BT_BYTE_ORDER_UNSPECIFIED;
-       bt_object_init(trace, bt_trace_destroy);
-       trace->clocks = g_ptr_array_new_with_free_func(
+       bt_object_init(trace, release_func);
+       trace->clock_classes = g_ptr_array_new_with_free_func(
                (GDestroyNotify) bt_put);
-       if (!trace->clocks) {
+       if (!trace->clock_classes) {
                BT_LOGE_STR("Failed to allocate one GPtrArray.");
                goto error;
        }
@@ -135,6 +144,68 @@ struct bt_trace *bt_trace_create(void)
                goto error;
        }
 
+       BT_LOGD("Initialized common trace object: addr=%p", trace);
+       goto end;
+
+error:
+       ret = -1;
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+void bt_trace_common_finalize(struct bt_trace_common *trace)
+{
+       BT_LOGD("Finalizing common trace object: addr=%p, name=\"%s\"",
+               trace, bt_trace_common_get_name(trace));
+
+       if (trace->environment) {
+               BT_LOGD_STR("Destroying environment attributes.");
+               bt_attributes_destroy(trace->environment);
+       }
+
+       if (trace->name) {
+               g_string_free(trace->name, TRUE);
+       }
+
+       if (trace->clock_classes) {
+               BT_LOGD_STR("Putting clock classes.");
+               g_ptr_array_free(trace->clock_classes, TRUE);
+       }
+
+       if (trace->streams) {
+               BT_LOGD_STR("Destroying streams.");
+               g_ptr_array_free(trace->streams, TRUE);
+       }
+
+       if (trace->stream_classes) {
+               BT_LOGD_STR("Destroying stream classes.");
+               g_ptr_array_free(trace->stream_classes, TRUE);
+       }
+
+       BT_LOGD_STR("Putting packet header field type.");
+       bt_put(trace->packet_header_field_type);
+}
+
+struct bt_trace *bt_trace_create(void)
+{
+       struct bt_trace *trace = NULL;
+       int ret;
+
+       BT_LOGD_STR("Creating trace object.");
+       trace = g_new0(struct bt_trace, 1);
+       if (!trace) {
+               BT_LOGE_STR("Failed to allocate one trace.");
+               goto error;
+       }
+
+       ret = bt_trace_common_initialize(BT_TO_COMMON(trace), bt_trace_destroy);
+       if (ret) {
+               /* bt_trace_common_initialize() logs errors */
+               goto error;
+       }
+
        trace->listeners = g_ptr_array_new_with_free_func(
                        (GDestroyNotify) g_free);
        if (!trace->listeners) {
@@ -159,11 +230,11 @@ error:
 
 const char *bt_trace_get_name(struct bt_trace *trace)
 {
-       BT_ASSERT_PRE_NON_NULL(trace, "Trace");
-       return trace->name ? trace->name->str : NULL;
+       return bt_trace_common_get_name(BT_TO_COMMON(trace));
 }
 
-int bt_trace_set_name(struct bt_trace *trace, const char *name)
+BT_HIDDEN
+int bt_trace_common_set_name(struct bt_trace_common *trace, const char *name)
 {
        int ret = 0;
 
@@ -182,7 +253,7 @@ int bt_trace_set_name(struct bt_trace *trace, const char *name)
        if (trace->frozen) {
                BT_LOGW("Invalid parameter: trace is frozen: "
                        "addr=%p, name=\"%s\"",
-                       trace, bt_trace_get_name(trace));
+                       trace, bt_trace_common_get_name(trace));
                ret = -1;
                goto end;
        }
@@ -201,13 +272,19 @@ end:
        return ret;
 }
 
+int bt_trace_set_name(struct bt_trace *trace, const char *name)
+{
+       return bt_trace_common_set_name(BT_TO_COMMON(trace), name);
+}
+
 const unsigned char *bt_trace_get_uuid(struct bt_trace *trace)
 {
-       BT_ASSERT_PRE_NON_NULL(trace, "Trace");
-       return trace->uuid_set ? trace->uuid : NULL;
+       return bt_trace_common_get_uuid(BT_TO_COMMON(trace));
 }
 
-int bt_trace_set_uuid(struct bt_trace *trace, const unsigned char *uuid)
+BT_HIDDEN
+int bt_trace_common_set_uuid(struct bt_trace_common *trace,
+               const unsigned char *uuid)
 {
        int ret = 0;
 
@@ -226,7 +303,7 @@ int bt_trace_set_uuid(struct bt_trace *trace, const unsigned char *uuid)
        if (trace->frozen) {
                BT_LOGW("Invalid parameter: trace is frozen: "
                        "addr=%p, name=\"%s\"",
-                       trace, bt_trace_get_name(trace));
+                       trace, bt_trace_common_get_name(trace));
                ret = -1;
                goto end;
        }
@@ -235,7 +312,7 @@ int bt_trace_set_uuid(struct bt_trace *trace, const unsigned char *uuid)
        trace->uuid_set = BT_TRUE;
        BT_LOGV("Set trace's UUID: addr=%p, name=\"%s\", "
                "uuid=\"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\"",
-               trace, bt_trace_get_name(trace),
+               trace, bt_trace_common_get_name(trace),
                (unsigned int) uuid[0],
                (unsigned int) uuid[1],
                (unsigned int) uuid[2],
@@ -257,69 +334,14 @@ end:
        return ret;
 }
 
-void bt_trace_destroy(struct bt_object *obj)
+int bt_trace_set_uuid(struct bt_trace *trace,
+               const unsigned char *uuid)
 {
-       struct bt_trace *trace;
-
-       trace = container_of(obj, struct bt_trace, base);
-
-       BT_LOGD("Destroying trace object: addr=%p, name=\"%s\"",
-               trace, bt_trace_get_name(trace));
-
-       /*
-        * Call remove listeners first so that everything else still
-        * exists in the trace.
-        */
-       if (trace->is_static_listeners) {
-               size_t i;
-
-               for (i = 0; i < trace->is_static_listeners->len; i++) {
-                       struct bt_trace_is_static_listener_elem elem =
-                               g_array_index(trace->is_static_listeners,
-                                       struct bt_trace_is_static_listener_elem, i);
-
-                       if (elem.removed) {
-                               elem.removed(trace, elem.data);
-                       }
-               }
-
-               g_array_free(trace->is_static_listeners, TRUE);
-       }
-
-       if (trace->listeners) {
-               g_ptr_array_free(trace->listeners, TRUE);
-       }
-
-       if (trace->environment) {
-               BT_LOGD_STR("Destroying environment attributes.");
-               bt_attributes_destroy(trace->environment);
-       }
-
-       if (trace->name) {
-               g_string_free(trace->name, TRUE);
-       }
-
-       if (trace->clocks) {
-               BT_LOGD_STR("Putting clock classes.");
-               g_ptr_array_free(trace->clocks, TRUE);
-       }
-
-       if (trace->streams) {
-               BT_LOGD_STR("Destroying streams.");
-               g_ptr_array_free(trace->streams, TRUE);
-       }
-
-       if (trace->stream_classes) {
-               BT_LOGD_STR("Destroying stream classes.");
-               g_ptr_array_free(trace->stream_classes, TRUE);
-       }
-
-       BT_LOGD_STR("Putting packet header field type.");
-       bt_put(trace->packet_header_type);
-       g_free(trace);
+       return bt_trace_common_set_uuid(BT_TO_COMMON(trace), uuid);
 }
 
-int bt_trace_set_environment_field(struct bt_trace *trace,
+BT_HIDDEN
+int bt_trace_common_set_environment_field(struct bt_trace_common *trace,
                const char *name, struct bt_value *value)
 {
        int ret = 0;
@@ -346,7 +368,7 @@ int bt_trace_set_environment_field(struct bt_trace *trace,
                BT_LOGW("Invalid parameter: environment field's name is not a valid CTF identifier: "
                        "trace-addr=%p, trace-name=\"%s\", "
                        "env-name=\"%s\"",
-                       trace, bt_trace_get_name(trace), name);
+                       trace, bt_trace_common_get_name(trace), name);
                ret = -1;
                goto end;
        }
@@ -355,20 +377,12 @@ int bt_trace_set_environment_field(struct bt_trace *trace,
                BT_LOGW("Invalid parameter: environment field's value is not an integer or string value: "
                        "trace-addr=%p, trace-name=\"%s\", "
                        "env-name=\"%s\", env-value-type=%s",
-                       trace, bt_trace_get_name(trace), name,
+                       trace, bt_trace_common_get_name(trace), name,
                        bt_value_type_string(bt_value_get_type(value)));
                ret = -1;
                goto end;
        }
 
-       if (trace->is_static) {
-               BT_LOGW("Invalid parameter: trace is static: "
-                       "addr=%p, name=\"%s\"",
-                       trace, bt_trace_get_name(trace));
-               ret = -1;
-               goto end;
-       }
-
        if (trace->frozen) {
                /*
                 * New environment fields may be added to a frozen trace,
@@ -384,7 +398,7 @@ int bt_trace_set_environment_field(struct bt_trace *trace,
                        BT_LOGW("Invalid parameter: trace is frozen and environment field already exists with this name: "
                                "trace-addr=%p, trace-name=\"%s\", "
                                "env-name=\"%s\"",
-                               trace, bt_trace_get_name(trace), name);
+                               trace, bt_trace_common_get_name(trace), name);
                        BT_PUT(attribute);
                        ret = -1;
                        goto end;
@@ -399,19 +413,40 @@ int bt_trace_set_environment_field(struct bt_trace *trace,
                BT_LOGE("Cannot set environment field's value: "
                        "trace-addr=%p, trace-name=\"%s\", "
                        "env-name=\"%s\"",
-                       trace, bt_trace_get_name(trace), name);
+                       trace, bt_trace_common_get_name(trace), name);
        } else {
                BT_LOGV("Set environment field's value: "
                        "trace-addr=%p, trace-name=\"%s\", "
                        "env-name=\"%s\", value-addr=%p",
-                       trace, bt_trace_get_name(trace), name, value);
+                       trace, bt_trace_common_get_name(trace), name, value);
        }
 
 end:
        return ret;
 }
 
-int bt_trace_set_environment_field_string(struct bt_trace *trace,
+int bt_trace_set_environment_field(struct bt_trace *trace,
+               const char *name, struct bt_value *value)
+{
+       int ret;
+
+       if (trace->is_static) {
+               BT_LOGW("Invalid parameter: trace is static: "
+                       "addr=%p, name=\"%s\"",
+                       trace, bt_trace_get_name(trace));
+               ret = -1;
+               goto end;
+       }
+
+       ret = bt_trace_common_set_environment_field(BT_TO_COMMON(trace),
+               name, value);
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+int bt_trace_common_set_environment_field_string(struct bt_trace_common *trace,
                const char *name, const char *value)
 {
        int ret = 0;
@@ -430,8 +465,8 @@ int bt_trace_set_environment_field_string(struct bt_trace *trace,
                goto end;
        }
 
-       /* bt_trace_set_environment_field() logs errors */
-       ret = bt_trace_set_environment_field(trace, name,
+       /* bt_trace_common_set_environment_field() logs errors */
+       ret = bt_trace_common_set_environment_field(trace, name,
                env_value_string_obj);
 
 end:
@@ -439,8 +474,16 @@ end:
        return ret;
 }
 
-int bt_trace_set_environment_field_integer(struct bt_trace *trace,
-               const char *name, int64_t value)
+int bt_trace_set_environment_field_string(struct bt_trace *trace,
+               const char *name, const char *value)
+{
+       return bt_trace_common_set_environment_field_string(BT_TO_COMMON(trace),
+               name, value);
+}
+
+BT_HIDDEN
+int bt_trace_common_set_environment_field_integer(
+               struct bt_trace_common *trace, const char *name, int64_t value)
 {
        int ret = 0;
        struct bt_value *env_value_integer_obj = NULL;
@@ -452,8 +495,8 @@ int bt_trace_set_environment_field_integer(struct bt_trace *trace,
                goto end;
        }
 
-       /* bt_trace_set_environment_field() logs errors */
-       ret = bt_trace_set_environment_field(trace, name,
+       /* bt_trace_common_set_environment_field() logs errors */
+       ret = bt_trace_common_set_environment_field(trace, name,
                env_value_integer_obj);
 
 end:
@@ -461,41 +504,42 @@ end:
        return ret;
 }
 
-int64_t bt_trace_get_environment_field_count(struct bt_trace *trace)
+int bt_trace_set_environment_field_integer(
+               struct bt_trace *trace, const char *name, int64_t value)
 {
-       int64_t ret;
+       return bt_trace_common_set_environment_field_integer(
+               BT_TO_COMMON(trace), name, value);
+}
 
-       BT_ASSERT_PRE_NON_NULL(trace, "Trace");
-       ret = bt_attributes_get_count(trace->environment);
-       BT_ASSERT(ret >= 0);
-       return ret;
+int64_t bt_trace_get_environment_field_count(struct bt_trace *trace)
+{
+       return bt_trace_common_get_environment_field_count(BT_TO_COMMON(trace));
 }
 
 const char *
 bt_trace_get_environment_field_name_by_index(struct bt_trace *trace,
                uint64_t index)
 {
-       BT_ASSERT_PRE_NON_NULL(trace, "Trace");
-       return bt_attributes_get_field_name(trace->environment, index);
+       return bt_trace_common_get_environment_field_name_by_index(
+               BT_TO_COMMON(trace), index);
 }
 
 struct bt_value *bt_trace_get_environment_field_value_by_index(
                struct bt_trace *trace, uint64_t index)
 {
-       BT_ASSERT_PRE_NON_NULL(trace, "Trace");
-       return bt_attributes_get_field_value(trace->environment, index);
+       return bt_trace_common_get_environment_field_value_by_index(
+               BT_TO_COMMON(trace), index);
 }
 
 struct bt_value *bt_trace_get_environment_field_value_by_name(
                struct bt_trace *trace, const char *name)
 {
-       BT_ASSERT_PRE_NON_NULL(trace, "Trace");
-       BT_ASSERT_PRE_NON_NULL(name, "Name");
-       return bt_attributes_get_field_value_by_name(trace->environment,
-               name);
+       return bt_trace_common_get_environment_field_value_by_name(
+               BT_TO_COMMON(trace), name);
 }
 
-int bt_trace_add_clock_class(struct bt_trace *trace,
+BT_HIDDEN
+int bt_trace_common_add_clock_class(struct bt_trace_common *trace,
                struct bt_clock_class *clock_class)
 {
        int ret = 0;
@@ -506,37 +550,29 @@ int bt_trace_add_clock_class(struct bt_trace *trace,
                goto end;
        }
 
-       if (trace->is_static) {
-               BT_LOGW("Invalid parameter: trace is static: "
-                       "addr=%p, name=\"%s\"",
-                       trace, bt_trace_get_name(trace));
-               ret = -1;
-               goto end;
-       }
-
        if (!bt_clock_class_is_valid(clock_class)) {
                BT_LOGW("Invalid parameter: clock class is invalid: "
                        "trace-addr=%p, trace-name=\"%s\", "
                        "clock-class-addr=%p, clock-class-name=\"%s\"",
-                       trace, bt_trace_get_name(trace),
+                       trace, bt_trace_common_get_name(trace),
                        clock_class, bt_clock_class_get_name(clock_class));
                ret = -1;
                goto end;
        }
 
        /* Check for duplicate clock classes */
-       if (bt_trace_has_clock_class(trace, clock_class)) {
+       if (bt_trace_common_has_clock_class(trace, clock_class)) {
                BT_LOGW("Invalid parameter: clock class already exists in trace: "
                        "trace-addr=%p, trace-name=\"%s\", "
                        "clock-class-addr=%p, clock-class-name=\"%s\"",
-                       trace, bt_trace_get_name(trace),
+                       trace, bt_trace_common_get_name(trace),
                        clock_class, bt_clock_class_get_name(clock_class));
                ret = -1;
                goto end;
        }
 
        bt_get(clock_class);
-       g_ptr_array_add(trace->clocks, clock_class);
+       g_ptr_array_add(trace->clock_classes, clock_class);
 
        if (trace->frozen) {
                BT_LOGV_STR("Freezing added clock class because trace is frozen.");
@@ -546,37 +582,52 @@ int bt_trace_add_clock_class(struct bt_trace *trace,
        BT_LOGV("Added clock class to trace: "
                "trace-addr=%p, trace-name=\"%s\", "
                "clock-class-addr=%p, clock-class-name=\"%s\"",
-               trace, bt_trace_get_name(trace),
+               trace, bt_trace_common_get_name(trace),
                clock_class, bt_clock_class_get_name(clock_class));
 
 end:
        return ret;
 }
 
+int bt_trace_add_clock_class(struct bt_trace *trace,
+               struct bt_clock_class *clock_class)
+{
+       int ret;
+
+       if (trace->is_static) {
+               BT_LOGW("Invalid parameter: trace is static: "
+                       "addr=%p, name=\"%s\"",
+                       trace, bt_trace_get_name(trace));
+               ret = -1;
+               goto end;
+       }
+
+       ret = bt_trace_common_add_clock_class(BT_TO_COMMON(trace),
+               clock_class);
+
+end:
+       return ret;
+}
+
 int64_t bt_trace_get_clock_class_count(struct bt_trace *trace)
 {
-       BT_ASSERT_PRE_NON_NULL(trace, "Trace");
-       return trace->clocks->len;
+       return bt_trace_common_get_clock_class_count(BT_TO_COMMON(trace));
 }
 
 struct bt_clock_class *bt_trace_get_clock_class_by_index(
                struct bt_trace *trace, uint64_t index)
 {
-       BT_ASSERT_PRE_NON_NULL(trace, "Trace");
-       BT_ASSERT_PRE(index < trace->clocks->len,
-               "Index is out of bounds: index=%" PRIu64 ", "
-               "count=%u",
-               index, trace->clocks->len);
-       return bt_get(g_ptr_array_index(trace->clocks, index));
+       return bt_trace_common_get_clock_class_by_index(
+               BT_TO_COMMON(trace), index);
 }
 
 static
-bool packet_header_field_type_is_valid(struct bt_trace *trace,
-               struct bt_field_type *packet_header_type)
+bool packet_header_field_type_is_valid(struct bt_trace_common *trace,
+               struct bt_field_type_common *packet_header_type)
 {
        int ret;
        bool is_valid = true;
-       struct bt_field_type *field_type = NULL;
+       struct bt_field_type_common *field_type = NULL;
 
        if (!packet_header_type) {
                /*
@@ -596,11 +647,11 @@ bool packet_header_field_type_is_valid(struct bt_trace *trace,
        }
 
        /* Packet header field type, if it exists, must be a structure */
-       if (!bt_field_type_is_structure(packet_header_type)) {
+       if (packet_header_type->id != BT_FIELD_TYPE_ID_STRUCT) {
                BT_LOGW("Invalid packet header field type: must be a structure field type if it exists: "
                        "ft-addr=%p, ft-id=%s",
                        packet_header_type,
-                       bt_field_type_id_string(packet_header_type->id));
+                       bt_common_field_type_id_string(packet_header_type->id));
                goto invalid;
        }
 
@@ -609,34 +660,34 @@ bool packet_header_field_type_is_valid(struct bt_trace *trace,
         * integer field type. Also it must be the first field of the
         * packet header field type.
         */
-       field_type = bt_field_type_structure_get_field_type_by_name(
+       field_type = bt_field_type_common_structure_get_field_type_by_name(
                packet_header_type, "magic");
        if (field_type) {
                const char *field_name;
 
-               if (!bt_field_type_is_integer(field_type)) {
+               if (field_type->id != BT_FIELD_TYPE_ID_INTEGER) {
                        BT_LOGW("Invalid packet header field type: `magic` field must be an integer field type: "
                                "magic-ft-addr=%p, magic-ft-id=%s",
                                field_type,
-                               bt_field_type_id_string(field_type->id));
+                               bt_common_field_type_id_string(field_type->id));
                        goto invalid;
                }
 
-               if (bt_field_type_integer_is_signed(field_type)) {
+               if (bt_field_type_common_integer_is_signed(field_type)) {
                        BT_LOGW("Invalid packet header field type: `magic` field must be an unsigned integer field type: "
                                "magic-ft-addr=%p", field_type);
                        goto invalid;
                }
 
-               if (bt_field_type_integer_get_size(field_type) != 32) {
+               if (bt_field_type_common_integer_get_size(field_type) != 32) {
                        BT_LOGW("Invalid packet header field type: `magic` field must be a 32-bit unsigned integer field type: "
                                "magic-ft-addr=%p, magic-ft-size=%u",
                                field_type,
-                               bt_field_type_integer_get_size(field_type));
+                               bt_field_type_common_integer_get_size(field_type));
                        goto invalid;
                }
 
-               ret = bt_field_type_structure_get_field_by_index(
+               ret = bt_field_type_common_structure_get_field_by_index(
                        packet_header_type, &field_name, NULL, 0);
                BT_ASSERT(ret == 0);
 
@@ -654,51 +705,51 @@ bool packet_header_field_type_is_valid(struct bt_trace *trace,
         * If there's a `uuid` field, it must be an array field type of
         * length 16 with an 8-bit unsigned integer element field type.
         */
-       field_type = bt_field_type_structure_get_field_type_by_name(
+       field_type = bt_field_type_common_structure_get_field_type_by_name(
                packet_header_type, "uuid");
        if (field_type) {
-               struct bt_field_type *elem_ft;
+               struct bt_field_type_common *elem_ft;
 
-               if (!bt_field_type_is_array(field_type)) {
+               if (field_type->id != BT_FIELD_TYPE_ID_ARRAY) {
                        BT_LOGW("Invalid packet header field type: `uuid` field must be an array field type: "
                                "uuid-ft-addr=%p, uuid-ft-id=%s",
                                field_type,
-                               bt_field_type_id_string(field_type->id));
+                               bt_common_field_type_id_string(field_type->id));
                        goto invalid;
                }
 
-               if (bt_field_type_array_get_length(field_type) != 16) {
+               if (bt_field_type_common_array_get_length(field_type) != 16) {
                        BT_LOGW("Invalid packet header field type: `uuid` array field type's length must be 16: "
                                "uuid-ft-addr=%p, uuid-ft-length=%" PRId64,
                                field_type,
-                               bt_field_type_array_get_length(field_type));
+                               bt_field_type_common_array_get_length(field_type));
                        goto invalid;
                }
 
-               elem_ft = bt_field_type_array_get_element_type(field_type);
+               elem_ft = bt_field_type_common_array_get_element_field_type(field_type);
                BT_ASSERT(elem_ft);
 
-               if (!bt_field_type_is_integer(elem_ft)) {
+               if (elem_ft->id != BT_FIELD_TYPE_ID_INTEGER) {
                        BT_LOGW("Invalid packet header field type: `uuid` field's element field type must be an integer field type: "
                                "elem-ft-addr=%p, elem-ft-id=%s",
                                elem_ft,
-                               bt_field_type_id_string(elem_ft->id));
+                               bt_common_field_type_id_string(elem_ft->id));
                        bt_put(elem_ft);
                        goto invalid;
                }
 
-               if (bt_field_type_integer_is_signed(elem_ft)) {
+               if (bt_field_type_common_integer_is_signed(elem_ft)) {
                        BT_LOGW("Invalid packet header field type: `uuid` field's element field type must be an unsigned integer field type: "
                                "elem-ft-addr=%p", elem_ft);
                        bt_put(elem_ft);
                        goto invalid;
                }
 
-               if (bt_field_type_integer_get_size(elem_ft) != 8) {
+               if (bt_field_type_common_integer_get_size(elem_ft) != 8) {
                        BT_LOGW("Invalid packet header field type: `uuid` field's element field type must be an 8-bit unsigned integer field type: "
                                "elem-ft-addr=%p, elem-ft-size=%u",
                                elem_ft,
-                               bt_field_type_integer_get_size(elem_ft));
+                               bt_field_type_common_integer_get_size(elem_ft));
                        bt_put(elem_ft);
                        goto invalid;
                }
@@ -711,7 +762,7 @@ bool packet_header_field_type_is_valid(struct bt_trace *trace,
         * The `stream_id` field must exist if there's more than one
         * stream classes in the trace.
         */
-       field_type = bt_field_type_structure_get_field_type_by_name(
+       field_type = bt_field_type_common_structure_get_field_type_by_name(
                packet_header_type, "stream_id");
 
        if (!field_type && trace->stream_classes->len >= 1) {
@@ -725,15 +776,15 @@ bool packet_header_field_type_is_valid(struct bt_trace *trace,
         * integer field type.
         */
        if (field_type) {
-               if (!bt_field_type_is_integer(field_type)) {
+               if (field_type->id != BT_FIELD_TYPE_ID_INTEGER) {
                        BT_LOGW("Invalid packet header field type: `stream_id` field must be an integer field type: "
                                "stream-id-ft-addr=%p, stream-id-ft-id=%s",
                                field_type,
-                               bt_field_type_id_string(field_type->id));
+                               bt_common_field_type_id_string(field_type->id));
                        goto invalid;
                }
 
-               if (bt_field_type_integer_is_signed(field_type)) {
+               if (bt_field_type_common_integer_is_signed(field_type)) {
                        BT_LOGW("Invalid packet header field type: `stream_id` field must be an unsigned integer field type: "
                                "stream-id-ft-addr=%p", field_type);
                        goto invalid;
@@ -746,18 +797,18 @@ bool packet_header_field_type_is_valid(struct bt_trace *trace,
         * If there's a `packet_seq_num` field, it must be an unsigned
         * integer field type.
         */
-       field_type = bt_field_type_structure_get_field_type_by_name(
+       field_type = bt_field_type_common_structure_get_field_type_by_name(
                packet_header_type, "packet_seq_num");
        if (field_type) {
-               if (!bt_field_type_is_integer(field_type)) {
+               if (field_type->id != BT_FIELD_TYPE_ID_INTEGER) {
                        BT_LOGW("Invalid packet header field type: `packet_seq_num` field must be an integer field type: "
                                "stream-id-ft-addr=%p, packet-seq-num-ft-id=%s",
                                field_type,
-                               bt_field_type_id_string(field_type->id));
+                               bt_common_field_type_id_string(field_type->id));
                        goto invalid;
                }
 
-               if (bt_field_type_integer_is_signed(field_type)) {
+               if (bt_field_type_common_integer_is_signed(field_type)) {
                        BT_LOGW("Invalid packet header field type: `packet_seq_num` field must be an unsigned integer field type: "
                                "packet-seq-num-ft-addr=%p", field_type);
                        goto invalid;
@@ -777,12 +828,13 @@ end:
 }
 
 static
-bool packet_context_field_type_is_valid(struct bt_trace *trace,
-               struct bt_stream_class *stream_class,
-               struct bt_field_type *packet_context_type)
+bool packet_context_field_type_is_valid(struct bt_trace_common *trace,
+               struct bt_stream_class_common *stream_class,
+               struct bt_field_type_common *packet_context_type,
+               bool check_ts_begin_end_mapped)
 {
        bool is_valid = true;
-       struct bt_field_type *field_type = NULL;
+       struct bt_field_type_common *field_type = NULL;
 
        if (!packet_context_type) {
                /* No packet context field type: valid at this point */
@@ -790,11 +842,11 @@ bool packet_context_field_type_is_valid(struct bt_trace *trace,
        }
 
        /* Packet context field type, if it exists, must be a structure */
-       if (!bt_field_type_is_structure(packet_context_type)) {
+       if (packet_context_type->id != BT_FIELD_TYPE_ID_STRUCT) {
                BT_LOGW("Invalid packet context field type: must be a structure field type if it exists: "
                        "ft-addr=%p, ft-id=%s",
                        packet_context_type,
-                       bt_field_type_id_string(packet_context_type->id));
+                       bt_common_field_type_id_string(packet_context_type->id));
                goto invalid;
        }
 
@@ -802,18 +854,18 @@ bool packet_context_field_type_is_valid(struct bt_trace *trace,
         * If there's a `packet_size` field, it must be an unsigned
         * integer field type.
         */
-       field_type = bt_field_type_structure_get_field_type_by_name(
+       field_type = bt_field_type_common_structure_get_field_type_by_name(
                packet_context_type, "packet_size");
        if (field_type) {
-               if (!bt_field_type_is_integer(field_type)) {
+               if (field_type->id != BT_FIELD_TYPE_ID_INTEGER) {
                        BT_LOGW("Invalid packet context field type: `packet_size` field must be an integer field type: "
                                "packet-size-ft-addr=%p, packet-size-ft-id=%s",
                                field_type,
-                               bt_field_type_id_string(field_type->id));
+                               bt_common_field_type_id_string(field_type->id));
                        goto invalid;
                }
 
-               if (bt_field_type_integer_is_signed(field_type)) {
+               if (bt_field_type_common_integer_is_signed(field_type)) {
                        BT_LOGW("Invalid packet context field type: `packet_size` field must be an unsigned integer field type: "
                                "packet-size-ft-addr=%p", field_type);
                        goto invalid;
@@ -826,18 +878,18 @@ bool packet_context_field_type_is_valid(struct bt_trace *trace,
         * If there's a `content_size` field, it must be an unsigned
         * integer field type.
         */
-       field_type = bt_field_type_structure_get_field_type_by_name(
+       field_type = bt_field_type_common_structure_get_field_type_by_name(
                packet_context_type, "content_size");
        if (field_type) {
-               if (!bt_field_type_is_integer(field_type)) {
+               if (field_type->id != BT_FIELD_TYPE_ID_INTEGER) {
                        BT_LOGW("Invalid packet context field type: `content_size` field must be an integer field type: "
                                "content-size-ft-addr=%p, content-size-ft-id=%s",
                                field_type,
-                               bt_field_type_id_string(field_type->id));
+                               bt_common_field_type_id_string(field_type->id));
                        goto invalid;
                }
 
-               if (bt_field_type_integer_is_signed(field_type)) {
+               if (bt_field_type_common_integer_is_signed(field_type)) {
                        BT_LOGW("Invalid packet context field type: `content_size` field must be an unsigned integer field type: "
                                "content-size-ft-addr=%p", field_type);
                        goto invalid;
@@ -850,18 +902,18 @@ bool packet_context_field_type_is_valid(struct bt_trace *trace,
         * If there's a `events_discarded` field, it must be an unsigned
         * integer field type.
         */
-       field_type = bt_field_type_structure_get_field_type_by_name(
+       field_type = bt_field_type_common_structure_get_field_type_by_name(
                packet_context_type, "events_discarded");
        if (field_type) {
-               if (!bt_field_type_is_integer(field_type)) {
+               if (field_type->id != BT_FIELD_TYPE_ID_INTEGER) {
                        BT_LOGW("Invalid packet context field type: `events_discarded` field must be an integer field type: "
                                "events-discarded-ft-addr=%p, events-discarded-ft-id=%s",
                                field_type,
-                               bt_field_type_id_string(field_type->id));
+                               bt_common_field_type_id_string(field_type->id));
                        goto invalid;
                }
 
-               if (bt_field_type_integer_is_signed(field_type)) {
+               if (bt_field_type_common_integer_is_signed(field_type)) {
                        BT_LOGW("Invalid packet context field type: `events_discarded` field must be an unsigned integer field type: "
                                "events-discarded-ft-addr=%p", field_type);
                        goto invalid;
@@ -876,26 +928,26 @@ bool packet_context_field_type_is_valid(struct bt_trace *trace,
         * trace, then we cannot automatically set the mapped clock
         * class of this field, so it must have a mapped clock class.
         */
-       field_type = bt_field_type_structure_get_field_type_by_name(
+       field_type = bt_field_type_common_structure_get_field_type_by_name(
                packet_context_type, "timestamp_begin");
        if (field_type) {
-               if (!bt_field_type_is_integer(field_type)) {
+               if (field_type->id != BT_FIELD_TYPE_ID_INTEGER) {
                        BT_LOGW("Invalid packet context field type: `timestamp_begin` field must be an integer field type: "
                                "timestamp-begin-ft-addr=%p, timestamp-begin-ft-id=%s",
                                field_type,
-                               bt_field_type_id_string(field_type->id));
+                               bt_common_field_type_id_string(field_type->id));
                        goto invalid;
                }
 
-               if (bt_field_type_integer_is_signed(field_type)) {
+               if (bt_field_type_common_integer_is_signed(field_type)) {
                        BT_LOGW("Invalid packet context field type: `timestamp_begin` field must be an unsigned integer field type: "
                                "timestamp-begin-ft-addr=%p", field_type);
                        goto invalid;
                }
 
-               if (!trace->is_created_by_writer) {
+               if (check_ts_begin_end_mapped) {
                        struct bt_clock_class *clock_class =
-                               bt_field_type_integer_get_mapped_clock_class(
+                               bt_field_type_common_integer_get_mapped_clock_class(
                                        field_type);
 
                        bt_put(clock_class);
@@ -915,26 +967,26 @@ bool packet_context_field_type_is_valid(struct bt_trace *trace,
         * trace, then we cannot automatically set the mapped clock
         * class of this field, so it must have a mapped clock class.
         */
-       field_type = bt_field_type_structure_get_field_type_by_name(
+       field_type = bt_field_type_common_structure_get_field_type_by_name(
                packet_context_type, "timestamp_end");
        if (field_type) {
-               if (!bt_field_type_is_integer(field_type)) {
+               if (field_type->id != BT_FIELD_TYPE_ID_INTEGER) {
                        BT_LOGW("Invalid packet context field type: `timestamp_end` field must be an integer field type: "
                                "timestamp-end-ft-addr=%p, timestamp-end-ft-id=%s",
                                field_type,
-                               bt_field_type_id_string(field_type->id));
+                               bt_common_field_type_id_string(field_type->id));
                        goto invalid;
                }
 
-               if (bt_field_type_integer_is_signed(field_type)) {
+               if (bt_field_type_common_integer_is_signed(field_type)) {
                        BT_LOGW("Invalid packet context field type: `timestamp_end` field must be an unsigned integer field type: "
                                "timestamp-end-ft-addr=%p", field_type);
                        goto invalid;
                }
 
-               if (!trace->is_created_by_writer) {
+               if (check_ts_begin_end_mapped) {
                        struct bt_clock_class *clock_class =
-                               bt_field_type_integer_get_mapped_clock_class(
+                               bt_field_type_common_integer_get_mapped_clock_class(
                                        field_type);
 
                        bt_put(clock_class);
@@ -959,12 +1011,12 @@ end:
 }
 
 static
-bool event_header_field_type_is_valid(struct bt_trace *trace,
-               struct bt_stream_class *stream_class,
-               struct bt_field_type *event_header_type)
+bool event_header_field_type_is_valid(struct bt_trace_common *trace,
+               struct bt_stream_class_common *stream_class,
+               struct bt_field_type_common *event_header_type)
 {
        bool is_valid = true;
-       struct bt_field_type *field_type = NULL;
+       struct bt_field_type_common *field_type = NULL;
 
        /*
         * We do not validate that the `timestamp` field exists here
@@ -977,7 +1029,7 @@ bool event_header_field_type_is_valid(struct bt_trace *trace,
                 * No event header field type: stream class must have
                 * only one event class.
                 */
-               if (bt_stream_class_get_event_class_count(stream_class) > 1) {
+               if (bt_stream_class_common_get_event_class_count(stream_class) > 1) {
                        BT_LOGW_STR("Invalid event header field type: "
                                "event header field type does not exist but there's more than one event class in the stream class.");
                        goto invalid;
@@ -988,11 +1040,11 @@ bool event_header_field_type_is_valid(struct bt_trace *trace,
        }
 
        /* Event header field type, if it exists, must be a structure */
-       if (!bt_field_type_is_structure(event_header_type)) {
+       if (event_header_type->id != BT_FIELD_TYPE_ID_STRUCT) {
                BT_LOGW("Invalid event header field type: must be a structure field type if it exists: "
                        "ft-addr=%p, ft-id=%s",
                        event_header_type,
-                       bt_field_type_id_string(event_header_type->id));
+                       bt_common_field_type_id_string(event_header_type->id));
                goto invalid;
        }
 
@@ -1001,26 +1053,26 @@ bool event_header_field_type_is_valid(struct bt_trace *trace,
         * field type or an enumeration field type with an unsigned
         * integer container field type.
         */
-       field_type = bt_field_type_structure_get_field_type_by_name(
+       field_type = bt_field_type_common_structure_get_field_type_by_name(
                event_header_type, "id");
        if (field_type) {
-               struct bt_field_type *int_ft;
+               struct bt_field_type_common *int_ft;
 
-               if (bt_field_type_is_integer(field_type)) {
+               if (field_type->id == BT_FIELD_TYPE_ID_INTEGER) {
                        int_ft = bt_get(field_type);
-               } else if (bt_field_type_is_enumeration(field_type)) {
-                       int_ft = bt_field_type_enumeration_get_container_type(
+               } else if (field_type->id == BT_FIELD_TYPE_ID_ENUM) {
+                       int_ft = bt_field_type_common_enumeration_get_container_field_type(
                                field_type);
                } else {
                        BT_LOGW("Invalid event header field type: `id` field must be an integer or enumeration field type: "
                                "id-ft-addr=%p, id-ft-id=%s",
                                field_type,
-                               bt_field_type_id_string(field_type->id));
+                               bt_common_field_type_id_string(field_type->id));
                        goto invalid;
                }
 
                BT_ASSERT(int_ft);
-               if (bt_field_type_integer_is_signed(int_ft)) {
+               if (bt_field_type_common_integer_is_signed(int_ft)) {
                        BT_LOGW("Invalid event header field type: `id` field must be an unsigned integer or enumeration field type: "
                                "id-ft-addr=%p", int_ft);
                        goto invalid;
@@ -1041,14 +1093,15 @@ end:
 }
 
 static
-int check_packet_header_type_has_no_clock_class(struct bt_trace *trace)
+int check_packet_header_type_has_no_clock_class(struct bt_trace_common *trace)
 {
        int ret = 0;
 
-       if (trace->packet_header_type) {
+       if (trace->packet_header_field_type) {
                struct bt_clock_class *clock_class = NULL;
 
-               ret = bt_validate_single_clock_class(trace->packet_header_type,
+               ret = bt_field_type_common_validate_single_clock_class(
+                       trace->packet_header_field_type,
                        &clock_class);
                bt_put(clock_class);
                if (ret || clock_class) {
@@ -1057,7 +1110,7 @@ int check_packet_header_type_has_no_clock_class(struct bt_trace *trace)
                                "a clock class: "
                                "trace-addr=%p, trace-name=\"%s\", "
                                "clock-class-name=\"%s\"",
-                               trace, bt_trace_get_name(trace),
+                               trace, bt_trace_common_get_name(trace),
                                clock_class ?
                                        bt_clock_class_get_name(clock_class) :
                                        NULL);
@@ -1068,8 +1121,15 @@ int check_packet_header_type_has_no_clock_class(struct bt_trace *trace)
        return ret;
 }
 
-int bt_trace_add_stream_class(struct bt_trace *trace,
-               struct bt_stream_class *stream_class)
+BT_HIDDEN
+int bt_trace_common_add_stream_class(struct bt_trace_common *trace,
+               struct bt_stream_class_common *stream_class,
+               bt_validation_flag_copy_field_type_func copy_field_type_func,
+               struct bt_clock_class *init_expected_clock_class,
+               int (*map_clock_classes_func)(struct bt_stream_class_common *stream_class,
+                       struct bt_field_type_common *packet_context_field_type,
+                       struct bt_field_type_common *event_header_field_type),
+               bool check_ts_begin_end_mapped)
 {
        int ret;
        int64_t i;
@@ -1081,13 +1141,16 @@ int bt_trace_add_stream_class(struct bt_trace *trace,
                BT_VALIDATION_FLAG_STREAM;
        const enum bt_validation_flag ec_validation_flags =
                BT_VALIDATION_FLAG_EVENT;
-       struct bt_field_type *packet_header_type = NULL;
-       struct bt_field_type *packet_context_type = NULL;
-       struct bt_field_type *event_header_type = NULL;
-       struct bt_field_type *stream_event_ctx_type = NULL;
+       struct bt_field_type_common *packet_header_type = NULL;
+       struct bt_field_type_common *packet_context_type = NULL;
+       struct bt_field_type_common *event_header_type = NULL;
+       struct bt_field_type_common *stream_event_ctx_type = NULL;
        int64_t event_class_count;
-       struct bt_trace *current_parent_trace = NULL;
-       struct bt_clock_class *expected_clock_class = NULL;
+       struct bt_trace_common *current_parent_trace = NULL;
+       struct bt_clock_class *expected_clock_class =
+               bt_get(init_expected_clock_class);
+
+       BT_ASSERT(copy_field_type_func);
 
        if (!trace) {
                BT_LOGW_STR("Invalid parameter: trace is NULL.");
@@ -1101,135 +1164,53 @@ int bt_trace_add_stream_class(struct bt_trace *trace,
                goto end;
        }
 
-       if (trace->is_static) {
-               BT_LOGW_STR("Invalid parameter: trace is static.");
-               ret = -1;
-               goto end;
-       }
-
        BT_LOGD("Adding stream class to trace: "
                "trace-addr=%p, trace-name=\"%s\", "
                "stream-class-addr=%p, stream-class-name=\"%s\", "
                "stream-class-id=%" PRId64,
-               trace, bt_trace_get_name(trace),
-               stream_class, bt_stream_class_get_name(stream_class),
-               bt_stream_class_get_id(stream_class));
+               trace, bt_trace_common_get_name(trace),
+               stream_class, bt_stream_class_common_get_name(stream_class),
+               bt_stream_class_common_get_id(stream_class));
 
-       current_parent_trace = bt_stream_class_get_trace(stream_class);
+       current_parent_trace = bt_stream_class_common_get_trace(stream_class);
        if (current_parent_trace) {
                /* Stream class is already associated to a trace, abort. */
                BT_LOGW("Invalid parameter: stream class is already part of a trace: "
                        "stream-class-trace-addr=%p, "
                        "stream-class-trace-name=\"%s\"",
                        current_parent_trace,
-                       bt_trace_get_name(current_parent_trace));
+                       bt_trace_common_get_name(current_parent_trace));
                ret = -1;
                goto end;
        }
 
        event_class_count =
-               bt_stream_class_get_event_class_count(stream_class);
+               bt_stream_class_common_get_event_class_count(stream_class);
        BT_ASSERT(event_class_count >= 0);
 
-       if (stream_class->clock) {
-               struct bt_clock_class *stream_clock_class =
-                       stream_class->clock->clock_class;
-
-               if (trace->is_created_by_writer) {
-                       /*
-                        * Make sure this clock was also added to the
-                        * trace (potentially through its CTF writer
-                        * owner).
-                        */
-                       size_t i;
-
-                       for (i = 0; i < trace->clocks->len; i++) {
-                               if (trace->clocks->pdata[i] ==
-                                               stream_clock_class) {
-                                       /* Found! */
-                                       break;
-                               }
-                       }
-
-                       if (i == trace->clocks->len) {
-                               /* Not found */
-                               BT_LOGW("Stream class's clock's class is not part of the trace: "
-                                       "clock-class-addr=%p, clock-class-name=\"%s\"",
-                                       stream_clock_class,
-                                       bt_clock_class_get_name(stream_clock_class));
-                               ret = -1;
-                               goto end;
-                       }
-               } else {
-                       /*
-                        * This trace was NOT created by a CTF writer,
-                        * thus do not allow the stream class to add to
-                        * have a clock at all. Those are two
-                        * independent APIs (non-writer and writer
-                        * APIs), and isolating them simplifies things.
-                        */
-                       BT_LOGW("Cannot add stream class with a clock to a trace which was not created by a CTF writer object: "
-                               "clock-class-addr=%p, clock-class-name=\"%s\"",
-                               stream_clock_class,
-                               bt_clock_class_get_name(stream_clock_class));
-                       ret = -1;
-                       goto end;
-               }
-
-               if (stream_class->clock_class &&
-                               stream_class->clock_class !=
-                               stream_class->clock->clock_class) {
-                       /*
-                        * Stream class already has an expected clock
-                        * class, but it does not match its clock's
-                        * class.
-                        */
-                       BT_LOGW("Invalid parameter: stream class's clock's "
-                               "class does not match stream class's "
-                               "expected clock class: "
-                               "stream-class-addr=%p, "
-                               "stream-class-id=%" PRId64 ", "
-                               "stream-class-name=\"%s\", "
-                               "expected-clock-class-addr=%p, "
-                               "expected-clock-class-name=\"%s\"",
-                               stream_class,
-                               bt_stream_class_get_id(stream_class),
-                               bt_stream_class_get_name(stream_class),
-                               expected_clock_class,
-                               bt_clock_class_get_name(expected_clock_class));
-               } else if (!stream_class->clock_class) {
-                       /*
-                        * Set expected clock class to stream class's
-                        * clock's class.
-                        */
-                       expected_clock_class =
-                               bt_get(stream_class->clock->clock_class);
-               }
-       }
-
        if (!stream_class->frozen) {
                /*
                 * Stream class is not frozen yet. Validate that the
                 * stream class contains at most a single clock class
                 * because the previous
-                * bt_stream_class_add_event_class() calls did not make
-                * this validation since the stream class's direct field
-                * types (packet context, event header, event context)
-                * could change afterwards. This stream class is about
-                * to be frozen and those field types won't be changed
-                * if this function succeeds.
+                * bt_stream_class_common_add_event_class() calls did
+                * not make this validation since the stream class's
+                * direct field types (packet context, event header,
+                * event context) could change afterwards. This stream
+                * class is about to be frozen and those field types
+                * won't be changed if this function succeeds.
                 *
                 * At this point we're also sure that the stream class's
                 * clock, if any, has the same class as the stream
                 * class's expected clock class, if any. This is why, if
-                * bt_stream_class_validate_single_clock_class()
+                * bt_stream_class_common_validate_single_clock_class()
                 * succeeds below, the call to
                 * bt_stream_class_map_clock_class() at the end of this
                 * function is safe because it maps to the same, single
                 * clock class.
                 */
-               ret = bt_stream_class_validate_single_clock_class(stream_class,
-                       &expected_clock_class);
+               ret = bt_stream_class_common_validate_single_clock_class(
+                       stream_class, &expected_clock_class);
                if (ret) {
                        BT_LOGW("Invalid parameter: stream class or one of its "
                                "event classes contains a field type which is "
@@ -1240,8 +1221,8 @@ int bt_trace_add_stream_class(struct bt_trace *trace,
                                "stream-class-name=\"%s\", "
                                "expected-clock-class-addr=%p, "
                                "expected-clock-class-name=\"%s\"",
-                               stream_class, bt_stream_class_get_id(stream_class),
-                               bt_stream_class_get_name(stream_class),
+                               stream_class, bt_stream_class_common_get_id(stream_class),
+                               bt_stream_class_common_get_name(stream_class),
                                expected_clock_class,
                                expected_clock_class ?
                                        bt_clock_class_get_name(expected_clock_class) :
@@ -1268,20 +1249,20 @@ int bt_trace_add_stream_class(struct bt_trace *trace,
         * class of this stream class can be validated individually.
         */
        packet_header_type =
-               bt_trace_get_packet_header_type(trace);
+               bt_trace_common_get_packet_header_field_type(trace);
        packet_context_type =
-               bt_stream_class_get_packet_context_type(stream_class);
+               bt_stream_class_common_get_packet_context_field_type(stream_class);
        event_header_type =
-               bt_stream_class_get_event_header_type(stream_class);
+               bt_stream_class_common_get_event_header_field_type(stream_class);
        stream_event_ctx_type =
-               bt_stream_class_get_event_context_type(stream_class);
+               bt_stream_class_common_get_event_context_field_type(stream_class);
 
        BT_LOGD("Validating trace and stream class field types.");
        ret = bt_validate_class_types(trace->environment,
                packet_header_type, packet_context_type, event_header_type,
                stream_event_ctx_type, NULL, NULL, trace->valid,
                stream_class->valid, 1, &trace_sc_validation_output,
-               trace_sc_validation_flags);
+               trace_sc_validation_flags, copy_field_type_func);
        BT_PUT(packet_header_type);
        BT_PUT(packet_context_type);
        BT_PUT(event_header_type);
@@ -1320,16 +1301,16 @@ int bt_trace_add_stream_class(struct bt_trace *trace,
 
        /* Validate each event class individually */
        for (i = 0; i < event_class_count; i++) {
-               struct bt_event_class *event_class =
-                       bt_stream_class_get_event_class_by_index(
+               struct bt_event_class_common *event_class =
+                       bt_stream_class_common_get_event_class_by_index(
                                stream_class, i);
-               struct bt_field_type *event_context_type = NULL;
-               struct bt_field_type *event_payload_type = NULL;
+               struct bt_field_type_common *event_context_type = NULL;
+               struct bt_field_type_common *event_payload_type = NULL;
 
                event_context_type =
-                       bt_event_class_get_context_type(event_class);
+                       bt_event_class_common_get_context_field_type(event_class);
                event_payload_type =
-                       bt_event_class_get_payload_type(event_class);
+                       bt_event_class_common_get_payload_field_type(event_class);
 
                /*
                 * It is important to use the field types returned by
@@ -1338,8 +1319,8 @@ int bt_trace_add_stream_class(struct bt_trace *trace,
                 */
                BT_LOGD("Validating event class's field types: "
                        "addr=%p, name=\"%s\", id=%" PRId64,
-                       event_class, bt_event_class_get_name(event_class),
-                       bt_event_class_get_id(event_class));
+                       event_class, bt_event_class_common_get_name(event_class),
+                       bt_event_class_common_get_id(event_class));
                ret = bt_validate_class_types(trace->environment,
                        trace_sc_validation_output.packet_header_type,
                        trace_sc_validation_output.packet_context_type,
@@ -1347,7 +1328,7 @@ int bt_trace_add_stream_class(struct bt_trace *trace,
                        trace_sc_validation_output.stream_event_ctx_type,
                        event_context_type, event_payload_type,
                        1, 1, event_class->valid, &ec_validation_outputs[i],
-                       ec_validation_flags);
+                       ec_validation_flags, copy_field_type_func);
                BT_PUT(event_context_type);
                BT_PUT(event_payload_type);
                BT_PUT(event_class);
@@ -1369,7 +1350,7 @@ int bt_trace_add_stream_class(struct bt_trace *trace,
                }
        }
 
-       stream_id = bt_stream_class_get_id(stream_class);
+       stream_id = bt_stream_class_common_get_id(stream_class);
        if (stream_id < 0) {
                stream_id = trace->next_stream_id++;
                if (stream_id < 0) {
@@ -1380,7 +1361,7 @@ int bt_trace_add_stream_class(struct bt_trace *trace,
 
                /* Try to assign a new stream id */
                for (i = 0; i < trace->stream_classes->len; i++) {
-                       if (stream_id == bt_stream_class_get_id(
+                       if (stream_id == bt_stream_class_common_get_id(
                                trace->stream_classes->pdata[i])) {
                                /* Duplicate stream id found */
                                BT_LOGW("Duplicate stream class ID: "
@@ -1390,7 +1371,7 @@ int bt_trace_add_stream_class(struct bt_trace *trace,
                        }
                }
 
-               if (bt_stream_class_set_id_no_check(stream_class,
+               if (bt_stream_class_common_set_id_no_check(stream_class,
                                stream_id)) {
                        /* TODO Should retry with a different stream id */
                        BT_LOGE("Cannot set stream class's ID: "
@@ -1414,7 +1395,8 @@ int bt_trace_add_stream_class(struct bt_trace *trace,
 
        if (!packet_context_field_type_is_valid(trace,
                        stream_class,
-                       trace_sc_validation_output.packet_context_type)) {
+                       trace_sc_validation_output.packet_context_type,
+                       check_ts_begin_end_mapped)) {
                BT_LOGW_STR("Invalid stream class's packet context field type.");
                ret = -1;
                goto end;
@@ -1437,11 +1419,11 @@ int bt_trace_add_stream_class(struct bt_trace *trace,
         * possible for the user to modify the stream class's clock, or
         * to map those field types to other clock classes.
         */
-       if (trace->is_created_by_writer) {
-               if (bt_stream_class_map_clock_class(stream_class,
+       if (map_clock_classes_func) {
+               if (map_clock_classes_func(stream_class,
                                trace_sc_validation_output.packet_context_type,
                                trace_sc_validation_output.event_header_type)) {
-                       BT_LOGW_STR("Cannot automatically map selected stream class's field types to stream class's clock's class.");
+                       /* map_clock_classes_func() logs errors */
                        ret = -1;
                        goto end;
                }
@@ -1469,8 +1451,8 @@ int bt_trace_add_stream_class(struct bt_trace *trace,
        bt_validation_output_put_types(&trace_sc_validation_output);
 
        for (i = 0; i < event_class_count; i++) {
-               struct bt_event_class *event_class =
-                       bt_stream_class_get_event_class_by_index(
+               struct bt_event_class_common *event_class =
+                       bt_stream_class_common_get_event_class_by_index(
                                stream_class, i);
 
                bt_validation_replace_types(NULL, NULL, event_class,
@@ -1488,8 +1470,8 @@ int bt_trace_add_stream_class(struct bt_trace *trace,
        /*
         * Freeze the trace and the stream class.
         */
-       bt_stream_class_freeze(stream_class);
-       bt_trace_freeze(trace);
+       bt_stream_class_common_freeze(stream_class);
+       bt_trace_common_freeze(trace);
 
        /*
         * It is safe to set the stream class's unique clock class
@@ -1499,16 +1481,13 @@ int bt_trace_add_stream_class(struct bt_trace *trace,
                BT_MOVE(stream_class->clock_class, expected_clock_class);
        }
 
-       /* Notifiy listeners of the trace's schema modification. */
-       bt_stream_class_visit(stream_class,
-                       bt_trace_object_modification, trace);
        BT_LOGD("Added stream class to trace: "
                "trace-addr=%p, trace-name=\"%s\", "
                "stream-class-addr=%p, stream-class-name=\"%s\", "
                "stream-class-id=%" PRId64,
-               trace, bt_trace_get_name(trace),
-               stream_class, bt_stream_class_get_name(stream_class),
-               bt_stream_class_get_id(stream_class));
+               trace, bt_trace_common_get_name(trace),
+               stream_class, bt_stream_class_common_get_name(stream_class),
+               bt_stream_class_common_get_id(stream_class));
 
 end:
        if (ret) {
@@ -1533,101 +1512,81 @@ end:
        return ret;
 }
 
+int bt_trace_add_stream_class(struct bt_trace *trace,
+               struct bt_stream_class *stream_class)
+{
+       int ret = 0;
+
+       if (!trace) {
+               BT_LOGW_STR("Invalid parameter: trace is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       if (trace->is_static) {
+               BT_LOGW_STR("Invalid parameter: trace is static.");
+               ret = -1;
+               goto end;
+       }
+
+       ret = bt_trace_common_add_stream_class(BT_TO_COMMON(trace),
+               BT_TO_COMMON(stream_class),
+               (bt_validation_flag_copy_field_type_func) bt_field_type_copy,
+               NULL, NULL, true);
+       if (ret) {
+               goto end;
+       }
+
+       /* Notifiy listeners of the trace's schema modification. */
+       bt_stream_class_common_visit(BT_TO_COMMON(stream_class),
+                       bt_trace_object_modification, trace);
+
+end:
+       return ret;
+}
+
 int64_t bt_trace_get_stream_count(struct bt_trace *trace)
 {
-       BT_ASSERT_PRE_NON_NULL(trace, "Trace");
-       return (int64_t) trace->streams->len;
+       return bt_trace_common_get_stream_count(BT_TO_COMMON(trace));
 }
 
 struct bt_stream *bt_trace_get_stream_by_index(
                struct bt_trace *trace,
                uint64_t index)
 {
-       BT_ASSERT_PRE_NON_NULL(trace, "Trace");
-       BT_ASSERT_PRE(index < trace->streams->len,
-               "Index is out of bounds: index=%" PRIu64 ", "
-               "count=%u",
-               index, trace->streams->len);
-       return bt_get(g_ptr_array_index(trace->streams, index));
+       return BT_FROM_COMMON(bt_trace_common_get_stream_by_index(
+               BT_TO_COMMON(trace), index));
 }
 
 int64_t bt_trace_get_stream_class_count(struct bt_trace *trace)
 {
-       BT_ASSERT_PRE_NON_NULL(trace, "Trace");
-       return (int64_t) trace->stream_classes->len;
+       return bt_trace_common_get_stream_class_count(BT_TO_COMMON(trace));
 }
 
 struct bt_stream_class *bt_trace_get_stream_class_by_index(
                struct bt_trace *trace, uint64_t index)
 {
-       BT_ASSERT_PRE_NON_NULL(trace, "Trace");
-       BT_ASSERT_PRE(index < trace->stream_classes->len,
-               "Index is out of bounds: index=%" PRIu64 ", "
-               "count=%u",
-               index, trace->stream_classes->len);
-       return bt_get(g_ptr_array_index(trace->stream_classes, index));
+       return BT_FROM_COMMON(bt_trace_common_get_stream_class_by_index(
+               BT_TO_COMMON(trace), index));
 }
 
 struct bt_stream_class *bt_trace_get_stream_class_by_id(
-               struct bt_trace *trace, uint64_t id_param)
+               struct bt_trace *trace, uint64_t id)
 {
-       int i;
-       struct bt_stream_class *stream_class = NULL;
-       int64_t id = (int64_t) id_param;
-
-       BT_ASSERT_PRE_NON_NULL(trace, "Trace");
-       BT_ASSERT_PRE(id >= 0,
-               "Invalid stream class ID: %" PRIu64, id_param);
-
-       for (i = 0; i < trace->stream_classes->len; i++) {
-               struct bt_stream_class *stream_class_candidate;
-
-               stream_class_candidate =
-                       g_ptr_array_index(trace->stream_classes, i);
-
-               if (bt_stream_class_get_id(stream_class_candidate) ==
-                               (int64_t) id) {
-                       stream_class = stream_class_candidate;
-                       bt_get(stream_class);
-                       goto end;
-               }
-       }
-
-end:
-       return stream_class;
+       return BT_FROM_COMMON(
+               bt_trace_common_get_stream_class_by_id(
+                       BT_TO_COMMON(trace), id));
 }
 
 struct bt_clock_class *bt_trace_get_clock_class_by_name(
                struct bt_trace *trace, const char *name)
 {
-       size_t i;
-       struct bt_clock_class *clock_class = NULL;
-
-       BT_ASSERT_PRE_NON_NULL(trace, "Trace");
-       BT_ASSERT_PRE_NON_NULL(name, "Name");
-
-       for (i = 0; i < trace->clocks->len; i++) {
-               struct bt_clock_class *cur_clk =
-                       g_ptr_array_index(trace->clocks, i);
-               const char *cur_clk_name = bt_clock_class_get_name(cur_clk);
-
-               if (!cur_clk_name) {
-                       goto end;
-               }
-
-               if (!strcmp(cur_clk_name, name)) {
-                       clock_class = cur_clk;
-                       bt_get(clock_class);
-                       goto end;
-               }
-       }
-
-end:
-       return clock_class;
+       return bt_trace_common_get_clock_class_by_name(BT_TO_COMMON(trace),
+               name);
 }
 
 BT_HIDDEN
-bt_bool bt_trace_has_clock_class(struct bt_trace *trace,
+bt_bool bt_trace_common_has_clock_class(struct bt_trace_common *trace,
                struct bt_clock_class *clock_class)
 {
        struct search_query query = { .value = clock_class, .found = 0 };
@@ -1635,217 +1594,19 @@ bt_bool bt_trace_has_clock_class(struct bt_trace *trace,
        BT_ASSERT(trace);
        BT_ASSERT(clock_class);
 
-       g_ptr_array_foreach(trace->clocks, value_exists, &query);
+       g_ptr_array_foreach(trace->clock_classes, value_exists, &query);
        return query.found;
 }
 
-BT_HIDDEN
-const char *get_byte_order_string(enum bt_byte_order byte_order)
-{
-       const char *string;
-
-       switch (byte_order) {
-       case BT_BYTE_ORDER_LITTLE_ENDIAN:
-               string = "le";
-               break;
-       case BT_BYTE_ORDER_BIG_ENDIAN:
-               string = "be";
-               break;
-       case BT_BYTE_ORDER_NATIVE:
-               string = "native";
-               break;
-       default:
-               abort();
-       }
-
-       return string;
-}
-
-static
-int append_trace_metadata(struct bt_trace *trace,
-               struct metadata_context *context)
-{
-       unsigned char *uuid = trace->uuid;
-       int ret = 0;
-
-       if (trace->native_byte_order == BT_BYTE_ORDER_NATIVE ||
-                       trace->native_byte_order == BT_BYTE_ORDER_UNSPECIFIED) {
-               BT_LOGW("Invalid parameter: trace's byte order cannot be BT_BYTE_ORDER_NATIVE or BT_BYTE_ORDER_UNSPECIFIED at this point; "
-                       "set it with bt_trace_set_native_byte_order(): "
-                       "addr=%p, name=\"%s\"",
-                       trace, bt_trace_get_name(trace));
-               ret = -1;
-               goto end;
-       }
-
-       g_string_append(context->string, "trace {\n");
-       g_string_append(context->string, "\tmajor = 1;\n");
-       g_string_append(context->string, "\tminor = 8;\n");
-       BT_ASSERT(trace->native_byte_order == BT_BYTE_ORDER_LITTLE_ENDIAN ||
-               trace->native_byte_order == BT_BYTE_ORDER_BIG_ENDIAN ||
-               trace->native_byte_order == BT_BYTE_ORDER_NETWORK);
-
-       if (trace->uuid_set) {
-               g_string_append_printf(context->string,
-                       "\tuuid = \"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\";\n",
-                       uuid[0], uuid[1], uuid[2], uuid[3],
-                       uuid[4], uuid[5], uuid[6], uuid[7],
-                       uuid[8], uuid[9], uuid[10], uuid[11],
-                       uuid[12], uuid[13], uuid[14], uuid[15]);
-       }
-
-       g_string_append_printf(context->string, "\tbyte_order = %s;\n",
-               get_byte_order_string(trace->native_byte_order));
-
-       if (trace->packet_header_type) {
-               g_string_append(context->string, "\tpacket.header := ");
-               context->current_indentation_level++;
-               g_string_assign(context->field_name, "");
-               BT_LOGD_STR("Serializing trace's packet header field type's metadata.");
-               ret = bt_field_type_serialize(trace->packet_header_type,
-                       context);
-               if (ret) {
-                       goto end;
-               }
-               context->current_indentation_level--;
-       }
-
-       g_string_append(context->string, ";\n};\n\n");
-end:
-       return ret;
-}
-
-static
-void append_env_metadata(struct bt_trace *trace,
-               struct metadata_context *context)
-{
-       int64_t i;
-       int64_t env_size;
-
-       env_size = bt_attributes_get_count(trace->environment);
-       if (env_size <= 0) {
-               return;
-       }
-
-       g_string_append(context->string, "env {\n");
-
-       for (i = 0; i < env_size; i++) {
-               struct bt_value *env_field_value_obj = NULL;
-               const char *entry_name;
-
-               entry_name = bt_attributes_get_field_name(
-                       trace->environment, i);
-               env_field_value_obj = bt_attributes_get_field_value(
-                       trace->environment, i);
-
-               BT_ASSERT(entry_name);
-               BT_ASSERT(env_field_value_obj);
-
-               switch (bt_value_get_type(env_field_value_obj)) {
-               case BT_VALUE_TYPE_INTEGER:
-               {
-                       int ret;
-                       int64_t int_value;
-
-                       ret = bt_value_integer_get(env_field_value_obj,
-                               &int_value);
-                       BT_ASSERT(ret == 0);
-                       g_string_append_printf(context->string,
-                               "\t%s = %" PRId64 ";\n", entry_name,
-                               int_value);
-                       break;
-               }
-               case BT_VALUE_TYPE_STRING:
-               {
-                       int ret;
-                       const char *str_value;
-                       char *escaped_str = NULL;
-
-                       ret = bt_value_string_get(env_field_value_obj,
-                               &str_value);
-                       BT_ASSERT(ret == 0);
-                       escaped_str = g_strescape(str_value, NULL);
-                       if (!escaped_str) {
-                               BT_LOGE("Cannot escape string: string=\"%s\"",
-                                       str_value);
-                               goto loop_next;
-                       }
-
-                       g_string_append_printf(context->string,
-                               "\t%s = \"%s\";\n", entry_name, escaped_str);
-                       free(escaped_str);
-                       break;
-               }
-               default:
-                       goto loop_next;
-               }
-
-loop_next:
-               BT_PUT(env_field_value_obj);
-       }
-
-       g_string_append(context->string, "};\n\n");
-}
-
-char *bt_trace_get_metadata_string(struct bt_trace *trace)
-{
-       char *metadata = NULL;
-       struct metadata_context *context = NULL;
-       int err = 0;
-       size_t i;
-
-       if (!trace) {
-               BT_LOGW_STR("Invalid parameter: trace is NULL.");
-               goto end;
-       }
-
-       context = g_new0(struct metadata_context, 1);
-       if (!context) {
-               BT_LOGE_STR("Failed to allocate one metadata context.");
-               goto end;
-       }
-
-       context->field_name = g_string_sized_new(DEFAULT_IDENTIFIER_SIZE);
-       context->string = g_string_sized_new(DEFAULT_METADATA_STRING_SIZE);
-       g_string_append(context->string, "/* CTF 1.8 */\n\n");
-       if (append_trace_metadata(trace, context)) {
-               /* append_trace_metadata() logs errors */
-               goto error;
-       }
-       append_env_metadata(trace, context);
-       g_ptr_array_foreach(trace->clocks,
-               (GFunc)bt_clock_class_serialize, context);
-
-       for (i = 0; i < trace->stream_classes->len; i++) {
-               /* bt_stream_class_serialize() logs details */
-               err = bt_stream_class_serialize(
-                       trace->stream_classes->pdata[i], context);
-               if (err) {
-                       /* bt_stream_class_serialize() logs errors */
-                       goto error;
-               }
-       }
-
-       metadata = context->string->str;
-
-error:
-       g_string_free(context->string, err ? TRUE : FALSE);
-       g_string_free(context->field_name, TRUE);
-       g_free(context);
-
-end:
-       return metadata;
-}
-
 enum bt_byte_order bt_trace_get_native_byte_order(
                struct bt_trace *trace)
 {
-       BT_ASSERT_PRE_NON_NULL(trace, "Trace");
-       return trace->native_byte_order;
+       return bt_trace_common_get_native_byte_order(BT_TO_COMMON(trace));
 }
 
-int bt_trace_set_native_byte_order(struct bt_trace *trace,
-               enum bt_byte_order byte_order)
+BT_HIDDEN
+int bt_trace_common_set_native_byte_order(struct bt_trace_common *trace,
+               enum bt_byte_order byte_order, bool allow_unspecified)
 {
        int ret = 0;
 
@@ -1858,16 +1619,15 @@ int bt_trace_set_native_byte_order(struct bt_trace *trace,
        if (trace->frozen) {
                BT_LOGW("Invalid parameter: trace is frozen: "
                        "addr=%p, name=\"%s\"",
-                       trace, bt_trace_get_name(trace));
+                       trace, bt_trace_common_get_name(trace));
                ret = -1;
                goto end;
        }
 
-       if (trace->is_created_by_writer &&
-                       byte_order == BT_BYTE_ORDER_UNSPECIFIED) {
-               BT_LOGW("Invalid parameter: BT_BYTE_ORDER_UNSPECIFIED byte order is not allowed for a CTF writer trace: "
+       if (byte_order == BT_BYTE_ORDER_UNSPECIFIED && !allow_unspecified) {
+               BT_LOGW("Invalid parameter: BT_BYTE_ORDER_UNSPECIFIED byte order is not allowed: "
                        "addr=%p, name=\"%s\"",
-                       trace, bt_trace_get_name(trace));
+                       trace, bt_trace_common_get_name(trace));
                ret = -1;
                goto end;
        }
@@ -1877,8 +1637,8 @@ int bt_trace_set_native_byte_order(struct bt_trace *trace,
                        byte_order != BT_BYTE_ORDER_NETWORK) {
                BT_LOGW("Invalid parameter: invalid byte order: "
                        "addr=%p, name=\"%s\", bo=%s",
-                       trace, bt_trace_get_name(trace),
-                       bt_byte_order_string(byte_order));
+                       trace, bt_trace_common_get_name(trace),
+                       bt_common_byte_order_string(byte_order));
                ret = -1;
                goto end;
        }
@@ -1886,22 +1646,30 @@ int bt_trace_set_native_byte_order(struct bt_trace *trace,
        trace->native_byte_order = byte_order;
        BT_LOGV("Set trace's native byte order: "
                "addr=%p, name=\"%s\", bo=%s",
-               trace, bt_trace_get_name(trace),
-               bt_byte_order_string(byte_order));
+               trace, bt_trace_common_get_name(trace),
+               bt_common_byte_order_string(byte_order));
 
 end:
        return ret;
 }
 
-struct bt_field_type *bt_trace_get_packet_header_type(
+int bt_trace_set_native_byte_order(struct bt_trace *trace,
+               enum bt_byte_order byte_order)
+{
+       return bt_trace_common_set_native_byte_order(BT_TO_COMMON(trace),
+               byte_order, true);
+}
+
+struct bt_field_type *bt_trace_get_packet_header_field_type(
                struct bt_trace *trace)
 {
-       BT_ASSERT_PRE_NON_NULL(trace, "Trace");
-       return bt_get(trace->packet_header_type);
+       return BT_FROM_COMMON(bt_trace_common_get_packet_header_field_type(
+               BT_TO_COMMON(trace)));
 }
 
-int bt_trace_set_packet_header_type(struct bt_trace *trace,
-               struct bt_field_type *packet_header_type)
+BT_HIDDEN
+int bt_trace_common_set_packet_header_field_type(struct bt_trace_common *trace,
+               struct bt_field_type_common *packet_header_type)
 {
        int ret = 0;
 
@@ -1914,32 +1682,39 @@ int bt_trace_set_packet_header_type(struct bt_trace *trace,
        if (trace->frozen) {
                BT_LOGW("Invalid parameter: trace is frozen: "
                        "addr=%p, name=\"%s\"",
-                       trace, bt_trace_get_name(trace));
+                       trace, bt_trace_common_get_name(trace));
                ret = -1;
                goto end;
        }
 
        /* packet_header_type must be a structure. */
        if (packet_header_type &&
-                       !bt_field_type_is_structure(packet_header_type)) {
+                       packet_header_type->id != BT_FIELD_TYPE_ID_STRUCT) {
                BT_LOGW("Invalid parameter: packet header field type must be a structure field type if it exists: "
                        "addr=%p, name=\"%s\", ft-addr=%p, ft-id=%s",
-                       trace, bt_trace_get_name(trace),
+                       trace, bt_trace_common_get_name(trace),
                        packet_header_type,
-                       bt_field_type_id_string(packet_header_type->id));
+                       bt_common_field_type_id_string(packet_header_type->id));
                ret = -1;
                goto end;
        }
 
-       bt_put(trace->packet_header_type);
-       trace->packet_header_type = bt_get(packet_header_type);
+       bt_put(trace->packet_header_field_type);
+       trace->packet_header_field_type = bt_get(packet_header_type);
        BT_LOGV("Set trace's packet header field type: "
                "addr=%p, name=\"%s\", packet-context-ft-addr=%p",
-               trace, bt_trace_get_name(trace), packet_header_type);
+               trace, bt_trace_common_get_name(trace), packet_header_type);
 end:
        return ret;
 }
 
+int bt_trace_set_packet_header_field_type(struct bt_trace *trace,
+               struct bt_field_type *packet_header_type)
+{
+       return bt_trace_common_set_packet_header_field_type(BT_TO_COMMON(trace),
+               (void *) packet_header_type);
+}
+
 static
 int64_t get_stream_class_count(void *element)
 {
@@ -2055,58 +1830,6 @@ end:
        return 0;
 }
 
-BT_HIDDEN
-struct bt_field_type *get_field_type(enum field_type_alias alias)
-{
-       int ret;
-       unsigned int alignment, size;
-       struct bt_field_type *field_type = NULL;
-
-       if (alias >= NR_FIELD_TYPE_ALIAS) {
-               goto end;
-       }
-
-       alignment = field_type_aliases_alignments[alias];
-       size = field_type_aliases_sizes[alias];
-       field_type = bt_field_type_integer_create(size);
-       ret = bt_field_type_set_alignment(field_type, alignment);
-       if (ret) {
-               BT_PUT(field_type);
-       }
-end:
-       return field_type;
-}
-
-static
-void bt_trace_freeze(struct bt_trace *trace)
-{
-       int i;
-
-       if (trace->frozen) {
-               return;
-       }
-
-       BT_LOGD("Freezing trace: addr=%p, name=\"%s\"",
-               trace, bt_trace_get_name(trace));
-       BT_LOGD_STR("Freezing packet header field type.");
-       bt_field_type_freeze(trace->packet_header_type);
-       BT_LOGD_STR("Freezing environment attributes.");
-       bt_attributes_freeze(trace->environment);
-
-       if (trace->clocks->len > 0) {
-               BT_LOGD_STR("Freezing clock classes.");
-       }
-
-       for (i = 0; i < trace->clocks->len; i++) {
-               struct bt_clock_class *clock_class =
-                       g_ptr_array_index(trace->clocks, i);
-
-               bt_clock_class_freeze(clock_class);
-       }
-
-       trace->frozen = 1;
-}
-
 bt_bool bt_trace_is_static(struct bt_trace *trace)
 {
        BT_ASSERT_PRE_NON_NULL(trace, "Trace");
@@ -2124,14 +1847,14 @@ int bt_trace_set_is_static(struct bt_trace *trace)
                goto end;
        }
 
-       ret = check_packet_header_type_has_no_clock_class(trace);
+       ret = check_packet_header_type_has_no_clock_class(BT_TO_COMMON(trace));
        if (ret) {
                /* check_packet_header_type_has_no_clock_class() logs errors */
                goto end;
        }
 
        trace->is_static = BT_TRUE;
-       bt_trace_freeze(trace);
+       bt_trace_common_freeze(BT_TO_COMMON(trace));
        BT_LOGV("Set trace static: addr=%p, name=\"%s\"",
                trace, bt_trace_get_name(trace));
 
index 8fffff9ec4d40aa800321ecd5930bc03e2fb3908..312deb9dea835308d06fb967d7351c306357d7c1 100644 (file)
@@ -32,7 +32,7 @@
 #include <stdlib.h>
 #include <glib.h>
 #include <babeltrace/ctf-ir/utils.h>
-#include <babeltrace/ctf-ir/field-types.h>
+#include <babeltrace/ctf-ir/field-types-internal.h>
 #include <babeltrace/ctf-ir/clock-class.h>
 #include <babeltrace/ref.h>
 #include <babeltrace/assert-internal.h>
@@ -79,29 +79,29 @@ void trace_finalize(void)
        }
 }
 
-int bt_validate_identifier(const char *input_string)
+bt_bool bt_identifier_is_valid(const char *identifier)
 {
-       int ret = 0;
+       bt_bool is_valid = BT_TRUE;
        char *string = NULL;
        char *save_ptr, *token;
 
-       if (!input_string) {
+       if (!identifier) {
                BT_LOGV_STR("Invalid parameter: input string is NULL.");
-               ret = -1;
+               is_valid = BT_FALSE;
                goto end;
        }
 
        try_init_reserved_keywords();
 
-       if (input_string[0] == '\0') {
-               ret = -1;
+       if (identifier[0] == '\0') {
+               is_valid = BT_FALSE;
                goto end;
        }
 
-       string = strdup(input_string);
+       string = strdup(identifier);
        if (!string) {
                BT_LOGE("strdup() failed.");
-               ret = -1;
+               is_valid = BT_FALSE;
                goto end;
        }
 
@@ -110,7 +110,7 @@ int bt_validate_identifier(const char *input_string)
                if (g_hash_table_lookup_extended(reserved_keywords_set,
                        GINT_TO_POINTER(g_quark_from_string(token)),
                        NULL, NULL)) {
-                       ret = -1;
+                       is_valid = BT_FALSE;
                        goto end;
                }
 
@@ -118,155 +118,5 @@ int bt_validate_identifier(const char *input_string)
        }
 end:
        free(string);
-       return ret;
-}
-
-bt_bool bt_identifier_is_valid(const char *identifier)
-{
-       return bt_validate_identifier(identifier) == 0;
-}
-
-BT_HIDDEN
-int bt_validate_single_clock_class(struct bt_field_type *field_type,
-               struct bt_clock_class **expected_clock_class)
-{
-       int ret = 0;
-
-       if (!field_type) {
-               goto end;
-       }
-
-       BT_ASSERT(expected_clock_class);
-
-       switch (bt_field_type_get_type_id(field_type)) {
-       case BT_FIELD_TYPE_ID_INTEGER:
-       {
-               struct bt_clock_class *mapped_clock_class =
-                       bt_field_type_integer_get_mapped_clock_class(field_type);
-
-               if (!mapped_clock_class) {
-                       goto end;
-               }
-
-               if (!*expected_clock_class) {
-                       /* Move reference to output parameter */
-                       *expected_clock_class = mapped_clock_class;
-                       mapped_clock_class = NULL;
-                       BT_LOGV("Setting expected clock class: "
-                               "expected-clock-class-addr=%p",
-                               *expected_clock_class);
-               } else {
-                       if (mapped_clock_class != *expected_clock_class) {
-                               BT_LOGW("Integer field type is not mapped to "
-                                       "the expected clock class: "
-                                       "mapped-clock-class-addr=%p, "
-                                       "mapped-clock-class-name=\"%s\", "
-                                       "expected-clock-class-addr=%p, "
-                                       "expected-clock-class-name=\"%s\"",
-                                       mapped_clock_class,
-                                       bt_clock_class_get_name(mapped_clock_class),
-                                       *expected_clock_class,
-                                       bt_clock_class_get_name(*expected_clock_class));
-                               bt_put(mapped_clock_class);
-                               ret = -1;
-                               goto end;
-                       }
-               }
-
-               bt_put(mapped_clock_class);
-               break;
-       }
-       case BT_FIELD_TYPE_ID_ENUM:
-       case BT_FIELD_TYPE_ID_ARRAY:
-       case BT_FIELD_TYPE_ID_SEQUENCE:
-       {
-               struct bt_field_type *subtype = NULL;
-
-               switch (bt_field_type_get_type_id(field_type)) {
-               case BT_FIELD_TYPE_ID_ENUM:
-                       subtype = bt_field_type_enumeration_get_container_type(
-                               field_type);
-                       break;
-               case BT_FIELD_TYPE_ID_ARRAY:
-                       subtype = bt_field_type_array_get_element_type(
-                               field_type);
-                       break;
-               case BT_FIELD_TYPE_ID_SEQUENCE:
-                       subtype = bt_field_type_sequence_get_element_type(
-                               field_type);
-                       break;
-               default:
-                       BT_LOGF("Unexpected field type ID: id=%d",
-                               bt_field_type_get_type_id(field_type));
-                       abort();
-               }
-
-               BT_ASSERT(subtype);
-               ret = bt_validate_single_clock_class(subtype,
-                       expected_clock_class);
-               bt_put(subtype);
-               break;
-       }
-       case BT_FIELD_TYPE_ID_STRUCT:
-       {
-               uint64_t i;
-               int64_t count = bt_field_type_structure_get_field_count(
-                       field_type);
-
-               for (i = 0; i < count; i++) {
-                       const char *name;
-                       struct bt_field_type *member_type;
-
-                       ret = bt_field_type_structure_get_field_by_index(
-                               field_type, &name, &member_type, i);
-                       BT_ASSERT(ret == 0);
-                       ret = bt_validate_single_clock_class(member_type,
-                               expected_clock_class);
-                       bt_put(member_type);
-                       if (ret) {
-                               BT_LOGW("Structure field type's field's type "
-                                       "is not recursively mapped to the "
-                                       "expected clock class: "
-                                       "field-ft-addr=%p, field-name=\"%s\"",
-                                       member_type, name);
-                               goto end;
-                       }
-               }
-
-               break;
-       }
-       case BT_FIELD_TYPE_ID_VARIANT:
-       {
-               uint64_t i;
-               int64_t count = bt_field_type_variant_get_field_count(
-                       field_type);
-
-               for (i = 0; i < count; i++) {
-                       const char *name;
-                       struct bt_field_type *member_type;
-
-                       ret = bt_field_type_variant_get_field_by_index(
-                               field_type, &name, &member_type, i);
-                       BT_ASSERT(ret == 0);
-                       ret = bt_validate_single_clock_class(member_type,
-                               expected_clock_class);
-                       bt_put(member_type);
-                       if (ret) {
-                               BT_LOGW("Variant field type's field's type "
-                                       "is not recursively mapped to the "
-                                       "expected clock class: "
-                                       "field-ft-addr=%p, field-name=\"%s\"",
-                                       member_type, name);
-                               goto end;
-                       }
-               }
-
-               break;
-       }
-       default:
-               break;
-       }
-
-end:
-       return ret;
+       return is_valid;
 }
index dd9a7afdb6e437a3081f2b7b3e55774657058c82..a17ef4af7a1de4b9bc53cb06b447fd13ff0c38a2 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Babeltrace - CTF IR: Validation of trace, stream class, and event class
  *
- * Copyright 2016 Philippe Proulx <pproulx@efficios.com>
+ * Copyright 2016-2018 Philippe Proulx <pproulx@efficios.com>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
 #define BT_LOG_TAG "VALIDATION"
 #include <babeltrace/lib-logging-internal.h>
 
+#include <babeltrace/assert-pre-internal.h>
 #include <babeltrace/ctf-ir/validation-internal.h>
 #include <babeltrace/ctf-ir/resolve-internal.h>
 #include <babeltrace/ctf-ir/trace-internal.h>
 #include <babeltrace/ctf-ir/stream-class-internal.h>
 #include <babeltrace/ctf-ir/field-types-internal.h>
 #include <babeltrace/ctf-ir/event-class-internal.h>
+#include <babeltrace/ctf-ir/field-types-internal.h>
 #include <babeltrace/values.h>
 #include <babeltrace/babeltrace-internal.h>
 #include <babeltrace/ref.h>
  */
 static
 int validate_event_class_types(struct bt_value *environment,
-               struct bt_field_type *packet_header_type,
-               struct bt_field_type *packet_context_type,
-               struct bt_field_type *event_header_type,
-               struct bt_field_type *stream_event_ctx_type,
-               struct bt_field_type *event_context_type,
-               struct bt_field_type *event_payload_type)
+               struct bt_field_type_common *packet_header_type,
+               struct bt_field_type_common *packet_context_type,
+               struct bt_field_type_common *event_header_type,
+               struct bt_field_type_common *stream_event_ctx_type,
+               struct bt_field_type_common *event_context_type,
+               struct bt_field_type_common *event_payload_type)
 {
        int ret = 0;
 
@@ -80,7 +82,7 @@ int validate_event_class_types(struct bt_value *environment,
 
        /* Validate field types individually */
        if (event_context_type) {
-               ret = bt_field_type_validate(event_context_type);
+               ret = bt_field_type_common_validate(event_context_type);
                if (ret) {
                        BT_LOGW("Invalid event class's context field type: "
                                "ret=%d", ret);
@@ -89,7 +91,7 @@ int validate_event_class_types(struct bt_value *environment,
        }
 
        if (event_payload_type) {
-               ret = bt_field_type_validate(event_payload_type);
+               ret = bt_field_type_common_validate(event_payload_type);
                if (ret) {
                        BT_LOGW("Invalid event class's payload field type: "
                                "ret=%d", ret);
@@ -111,10 +113,10 @@ end:
  */
 static
 int validate_stream_class_types(struct bt_value *environment,
-               struct bt_field_type *packet_header_type,
-               struct bt_field_type *packet_context_type,
-               struct bt_field_type *event_header_type,
-               struct bt_field_type *stream_event_ctx_type)
+               struct bt_field_type_common *packet_header_type,
+               struct bt_field_type_common *packet_context_type,
+               struct bt_field_type_common *event_header_type,
+               struct bt_field_type_common *stream_event_ctx_type)
 {
        int ret = 0;
 
@@ -141,7 +143,7 @@ int validate_stream_class_types(struct bt_value *environment,
 
        /* Validate field types individually */
        if (packet_context_type) {
-               ret = bt_field_type_validate(packet_context_type);
+               ret = bt_field_type_common_validate(packet_context_type);
                if (ret) {
                        BT_LOGW("Invalid stream class's packet context field type: "
                                "ret=%d", ret);
@@ -150,7 +152,7 @@ int validate_stream_class_types(struct bt_value *environment,
        }
 
        if (event_header_type) {
-               ret = bt_field_type_validate(event_header_type);
+               ret = bt_field_type_common_validate(event_header_type);
                if (ret) {
                        BT_LOGW("Invalid stream class's event header field type: "
                                "ret=%d", ret);
@@ -159,7 +161,7 @@ int validate_stream_class_types(struct bt_value *environment,
        }
 
        if (stream_event_ctx_type) {
-               ret = bt_field_type_validate(
+               ret = bt_field_type_common_validate(
                        stream_event_ctx_type);
                if (ret) {
                        BT_LOGW("Invalid stream class's event context field type: "
@@ -179,7 +181,7 @@ end:
  */
 static
 int validate_trace_types(struct bt_value *environment,
-               struct bt_field_type *packet_header_type)
+               struct bt_field_type_common *packet_header_type)
 {
        int ret = 0;
 
@@ -198,7 +200,7 @@ int validate_trace_types(struct bt_value *environment,
 
        /* Validate field types individually */
        if (packet_header_type) {
-               ret = bt_field_type_validate(packet_header_type);
+               ret = bt_field_type_common_validate(packet_header_type);
                if (ret) {
                        BT_LOGW("Invalid trace's packet header field type: "
                                "ret=%d", ret);
@@ -217,10 +219,10 @@ end:
  * `field_type` is owned by the caller.
  */
 static
-int field_type_contains_sequence_or_variant_ft(struct bt_field_type *type)
+int field_type_contains_sequence_or_variant_ft(struct bt_field_type_common *type)
 {
        int ret = 0;
-       enum bt_field_type_id type_id = bt_field_type_get_type_id(type);
+       enum bt_field_type_id type_id = bt_field_type_common_get_type_id(type);
 
        switch (type_id) {
        case BT_FIELD_TYPE_ID_SEQUENCE:
@@ -231,7 +233,7 @@ int field_type_contains_sequence_or_variant_ft(struct bt_field_type *type)
        case BT_FIELD_TYPE_ID_STRUCT:
        {
                int i;
-               int field_count = bt_field_type_get_field_count(type);
+               int field_count = bt_field_type_common_get_field_count(type);
 
                if (field_count < 0) {
                        ret = -1;
@@ -239,8 +241,8 @@ int field_type_contains_sequence_or_variant_ft(struct bt_field_type *type)
                }
 
                for (i = 0; i < field_count; ++i) {
-                       struct bt_field_type *child_type =
-                               bt_field_type_get_field_at_index(type, i);
+                       struct bt_field_type_common *child_type =
+                               bt_field_type_common_get_field_at_index(type, i);
 
                        ret = field_type_contains_sequence_or_variant_ft(
                                child_type);
@@ -261,15 +263,16 @@ end:
 
 BT_HIDDEN
 int bt_validate_class_types(struct bt_value *environment,
-               struct bt_field_type *packet_header_type,
-               struct bt_field_type *packet_context_type,
-               struct bt_field_type *event_header_type,
-               struct bt_field_type *stream_event_ctx_type,
-               struct bt_field_type *event_context_type,
-               struct bt_field_type *event_payload_type,
+               struct bt_field_type_common *packet_header_type,
+               struct bt_field_type_common *packet_context_type,
+               struct bt_field_type_common *event_header_type,
+               struct bt_field_type_common *stream_event_ctx_type,
+               struct bt_field_type_common *event_context_type,
+               struct bt_field_type_common *event_payload_type,
                int trace_valid, int stream_class_valid, int event_class_valid,
                struct bt_validation_output *output,
-               enum bt_validation_flag validate_flags)
+               enum bt_validation_flag validate_flags,
+               bt_validation_flag_copy_field_type_func copy_field_type_func)
 {
        int ret = 0;
        int contains_seq_var;
@@ -315,7 +318,7 @@ int bt_validate_class_types(struct bt_value *environment,
 
        /* Validate trace */
        if ((validate_flags & BT_VALIDATION_FLAG_TRACE) && !trace_valid) {
-               struct bt_field_type *packet_header_type_copy = NULL;
+               struct bt_field_type_common *packet_header_type_copy = NULL;
 
                /* Create field type copies */
                if (packet_header_type) {
@@ -334,7 +337,7 @@ int bt_validate_class_types(struct bt_value *environment,
 
                        BT_LOGV_STR("Copying packet header field type because it contains at least one sequence or variant field type.");
                        packet_header_type_copy =
-                               bt_field_type_copy(packet_header_type);
+                               copy_field_type_func(packet_header_type);
                        if (!packet_header_type_copy) {
                                ret = -1;
                                BT_LOGE_STR("Cannot copy packet header field type.");
@@ -346,7 +349,7 @@ int bt_validate_class_types(struct bt_value *environment,
                         * caller, it cannot be modified any way since
                         * it will be resolved.
                         */
-                       bt_field_type_freeze(packet_header_type_copy);
+                       bt_field_type_common_freeze(packet_header_type_copy);
                }
 
 skip_packet_header_type_copy:
@@ -365,9 +368,9 @@ skip_packet_header_type_copy:
        /* Validate stream class */
        if ((validate_flags & BT_VALIDATION_FLAG_STREAM) &&
                        !stream_class_valid) {
-               struct bt_field_type *packet_context_type_copy = NULL;
-               struct bt_field_type *event_header_type_copy = NULL;
-               struct bt_field_type *stream_event_ctx_type_copy = NULL;
+               struct bt_field_type_common *packet_context_type_copy = NULL;
+               struct bt_field_type_common *event_header_type_copy = NULL;
+               struct bt_field_type_common *stream_event_ctx_type_copy = NULL;
 
                if (packet_context_type) {
                        contains_seq_var =
@@ -385,7 +388,7 @@ skip_packet_header_type_copy:
 
                        BT_LOGV_STR("Copying packet context field type because it contains at least one sequence or variant field type.");
                        packet_context_type_copy =
-                               bt_field_type_copy(packet_context_type);
+                               copy_field_type_func(packet_context_type);
                        if (!packet_context_type_copy) {
                                BT_LOGE_STR("Cannot copy packet context field type.");
                                goto sc_validation_error;
@@ -396,7 +399,7 @@ skip_packet_header_type_copy:
                         * caller, it cannot be modified any way since
                         * it will be resolved.
                         */
-                       bt_field_type_freeze(packet_context_type_copy);
+                       bt_field_type_common_freeze(packet_context_type_copy);
                }
 
 skip_packet_context_type_copy:
@@ -416,7 +419,7 @@ skip_packet_context_type_copy:
 
                        BT_LOGV_STR("Copying event header field type because it contains at least one sequence or variant field type.");
                        event_header_type_copy =
-                               bt_field_type_copy(event_header_type);
+                               copy_field_type_func(event_header_type);
                        if (!event_header_type_copy) {
                                BT_LOGE_STR("Cannot copy event header field type.");
                                goto sc_validation_error;
@@ -427,7 +430,7 @@ skip_packet_context_type_copy:
                         * caller, it cannot be modified any way since
                         * it will be resolved.
                         */
-                       bt_field_type_freeze(event_header_type_copy);
+                       bt_field_type_common_freeze(event_header_type_copy);
                }
 
 skip_event_header_type_copy:
@@ -448,7 +451,7 @@ skip_event_header_type_copy:
 
                        BT_LOGV_STR("Copying stream event context field type because it contains at least one sequence or variant field type.");
                        stream_event_ctx_type_copy =
-                               bt_field_type_copy(stream_event_ctx_type);
+                               copy_field_type_func(stream_event_ctx_type);
                        if (!stream_event_ctx_type_copy) {
                                BT_LOGE_STR("Cannot copy stream event context field type.");
                                goto sc_validation_error;
@@ -459,7 +462,7 @@ skip_event_header_type_copy:
                         * caller, it cannot be modified any way since
                         * it will be resolved.
                         */
-                       bt_field_type_freeze(stream_event_ctx_type_copy);
+                       bt_field_type_common_freeze(stream_event_ctx_type_copy);
                }
 
 skip_stream_event_ctx_type_copy:
@@ -491,8 +494,8 @@ sc_validation_done:
        /* Validate event class */
        if ((validate_flags & BT_VALIDATION_FLAG_EVENT) &&
                        !event_class_valid) {
-               struct bt_field_type *event_context_type_copy = NULL;
-               struct bt_field_type *event_payload_type_copy = NULL;
+               struct bt_field_type_common *event_context_type_copy = NULL;
+               struct bt_field_type_common *event_payload_type_copy = NULL;
 
                if (event_context_type) {
                        contains_seq_var =
@@ -510,7 +513,7 @@ sc_validation_done:
 
                        BT_LOGV_STR("Copying event context field type because it contains at least one sequence or variant field type.");
                        event_context_type_copy =
-                               bt_field_type_copy(event_context_type);
+                               copy_field_type_func(event_context_type);
                        if (!event_context_type_copy) {
                                BT_LOGE_STR("Cannot copy event context field type.");
                                goto ec_validation_error;
@@ -521,7 +524,7 @@ sc_validation_done:
                         * caller, it cannot be modified any way since
                         * it will be resolved.
                         */
-                       bt_field_type_freeze(event_context_type_copy);
+                       bt_field_type_common_freeze(event_context_type_copy);
                }
 
 skip_event_context_type_copy:
@@ -541,7 +544,7 @@ skip_event_context_type_copy:
 
                        BT_LOGV_STR("Copying event payload field type because it contains at least one sequence or variant field type.");
                        event_payload_type_copy =
-                               bt_field_type_copy(event_payload_type);
+                               copy_field_type_func(event_payload_type);
                        if (!event_payload_type_copy) {
                                BT_LOGE_STR("Cannot copy event payload field type.");
                                goto ec_validation_error;
@@ -552,7 +555,7 @@ skip_event_context_type_copy:
                         * caller, it cannot be modified any way since
                         * it will be resolved.
                         */
-                       bt_field_type_freeze(event_payload_type_copy);
+                       bt_field_type_common_freeze(event_payload_type_copy);
                }
 
 skip_event_payload_type_copy:
@@ -604,34 +607,35 @@ error:
 }
 
 BT_HIDDEN
-void bt_validation_replace_types(struct bt_trace *trace,
-               struct bt_stream_class *stream_class,
-               struct bt_event_class *event_class,
+void bt_validation_replace_types(struct bt_trace_common *trace,
+               struct bt_stream_class_common *stream_class,
+               struct bt_event_class_common *event_class,
                struct bt_validation_output *output,
                enum bt_validation_flag replace_flags)
 {
        if ((replace_flags & BT_VALIDATION_FLAG_TRACE) && trace) {
-               bt_field_type_freeze(trace->packet_header_type);
-               BT_MOVE(trace->packet_header_type, output->packet_header_type);
+               bt_field_type_common_freeze(trace->packet_header_field_type);
+               BT_MOVE(trace->packet_header_field_type,
+                       output->packet_header_type);
        }
 
        if ((replace_flags & BT_VALIDATION_FLAG_STREAM) && stream_class) {
-               bt_field_type_freeze(stream_class->packet_context_type);
-               bt_field_type_freeze(stream_class->event_header_type);
-               bt_field_type_freeze(stream_class->event_context_type);
-               BT_MOVE(stream_class->packet_context_type,
+               bt_field_type_common_freeze(stream_class->packet_context_field_type);
+               bt_field_type_common_freeze(stream_class->event_header_field_type);
+               bt_field_type_common_freeze(stream_class->event_context_field_type);
+               BT_MOVE(stream_class->packet_context_field_type,
                        output->packet_context_type);
-               BT_MOVE(stream_class->event_header_type,
+               BT_MOVE(stream_class->event_header_field_type,
                        output->event_header_type);
-               BT_MOVE(stream_class->event_context_type,
+               BT_MOVE(stream_class->event_context_field_type,
                        output->stream_event_ctx_type);
        }
 
        if ((replace_flags & BT_VALIDATION_FLAG_EVENT) && event_class) {
-               bt_field_type_freeze(event_class->context);
-               bt_field_type_freeze(event_class->fields);
-               BT_MOVE(event_class->context, output->event_context_type);
-               BT_MOVE(event_class->fields, output->event_payload_type);
+               bt_field_type_common_freeze(event_class->context_field_type);
+               bt_field_type_common_freeze(event_class->payload_field_type);
+               BT_MOVE(event_class->context_field_type, output->event_context_type);
+               BT_MOVE(event_class->payload_field_type, output->event_payload_type);
        }
 }
 
index 8ea82b0bde9fac5d2dcf77acee42c9c9b8c3d89d..1557f2e1c19bdd846edea9e8a9dbcad8ad86d8c3 100644 (file)
@@ -2,8 +2,15 @@ noinst_LTLIBRARIES = libctf-writer.la
 
 libctf_writer_la_SOURCES = \
        clock.c \
-       writer.c \
+       event-class.c \
+       event.c \
+       field-types.c \
+       fields.c \
        functor.c \
-       serialize.c
+       serialize.c \
+       stream-class.c \
+       stream.c \
+       trace.c \
+       writer.c
 
 libctf_writer_la_LIBADD = $(UUID_LIBS)
index 7386096c8956ff258ee10526479af14717a0a74f..106947e2cc05cc76d88c6a72afd93233928892e0 100644 (file)
@@ -31,6 +31,7 @@
 #include <babeltrace/lib-logging-internal.h>
 
 #include <babeltrace/ctf-writer/clock-internal.h>
+#include <babeltrace/ctf-writer/writer-internal.h>
 #include <babeltrace/ctf-ir/clock-class.h>
 #include <babeltrace/ctf-ir/clock-class-internal.h>
 #include <babeltrace/ctf-ir/utils.h>
@@ -39,7 +40,6 @@
 #include <babeltrace/object-internal.h>
 #include <babeltrace/compiler-internal.h>
 #include <babeltrace/assert-internal.h>
-#include <babeltrace/assert-pre-internal.h>
 #include <inttypes.h>
 
 static
@@ -61,7 +61,7 @@ struct bt_ctf_clock *bt_ctf_clock_create(const char *name)
        clock->value = 0;
 
        /* Pre-2.0.0 backward compatibility: default frequency is 1 GHz */
-       clock->clock_class = bt_clock_class_create(name, 1000000000);
+       clock->clock_class = (void *) bt_clock_class_create(name, 1000000000);
        if (!clock->clock_class) {
                goto error;
        }
@@ -72,7 +72,8 @@ struct bt_ctf_clock *bt_ctf_clock_create(const char *name)
                goto error;
        }
 
-       ret = bt_clock_class_set_uuid(clock->clock_class, cc_uuid);
+       ret = bt_clock_class_set_uuid(BT_TO_COMMON(clock->clock_class),
+               cc_uuid);
        BT_ASSERT(ret == 0);
        return clock;
 
@@ -84,105 +85,115 @@ error:
 const char *bt_ctf_clock_get_name(struct bt_ctf_clock *clock)
 {
        BT_ASSERT_PRE_NON_NULL(clock, "CTF writer clock");
-       return bt_clock_class_get_name(clock->clock_class);
+       return bt_clock_class_get_name(BT_TO_COMMON(clock->clock_class));
 }
 
 const char *bt_ctf_clock_get_description(struct bt_ctf_clock *clock)
 {
        BT_ASSERT_PRE_NON_NULL(clock, "CTF writer clock");
-       return bt_clock_class_get_description(clock->clock_class);
+       return bt_clock_class_get_description(BT_TO_COMMON(clock->clock_class));
 }
 
 int bt_ctf_clock_set_description(struct bt_ctf_clock *clock, const char *desc)
 {
        BT_ASSERT_PRE_NON_NULL(clock, "CTF writer clock");
-       return bt_clock_class_set_description(clock->clock_class, desc);
+       return bt_clock_class_set_description(BT_TO_COMMON(clock->clock_class),
+               desc);
 }
 
 uint64_t bt_ctf_clock_get_frequency(struct bt_ctf_clock *clock)
 {
        BT_ASSERT_PRE_NON_NULL(clock, "CTF writer clock");
-       return bt_clock_class_get_frequency(clock->clock_class);
+       return bt_clock_class_get_frequency(BT_TO_COMMON(clock->clock_class));
 }
 
 int bt_ctf_clock_set_frequency(struct bt_ctf_clock *clock, uint64_t freq)
 {
        BT_ASSERT_PRE_NON_NULL(clock, "CTF writer clock");
-       return bt_clock_class_set_frequency(clock->clock_class, freq);
+       return bt_clock_class_set_frequency(BT_TO_COMMON(clock->clock_class),
+               freq);
 }
 
 uint64_t bt_ctf_clock_get_precision(struct bt_ctf_clock *clock)
 {
        BT_ASSERT_PRE_NON_NULL(clock, "CTF writer clock");
-       return bt_clock_class_get_precision(clock->clock_class);
+       return bt_clock_class_get_precision(BT_TO_COMMON(clock->clock_class));
 }
 
 int bt_ctf_clock_set_precision(struct bt_ctf_clock *clock, uint64_t precision)
 {
        BT_ASSERT_PRE_NON_NULL(clock, "CTF writer clock");
-       return bt_clock_class_set_precision(clock->clock_class, precision);
+       return bt_clock_class_set_precision(BT_TO_COMMON(clock->clock_class),
+               precision);
 }
 
 int bt_ctf_clock_get_offset_s(struct bt_ctf_clock *clock, int64_t *offset_s)
 {
        BT_ASSERT_PRE_NON_NULL(clock, "CTF writer clock");
-       return bt_clock_class_get_offset_s(clock->clock_class, offset_s);
+       return bt_clock_class_get_offset_s(BT_TO_COMMON(clock->clock_class),
+               offset_s);
 }
 
 int bt_ctf_clock_set_offset_s(struct bt_ctf_clock *clock, int64_t offset_s)
 {
        BT_ASSERT_PRE_NON_NULL(clock, "CTF writer clock");
-       return bt_clock_class_set_offset_s(clock->clock_class, offset_s);
+       return bt_clock_class_set_offset_s(BT_TO_COMMON(clock->clock_class),
+               offset_s);
 }
 
 int bt_ctf_clock_get_offset(struct bt_ctf_clock *clock, int64_t *offset)
 {
        BT_ASSERT_PRE_NON_NULL(clock, "CTF writer clock");
-       return bt_clock_class_get_offset_cycles(clock->clock_class, offset);
+       return bt_clock_class_get_offset_cycles(BT_TO_COMMON(clock->clock_class),
+               offset);
 }
 
 int bt_ctf_clock_set_offset(struct bt_ctf_clock *clock, int64_t offset)
 {
        BT_ASSERT_PRE_NON_NULL(clock, "CTF writer clock");
-       return bt_clock_class_set_offset_cycles(clock->clock_class, offset);
+       return bt_clock_class_set_offset_cycles(BT_TO_COMMON(clock->clock_class),
+               offset);
 }
 
 int bt_ctf_clock_get_is_absolute(struct bt_ctf_clock *clock)
 {
        BT_ASSERT_PRE_NON_NULL(clock, "CTF writer clock");
-       return bt_clock_class_is_absolute(clock->clock_class);
+       return bt_clock_class_is_absolute(BT_TO_COMMON(clock->clock_class));
 }
 
 int bt_ctf_clock_set_is_absolute(struct bt_ctf_clock *clock, int is_absolute)
 {
        BT_ASSERT_PRE_NON_NULL(clock, "CTF writer clock");
-       return bt_clock_class_set_is_absolute(clock->clock_class, is_absolute);
+       return bt_clock_class_set_is_absolute(BT_TO_COMMON(clock->clock_class),
+               is_absolute);
 }
 
 const unsigned char *bt_ctf_clock_get_uuid(struct bt_ctf_clock *clock)
 {
        BT_ASSERT_PRE_NON_NULL(clock, "CTF writer clock");
-       return bt_clock_class_get_uuid(clock->clock_class);
+       return bt_clock_class_get_uuid(BT_TO_COMMON(clock->clock_class));
 }
 
 int bt_ctf_clock_set_uuid(struct bt_ctf_clock *clock, const unsigned char *uuid)
 {
        BT_ASSERT_PRE_NON_NULL(clock, "CTF writer clock");
-       return bt_clock_class_set_uuid(clock->clock_class, uuid);
+       return bt_clock_class_set_uuid(BT_TO_COMMON(clock->clock_class), uuid);
 }
 
 int bt_ctf_clock_set_time(struct bt_ctf_clock *clock, int64_t time)
 {
        int64_t value;
+       struct bt_clock_class *cc;
 
        BT_ASSERT_PRE_NON_NULL(clock, "CTF writer clock");
+       cc = BT_TO_COMMON(clock->clock_class);
 
        /* Common case where cycles are actually nanoseconds */
-       if (clock->clock_class->frequency == 1000000000) {
+       if (cc->frequency == 1000000000) {
                value = time;
        } else {
                value = (uint64_t) (((double) time *
-                       (double) clock->clock_class->frequency) / 1e9);
+                       (double) cc->frequency) / 1e9);
        }
 
        BT_ASSERT_PRE(clock->value <= value,
@@ -193,16 +204,6 @@ int bt_ctf_clock_set_time(struct bt_ctf_clock *clock, int64_t time)
        return 0;
 }
 
-void bt_ctf_clock_get(struct bt_ctf_clock *clock)
-{
-       bt_get(clock);
-}
-
-void bt_ctf_clock_put(struct bt_ctf_clock *clock)
-{
-       bt_put(clock);
-}
-
 BT_HIDDEN
 int bt_ctf_clock_get_value(struct bt_ctf_clock *clock, uint64_t *value)
 {
@@ -218,6 +219,165 @@ void bt_ctf_clock_destroy(struct bt_object *obj)
        struct bt_ctf_clock *clock;
 
        clock = container_of(obj, struct bt_ctf_clock, base);
-       bt_put(clock->clock_class);
+       bt_put(BT_TO_COMMON(clock->clock_class));
        g_free(clock);
 }
+
+BT_HIDDEN
+void bt_ctf_clock_class_serialize(struct bt_ctf_clock_class *clock_class,
+               struct metadata_context *context)
+{
+       unsigned char *uuid;
+
+       BT_LOGD("Serializing clock class's metadata: clock-class-addr=%p, "
+               "name=\"%s\", metadata-context-addr=%p", clock_class,
+               bt_clock_class_get_name(BT_TO_COMMON(clock_class)),
+               context);
+
+       if (!clock_class || !context) {
+               BT_LOGW("Invalid parameter: clock class or metadata context is NULL: "
+                       "clock-class-addr=%p, name=\"%s\", metadata-context-addr=%p",
+                       clock_class,
+                       bt_clock_class_get_name(BT_TO_COMMON(clock_class)),
+                       context);
+               return;
+       }
+
+       uuid = clock_class->common.uuid;
+       g_string_append(context->string, "clock {\n");
+       g_string_append_printf(context->string, "\tname = %s;\n",
+               clock_class->common.name->str);
+
+       if (clock_class->common.uuid_set) {
+               g_string_append_printf(context->string,
+                       "\tuuid = \"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\";\n",
+                       uuid[0], uuid[1], uuid[2], uuid[3],
+                       uuid[4], uuid[5], uuid[6], uuid[7],
+                       uuid[8], uuid[9], uuid[10], uuid[11],
+                       uuid[12], uuid[13], uuid[14], uuid[15]);
+       }
+
+       if (clock_class->common.description) {
+               g_string_append_printf(context->string, "\tdescription = \"%s\";\n",
+                       clock_class->common.description->str);
+       }
+
+       g_string_append_printf(context->string, "\tfreq = %" PRIu64 ";\n",
+               clock_class->common.frequency);
+       g_string_append_printf(context->string, "\tprecision = %" PRIu64 ";\n",
+               clock_class->common.precision);
+       g_string_append_printf(context->string, "\toffset_s = %" PRIu64 ";\n",
+               clock_class->common.offset_s);
+       g_string_append_printf(context->string, "\toffset = %" PRIu64 ";\n",
+               clock_class->common.offset);
+       g_string_append_printf(context->string, "\tabsolute = %s;\n",
+               clock_class->common.absolute ? "true" : "false");
+       g_string_append(context->string, "};\n\n");
+}
+
+struct bt_ctf_clock_class *bt_ctf_clock_class_create(const char *name,
+                uint64_t freq)
+{
+       return BT_FROM_COMMON(bt_clock_class_create(name, freq));
+}
+
+const char *bt_ctf_clock_class_get_name(
+                struct bt_ctf_clock_class *clock_class)
+{
+       return bt_clock_class_get_name(BT_TO_COMMON(clock_class));
+}
+
+int bt_ctf_clock_class_set_name(struct bt_ctf_clock_class *clock_class,
+                const char *name)
+{
+       return bt_clock_class_set_name(BT_TO_COMMON(clock_class), name);
+}
+
+const char *bt_ctf_clock_class_get_description(
+                struct bt_ctf_clock_class *clock_class)
+{
+       return bt_clock_class_get_description(BT_TO_COMMON(clock_class));
+}
+
+int bt_ctf_clock_class_set_description(
+                struct bt_ctf_clock_class *clock_class,
+                const char *desc)
+{
+       return bt_clock_class_set_description(BT_TO_COMMON(clock_class), desc);
+}
+
+uint64_t bt_ctf_clock_class_get_frequency(
+                struct bt_ctf_clock_class *clock_class)
+{
+       return bt_clock_class_get_frequency(BT_TO_COMMON(clock_class));
+}
+
+int bt_ctf_clock_class_set_frequency(
+                struct bt_ctf_clock_class *clock_class, uint64_t freq)
+{
+       return bt_clock_class_set_frequency(BT_TO_COMMON(clock_class), freq);
+}
+
+uint64_t bt_ctf_clock_class_get_precision(
+                struct bt_ctf_clock_class *clock_class)
+{
+       return bt_clock_class_get_precision(BT_TO_COMMON(clock_class));
+}
+
+int bt_ctf_clock_class_set_precision(
+                struct bt_ctf_clock_class *clock_class, uint64_t precision)
+{
+       return bt_clock_class_set_precision(BT_TO_COMMON(clock_class),
+               precision);
+}
+
+int bt_ctf_clock_class_get_offset_s(
+                struct bt_ctf_clock_class *clock_class, int64_t *seconds)
+{
+       return bt_clock_class_get_offset_s(BT_TO_COMMON(clock_class), seconds);
+}
+
+int bt_ctf_clock_class_set_offset_s(
+                struct bt_ctf_clock_class *clock_class, int64_t seconds)
+{
+       return bt_clock_class_set_offset_s(BT_TO_COMMON(clock_class), seconds);
+}
+
+int bt_ctf_clock_class_get_offset_cycles(
+                struct bt_ctf_clock_class *clock_class, int64_t *cycles)
+{
+       return bt_clock_class_get_offset_cycles(BT_TO_COMMON(clock_class),
+               cycles);
+}
+
+int bt_ctf_clock_class_set_offset_cycles(
+                struct bt_ctf_clock_class *clock_class, int64_t cycles)
+{
+       return bt_clock_class_set_offset_cycles(BT_TO_COMMON(clock_class),
+               cycles);
+}
+
+bt_bool bt_ctf_clock_class_is_absolute(
+                struct bt_ctf_clock_class *clock_class)
+{
+       return bt_clock_class_is_absolute(BT_TO_COMMON(clock_class));
+}
+
+int bt_ctf_clock_class_set_is_absolute(
+                struct bt_ctf_clock_class *clock_class, bt_bool is_absolute)
+{
+       return bt_clock_class_set_is_absolute(BT_TO_COMMON(clock_class),
+               is_absolute);
+}
+
+const unsigned char *bt_ctf_clock_class_get_uuid(
+                struct bt_ctf_clock_class *clock_class)
+{
+       return bt_clock_class_get_uuid(BT_TO_COMMON(clock_class));
+}
+
+int bt_ctf_clock_class_set_uuid(struct bt_ctf_clock_class *clock_class,
+                const unsigned char *uuid)
+{
+       return bt_clock_class_set_uuid(BT_TO_COMMON(clock_class), uuid);
+}
diff --git a/lib/ctf-writer/event-class.c b/lib/ctf-writer/event-class.c
new file mode 100644 (file)
index 0000000..ca49d97
--- /dev/null
@@ -0,0 +1,442 @@
+/*
+ * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ * Copyright 2017-2018 Philippe Proulx <pproulx@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#define BT_LOG_TAG "CTF-WRITER-EVENT-CLASS"
+#include <babeltrace/lib-logging-internal.h>
+
+#include <babeltrace/ctf-ir/event-class-internal.h>
+#include <babeltrace/ctf-ir/utils.h>
+#include <babeltrace/ctf-writer/event.h>
+#include <babeltrace/ctf-writer/event-internal.h>
+#include <babeltrace/ctf-writer/field-types.h>
+#include <babeltrace/ctf-writer/field-types-internal.h>
+#include <babeltrace/ctf-writer/writer-internal.h>
+#include <babeltrace/ref.h>
+#include <babeltrace/compiler-internal.h>
+#include <babeltrace/assert-internal.h>
+#include <babeltrace/assert-pre-internal.h>
+#include <inttypes.h>
+#include <glib.h>
+
+static
+void bt_ctf_event_class_destroy(struct bt_object *obj)
+{
+       bt_event_class_common_finalize(obj);
+       g_free(obj);
+}
+
+struct bt_ctf_event_class *bt_ctf_event_class_create(const char *name)
+{
+       struct bt_ctf_event_class *ctf_event_class = NULL;
+       int ret;
+
+       if (!name) {
+               BT_LOGW_STR("Invalid parameter: name is NULL.");
+               goto error;
+       }
+
+       BT_LOGD("Creating event class object: name=\"%s\"",
+               name);
+       ctf_event_class = g_new0(struct bt_ctf_event_class, 1);
+       if (!ctf_event_class) {
+               BT_LOGE_STR("Failed to allocate one event class.");
+               goto error;
+       }
+
+       ret = bt_event_class_common_initialize(BT_TO_COMMON(ctf_event_class),
+               name, bt_ctf_event_class_destroy,
+               (bt_field_type_structure_create_func)
+                       bt_ctf_field_type_structure_create);
+       if (ret) {
+               goto error;
+       }
+
+       goto end;
+
+error:
+       bt_put(ctf_event_class);
+
+end:
+       return ctf_event_class;
+}
+
+const char *bt_ctf_event_class_get_name(struct bt_ctf_event_class *event_class)
+{
+       return bt_event_class_common_get_name(BT_TO_COMMON(event_class));
+}
+
+int64_t bt_ctf_event_class_get_id(struct bt_ctf_event_class *event_class)
+{
+       return bt_event_class_common_get_id(BT_TO_COMMON(event_class));
+}
+
+int bt_ctf_event_class_set_id(struct bt_ctf_event_class *event_class,
+               uint64_t id)
+{
+       return bt_event_class_common_set_id(BT_TO_COMMON(event_class), id);
+}
+
+enum bt_ctf_event_class_log_level bt_ctf_event_class_get_log_level(
+               struct bt_ctf_event_class *event_class)
+{
+       return bt_event_class_common_get_log_level(BT_TO_COMMON(event_class));
+}
+
+int bt_ctf_event_class_set_log_level(struct bt_ctf_event_class *event_class,
+               enum bt_ctf_event_class_log_level log_level)
+{
+       return bt_event_class_common_set_log_level(BT_TO_COMMON(event_class),
+               log_level);
+}
+
+const char *bt_ctf_event_class_get_emf_uri(
+               struct bt_ctf_event_class *event_class)
+{
+       return bt_event_class_common_get_emf_uri(BT_TO_COMMON(event_class));
+}
+
+int bt_ctf_event_class_set_emf_uri(struct bt_ctf_event_class *event_class,
+               const char *emf_uri)
+{
+       return bt_event_class_common_set_emf_uri(BT_TO_COMMON(event_class),
+               emf_uri);
+}
+
+struct bt_ctf_stream_class *bt_ctf_event_class_get_stream_class(
+               struct bt_ctf_event_class *event_class)
+{
+       BT_ASSERT_PRE_NON_NULL(event_class, "Event class");
+       return bt_get(bt_event_class_common_borrow_stream_class(
+               BT_TO_COMMON(event_class)));
+}
+
+struct bt_ctf_field_type *bt_ctf_event_class_get_payload_field_type(
+               struct bt_ctf_event_class *event_class)
+{
+       return BT_FROM_COMMON(bt_event_class_common_get_payload_field_type(
+               BT_TO_COMMON(event_class)));
+}
+
+int bt_ctf_event_class_set_payload_field_type(
+               struct bt_ctf_event_class *event_class,
+               struct bt_ctf_field_type *field_type)
+{
+       return bt_event_class_common_set_payload_field_type(
+               BT_TO_COMMON(event_class), (void *) field_type);
+}
+
+struct bt_ctf_field_type *bt_ctf_event_class_get_context_field_type(
+               struct bt_ctf_event_class *event_class)
+{
+       return BT_FROM_COMMON(bt_event_class_common_get_context_field_type(
+               BT_TO_COMMON(event_class)));
+}
+
+int bt_ctf_event_class_set_context_field_type(
+               struct bt_ctf_event_class *event_class,
+               struct bt_ctf_field_type *field_type)
+{
+       return bt_event_class_common_set_context_field_type(
+               BT_TO_COMMON(event_class), (void *) field_type);
+}
+
+int bt_ctf_event_class_add_field(struct bt_ctf_event_class *event_class,
+               struct bt_ctf_field_type *type,
+               const char *name)
+{
+       int ret = 0;
+
+       if (!event_class || !type) {
+               BT_LOGW("Invalid parameter: event class or field type is NULL: "
+                       "event-class-addr=%p, field-type-addr=%p",
+                       event_class, type);
+               ret = -1;
+               goto end;
+       }
+
+       if (!bt_identifier_is_valid(name)) {
+               BT_LOGW("Invalid parameter: event class's payload field type's field name is not a valid CTF identifier: "
+                       "addr=%p, name=\"%s\", id=%" PRId64 ", field-name=\"%s\"",
+                       event_class, bt_ctf_event_class_get_name(event_class),
+                       bt_ctf_event_class_get_id(event_class),
+                       name);
+               ret = -1;
+               goto end;
+       }
+
+       if (event_class->common.frozen) {
+               BT_LOGW("Invalid parameter: event class is frozen: "
+                       "addr=%p, name=\"%s\", id=%" PRId64,
+                       event_class, bt_ctf_event_class_get_name(event_class),
+                       bt_ctf_event_class_get_id(event_class));
+               ret = -1;
+               goto end;
+       }
+
+       if (!event_class->common.payload_field_type) {
+               BT_LOGW("Event class has no payload field type: "
+                       "addr=%p, name=\"%s\", id=%" PRId64,
+                       event_class, bt_ctf_event_class_get_name(event_class),
+                       bt_ctf_event_class_get_id(event_class));
+               ret = -1;
+               goto end;
+       }
+
+       BT_ASSERT(bt_field_type_common_get_type_id(
+               event_class->common.payload_field_type) ==
+               BT_FIELD_TYPE_ID_STRUCT);
+       ret = bt_ctf_field_type_structure_add_field(
+               (void *) event_class->common.payload_field_type,
+               (void *) type, name);
+       BT_LOGV("Added field to event class's payload field type: "
+               "event-class-addr=%p, event-class-name=\"%s\", "
+               "event-class-id=%" PRId64 ", field-name=\"%s\", ft-addr=%p",
+               event_class, bt_ctf_event_class_get_name(event_class),
+               bt_ctf_event_class_get_id(event_class), name, type);
+end:
+       return ret;
+}
+
+int64_t bt_ctf_event_class_get_payload_type_field_count(
+               struct bt_ctf_event_class *event_class)
+{
+       int64_t ret;
+
+       if (!event_class) {
+               BT_LOGW_STR("Invalid parameter: event class is NULL.");
+               ret = (int64_t) -1;
+               goto end;
+       }
+
+       if (!event_class->common.payload_field_type) {
+               BT_LOGV("Event class has no payload field type: "
+                       "addr=%p, name=\"%s\", id=%" PRId64,
+                       event_class, bt_ctf_event_class_get_name(event_class),
+                       bt_ctf_event_class_get_id(event_class));
+               ret = (int64_t) -1;
+               goto end;
+       }
+
+       BT_ASSERT(bt_field_type_common_get_type_id(
+               event_class->common.payload_field_type) ==
+                       BT_FIELD_TYPE_ID_STRUCT);
+       ret = bt_field_type_common_structure_get_field_count(
+               event_class->common.payload_field_type);
+end:
+       return ret;
+}
+
+int bt_ctf_event_class_get_payload_type_field_by_index(
+               struct bt_ctf_event_class *event_class,
+               const char **field_name, struct bt_ctf_field_type **field_type,
+               uint64_t index)
+{
+       int ret;
+
+       if (!event_class) {
+               BT_LOGW_STR("Invalid parameter: event class is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       if (!event_class->common.payload_field_type) {
+               BT_LOGV("Event class has no payload field type: "
+                       "addr=%p, name=\"%s\", id=%" PRId64 ", index=%" PRIu64,
+                       event_class, bt_ctf_event_class_get_name(event_class),
+                       bt_ctf_event_class_get_id(event_class), index);
+               ret = -1;
+               goto end;
+       }
+
+       BT_ASSERT(bt_field_type_common_get_type_id(
+               event_class->common.payload_field_type) ==
+                       BT_FIELD_TYPE_ID_STRUCT);
+       ret = bt_ctf_field_type_structure_get_field_by_index(
+               (void *) event_class->common.payload_field_type,
+               field_name, (void *) field_type, index);
+
+end:
+       return ret;
+}
+
+struct bt_field_type *
+bt_ctf_event_class_get_payload_type_field_type_by_name(
+               struct bt_ctf_event_class *event_class, const char *name)
+{
+       GQuark name_quark;
+       struct bt_field_type *field_type = NULL;
+
+       if (!event_class || !name) {
+               BT_LOGW("Invalid parameter: event class or name is NULL: "
+                       "event-class-addr=%p, name-addr=%p",
+                       event_class, name);
+               goto end;
+       }
+
+       if (!event_class->common.payload_field_type) {
+               BT_LOGV("Event class has no payload field type: "
+                       "addr=%p, name=\"%s\", id=%" PRId64,
+                       event_class, bt_ctf_event_class_get_name(event_class),
+                       bt_ctf_event_class_get_id(event_class));
+               goto end;
+       }
+
+       BT_ASSERT(bt_field_type_common_get_type_id(
+               event_class->common.payload_field_type) ==
+                       BT_FIELD_TYPE_ID_STRUCT);
+       name_quark = g_quark_try_string(name);
+       if (!name_quark) {
+               BT_LOGE("Cannot get GQuark: string=\"%s\"", name);
+               goto end;
+       }
+
+       /*
+        * No need to increment field_type's reference count since getting it
+        * from the structure already does.
+        */
+       field_type = (void *)
+               bt_ctf_field_type_structure_get_field_type_by_name(
+                       (void *) event_class->common.payload_field_type, name);
+
+end:
+       return field_type;
+}
+
+BT_HIDDEN
+int bt_ctf_event_class_serialize(struct bt_ctf_event_class *event_class,
+               struct metadata_context *context)
+{
+       int ret = 0;
+       struct bt_value *attr_value = NULL;
+
+       BT_ASSERT(event_class);
+       BT_ASSERT(context);
+       BT_LOGD("Serializing event class's metadata: "
+               "event-class-addr=%p, event-class-name=\"%s\", "
+               "event-class-id=%" PRId64 ", metadata-context-addr=%p",
+               event_class, bt_ctf_event_class_get_name(event_class),
+               bt_ctf_event_class_get_id(event_class), context);
+       context->current_indentation_level = 1;
+       g_string_assign(context->field_name, "");
+       g_string_append(context->string, "event {\n");
+
+       /* Serialize attributes */
+       g_string_append_printf(context->string, "\tname = \"%s\";\n",
+               event_class->common.name->str);
+       BT_ASSERT(event_class->common.id >= 0);
+       g_string_append_printf(context->string, "\tid = %" PRId64 ";\n",
+               event_class->common.id);
+       g_string_append_printf(context->string, "\tstream_id = %" PRId64 ";\n",
+               bt_stream_class_common_get_id(
+                       bt_event_class_common_borrow_stream_class(
+                               BT_TO_COMMON(event_class))));
+
+       if (event_class->common.log_level !=
+                       BT_EVENT_CLASS_LOG_LEVEL_UNSPECIFIED) {
+               g_string_append_printf(context->string, "\tloglevel = %d;\n",
+                       (int) event_class->common.log_level);
+       }
+
+       if (event_class->common.emf_uri->len > 0) {
+               g_string_append_printf(context->string, "\tmodel.emf.uri = \"%s\";\n",
+                       event_class->common.emf_uri->str);
+       }
+
+       /* Serialize context field type */
+       if (event_class->common.context_field_type) {
+               g_string_append(context->string, "\tcontext := ");
+               BT_LOGD_STR("Serializing event class's context field type metadata.");
+               ret = bt_ctf_field_type_serialize_recursive(
+                       (void *) event_class->common.context_field_type,
+                       context);
+               if (ret) {
+                       BT_LOGW("Cannot serialize event class's context field type's metadata: "
+                               "ret=%d", ret);
+                       goto end;
+               }
+               g_string_append(context->string, ";\n");
+       }
+
+       /* Serialize payload field type */
+       if (event_class->common.payload_field_type) {
+               g_string_append(context->string, "\tfields := ");
+               BT_LOGD_STR("Serializing event class's payload field type metadata.");
+               ret = bt_ctf_field_type_serialize_recursive(
+                       (void *) event_class->common.payload_field_type,
+                       context);
+               if (ret) {
+                       BT_LOGW("Cannot serialize event class's payload field type's metadata: "
+                               "ret=%d", ret);
+                       goto end;
+               }
+               g_string_append(context->string, ";\n");
+       }
+
+       g_string_append(context->string, "};\n\n");
+
+end:
+       context->current_indentation_level = 0;
+       BT_PUT(attr_value);
+       return ret;
+}
+
+struct bt_ctf_field_type *bt_ctf_event_class_get_field_by_name(
+               struct bt_ctf_event_class *event_class, const char *name)
+{
+       GQuark name_quark;
+       struct bt_ctf_field_type *field_type = NULL;
+
+       if (!event_class || !name) {
+               BT_LOGW("Invalid parameter: event class or name is NULL: "
+                       "event-class-addr=%p, name-addr=%p",
+                       event_class, name);
+               goto end;
+       }
+
+       if (!event_class->common.payload_field_type) {
+               BT_LOGV("Event class has no payload field type: "
+                       "addr=%p, name=\"%s\", id=%" PRId64,
+                       event_class,
+                       bt_ctf_event_class_get_name(event_class),
+                       bt_ctf_event_class_get_id(event_class));
+               goto end;
+       }
+
+       BT_ASSERT(event_class->common.payload_field_type->id ==
+               BT_FIELD_TYPE_ID_STRUCT);
+       name_quark = g_quark_try_string(name);
+       if (!name_quark) {
+               BT_LOGE("Cannot get GQuark: string=\"%s\"", name);
+               goto end;
+       }
+
+       /*
+        * No need to increment field_type's reference count since getting it
+        * from the structure already does.
+        */
+       field_type = (void *) bt_field_type_common_structure_get_field_type_by_name(
+               event_class->common.payload_field_type, name);
+
+end:
+       return field_type;
+}
diff --git a/lib/ctf-writer/event.c b/lib/ctf-writer/event.c
new file mode 100644 (file)
index 0000000..3fff114
--- /dev/null
@@ -0,0 +1,262 @@
+/*
+ * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ * Copyright 2017-2018 Philippe Proulx <pproulx@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#define BT_LOG_TAG "CTF-WRITER-EVENT"
+#include <babeltrace/lib-logging-internal.h>
+
+#include <babeltrace/ctf-ir/event-internal.h>
+#include <babeltrace/ctf-writer/clock-internal.h>
+#include <babeltrace/ctf-writer/event-internal.h>
+#include <babeltrace/ctf-writer/event.h>
+#include <babeltrace/ctf-writer/fields-internal.h>
+#include <babeltrace/ctf-writer/field-types-internal.h>
+#include <babeltrace/ctf-writer/field-types.h>
+#include <babeltrace/ctf-writer/fields.h>
+#include <babeltrace/ctf-writer/stream-class-internal.h>
+#include <babeltrace/ctf-writer/stream-class.h>
+#include <babeltrace/ctf-writer/trace-internal.h>
+#include <babeltrace/ctf-writer/trace.h>
+#include <babeltrace/ref.h>
+#include <babeltrace/compiler-internal.h>
+#include <babeltrace/assert-internal.h>
+#include <babeltrace/assert-pre-internal.h>
+#include <inttypes.h>
+
+static
+void bt_ctf_event_destroy(struct bt_object *obj);
+
+static
+int map_clock_classes_func(struct bt_stream_class_common *stream_class,
+               struct bt_field_type_common *packet_context_type,
+               struct bt_field_type_common *event_header_type)
+{
+       int ret = bt_ctf_stream_class_map_clock_class(
+               BT_FROM_COMMON(stream_class),
+               BT_FROM_COMMON(packet_context_type),
+               BT_FROM_COMMON(event_header_type));
+
+       if (ret) {
+               BT_LOGW_STR("Cannot automatically map selected stream class's field types to stream class's clock's class.");
+       }
+
+       return ret;
+}
+
+struct bt_ctf_event *bt_ctf_event_create(struct bt_ctf_event_class *event_class)
+{
+       int ret;
+       struct bt_ctf_event *event = NULL;
+       struct bt_clock_class *expected_clock_class = NULL;
+
+       event = g_new0(struct bt_ctf_event, 1);
+       if (!event) {
+               BT_LOGE_STR("Failed to allocate one CTF writer event.");
+               goto error;
+       }
+
+       if (event_class) {
+               struct bt_ctf_stream_class *stream_class =
+                       BT_FROM_COMMON(bt_event_class_common_borrow_stream_class(
+                               BT_TO_COMMON(event_class)));
+
+               if (stream_class && stream_class->clock) {
+                       expected_clock_class = BT_TO_COMMON(
+                               stream_class->clock->clock_class);
+               }
+       }
+
+       ret = bt_event_common_initialize(BT_TO_COMMON(event),
+               BT_TO_COMMON(event_class), expected_clock_class,
+               bt_ctf_event_destroy,
+               (bt_validation_flag_copy_field_type_func)
+                       bt_ctf_field_type_copy,
+               false, map_clock_classes_func,
+               (void *) bt_ctf_field_create);
+       if (ret) {
+               /* bt_event_common_initialize() logs errors */
+               goto error;
+       }
+
+       goto end;
+
+error:
+       BT_PUT(event);
+
+end:
+       return event;
+}
+
+struct bt_ctf_event_class *bt_ctf_event_get_class(struct bt_ctf_event *event)
+{
+       BT_ASSERT_PRE_NON_NULL(event, "Event");
+       return bt_get(bt_event_common_borrow_class(BT_TO_COMMON(event)));
+}
+
+BT_HIDDEN
+struct bt_ctf_stream *bt_ctf_event_borrow_stream(struct bt_ctf_event *event)
+{
+       BT_ASSERT(event);
+       return (struct bt_ctf_stream *)
+               bt_object_borrow_parent(BT_TO_COMMON(event));
+}
+
+struct bt_ctf_stream *bt_ctf_event_get_stream(struct bt_ctf_event *event)
+{
+       BT_ASSERT_PRE_NON_NULL(event, "Event");
+       return bt_get(bt_ctf_event_borrow_stream(event));
+}
+
+int bt_ctf_event_set_payload(struct bt_ctf_event *event, const char *name,
+               struct bt_ctf_field *field)
+{
+       BT_ASSERT_PRE_NON_NULL(event, "Event");
+       BT_ASSERT_PRE_NON_NULL(field, "Payload field");
+       BT_ASSERT_PRE_EVENT_COMMON_HOT(BT_TO_COMMON(event), "Event");
+       return bt_ctf_field_structure_set_field_by_name(
+               BT_FROM_COMMON(event->common.payload_field), name, field);
+}
+
+struct bt_ctf_field *bt_ctf_event_get_payload(struct bt_ctf_event *event,
+               const char *name)
+{
+       struct bt_ctf_field *field = NULL;
+
+       BT_ASSERT_PRE_NON_NULL(event, "Event");
+
+       if (name) {
+               field = bt_ctf_field_structure_get_field_by_name(
+                       BT_FROM_COMMON(event->common.payload_field), name);
+       } else {
+               field = BT_FROM_COMMON(event->common.payload_field);
+               bt_get(field);
+       }
+
+       return field;
+}
+
+struct bt_ctf_field *bt_ctf_event_get_payload_field(
+               struct bt_ctf_event *event)
+{
+       return (void *) bt_event_common_get_payload(BT_TO_COMMON(event));
+}
+
+int bt_ctf_event_set_payload_field(struct bt_ctf_event *event,
+               struct bt_ctf_field *field)
+{
+       return bt_event_common_set_payload(BT_TO_COMMON(event), (void *) field);
+}
+
+struct bt_ctf_field *bt_ctf_event_get_header(struct bt_ctf_event *event)
+{
+       return BT_FROM_COMMON(bt_event_common_get_header(BT_TO_COMMON(event)));
+}
+
+int bt_ctf_event_set_header(struct bt_ctf_event *event,
+               struct bt_ctf_field *field)
+{
+       return bt_event_common_set_header(BT_TO_COMMON(event), (void *) field);
+}
+
+struct bt_ctf_field *bt_ctf_event_get_context(struct bt_ctf_event *event)
+{
+       return BT_FROM_COMMON(bt_event_common_get_context(BT_TO_COMMON(event)));
+}
+
+int bt_ctf_event_set_context(struct bt_ctf_event *event,
+               struct bt_ctf_field *field)
+{
+       return bt_event_common_set_context(BT_TO_COMMON(event), (void *) field);
+}
+
+struct bt_ctf_field *bt_ctf_event_get_stream_event_context(
+               struct bt_ctf_event *event)
+{
+       return BT_FROM_COMMON(bt_event_common_get_stream_event_context(
+               BT_TO_COMMON(event)));
+}
+
+int bt_ctf_event_set_stream_event_context(struct bt_ctf_event *event,
+               struct bt_ctf_field *field)
+{
+       return bt_event_common_set_stream_event_context(
+               BT_TO_COMMON(event), (void *) field);
+}
+
+static
+void bt_ctf_event_destroy(struct bt_object *obj)
+{
+       bt_event_common_finalize(obj);
+       g_free(obj);
+}
+
+BT_HIDDEN
+int bt_ctf_event_serialize(struct bt_ctf_event *event,
+               struct bt_ctf_stream_pos *pos,
+               enum bt_ctf_byte_order native_byte_order)
+{
+       int ret = 0;
+
+       BT_ASSERT(event);
+       BT_ASSERT(pos);
+
+       BT_LOGV_STR("Serializing event's context field.");
+       if (event->common.context_field) {
+               ret = bt_ctf_field_serialize_recursive(
+                       (void *) event->common.context_field, pos,
+                       native_byte_order);
+               if (ret) {
+                       BT_LOGW("Cannot serialize event's context field: "
+                               "event-addr=%p, event-class-name=\"%s\", "
+                               "event-class-id=%" PRId64,
+                               event,
+                               bt_event_class_common_get_name(event->common.class),
+                               bt_event_class_common_get_id(event->common.class));
+                       goto end;
+               }
+       }
+
+       BT_LOGV_STR("Serializing event's payload field.");
+       if (event->common.payload_field) {
+               ret = bt_ctf_field_serialize_recursive(
+                       (void *) event->common.payload_field, pos,
+                       native_byte_order);
+               if (ret) {
+                       BT_LOGW("Cannot serialize event's payload field: "
+                               "event-addr=%p, event-class-name=\"%s\", "
+                               "event-class-id=%" PRId64,
+                               event,
+                               bt_event_class_common_get_name(event->common.class),
+                               bt_event_class_common_get_id(event->common.class));
+                       goto end;
+               }
+       }
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+void _bt_ctf_event_freeze(struct bt_ctf_event *event)
+{
+       _bt_event_common_freeze(BT_TO_COMMON(event));
+}
diff --git a/lib/ctf-writer/field-types.c b/lib/ctf-writer/field-types.c
new file mode 100644 (file)
index 0000000..4990e2c
--- /dev/null
@@ -0,0 +1,1533 @@
+/*
+ * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#define BT_LOG_TAG "CTF-WRITER-FIELD-TYPES"
+#include <babeltrace/lib-logging-internal.h>
+
+#include <babeltrace/assert-pre-internal.h>
+#include <babeltrace/ctf-ir/field-types-internal.h>
+#include <babeltrace/ctf-ir/utils-internal.h>
+#include <babeltrace/ctf-ir/utils.h>
+#include <babeltrace/ctf-ir/field-path-internal.h>
+#include <babeltrace/ctf-writer/field-types.h>
+#include <babeltrace/ctf-writer/field-types-internal.h>
+#include <babeltrace/ctf-writer/fields.h>
+#include <babeltrace/ctf-writer/clock-internal.h>
+#include <babeltrace/object-internal.h>
+#include <babeltrace/ref.h>
+#include <babeltrace/compiler-internal.h>
+#include <babeltrace/endian-internal.h>
+#include <babeltrace/assert-internal.h>
+#include <float.h>
+#include <inttypes.h>
+#include <stdlib.h>
+
+static
+struct bt_ctf_field_type *bt_ctf_field_type_integer_copy(
+               struct bt_ctf_field_type *ft);
+
+static
+struct bt_ctf_field_type *bt_ctf_field_type_enumeration_copy_recursive(
+               struct bt_ctf_field_type *ft);
+
+static
+struct bt_ctf_field_type *bt_ctf_field_type_floating_point_copy(
+               struct bt_ctf_field_type *ft);
+
+static
+struct bt_ctf_field_type *bt_ctf_field_type_structure_copy_recursive(
+               struct bt_ctf_field_type *ft);
+
+static
+struct bt_ctf_field_type *bt_ctf_field_type_variant_copy_recursive(
+               struct bt_ctf_field_type *ft);
+
+static
+struct bt_ctf_field_type *bt_ctf_field_type_array_copy_recursive(
+               struct bt_ctf_field_type *ft);
+
+static
+struct bt_ctf_field_type *bt_ctf_field_type_sequence_copy_recursive(
+               struct bt_ctf_field_type *type);
+
+static
+struct bt_ctf_field_type *bt_ctf_field_type_string_copy(
+               struct bt_ctf_field_type *type);
+
+static struct bt_field_type_common_methods bt_ctf_field_type_integer_methods = {
+       .freeze = bt_field_type_common_generic_freeze,
+       .validate = bt_field_type_common_integer_validate,
+       .set_byte_order = bt_field_type_common_integer_set_byte_order,
+       .copy = (bt_field_type_common_method_copy)
+               bt_ctf_field_type_integer_copy,
+       .compare = bt_field_type_common_integer_compare,
+};
+
+static struct bt_field_type_common_methods bt_ctf_field_type_floating_point_methods = {
+       .freeze = bt_field_type_common_generic_freeze,
+       .validate = NULL,
+       .set_byte_order = bt_field_type_common_floating_point_set_byte_order,
+       .copy = (bt_field_type_common_method_copy)
+               bt_ctf_field_type_floating_point_copy,
+       .compare = bt_field_type_common_floating_point_compare,
+};
+
+static struct bt_field_type_common_methods bt_ctf_field_type_enumeration_methods = {
+       .freeze = bt_field_type_common_enumeration_freeze_recursive,
+       .validate = bt_field_type_common_enumeration_validate_recursive,
+       .set_byte_order = bt_field_type_common_enumeration_set_byte_order_recursive,
+       .copy = (bt_field_type_common_method_copy)
+               bt_ctf_field_type_enumeration_copy_recursive,
+       .compare = bt_field_type_common_enumeration_compare_recursive,
+};
+
+static struct bt_field_type_common_methods bt_ctf_field_type_string_methods = {
+       .freeze = bt_field_type_common_generic_freeze,
+       .validate = NULL,
+       .set_byte_order = NULL,
+       .copy = (bt_field_type_common_method_copy)
+               bt_ctf_field_type_string_copy,
+       .compare = bt_field_type_common_string_compare,
+};
+
+static struct bt_field_type_common_methods bt_ctf_field_type_array_methods = {
+       .freeze = bt_field_type_common_array_freeze_recursive,
+       .validate = bt_field_type_common_array_validate_recursive,
+       .set_byte_order = bt_field_type_common_array_set_byte_order_recursive,
+       .copy = (bt_field_type_common_method_copy)
+               bt_ctf_field_type_array_copy_recursive,
+       .compare = bt_field_type_common_array_compare_recursive,
+};
+
+static struct bt_field_type_common_methods bt_ctf_field_type_sequence_methods = {
+       .freeze = bt_field_type_common_sequence_freeze_recursive,
+       .validate = bt_field_type_common_sequence_validate_recursive,
+       .set_byte_order = bt_field_type_common_sequence_set_byte_order_recursive,
+       .copy = (bt_field_type_common_method_copy)
+               bt_ctf_field_type_sequence_copy_recursive,
+       .compare = bt_field_type_common_sequence_compare_recursive,
+};
+
+static struct bt_field_type_common_methods bt_ctf_field_type_structure_methods = {
+       .freeze = bt_field_type_common_structure_freeze_recursive,
+       .validate = bt_field_type_common_structure_validate_recursive,
+       .set_byte_order = bt_field_type_common_structure_set_byte_order_recursive,
+       .copy = (bt_field_type_common_method_copy)
+               bt_ctf_field_type_structure_copy_recursive,
+       .compare = bt_field_type_common_structure_compare_recursive,
+};
+
+static struct bt_field_type_common_methods bt_ctf_field_type_variant_methods = {
+       .freeze = bt_field_type_common_variant_freeze_recursive,
+       .validate = bt_field_type_common_variant_validate_recursive,
+       .set_byte_order = bt_field_type_common_variant_set_byte_order_recursive,
+       .copy = (bt_field_type_common_method_copy)
+               bt_ctf_field_type_variant_copy_recursive,
+       .compare = bt_field_type_common_variant_compare_recursive,
+};
+
+typedef int (*bt_ctf_field_type_serialize_func)(struct bt_field_type_common *,
+               struct metadata_context *);
+
+BT_HIDDEN
+int bt_ctf_field_type_serialize_recursive(struct bt_ctf_field_type *type,
+               struct metadata_context *context)
+{
+       int ret;
+       struct bt_field_type_common *type_common = (void *) type;
+       bt_ctf_field_type_serialize_func serialize_func;
+
+       BT_ASSERT(type);
+       BT_ASSERT(context);
+
+       /* Make sure field type is valid before serializing it */
+       ret = bt_field_type_common_validate((void *) type);
+       if (ret) {
+               BT_LOGW("Cannot serialize field type's metadata: field type is invalid: "
+                       "addr=%p", type);
+               goto end;
+       }
+
+       serialize_func = type_common->spec.writer.serialize_func;
+       ret = serialize_func((void *) type, context);
+
+end:
+       return ret;
+}
+
+static
+const char *get_encoding_string(enum bt_string_encoding encoding)
+{
+       const char *encoding_string;
+
+       switch (encoding) {
+       case BT_STRING_ENCODING_NONE:
+               encoding_string = "none";
+               break;
+       case BT_STRING_ENCODING_ASCII:
+               encoding_string = "ASCII";
+               break;
+       case BT_STRING_ENCODING_UTF8:
+               encoding_string = "UTF8";
+               break;
+       default:
+               encoding_string = "unknown";
+               break;
+       }
+
+       return encoding_string;
+}
+
+static
+const char *get_integer_base_string(enum bt_integer_base base)
+{
+       const char *base_string;
+
+       switch (base) {
+       case BT_INTEGER_BASE_DECIMAL:
+       case BT_INTEGER_BASE_UNSPECIFIED:
+               base_string = "decimal";
+               break;
+       case BT_INTEGER_BASE_HEXADECIMAL:
+               base_string = "hexadecimal";
+               break;
+       case BT_INTEGER_BASE_OCTAL:
+               base_string = "octal";
+               break;
+       case BT_INTEGER_BASE_BINARY:
+               base_string = "binary";
+               break;
+       default:
+               base_string = "unknown";
+               break;
+       }
+
+       return base_string;
+}
+
+static
+void append_field_name(struct metadata_context *context,
+               const char *name)
+{
+       g_string_append_c(context->string, ' ');
+
+       if (!bt_identifier_is_valid(name) || *name == '_') {
+               g_string_append_c(context->string, '_');
+       }
+
+       g_string_append(context->string, name);
+}
+
+static
+int bt_ctf_field_type_integer_serialize(struct bt_field_type_common *type,
+               struct metadata_context *context)
+{
+       struct bt_field_type_common_integer *integer = BT_FROM_COMMON(type);
+       int ret = 0;
+
+       BT_LOGD("Serializing CTF writer integer field type's metadata: "
+               "ft-addr=%p, metadata-context-addr=%p", type, context);
+       g_string_append_printf(context->string,
+               "integer { size = %u; align = %u; signed = %s; encoding = %s; base = %s; byte_order = %s",
+               integer->size, type->alignment,
+               (integer->is_signed ? "true" : "false"),
+               get_encoding_string(integer->encoding),
+               get_integer_base_string(integer->base),
+               get_byte_order_string(integer->user_byte_order));
+       if (integer->mapped_clock_class) {
+               const char *clock_name = bt_clock_class_get_name(
+                       integer->mapped_clock_class);
+
+               BT_ASSERT(clock_name);
+               g_string_append_printf(context->string,
+                       "; map = clock.%s.value", clock_name);
+       }
+
+       g_string_append(context->string, "; }");
+       return ret;
+}
+
+static
+int bt_ctf_field_type_enumeration_serialize_recursive(
+               struct bt_field_type_common *type,
+               struct metadata_context *context)
+{
+       size_t entry;
+       int ret;
+       struct bt_field_type_common_enumeration *enumeration =
+               BT_FROM_COMMON(type);
+       struct bt_field_type_common *container_type;
+       int container_signed;
+
+       BT_LOGD("Serializing CTF writer enumeration field type's metadata: "
+               "ft-addr=%p, metadata-context-addr=%p", type, context);
+       container_type =
+               bt_field_type_common_enumeration_get_container_field_type(type);
+       BT_ASSERT(container_type);
+       container_signed = bt_field_type_common_integer_is_signed(
+               container_type);
+       BT_ASSERT(container_signed >= 0);
+       g_string_append(context->string, "enum : ");
+       BT_LOGD_STR("Serializing CTF writer enumeration field type's container field type's metadata.");
+       ret = bt_ctf_field_type_serialize_recursive(
+               (void *) enumeration->container_ft, context);
+       if (ret) {
+               BT_LOGW("Cannot serialize CTF writer enumeration field type's container field type's metadata: "
+                       "container-ft-addr=%p", enumeration->container_ft);
+               goto end;
+       }
+
+       g_string_append(context->string, " { ");
+       for (entry = 0; entry < enumeration->entries->len; entry++) {
+               struct enumeration_mapping *mapping =
+                       enumeration->entries->pdata[entry];
+               const char *label = g_quark_to_string(mapping->string);
+
+               g_string_append(context->string, "\"");
+
+               if (!bt_identifier_is_valid(label) || label[0] == '_') {
+                       g_string_append(context->string, "_");
+               }
+
+               g_string_append_printf(context->string, "%s\" = ", label);
+
+               if (container_signed) {
+                       if (mapping->range_start._signed ==
+                               mapping->range_end._signed) {
+                               g_string_append_printf(context->string,
+                                       "%" PRId64,
+                                       mapping->range_start._signed);
+                       } else {
+                               g_string_append_printf(context->string,
+                                       "%" PRId64 " ... %" PRId64,
+                                       mapping->range_start._signed,
+                                       mapping->range_end._signed);
+                       }
+               } else {
+                       if (mapping->range_start._unsigned ==
+                               mapping->range_end._unsigned) {
+                               g_string_append_printf(context->string,
+                                       "%" PRIu64,
+                                       mapping->range_start._unsigned);
+                       } else {
+                               g_string_append_printf(context->string,
+                                       "%" PRIu64 " ... %" PRIu64,
+                                       mapping->range_start._unsigned,
+                                       mapping->range_end._unsigned);
+                       }
+               }
+
+               g_string_append(context->string,
+                       ((entry != (enumeration->entries->len - 1)) ?
+                       ", " : " }"));
+       }
+
+       if (context->field_name->len) {
+               append_field_name(context,
+                       context->field_name->str);
+               g_string_assign(context->field_name, "");
+       }
+
+end:
+       bt_put(container_type);
+       return ret;
+}
+
+static
+int bt_ctf_field_type_floating_point_serialize(struct bt_field_type_common *type,
+               struct metadata_context *context)
+{
+       struct bt_field_type_common_floating_point *floating_point =
+               BT_FROM_COMMON(type);
+
+       BT_LOGD("Serializing CTF writer floating point number field type's metadata: "
+               "ft-addr=%p, metadata-context-addr=%p", type, context);
+       g_string_append_printf(context->string,
+               "floating_point { exp_dig = %u; mant_dig = %u; byte_order = %s; align = %u; }",
+               floating_point->exp_dig,
+               floating_point->mant_dig,
+               get_byte_order_string(floating_point->user_byte_order),
+               type->alignment);
+       return 0;
+}
+
+static
+int bt_ctf_field_type_structure_serialize_recursive(
+               struct bt_field_type_common *type,
+               struct metadata_context *context)
+{
+       size_t i;
+       unsigned int indent;
+       int ret = 0;
+       struct bt_field_type_common_structure *structure = BT_FROM_COMMON(type);
+       GString *structure_field_name = context->field_name;
+
+       BT_LOGD("Serializing CTF writer structure field type's metadata: "
+               "ft-addr=%p, metadata-context-addr=%p", type, context);
+       context->field_name = g_string_new("");
+
+       context->current_indentation_level++;
+       g_string_append(context->string, "struct {\n");
+
+       for (i = 0; i < structure->fields->len; i++) {
+               struct structure_field_common *field = structure->fields->pdata[i];
+
+               BT_LOGD("Serializing CTF writer structure field type's field metadata: "
+                       "index=%zu, "
+                       "field-ft-addr=%p, field-name=\"%s\"",
+                       i, field, g_quark_to_string(field->name));
+
+               for (indent = 0; indent < context->current_indentation_level;
+                       indent++) {
+                       g_string_append_c(context->string, '\t');
+               }
+
+               g_string_assign(context->field_name,
+                       g_quark_to_string(field->name));
+               ret = bt_ctf_field_type_serialize_recursive(
+                       (void *) field->type, context);
+               if (ret) {
+                       BT_LOGW("Cannot serialize CTF writer structure field type's field's metadata: "
+                               "index=%zu, "
+                               "field-ft-addr=%p, field-name=\"%s\"",
+                               i, field->type,
+                               g_quark_to_string(field->name));
+                       goto end;
+               }
+
+               if (context->field_name->len) {
+                       append_field_name(context,
+                               context->field_name->str);
+               }
+               g_string_append(context->string, ";\n");
+       }
+
+       context->current_indentation_level--;
+       for (indent = 0; indent < context->current_indentation_level;
+               indent++) {
+               g_string_append_c(context->string, '\t');
+       }
+
+       g_string_append_printf(context->string, "} align(%u)",
+                type->alignment);
+
+end:
+       g_string_free(context->field_name, TRUE);
+       context->field_name = structure_field_name;
+       return ret;
+}
+
+static
+int bt_ctf_field_type_variant_serialize_recursive(
+               struct bt_field_type_common *type,
+               struct metadata_context *context)
+{
+       size_t i;
+       unsigned int indent;
+       int ret = 0;
+       struct bt_field_type_common_variant *variant = BT_FROM_COMMON(type);
+       GString *variant_field_name = context->field_name;
+
+       BT_LOGD("Serializing CTF writer variant field type's metadata: "
+               "ft-addr=%p, metadata-context-addr=%p", type, context);
+       context->field_name = g_string_new("");
+       if (variant->tag_name->len > 0) {
+               g_string_append(context->string, "variant <");
+               append_field_name(context, variant->tag_name->str);
+               g_string_append(context->string, "> {\n");
+       } else {
+               g_string_append(context->string, "variant {\n");
+       }
+
+       context->current_indentation_level++;
+       for (i = 0; i < variant->fields->len; i++) {
+               struct structure_field_common *field =
+                       variant->fields->pdata[i];
+
+               BT_LOGD("Serializing CTF writer variant field type's field metadata: "
+                       "index=%zu, "
+                       "field-ft-addr=%p, field-name=\"%s\"",
+                       i, field, g_quark_to_string(field->name));
+
+               g_string_assign(context->field_name,
+                       g_quark_to_string(field->name));
+               for (indent = 0; indent < context->current_indentation_level;
+                       indent++) {
+                       g_string_append_c(context->string, '\t');
+               }
+
+               g_string_assign(context->field_name,
+                       g_quark_to_string(field->name));
+               ret = bt_ctf_field_type_serialize_recursive(
+                       (void *) field->type, context);
+               if (ret) {
+                       BT_LOGW("Cannot serialize CTF writer variant field type's field's metadata: "
+                               "index=%zu, "
+                               "field-ft-addr=%p, field-name=\"%s\"",
+                               i, field->type,
+                               g_quark_to_string(field->name));
+                       goto end;
+               }
+
+               if (context->field_name->len) {
+                       append_field_name(context,
+                               context->field_name->str);
+                       g_string_append_c(context->string, ';');
+               }
+
+               g_string_append_c(context->string, '\n');
+       }
+
+       context->current_indentation_level--;
+       for (indent = 0; indent < context->current_indentation_level;
+               indent++) {
+               g_string_append_c(context->string, '\t');
+       }
+
+       g_string_append(context->string, "}");
+
+end:
+       g_string_free(context->field_name, TRUE);
+       context->field_name = variant_field_name;
+       return ret;
+}
+
+static
+int bt_ctf_field_type_array_serialize_recursive(
+               struct bt_field_type_common *type,
+               struct metadata_context *context)
+{
+       int ret = 0;
+       struct bt_field_type_common_array *array = BT_FROM_COMMON(type);
+
+       BT_LOGD("Serializing CTF writer array field type's metadata: "
+               "ft-addr=%p, metadata-context-addr=%p", type, context);
+       BT_LOGD_STR("Serializing CTF writer array field type's element field type's metadata.");
+       ret = bt_ctf_field_type_serialize_recursive(
+               (void *) array->element_ft, context);
+       if (ret) {
+               BT_LOGW("Cannot serialize CTF writer array field type's element field type's metadata: "
+                       "element-ft-addr=%p", array->element_ft);
+               goto end;
+       }
+
+       if (context->field_name->len) {
+               append_field_name(context,
+                       context->field_name->str);
+
+               g_string_append_printf(context->string, "[%u]", array->length);
+               g_string_assign(context->field_name, "");
+       } else {
+               g_string_append_printf(context->string, "[%u]", array->length);
+       }
+
+end:
+       return ret;
+}
+
+static
+int bt_ctf_field_type_sequence_serialize_recursive(
+               struct bt_field_type_common *type,
+               struct metadata_context *context)
+{
+       int ret = 0;
+       struct bt_field_type_common_sequence *sequence = BT_FROM_COMMON(type);
+
+       BT_LOGD("Serializing CTF writer sequence field type's metadata: "
+               "ft-addr=%p, metadata-context-addr=%p", type, context);
+       BT_LOGD_STR("Serializing CTF writer sequence field type's element field type's metadata.");
+       ret = bt_ctf_field_type_serialize_recursive(
+               (void *) sequence->element_ft, context);
+       if (ret) {
+               BT_LOGW("Cannot serialize CTF writer sequence field type's element field type's metadata: "
+                       "element-ft-addr=%p", sequence->element_ft);
+               goto end;
+       }
+
+       if (context->field_name->len) {
+               append_field_name(context, context->field_name->str);
+               g_string_assign(context->field_name, "");
+       }
+       g_string_append(context->string, "[");
+       append_field_name(context, sequence->length_field_name->str);
+       g_string_append(context->string, "]");
+
+end:
+       return ret;
+}
+
+static
+int bt_ctf_field_type_string_serialize(struct bt_field_type_common *type,
+               struct metadata_context *context)
+{
+       struct bt_field_type_common_string *string = BT_FROM_COMMON(type);
+
+       BT_LOGD("Serializing CTF writer string field type's metadata: "
+               "ft-addr=%p, metadata-context-addr=%p", type, context);
+       g_string_append_printf(context->string,
+               "string { encoding = %s; }",
+               get_encoding_string(string->encoding));
+       return 0;
+}
+
+struct bt_ctf_field_type *bt_ctf_field_type_integer_create(unsigned int size)
+{
+       struct bt_field_type_common_integer *integer = NULL;
+
+       BT_LOGD("Creating CTF writer integer field type object: size=%u", size);
+
+       if (size == 0 || size > 64) {
+               BT_LOGW("Invalid parameter: size must be between 1 and 64: "
+                       "size=%u", size);
+               goto error;
+       }
+
+       integer = g_new0(struct bt_field_type_common_integer, 1);
+       if (!integer) {
+               BT_LOGE_STR("Failed to allocate one integer field type.");
+               goto error;
+       }
+
+       bt_field_type_common_integer_initialize(BT_TO_COMMON(integer),
+               size, bt_field_type_common_integer_destroy,
+               &bt_ctf_field_type_integer_methods);
+       integer->common.spec.writer.serialize_func =
+               bt_ctf_field_type_integer_serialize;
+       BT_LOGD("Created CTF writer integer field type object: addr=%p, size=%u",
+               integer, size);
+       goto end;
+
+error:
+       BT_PUT(integer);
+
+end:
+       return (void *) integer;
+}
+
+int bt_ctf_field_type_integer_get_size(struct bt_ctf_field_type *ft)
+{
+       return bt_field_type_common_integer_get_size((void *) ft);
+}
+
+bt_bool bt_ctf_field_type_integer_is_signed(struct bt_ctf_field_type *ft)
+{
+       return bt_field_type_common_integer_is_signed((void *) ft);
+}
+
+int bt_ctf_field_type_integer_set_is_signed(struct bt_ctf_field_type *ft,
+               bt_bool is_signed)
+{
+       return bt_field_type_common_integer_set_is_signed((void *) ft,
+               is_signed);
+}
+
+int bt_ctf_field_type_integer_set_size(struct bt_ctf_field_type *ft,
+               unsigned int size)
+{
+       return bt_field_type_common_integer_set_size((void *) ft, size);
+}
+
+enum bt_ctf_integer_base bt_ctf_field_type_integer_get_base(
+               struct bt_ctf_field_type *ft)
+{
+       return (int) bt_field_type_common_integer_get_base((void *) ft);
+}
+
+int bt_ctf_field_type_integer_set_base(struct bt_ctf_field_type *ft,
+               enum bt_ctf_integer_base base)
+{
+       return bt_field_type_common_integer_set_base((void *) ft,
+               (int) base);
+}
+
+enum bt_ctf_string_encoding bt_ctf_field_type_integer_get_encoding(
+               struct bt_ctf_field_type *ft)
+{
+       return (int) bt_field_type_common_integer_get_encoding((void *) ft);
+}
+
+int bt_ctf_field_type_integer_set_encoding(struct bt_ctf_field_type *ft,
+               enum bt_ctf_string_encoding encoding)
+{
+       return bt_field_type_common_integer_set_encoding((void *) ft,
+               (int) encoding);
+}
+
+struct bt_ctf_clock_class *bt_ctf_field_type_integer_get_mapped_clock_class(
+               struct bt_ctf_field_type *ft)
+{
+       return BT_FROM_COMMON(
+               bt_field_type_common_integer_get_mapped_clock_class((void *) ft));
+}
+
+int bt_ctf_field_type_integer_set_mapped_clock_class(
+               struct bt_ctf_field_type *ft,
+               struct bt_ctf_clock_class *clock_class)
+{
+       return bt_field_type_common_integer_set_mapped_clock_class((void *) ft,
+               BT_TO_COMMON(clock_class));
+}
+
+int bt_ctf_field_type_enumeration_signed_get_mapping_by_index(
+               struct bt_ctf_field_type *ft, uint64_t index,
+               const char **mapping_name, int64_t *range_begin,
+               int64_t *range_end)
+{
+       return bt_field_type_common_enumeration_signed_get_mapping_by_index(
+               (void *) ft, index, mapping_name, range_begin, range_end);
+}
+
+int bt_ctf_field_type_enumeration_unsigned_get_mapping_by_index(
+               struct bt_ctf_field_type *ft, uint64_t index,
+               const char **mapping_name, uint64_t *range_begin,
+               uint64_t *range_end)
+{
+       return bt_field_type_common_enumeration_unsigned_get_mapping_by_index(
+               (void *) ft, index, mapping_name, range_begin, range_end);
+}
+
+struct bt_ctf_field_type *bt_ctf_field_type_enumeration_create(
+               struct bt_ctf_field_type *container_ft)
+{
+       struct bt_field_type_common_enumeration *enumeration = NULL;
+       struct bt_field_type_common *int_ft = (void *) container_ft;
+
+       BT_LOGD("Creating CTF writer enumeration field type object: int-ft-addr=%p",
+               container_ft);
+
+       if (!container_ft) {
+               BT_LOGW_STR("Invalid parameter: field type is NULL.");
+               goto error;
+       }
+
+       if (int_ft->id != BT_FIELD_TYPE_ID_INTEGER) {
+               BT_LOGW("Invalid parameter: container field type is not an integer field type: "
+                       "container-ft-addr=%p, container-ft-id=%s",
+                       container_ft, bt_common_field_type_id_string(int_ft->id));
+               goto error;
+       }
+
+       enumeration = g_new0(struct bt_field_type_common_enumeration, 1);
+       if (!enumeration) {
+               BT_LOGE_STR("Failed to allocate one enumeration field type.");
+               goto error;
+       }
+
+       bt_field_type_common_enumeration_initialize(BT_TO_COMMON(enumeration),
+               int_ft, bt_field_type_common_enumeration_destroy_recursive,
+               &bt_ctf_field_type_enumeration_methods);
+       enumeration->common.spec.writer.serialize_func =
+               bt_ctf_field_type_enumeration_serialize_recursive;
+       BT_LOGD("Created CTF writer enumeration field type object: addr=%p, "
+               "int-ft-addr=%p, int-ft-size=%u",
+               enumeration, container_ft,
+               bt_ctf_field_type_integer_get_size(container_ft));
+       goto end;
+
+error:
+       BT_PUT(enumeration);
+
+end:
+       return (void *) enumeration;
+}
+
+struct bt_ctf_field_type *bt_ctf_field_type_enumeration_get_container_field_type(
+               struct bt_ctf_field_type *ft)
+{
+       return (void *) bt_field_type_common_enumeration_get_container_field_type(
+               (void *) ft);
+}
+
+int bt_ctf_field_type_enumeration_signed_add_mapping(
+               struct bt_ctf_field_type *ft, const char *string,
+               int64_t range_start, int64_t range_end)
+{
+       return bt_field_type_common_enumeration_signed_add_mapping(
+               (void *) ft, string, range_start, range_end);
+}
+
+int bt_ctf_field_type_enumeration_unsigned_add_mapping(
+               struct bt_ctf_field_type *ft, const char *string,
+               uint64_t range_start, uint64_t range_end)
+{
+       return bt_field_type_common_enumeration_unsigned_add_mapping(
+               (void *) ft, string, range_start, range_end);
+}
+
+int64_t bt_ctf_field_type_enumeration_get_mapping_count(
+               struct bt_ctf_field_type *ft)
+{
+       return bt_field_type_common_enumeration_get_mapping_count((void *) ft);
+}
+
+struct bt_ctf_field_type *bt_ctf_field_type_floating_point_create(void)
+{
+       struct bt_field_type_common_floating_point *floating_point =
+               g_new0(struct bt_field_type_common_floating_point, 1);
+
+       BT_LOGD_STR("Creating CTF writer floating point number field type object.");
+
+       if (!floating_point) {
+               BT_LOGE_STR("Failed to allocate one floating point number field type.");
+               goto end;
+       }
+
+       bt_field_type_common_floating_point_initialize(
+               BT_TO_COMMON(floating_point),
+               bt_field_type_common_floating_point_destroy,
+               &bt_ctf_field_type_floating_point_methods);
+       floating_point->common.spec.writer.serialize_func =
+               bt_ctf_field_type_floating_point_serialize;
+       BT_LOGD("Created CTF writer floating point number field type object: addr=%p, "
+               "exp-size=%u, mant-size=%u", floating_point,
+               floating_point->exp_dig, floating_point->mant_dig);
+
+end:
+       return (void *) floating_point;
+}
+
+int bt_ctf_field_type_floating_point_get_exponent_digits(
+               struct bt_ctf_field_type *ft)
+{
+       return bt_field_type_common_floating_point_get_exponent_digits(
+               (void *) ft);
+}
+
+int bt_ctf_field_type_floating_point_set_exponent_digits(
+               struct bt_ctf_field_type *ft, unsigned int exponent_digits)
+{
+       return bt_field_type_common_floating_point_set_exponent_digits(
+               (void *) ft, exponent_digits);
+}
+
+int bt_ctf_field_type_floating_point_get_mantissa_digits(
+               struct bt_ctf_field_type *ft)
+{
+       return bt_field_type_common_floating_point_get_mantissa_digits(
+               (void *) ft);
+}
+
+int bt_ctf_field_type_floating_point_set_mantissa_digits(
+               struct bt_ctf_field_type *ft, unsigned int mantissa_digits)
+{
+       return bt_field_type_common_floating_point_set_mantissa_digits(
+               (void *) ft, mantissa_digits);
+}
+
+struct bt_ctf_field_type *bt_ctf_field_type_structure_create(void)
+{
+       struct bt_field_type_common_structure *structure =
+               g_new0(struct bt_field_type_common_structure, 1);
+
+       BT_LOGD_STR("Creating CTF writer structure field type object.");
+
+       if (!structure) {
+               BT_LOGE_STR("Failed to allocate one structure field type.");
+               goto error;
+       }
+
+       bt_field_type_common_structure_initialize(BT_TO_COMMON(structure),
+               bt_field_type_common_structure_destroy_recursive,
+               &bt_ctf_field_type_structure_methods);
+       structure->common.spec.writer.serialize_func =
+               bt_ctf_field_type_structure_serialize_recursive;
+       BT_LOGD("Created CTF writer structure field type object: addr=%p",
+               structure);
+       goto end;
+
+error:
+       BT_PUT(structure);
+
+end:
+       return (void *) structure;
+}
+
+int bt_ctf_field_type_structure_add_field(struct bt_ctf_field_type *ft,
+               struct bt_ctf_field_type *field_type,
+               const char *field_name)
+{
+       return bt_field_type_common_structure_add_field((void *) ft,
+               (void *) field_type, field_name);
+}
+
+int64_t bt_ctf_field_type_structure_get_field_count(struct bt_ctf_field_type *ft)
+{
+       return bt_field_type_common_structure_get_field_count((void *) ft);
+}
+
+int bt_ctf_field_type_structure_get_field_by_index(
+               struct bt_ctf_field_type *ft,
+               const char **field_name,
+               struct bt_ctf_field_type **field_type, uint64_t index)
+{
+       return bt_field_type_common_structure_get_field_by_index(
+               (void *) ft, field_name, (void *) field_type, index);
+}
+
+struct bt_ctf_field_type *bt_ctf_field_type_structure_get_field_type_by_name(
+               struct bt_ctf_field_type *ft, const char *name)
+{
+       return (void *) bt_field_type_common_structure_get_field_type_by_name(
+               (void *) ft, name);
+}
+
+struct bt_ctf_field_type *bt_ctf_field_type_variant_create(
+       struct bt_ctf_field_type *tag_ft, const char *tag_name)
+{
+       struct bt_field_type_common_variant *var_ft = NULL;
+
+       BT_LOGD("Creating CTF writer variant field type object: "
+               "tag-ft-addr=%p, tag-field-name=\"%s\"",
+               tag_ft, tag_name);
+
+       if (tag_name && !bt_identifier_is_valid(tag_name)) {
+               BT_LOGW("Invalid parameter: tag field name is not a valid CTF identifier: "
+                       "tag-ft-addr=%p, tag-field-name=\"%s\"",
+                       tag_ft, tag_name);
+               goto error;
+       }
+
+       var_ft = g_new0(struct bt_field_type_common_variant, 1);
+       if (!var_ft) {
+               BT_LOGE_STR("Failed to allocate one variant field type.");
+               goto error;
+       }
+
+       bt_field_type_common_variant_initialize(BT_TO_COMMON(var_ft),
+               (void *) tag_ft, tag_name,
+               bt_field_type_common_variant_destroy_recursive,
+               &bt_ctf_field_type_variant_methods);
+       var_ft->common.spec.writer.serialize_func =
+               bt_ctf_field_type_variant_serialize_recursive;
+       BT_LOGD("Created CTF writer variant field type object: addr=%p, "
+               "tag-ft-addr=%p, tag-field-name=\"%s\"",
+               var_ft, tag_ft, tag_name);
+       goto end;
+
+error:
+       BT_PUT(var_ft);
+
+end:
+       return (void *) var_ft;
+}
+
+struct bt_ctf_field_type *bt_ctf_field_type_variant_get_tag_field_type(
+               struct bt_ctf_field_type *ft)
+{
+       return (void *) bt_field_type_common_variant_get_tag_field_type(
+               (void *) ft);
+}
+
+const char *bt_ctf_field_type_variant_get_tag_name(struct bt_ctf_field_type *ft)
+{
+       return bt_field_type_common_variant_get_tag_name((void *) ft);
+}
+
+int bt_ctf_field_type_variant_set_tag_name(
+               struct bt_ctf_field_type *ft, const char *name)
+{
+       return bt_field_type_common_variant_set_tag_name((void *) ft, name);
+}
+
+int bt_ctf_field_type_variant_add_field(struct bt_ctf_field_type *ft,
+               struct bt_ctf_field_type *field_type,
+               const char *field_name)
+{
+       return bt_field_type_common_variant_add_field((void *) ft,
+               (void *) field_type, field_name);
+}
+
+struct bt_ctf_field_type *bt_ctf_field_type_variant_get_field_type_by_name(
+               struct bt_ctf_field_type *ft,
+               const char *field_name)
+{
+       return (void *) bt_field_type_common_variant_get_field_type_by_name(
+               (void *) ft, field_name);
+}
+
+struct bt_ctf_field_type *bt_ctf_field_type_variant_get_field_type_from_tag(
+               struct bt_ctf_field_type *ft,
+               struct bt_ctf_field *tag_field)
+{
+       return (void *) bt_field_type_common_variant_get_field_type_from_tag(
+               (void *) ft, (void *) tag_field,
+               (bt_field_common_create_func) bt_field_create);
+}
+
+int64_t bt_ctf_field_type_variant_get_field_count(struct bt_ctf_field_type *ft)
+{
+       return bt_field_type_common_variant_get_field_count((void *) ft);
+}
+
+int bt_ctf_field_type_variant_get_field_by_index(struct bt_ctf_field_type *ft,
+               const char **field_name, struct bt_ctf_field_type **field_type,
+               uint64_t index)
+{
+       return bt_field_type_common_variant_get_field_by_index((void *) ft,
+               field_name, (void *) field_type, index);
+}
+
+struct bt_ctf_field_type *bt_ctf_field_type_array_create(
+               struct bt_ctf_field_type *element_ft, unsigned int length)
+{
+       struct bt_field_type_common_array *array = NULL;
+
+       BT_LOGD("Creating CTF writer array field type object: element-ft-addr=%p, "
+               "length=%u", element_ft, length);
+
+       if (!element_ft) {
+               BT_LOGW_STR("Invalid parameter: element field type is NULL.");
+               goto error;
+       }
+
+       if (length == 0) {
+               BT_LOGW_STR("Invalid parameter: length is zero.");
+               goto error;
+       }
+
+       array = g_new0(struct bt_field_type_common_array, 1);
+       if (!array) {
+               BT_LOGE_STR("Failed to allocate one array field type.");
+               goto error;
+       }
+
+       bt_field_type_common_array_initialize(BT_TO_COMMON(array),
+               (void *) element_ft, length,
+               bt_field_type_common_array_destroy_recursive,
+               &bt_ctf_field_type_array_methods);
+       array->common.spec.writer.serialize_func =
+               bt_ctf_field_type_array_serialize_recursive;
+       BT_LOGD("Created CTF writer array field type object: addr=%p, "
+               "element-ft-addr=%p, length=%u",
+               array, element_ft, length);
+       goto end;
+
+error:
+       BT_PUT(array);
+
+end:
+       return (void *) array;
+}
+
+struct bt_ctf_field_type *bt_ctf_field_type_array_get_element_field_type(
+               struct bt_ctf_field_type *ft)
+{
+       return (void *) bt_field_type_common_array_get_element_field_type(
+               (void *) ft);
+}
+
+int64_t bt_ctf_field_type_array_get_length(struct bt_ctf_field_type *ft)
+{
+       return bt_field_type_common_array_get_length((void *) ft);
+}
+
+struct bt_ctf_field_type *bt_ctf_field_type_sequence_create(
+               struct bt_ctf_field_type *element_ft,
+               const char *length_field_name)
+{
+       struct bt_field_type_common_sequence *sequence = NULL;
+
+       BT_LOGD("Creating CTF writer sequence field type object: element-ft-addr=%p, "
+               "length-field-name=\"%s\"", element_ft, length_field_name);
+
+       if (!element_ft) {
+               BT_LOGW_STR("Invalid parameter: element field type is NULL.");
+               goto error;
+       }
+
+       if (!bt_identifier_is_valid(length_field_name)) {
+               BT_LOGW("Invalid parameter: length field name is not a valid CTF identifier: "
+                       "length-field-name=\"%s\"", length_field_name);
+               goto error;
+       }
+
+       sequence = g_new0(struct bt_field_type_common_sequence, 1);
+       if (!sequence) {
+               BT_LOGE_STR("Failed to allocate one sequence field type.");
+               goto error;
+       }
+
+       bt_field_type_common_sequence_initialize(BT_TO_COMMON(sequence),
+               (void *) element_ft, length_field_name,
+               bt_field_type_common_sequence_destroy_recursive,
+               &bt_ctf_field_type_sequence_methods);
+       sequence->common.spec.writer.serialize_func =
+               bt_ctf_field_type_sequence_serialize_recursive;
+       BT_LOGD("Created CTF writer sequence field type object: addr=%p, "
+               "element-ft-addr=%p, length-field-name=\"%s\"",
+               sequence, element_ft, length_field_name);
+       goto end;
+
+error:
+       BT_PUT(sequence);
+
+end:
+       return (void *) sequence;
+}
+
+struct bt_ctf_field_type *bt_ctf_field_type_sequence_get_element_field_type(
+               struct bt_ctf_field_type *ft)
+{
+       return (void *) bt_field_type_common_sequence_get_element_field_type(
+               (void *) ft);
+}
+
+const char *bt_ctf_field_type_sequence_get_length_field_name(
+               struct bt_ctf_field_type *ft)
+{
+       return bt_field_type_common_sequence_get_length_field_name((void *) ft);
+}
+
+struct bt_ctf_field_type *bt_ctf_field_type_string_create(void)
+{
+       struct bt_field_type_common_string *string =
+               g_new0(struct bt_field_type_common_string, 1);
+
+       BT_LOGD_STR("Creating CTF writer string field type object.");
+
+       if (!string) {
+               BT_LOGE_STR("Failed to allocate one string field type.");
+               return NULL;
+       }
+
+       bt_field_type_common_string_initialize(BT_TO_COMMON(string),
+               bt_field_type_common_string_destroy,
+               &bt_ctf_field_type_string_methods);
+       string->common.spec.writer.serialize_func =
+               bt_ctf_field_type_string_serialize;
+       BT_LOGD("Created CTF writer string field type object: addr=%p", string);
+       return (void *) string;
+}
+
+enum bt_ctf_string_encoding bt_ctf_field_type_string_get_encoding(
+               struct bt_ctf_field_type *ft)
+{
+       return (int) bt_field_type_common_string_get_encoding((void *) ft);
+}
+
+int bt_ctf_field_type_string_set_encoding(struct bt_ctf_field_type *ft,
+               enum bt_ctf_string_encoding encoding)
+{
+       return bt_field_type_common_string_set_encoding((void *) ft,
+               (int) encoding);
+}
+
+int bt_ctf_field_type_get_alignment(struct bt_ctf_field_type *ft)
+{
+       return bt_field_type_common_get_alignment((void *) ft);
+}
+
+int bt_ctf_field_type_set_alignment(struct bt_ctf_field_type *ft,
+               unsigned int alignment)
+{
+       return bt_field_type_common_set_alignment((void *) ft, alignment);
+}
+
+enum bt_ctf_byte_order bt_ctf_field_type_get_byte_order(
+               struct bt_ctf_field_type *ft)
+{
+       return (int) bt_field_type_common_get_byte_order((void *) ft);
+}
+
+int bt_ctf_field_type_set_byte_order(struct bt_ctf_field_type *ft,
+               enum bt_ctf_byte_order byte_order)
+{
+       return bt_field_type_common_set_byte_order((void *) ft,
+               (int) byte_order);
+}
+
+enum bt_ctf_field_type_id bt_ctf_field_type_get_type_id(
+               struct bt_ctf_field_type *ft)
+{
+       return (int) bt_field_type_common_get_type_id((void *) ft);
+}
+
+BT_HIDDEN
+struct bt_ctf_field_type *bt_ctf_field_type_copy(struct bt_ctf_field_type *ft)
+{
+       return (void *) bt_field_type_common_copy((void *) ft);
+}
+
+static
+struct bt_ctf_field_type *bt_ctf_field_type_integer_copy(
+               struct bt_ctf_field_type *ft)
+{
+       struct bt_field_type_common_integer *int_ft = (void *) ft;
+       struct bt_field_type_common_integer *copy_ft;
+
+       BT_LOGD("Copying CTF writer integer field type's: addr=%p", ft);
+       copy_ft = (void *) bt_ctf_field_type_integer_create(int_ft->size);
+       if (!copy_ft) {
+               BT_LOGE_STR("Cannot create CTF writer integer field type.");
+               goto end;
+       }
+
+       copy_ft->mapped_clock_class = bt_get(int_ft->mapped_clock_class);
+       copy_ft->user_byte_order = int_ft->user_byte_order;
+       copy_ft->is_signed = int_ft->is_signed;
+       copy_ft->size = int_ft->size;
+       copy_ft->base = int_ft->base;
+       copy_ft->encoding = int_ft->encoding;
+       BT_LOGD("Copied CTF writer integer field type: original-ft-addr=%p, copy-ft-addr=%p",
+               ft, copy_ft);
+
+end:
+       return (void *) copy_ft;
+}
+
+static
+struct bt_ctf_field_type *bt_ctf_field_type_enumeration_copy_recursive(
+               struct bt_ctf_field_type *ft)
+{
+       size_t i;
+       struct bt_field_type_common_enumeration *enum_ft = (void *) ft;
+       struct bt_field_type_common_enumeration *copy_ft = NULL;
+       struct bt_field_type_common_enumeration *container_copy_ft;
+
+       BT_LOGD("Copying CTF writer enumeration field type's: addr=%p", ft);
+
+       /* Copy the source enumeration's container */
+       BT_LOGD_STR("Copying CTF writer enumeration field type's container field type.");
+       container_copy_ft = BT_FROM_COMMON(bt_field_type_common_copy(
+               BT_TO_COMMON(enum_ft->container_ft)));
+       if (!container_copy_ft) {
+               BT_LOGE_STR("Cannot copy CTF writer enumeration field type's container field type.");
+               goto end;
+       }
+
+       copy_ft = (void *) bt_ctf_field_type_enumeration_create(
+               (void *) container_copy_ft);
+       if (!copy_ft) {
+               BT_LOGE_STR("Cannot create CTF writer enumeration field type.");
+               goto end;
+       }
+
+       /* Copy all enumaration entries */
+       for (i = 0; i < enum_ft->entries->len; i++) {
+               struct enumeration_mapping *mapping = g_ptr_array_index(
+                       enum_ft->entries, i);
+               struct enumeration_mapping *copy_mapping = g_new0(
+                       struct enumeration_mapping, 1);
+
+               if (!copy_mapping) {
+                       BT_LOGE_STR("Failed to allocate one enumeration mapping.");
+                       goto error;
+               }
+
+               *copy_mapping = *mapping;
+               g_ptr_array_add(copy_ft->entries, copy_mapping);
+       }
+
+       BT_LOGD("Copied CTF writer enumeration field type: original-ft-addr=%p, copy-ft-addr=%p",
+               ft, copy_ft);
+
+end:
+       bt_put(container_copy_ft);
+       return (void *) copy_ft;
+
+error:
+       bt_put(container_copy_ft);
+        BT_PUT(copy_ft);
+       return (void *) copy_ft;
+}
+
+static
+struct bt_ctf_field_type *bt_ctf_field_type_floating_point_copy(
+               struct bt_ctf_field_type *ft)
+{
+       struct bt_field_type_common_floating_point *flt_ft = BT_FROM_COMMON(ft);
+       struct bt_field_type_common_floating_point *copy_ft;
+
+       BT_LOGD("Copying CTF writer floating point number field type's: addr=%p", ft);
+       copy_ft = (void *) bt_ctf_field_type_floating_point_create();
+       if (!copy_ft) {
+               BT_LOGE_STR("Cannot create CTF writer floating point number field type.");
+               goto end;
+       }
+
+       copy_ft->user_byte_order = flt_ft->user_byte_order;
+       copy_ft->exp_dig = flt_ft->exp_dig;
+       copy_ft->mant_dig = flt_ft->mant_dig;
+       BT_LOGD("Copied CTF writer floating point number field type: original-ft-addr=%p, copy-ft-addr=%p",
+               ft, copy_ft);
+
+end:
+       return (void *) copy_ft;
+}
+
+static
+struct bt_ctf_field_type *bt_ctf_field_type_structure_copy_recursive(
+               struct bt_ctf_field_type *ft)
+{
+       int64_t i;
+       GHashTableIter iter;
+       gpointer key, value;
+       struct bt_field_type_common_structure *struct_ft = (void *) ft;
+       struct bt_field_type_common_structure *copy_ft;
+
+       BT_LOGD("Copying CTF writer structure field type's: addr=%p", ft);
+       copy_ft = (void *) bt_ctf_field_type_structure_create();
+       if (!copy_ft) {
+               BT_LOGE_STR("Cannot create CTF writer structure field type.");
+               goto end;
+       }
+
+       /* Copy field_name_to_index */
+       g_hash_table_iter_init(&iter, struct_ft->field_name_to_index);
+       while (g_hash_table_iter_next(&iter, &key, &value)) {
+               g_hash_table_insert(copy_ft->field_name_to_index,
+                       key, value);
+       }
+
+       for (i = 0; i < struct_ft->fields->len; i++) {
+               struct structure_field_common *entry, *copy_entry;
+               struct bt_field_type_common *field_ft_copy;
+
+               entry = g_ptr_array_index(struct_ft->fields, i);
+               BT_LOGD("Copying CTF writer structure field type's field: "
+                       "index=%" PRId64 ", "
+                       "field-ft-addr=%p, field-name=\"%s\"",
+                       i, entry, g_quark_to_string(entry->name));
+               copy_entry = g_new0(struct structure_field_common, 1);
+               if (!copy_entry) {
+                       BT_LOGE_STR("Failed to allocate one structure field type field.");
+                       goto error;
+               }
+
+               field_ft_copy = (void *) bt_ctf_field_type_copy(
+                       (void *) entry->type);
+               if (!field_ft_copy) {
+                       BT_LOGE("Cannot copy CTF writer structure field type's field: "
+                               "index=%" PRId64 ", "
+                               "field-ft-addr=%p, field-name=\"%s\"",
+                               i, entry, g_quark_to_string(entry->name));
+                       g_free(copy_entry);
+                       goto error;
+               }
+
+               copy_entry->name = entry->name;
+               copy_entry->type = field_ft_copy;
+               g_ptr_array_add(copy_ft->fields, copy_entry);
+       }
+
+       BT_LOGD("Copied CTF writer structure field type: original-ft-addr=%p, copy-ft-addr=%p",
+               ft, copy_ft);
+
+end:
+       return (void *) copy_ft;
+
+error:
+        BT_PUT(copy_ft);
+       return NULL;
+}
+
+static
+struct bt_ctf_field_type *bt_ctf_field_type_variant_copy_recursive(
+               struct bt_ctf_field_type *ft)
+{
+       int64_t i;
+       GHashTableIter iter;
+       gpointer key, value;
+       struct bt_field_type_common *tag_ft_copy = NULL;
+       struct bt_field_type_common_variant *var_ft = (void *) ft;
+       struct bt_field_type_common_variant *copy_ft = NULL;
+
+       BT_LOGD("Copying CTF writer variant field type's: addr=%p", ft);
+       if (var_ft->tag_ft) {
+               BT_LOGD_STR("Copying CTF writer variant field type's tag field type.");
+               tag_ft_copy = bt_field_type_common_copy(
+                       BT_TO_COMMON(var_ft->tag_ft));
+               if (!tag_ft_copy) {
+                       BT_LOGE_STR("Cannot copy CTF writer variant field type's tag field type.");
+                       goto end;
+               }
+       }
+
+       copy_ft = (void *) bt_ctf_field_type_variant_create(
+               (void *) tag_ft_copy,
+               var_ft->tag_name->len ? var_ft->tag_name->str : NULL);
+       if (!copy_ft) {
+               BT_LOGE_STR("Cannot create CTF writer variant field type.");
+               goto end;
+       }
+
+       /* Copy field_name_to_index */
+       g_hash_table_iter_init(&iter, var_ft->field_name_to_index);
+       while (g_hash_table_iter_next(&iter, &key, &value)) {
+               g_hash_table_insert(copy_ft->field_name_to_index,
+                       key, value);
+       }
+
+       for (i = 0; i < var_ft->fields->len; i++) {
+               struct structure_field_common *entry, *copy_entry;
+               struct bt_field_type_common *field_ft_copy;
+
+               entry = g_ptr_array_index(var_ft->fields, i);
+               BT_LOGD("Copying CTF writer variant field type's field: "
+                       "index=%" PRId64 ", "
+                       "field-ft-addr=%p, field-name=\"%s\"",
+                       i, entry, g_quark_to_string(entry->name));
+               copy_entry = g_new0(struct structure_field_common, 1);
+               if (!copy_entry) {
+                       BT_LOGE_STR("Failed to allocate one variant field type field.");
+                       goto error;
+               }
+
+               field_ft_copy = (void *) bt_ctf_field_type_copy(
+                       (void *) entry->type);
+               if (!field_ft_copy) {
+                       BT_LOGE("Cannot copy CTF writer variant field type's field: "
+                               "index=%" PRId64 ", "
+                               "field-ft-addr=%p, field-name=\"%s\"",
+                               i, entry, g_quark_to_string(entry->name));
+                       g_free(copy_entry);
+                       goto error;
+               }
+
+               copy_entry->name = entry->name;
+               copy_entry->type = field_ft_copy;
+               g_ptr_array_add(copy_ft->fields, copy_entry);
+       }
+
+       if (var_ft->tag_field_path) {
+               BT_LOGD_STR("Copying CTF writer variant field type's tag field path.");
+               copy_ft->tag_field_path = bt_field_path_copy(
+                       var_ft->tag_field_path);
+               if (!copy_ft->tag_field_path) {
+                       BT_LOGE_STR("Cannot copy CTF writer variant field type's tag field path.");
+                       goto error;
+               }
+       }
+
+       BT_LOGD("Copied variant field type: original-ft-addr=%p, copy-ft-addr=%p",
+               ft, copy_ft);
+
+end:
+       bt_put(tag_ft_copy);
+       return (void *) copy_ft;
+
+error:
+       bt_put(tag_ft_copy);
+        BT_PUT(copy_ft);
+       return NULL;
+}
+
+static
+struct bt_ctf_field_type *bt_ctf_field_type_array_copy_recursive(
+               struct bt_ctf_field_type *ft)
+{
+       struct bt_field_type_common *container_ft_copy = NULL;
+       struct bt_field_type_common_array *array_ft = (void *) ft;
+       struct bt_field_type_common_array *copy_ft = NULL;
+
+       BT_LOGD("Copying CTF writer array field type's: addr=%p", ft);
+       BT_LOGD_STR("Copying CTF writer array field type's element field type.");
+       container_ft_copy = bt_field_type_common_copy(array_ft->element_ft);
+       if (!container_ft_copy) {
+               BT_LOGE_STR("Cannot copy CTF writer array field type's element field type.");
+               goto end;
+       }
+
+       copy_ft = (void *) bt_ctf_field_type_array_create(
+               (void *) container_ft_copy, array_ft->length);
+       if (!copy_ft) {
+               BT_LOGE_STR("Cannot create CTF writer array field type.");
+               goto end;
+       }
+
+       BT_LOGD("Copied CTF writer array field type: original-ft-addr=%p, copy-ft-addr=%p",
+               ft, copy_ft);
+
+end:
+       bt_put(container_ft_copy);
+       return (void *) copy_ft;
+}
+
+static
+struct bt_ctf_field_type *bt_ctf_field_type_sequence_copy_recursive(
+               struct bt_ctf_field_type *ft)
+{
+       struct bt_field_type_common *container_ft_copy = NULL;
+       struct bt_field_type_common_sequence *seq_ft = (void *) ft;
+       struct bt_field_type_common_sequence *copy_ft = NULL;
+
+       BT_LOGD("Copying CTF writer sequence field type's: addr=%p", ft);
+       BT_LOGD_STR("Copying CTF writer sequence field type's element field type.");
+       container_ft_copy = bt_field_type_common_copy(seq_ft->element_ft);
+       if (!container_ft_copy) {
+               BT_LOGE_STR("Cannot copy CTF writer sequence field type's element field type.");
+               goto end;
+       }
+
+       copy_ft = (void *) bt_ctf_field_type_sequence_create(
+               (void *) container_ft_copy,
+               seq_ft->length_field_name->len ?
+                       seq_ft->length_field_name->str : NULL);
+       if (!copy_ft) {
+               BT_LOGE_STR("Cannot create CTF writer sequence field type.");
+               goto end;
+       }
+
+       if (seq_ft->length_field_path) {
+               BT_LOGD_STR("Copying CTF writer sequence field type's length field path.");
+               copy_ft->length_field_path = bt_field_path_copy(
+                       seq_ft->length_field_path);
+               if (!copy_ft->length_field_path) {
+                       BT_LOGE_STR("Cannot copy CTF writer sequence field type's length field path.");
+                       goto error;
+               }
+       }
+
+       BT_LOGD("Copied CTF writer sequence field type: original-ft-addr=%p, copy-ft-addr=%p",
+               ft, copy_ft);
+
+end:
+       bt_put(container_ft_copy);
+       return (void *) copy_ft;
+error:
+       bt_put(container_ft_copy);
+       BT_PUT(copy_ft);
+       return NULL;
+}
+
+static
+struct bt_ctf_field_type *bt_ctf_field_type_string_copy(struct bt_ctf_field_type *ft)
+{
+       struct bt_field_type_common_string *string_ft = (void *) ft;
+       struct bt_field_type_common_string *copy_ft = NULL;
+
+       BT_LOGD("Copying CTF writer string field type's: addr=%p", ft);
+       copy_ft = (void *) bt_ctf_field_type_string_create();
+       if (!copy_ft) {
+               BT_LOGE_STR("Cannot create CTF writer string field type.");
+               goto end;
+       }
+
+       copy_ft->encoding = string_ft->encoding;
+       BT_LOGD("Copied CTF writer string field type: original-ft-addr=%p, copy-ft-addr=%p",
+               ft, copy_ft);
+
+end:
+       return (void *) copy_ft;
+}
diff --git a/lib/ctf-writer/fields.c b/lib/ctf-writer/fields.c
new file mode 100644 (file)
index 0000000..f7032fc
--- /dev/null
@@ -0,0 +1,861 @@
+/*
+ * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#define BT_LOG_TAG "CTF-WRITER-FIELDS"
+#include <babeltrace/lib-logging-internal.h>
+
+#include <babeltrace/compat/fcntl-internal.h>
+#include <babeltrace/ctf-writer/fields-internal.h>
+#include <babeltrace/ctf-writer/field-types-internal.h>
+#include <babeltrace/ctf-writer/serialize-internal.h>
+#include <babeltrace/ctf-ir/fields-internal.h>
+#include <babeltrace/ctf-ir/field-types-internal.h>
+#include <babeltrace/assert-pre-internal.h>
+#include <babeltrace/object-internal.h>
+#include <babeltrace/ref.h>
+#include <babeltrace/compiler-internal.h>
+#include <babeltrace/endian-internal.h>
+#include <babeltrace/assert-internal.h>
+#include <float.h>
+#include <inttypes.h>
+#include <stdlib.h>
+
+static struct bt_field_common_methods bt_ctf_field_integer_methods = {
+       .freeze = bt_field_common_generic_freeze,
+       .validate = bt_field_common_generic_validate,
+       .copy = NULL,
+       .is_set = bt_field_common_generic_is_set,
+       .reset = bt_field_common_generic_reset,
+};
+
+static struct bt_field_common_methods bt_ctf_field_floating_point_methods = {
+       .freeze = bt_field_common_generic_freeze,
+       .validate = bt_field_common_generic_validate,
+       .copy = NULL,
+       .is_set = bt_field_common_generic_is_set,
+       .reset = bt_field_common_generic_reset,
+};
+
+static struct bt_field_common_methods bt_ctf_field_enumeration_methods = {
+       .freeze = bt_field_common_enumeration_freeze_recursive,
+       .validate = bt_field_common_enumeration_validate_recursive,
+       .copy = NULL,
+       .is_set = bt_field_common_enumeration_is_set_recursive,
+       .reset = bt_field_common_enumeration_reset_recursive,
+};
+
+static struct bt_field_common_methods bt_ctf_field_string_methods = {
+       .freeze = bt_field_common_generic_freeze,
+       .validate = bt_field_common_generic_validate,
+       .copy = NULL,
+       .is_set = bt_field_common_generic_is_set,
+       .reset = bt_field_common_generic_reset,
+};
+
+static struct bt_field_common_methods bt_ctf_field_structure_methods = {
+       .freeze = bt_field_common_structure_freeze_recursive,
+       .validate = bt_field_common_structure_validate_recursive,
+       .copy = NULL,
+       .is_set = bt_field_common_structure_is_set_recursive,
+       .reset = bt_field_common_structure_reset_recursive,
+};
+
+static struct bt_field_common_methods bt_ctf_field_sequence_methods = {
+       .freeze = bt_field_common_sequence_freeze_recursive,
+       .validate = bt_field_common_sequence_validate_recursive,
+       .copy = NULL,
+       .is_set = bt_field_common_sequence_is_set_recursive,
+       .reset = bt_field_common_sequence_reset_recursive,
+};
+
+static struct bt_field_common_methods bt_ctf_field_array_methods = {
+       .freeze = bt_field_common_array_freeze_recursive,
+       .validate = bt_field_common_array_validate_recursive,
+       .copy = NULL,
+       .is_set = bt_field_common_array_is_set_recursive,
+       .reset = bt_field_common_array_reset_recursive,
+};
+
+static struct bt_field_common_methods bt_ctf_field_variant_methods = {
+       .freeze = bt_field_common_variant_freeze_recursive,
+       .validate = bt_field_common_variant_validate_recursive,
+       .copy = NULL,
+       .is_set = bt_field_common_variant_is_set_recursive,
+       .reset = bt_field_common_variant_reset_recursive,
+};
+
+static
+struct bt_ctf_field *bt_ctf_field_integer_create(struct bt_ctf_field_type *);
+
+static
+struct bt_ctf_field *bt_ctf_field_enumeration_create(struct bt_ctf_field_type *);
+
+static
+struct bt_ctf_field *bt_ctf_field_floating_point_create(struct bt_ctf_field_type *);
+
+static
+struct bt_ctf_field *bt_ctf_field_structure_create(struct bt_ctf_field_type *);
+
+static
+struct bt_ctf_field *bt_ctf_field_variant_create(struct bt_ctf_field_type *);
+
+static
+struct bt_ctf_field *bt_ctf_field_array_create(struct bt_ctf_field_type *);
+
+static
+struct bt_ctf_field *bt_ctf_field_sequence_create(struct bt_ctf_field_type *);
+
+static
+struct bt_ctf_field *bt_ctf_field_string_create(struct bt_ctf_field_type *);
+
+static
+struct bt_ctf_field *(* const field_create_funcs[])(struct bt_ctf_field_type *) = {
+       [BT_FIELD_TYPE_ID_INTEGER] =    bt_ctf_field_integer_create,
+       [BT_FIELD_TYPE_ID_ENUM] =       bt_ctf_field_enumeration_create,
+       [BT_FIELD_TYPE_ID_FLOAT] =      bt_ctf_field_floating_point_create,
+       [BT_FIELD_TYPE_ID_STRUCT] =     bt_ctf_field_structure_create,
+       [BT_FIELD_TYPE_ID_VARIANT] =    bt_ctf_field_variant_create,
+       [BT_FIELD_TYPE_ID_ARRAY] =      bt_ctf_field_array_create,
+       [BT_FIELD_TYPE_ID_SEQUENCE] =   bt_ctf_field_sequence_create,
+       [BT_FIELD_TYPE_ID_STRING] =     bt_ctf_field_string_create,
+};
+
+typedef int (*bt_ctf_field_serialize_recursive_func)(
+               struct bt_field_common *, struct bt_ctf_stream_pos *,
+               enum bt_ctf_byte_order);
+
+BT_HIDDEN
+int bt_ctf_field_serialize_recursive(struct bt_ctf_field *field,
+               struct bt_ctf_stream_pos *pos,
+               enum bt_ctf_byte_order native_byte_order)
+{
+       struct bt_field_common *field_common = (void *) field;
+       bt_ctf_field_serialize_recursive_func serialize_func;
+
+       BT_ASSERT(pos);
+       BT_ASSERT_PRE_NON_NULL(field, "Field");
+       BT_ASSERT(field_common->spec.writer.serialize_func);
+       serialize_func = field_common->spec.writer.serialize_func;
+       return serialize_func(field_common, pos,
+               native_byte_order);
+}
+
+static
+int increase_packet_size(struct bt_ctf_stream_pos *pos)
+{
+       int ret;
+
+       BT_ASSERT(pos);
+       BT_LOGV("Increasing packet size: pos-offset=%" PRId64 ", "
+               "cur-packet-size=%" PRIu64,
+               pos->offset, pos->packet_size);
+       ret = munmap_align(pos->base_mma);
+       if (ret) {
+               BT_LOGE_ERRNO("Failed to perform an aligned memory unmapping",
+                       ": ret=%d", ret);
+               goto end;
+       }
+
+       pos->packet_size += PACKET_LEN_INCREMENT;
+       do {
+               ret = bt_posix_fallocate(pos->fd, pos->mmap_offset,
+                       pos->packet_size / CHAR_BIT);
+       } while (ret == EINTR);
+       if (ret) {
+               BT_LOGE_ERRNO("Failed to preallocate memory space",
+                       ": ret=%d", ret);
+               errno = EINTR;
+               ret = -1;
+               goto end;
+       }
+
+       pos->base_mma = mmap_align(pos->packet_size / CHAR_BIT, pos->prot,
+               pos->flags, pos->fd, pos->mmap_offset);
+       if (pos->base_mma == MAP_FAILED) {
+               BT_LOGE_ERRNO("Failed to perform an aligned memory mapping",
+                       ": ret=%d", ret);
+               ret = -1;
+       }
+
+       BT_LOGV("Increased packet size: pos-offset=%" PRId64 ", "
+               "new-packet-size=%" PRIu64,
+               pos->offset, pos->packet_size);
+       BT_ASSERT(pos->packet_size % 8 == 0);
+
+end:
+       return ret;
+}
+
+static
+int bt_ctf_field_integer_serialize(struct bt_field_common *field,
+               struct bt_ctf_stream_pos *pos,
+               enum bt_ctf_byte_order native_byte_order)
+{
+       int ret = 0;
+
+       BT_ASSERT_PRE_FIELD_COMMON_IS_SET(field, "Integer field");
+       BT_LOGV("Serializing CTF writer integer field: addr=%p, pos-offset=%" PRId64 ", "
+               "native-bo=%s", field, pos->offset,
+               bt_common_byte_order_string((int) native_byte_order));
+
+retry:
+       ret = bt_ctf_field_integer_write(field, pos, native_byte_order);
+       if (ret == -EFAULT) {
+               /*
+                * The field is too large to fit in the current packet's
+                * remaining space. Bump the packet size and retry.
+                */
+               ret = increase_packet_size(pos);
+               if (ret) {
+                       BT_LOGE("Cannot increase packet size: ret=%d", ret);
+                       goto end;
+               }
+               goto retry;
+       }
+
+end:
+       return ret;
+}
+
+static
+int bt_ctf_field_enumeration_serialize_recursive(struct bt_field_common *field,
+               struct bt_ctf_stream_pos *pos,
+               enum bt_ctf_byte_order native_byte_order)
+{
+       struct bt_field_common_enumeration *enumeration = BT_FROM_COMMON(field);
+
+       BT_LOGV("Serializing enumeration field: addr=%p, pos-offset=%" PRId64 ", "
+               "native-bo=%s", field, pos->offset,
+               bt_common_byte_order_string((int) native_byte_order));
+       BT_LOGV_STR("Serializing enumeration field's payload field.");
+       return bt_ctf_field_serialize_recursive((void *) enumeration->payload,
+               pos, native_byte_order);
+}
+
+static
+int bt_ctf_field_floating_point_serialize(struct bt_field_common *field,
+               struct bt_ctf_stream_pos *pos,
+               enum bt_ctf_byte_order native_byte_order)
+{
+       int ret = 0;
+
+       BT_ASSERT_PRE_FIELD_COMMON_IS_SET(field, "Floating point number field");
+       BT_LOGV("Serializing floating point number field: addr=%p, pos-offset=%" PRId64 ", "
+               "native-bo=%s", field, pos->offset,
+               bt_common_byte_order_string((int) native_byte_order));
+
+retry:
+       ret = bt_ctf_field_floating_point_write(field, pos,
+               native_byte_order);
+       if (ret == -EFAULT) {
+               /*
+                * The field is too large to fit in the current packet's
+                * remaining space. Bump the packet size and retry.
+                */
+               ret = increase_packet_size(pos);
+               if (ret) {
+                       BT_LOGE("Cannot increase packet size: ret=%d", ret);
+                       goto end;
+               }
+               goto retry;
+       }
+
+end:
+       return ret;
+}
+
+static
+int bt_ctf_field_structure_serialize_recursive(struct bt_field_common *field,
+               struct bt_ctf_stream_pos *pos,
+               enum bt_ctf_byte_order native_byte_order)
+{
+       int64_t i;
+       int ret = 0;
+       struct bt_field_common_structure *structure = BT_FROM_COMMON(field);
+
+       BT_LOGV("Serializing structure field: addr=%p, pos-offset=%" PRId64 ", "
+               "native-bo=%s", field, pos->offset,
+               bt_common_byte_order_string((int) native_byte_order));
+
+       while (!bt_ctf_stream_pos_access_ok(pos,
+               offset_align(pos->offset, field->type->alignment))) {
+               ret = increase_packet_size(pos);
+               if (ret) {
+                       BT_LOGE("Cannot increase packet size: ret=%d", ret);
+                       goto end;
+               }
+       }
+
+       if (!bt_ctf_stream_pos_align(pos, field->type->alignment)) {
+               BT_LOGE("Cannot align packet's position: pos-offset=%" PRId64 ", "
+                       "align=%u", pos->offset, field->type->alignment);
+               ret = -1;
+               goto end;
+       }
+
+       for (i = 0; i < structure->fields->len; i++) {
+               struct bt_field_common *member = g_ptr_array_index(
+                       structure->fields, i);
+               const char *field_name = NULL;
+
+               BT_LOGV("Serializing structure field's field: pos-offset=%" PRId64 ", "
+                       "field-addr=%p, index=%" PRId64,
+                       pos->offset, member, i);
+
+               if (!member) {
+                       ret = bt_field_type_common_structure_get_field_by_index(
+                               field->type, &field_name, NULL, i);
+                       BT_ASSERT(ret == 0);
+                       BT_LOGW("Cannot serialize structure field's field: field is not set: "
+                               "struct-field-addr=%p, "
+                               "field-name=\"%s\", index=%" PRId64,
+                               field, field_name, i);
+                       ret = -1;
+                       goto end;
+               }
+
+               ret = bt_ctf_field_serialize_recursive((void *) member, pos,
+                       native_byte_order);
+               if (ret) {
+                       ret = bt_field_type_common_structure_get_field_by_index(
+                               field->type, &field_name, NULL, i);
+                       BT_ASSERT(ret == 0);
+                       BT_LOGW("Cannot serialize structure field's field: "
+                               "struct-field-addr=%p, field-addr=%p, "
+                               "field-name=\"%s\", index=%" PRId64,
+                               field->type, member, field_name, i);
+                       break;
+               }
+       }
+
+end:
+       return ret;
+}
+
+static
+int bt_ctf_field_variant_serialize_recursive(struct bt_field_common *field,
+               struct bt_ctf_stream_pos *pos,
+               enum bt_ctf_byte_order native_byte_order)
+{
+       struct bt_field_common_variant *variant = BT_FROM_COMMON(field);
+
+       BT_LOGV("Serializing variant field: addr=%p, pos-offset=%" PRId64 ", "
+               "native-bo=%s", field, pos->offset,
+               bt_common_byte_order_string((int) native_byte_order));
+       BT_LOGV_STR("Serializing variant field's payload field.");
+       return bt_ctf_field_serialize_recursive(
+               (void *) variant->payload, pos, native_byte_order);
+}
+
+static
+int bt_ctf_field_array_serialize_recursive(struct bt_field_common *field,
+               struct bt_ctf_stream_pos *pos,
+               enum bt_ctf_byte_order native_byte_order)
+{
+       int64_t i;
+       int ret = 0;
+       struct bt_field_common_array *array = BT_FROM_COMMON(field);
+
+       BT_LOGV("Serializing array field: addr=%p, pos-offset=%" PRId64 ", "
+               "native-bo=%s", field, pos->offset,
+               bt_common_byte_order_string((int) native_byte_order));
+
+       for (i = 0; i < array->elements->len; i++) {
+               struct bt_field_common *elem_field =
+                       g_ptr_array_index(array->elements, i);
+
+               BT_LOGV("Serializing array field's element field: "
+                       "pos-offset=%" PRId64 ", field-addr=%p, index=%" PRId64,
+                       pos->offset, elem_field, i);
+               ret = bt_ctf_field_serialize_recursive(
+                       (void *) elem_field, pos, native_byte_order);
+               if (ret) {
+                       BT_LOGW("Cannot serialize array field's element field: "
+                               "array-field-addr=%p, field-addr=%p, "
+                               "index=%" PRId64, field, elem_field, i);
+                       goto end;
+               }
+       }
+
+end:
+       return ret;
+}
+
+static
+int bt_ctf_field_sequence_serialize_recursive(struct bt_field_common *field,
+               struct bt_ctf_stream_pos *pos,
+               enum bt_ctf_byte_order native_byte_order)
+{
+       int64_t i;
+       int ret = 0;
+       struct bt_field_common_sequence *sequence = BT_FROM_COMMON(field);
+
+       BT_LOGV("Serializing sequence field: addr=%p, pos-offset=%" PRId64 ", "
+               "native-bo=%s", field, pos->offset,
+               bt_common_byte_order_string((int) native_byte_order));
+
+       for (i = 0; i < sequence->elements->len; i++) {
+               struct bt_field_common *elem_field =
+                       g_ptr_array_index(sequence->elements, i);
+
+               BT_LOGV("Serializing sequence field's element field: "
+                       "pos-offset=%" PRId64 ", field-addr=%p, index=%" PRId64,
+                       pos->offset, elem_field, i);
+               ret = bt_ctf_field_serialize_recursive(
+                       (void *) elem_field, pos, native_byte_order);
+               if (ret) {
+                       BT_LOGW("Cannot serialize sequence field's element field: "
+                               "sequence-field-addr=%p, field-addr=%p, "
+                               "index=%" PRId64, field, elem_field, i);
+                       goto end;
+               }
+       }
+
+end:
+       return ret;
+}
+
+static
+int bt_ctf_field_string_serialize(struct bt_field_common *field,
+               struct bt_ctf_stream_pos *pos,
+               enum bt_ctf_byte_order native_byte_order)
+{
+       int64_t i;
+       int ret = 0;
+       struct bt_field_common_string *string = BT_FROM_COMMON(field);
+       struct bt_ctf_field_type *character_type =
+               get_field_type(FIELD_TYPE_ALIAS_UINT8_T);
+       struct bt_ctf_field *character;
+
+       BT_ASSERT_PRE_FIELD_COMMON_IS_SET(field, "String field");
+       BT_LOGV("Serializing string field: addr=%p, pos-offset=%" PRId64 ", "
+               "native-bo=%s", field, pos->offset,
+               bt_common_byte_order_string((int) native_byte_order));
+
+       BT_LOGV_STR("Creating character field from string field's character field type.");
+       character = bt_ctf_field_create(character_type);
+
+       for (i = 0; i < string->payload->len + 1; i++) {
+               const uint64_t chr = (uint64_t) string->payload->str[i];
+
+               ret = bt_ctf_field_integer_unsigned_set_value(character, chr);
+               BT_ASSERT(ret == 0);
+               BT_LOGV("Serializing string field's character field: "
+                       "pos-offset=%" PRId64 ", field-addr=%p, "
+                       "index=%" PRId64 ", char-int=%" PRIu64,
+                       pos->offset, character, i, chr);
+               ret = bt_ctf_field_integer_serialize(
+                       (void *) character, pos, native_byte_order);
+               if (ret) {
+                       BT_LOGW_STR("Cannot serialize character field.");
+                       goto end;
+               }
+       }
+
+end:
+       bt_put(character);
+       bt_put(character_type);
+       return ret;
+}
+
+struct bt_ctf_field *bt_ctf_field_create(struct bt_ctf_field_type *type)
+{
+       struct bt_ctf_field *field = NULL;
+       enum bt_ctf_field_type_id type_id;
+
+       BT_ASSERT_PRE_NON_NULL(type, "Field type");
+       BT_ASSERT(field_type_common_has_known_id((void *) type));
+       BT_ASSERT_PRE(bt_field_type_common_validate((void *) type) == 0,
+               "Field type is invalid: %!+wF", type);
+       type_id = bt_ctf_field_type_get_type_id(type);
+       field = field_create_funcs[type_id](type);
+       if (!field) {
+               goto end;
+       }
+
+       bt_field_type_common_freeze((void *) type);
+
+end:
+       return field;
+}
+
+struct bt_ctf_field_type *bt_ctf_field_get_type(struct bt_ctf_field *field)
+{
+       return (void *) bt_field_common_get_type((void *) field);
+}
+
+enum bt_ctf_field_type_id bt_ctf_field_get_type_id(struct bt_ctf_field *field)
+{
+       struct bt_field_common *field_common = (void *) field;
+
+       BT_ASSERT_PRE_NON_NULL(field, "Field");
+       return (int) field_common->type->id;
+}
+
+struct bt_ctf_field *bt_ctf_field_sequence_get_length(
+               struct bt_ctf_field *field)
+{
+       return (void *) bt_field_common_sequence_get_length((void *) field);
+}
+
+int bt_ctf_field_sequence_set_length(struct bt_ctf_field *field,
+               struct bt_ctf_field *length_field)
+{
+       return bt_field_common_sequence_set_length((void *) field,
+               (void *) length_field);
+}
+
+struct bt_ctf_field *bt_ctf_field_structure_get_field_by_index(
+               struct bt_ctf_field *field, uint64_t index)
+{
+       return (void *) bt_field_common_structure_get_field_by_index(
+               (void *) field, index);
+}
+
+struct bt_ctf_field *bt_ctf_field_structure_get_field_by_name(
+               struct bt_ctf_field *field, const char *name)
+{
+       return (void *) bt_field_common_structure_get_field_by_name(
+               (void *) field, name);
+}
+
+int bt_ctf_field_structure_set_field_by_name(struct bt_ctf_field *field,
+               const char *name, struct bt_ctf_field *value)
+{
+       return bt_field_common_structure_set_field_by_name((void *) field,
+               name, (void *) value);
+}
+
+struct bt_ctf_field *bt_ctf_field_array_get_field(
+               struct bt_ctf_field *field, uint64_t index)
+{
+       return (void *) bt_field_common_array_get_field((void *) field, index,
+               (bt_field_common_create_func) bt_ctf_field_create);
+}
+
+struct bt_ctf_field *bt_ctf_field_sequence_get_field(
+               struct bt_ctf_field *field, uint64_t index)
+{
+       return (void *) bt_field_common_sequence_get_field((void *) field,
+               index, (bt_field_common_create_func) bt_ctf_field_create);
+}
+
+struct bt_ctf_field *bt_ctf_field_variant_get_field(struct bt_ctf_field *field,
+               struct bt_ctf_field *tag_field)
+{
+       return (void *) bt_field_common_variant_get_field((void *) field,
+               (void *) tag_field,
+               (bt_field_common_create_func) bt_ctf_field_create);
+}
+
+struct bt_ctf_field *bt_ctf_field_variant_get_current_field(
+               struct bt_ctf_field *variant_field)
+{
+       return (void *) bt_field_common_variant_get_current_field(
+               (void *) variant_field);
+}
+
+struct bt_ctf_field *bt_ctf_field_variant_get_tag(
+               struct bt_ctf_field *variant_field)
+{
+       return (void *) bt_field_common_variant_get_tag((void *) variant_field);
+}
+
+struct bt_ctf_field *bt_ctf_field_enumeration_get_container(struct bt_ctf_field *field)
+{
+       return (void *) bt_field_common_enumeration_get_container(
+               (void *) field, (bt_field_common_create_func) bt_ctf_field_create);
+}
+
+int bt_ctf_field_integer_signed_get_value(struct bt_ctf_field *field, int64_t *value)
+{
+       return bt_field_common_integer_signed_get_value((void *) field, value);
+}
+
+int bt_ctf_field_integer_signed_set_value(struct bt_ctf_field *field,
+               int64_t value)
+{
+       return bt_field_common_integer_signed_set_value((void *) field, value);
+}
+
+int bt_ctf_field_integer_unsigned_get_value(struct bt_ctf_field *field,
+               uint64_t *value)
+{
+       return bt_field_common_integer_unsigned_get_value((void *) field,
+               value);
+}
+
+int bt_ctf_field_integer_unsigned_set_value(struct bt_ctf_field *field, uint64_t value)
+{
+       return bt_field_common_integer_unsigned_set_value((void *) field, value);
+}
+
+int bt_ctf_field_floating_point_get_value(struct bt_ctf_field *field,
+               double *value)
+{
+       return bt_field_common_floating_point_get_value((void *) field, value);
+}
+
+int bt_ctf_field_floating_point_set_value(struct bt_ctf_field *field,
+               double value)
+{
+       return bt_field_common_floating_point_set_value((void *) field, value);
+}
+
+const char *bt_ctf_field_string_get_value(struct bt_ctf_field *field)
+{
+       return bt_field_common_string_get_value((void *) field);
+}
+
+int bt_ctf_field_string_set_value(struct bt_ctf_field *field, const char *value)
+{
+       return bt_field_common_string_set_value((void *) field, value);
+}
+
+int bt_ctf_field_string_append(struct bt_ctf_field *field, const char *value)
+{
+       return bt_field_common_string_append((void *) field, value);
+}
+
+int bt_ctf_field_string_append_len(struct bt_ctf_field *field,
+               const char *value, unsigned int length)
+{
+       return bt_field_common_string_append_len((void *) field, value, length);
+}
+
+struct bt_ctf_field *bt_ctf_field_copy(struct bt_ctf_field *field)
+{
+       return (void *) bt_field_common_copy((void *) field);
+}
+
+static
+struct bt_ctf_field *bt_ctf_field_integer_create(struct bt_ctf_field_type *type)
+{
+       struct bt_field_common_integer *integer =
+               g_new0(struct bt_field_common_integer, 1);
+
+       BT_LOGD("Creating CTF writer integer field object: ft-addr=%p", type);
+
+       if (integer) {
+               bt_field_common_initialize(BT_TO_COMMON(integer), (void *) type,
+                       bt_field_common_integer_destroy,
+                       &bt_ctf_field_integer_methods);
+               integer->common.spec.writer.serialize_func =
+                       (bt_ctf_field_serialize_recursive_func) bt_ctf_field_integer_serialize;
+               BT_LOGD("Created CTF writer integer field object: addr=%p, ft-addr=%p",
+                       integer, type);
+       } else {
+               BT_LOGE_STR("Failed to allocate one integer field.");
+       }
+
+       return (void *) integer;
+}
+
+static
+struct bt_ctf_field *bt_ctf_field_enumeration_create(
+               struct bt_ctf_field_type *type)
+{
+       struct bt_field_common_enumeration *enumeration = g_new0(
+               struct bt_field_common_enumeration, 1);
+
+       BT_LOGD("Creating CTF writer enumeration field object: ft-addr=%p", type);
+
+       if (enumeration) {
+               bt_field_common_initialize(BT_TO_COMMON(enumeration),
+                       (void *) type,
+                       bt_field_common_enumeration_destroy_recursive,
+                       &bt_ctf_field_enumeration_methods);
+               enumeration->common.spec.writer.serialize_func =
+                       (bt_ctf_field_serialize_recursive_func) bt_ctf_field_enumeration_serialize_recursive;
+               BT_LOGD("Created CTF writer enumeration field object: addr=%p, ft-addr=%p",
+                       enumeration, type);
+       } else {
+               BT_LOGE_STR("Failed to allocate one enumeration field.");
+       }
+
+       return (void *) enumeration;
+}
+
+static
+struct bt_ctf_field *bt_ctf_field_floating_point_create(
+               struct bt_ctf_field_type *type)
+{
+       struct bt_field_common_floating_point *floating_point;
+
+       BT_LOGD("Creating CTF writer floating point number field object: ft-addr=%p", type);
+       floating_point = g_new0(struct bt_field_common_floating_point, 1);
+
+       if (floating_point) {
+               bt_field_common_initialize(BT_TO_COMMON(floating_point),
+                       (void *) type,
+                       bt_field_common_floating_point_destroy,
+                       &bt_ctf_field_floating_point_methods);
+               floating_point->common.spec.writer.serialize_func =
+                       (bt_ctf_field_serialize_recursive_func) bt_ctf_field_floating_point_serialize;
+               BT_LOGD("Created CTF writer floating point number field object: addr=%p, ft-addr=%p",
+                       floating_point, type);
+       } else {
+               BT_LOGE_STR("Failed to allocate one floating point number field.");
+       }
+
+       return (void *) floating_point;
+}
+
+static
+struct bt_ctf_field *bt_ctf_field_structure_create(
+               struct bt_ctf_field_type *type)
+{
+       struct bt_field_common_structure *structure = g_new0(
+               struct bt_field_common_structure, 1);
+       int iret;
+
+       BT_LOGD("Creating CTF writer structure field object: ft-addr=%p", type);
+
+       if (!structure) {
+               BT_LOGE_STR("Failed to allocate one structure field.");
+               goto end;
+       }
+
+       iret = bt_field_common_structure_initialize(BT_TO_COMMON(structure),
+               (void *) type, bt_field_common_structure_destroy_recursive,
+               &bt_ctf_field_structure_methods,
+               (bt_field_common_create_func) bt_ctf_field_create);
+       structure->common.spec.writer.serialize_func =
+               (bt_ctf_field_serialize_recursive_func) bt_ctf_field_structure_serialize_recursive;
+       if (iret) {
+               BT_PUT(structure);
+               goto end;
+       }
+
+       BT_LOGD("Created CTF writer structure field object: addr=%p, ft-addr=%p",
+               structure, type);
+
+end:
+       return (void *) structure;
+}
+
+static
+struct bt_ctf_field *bt_ctf_field_variant_create(struct bt_ctf_field_type *type)
+{
+       struct bt_field_common_variant *variant = g_new0(
+               struct bt_field_common_variant, 1);
+
+       BT_LOGD("Creating CTF writer variant field object: ft-addr=%p", type);
+
+       if (variant) {
+               bt_field_common_initialize(BT_TO_COMMON(variant),
+                       (void *) type,
+                       bt_field_common_variant_destroy_recursive,
+                       &bt_ctf_field_variant_methods);
+               variant->common.spec.writer.serialize_func =
+                       (bt_ctf_field_serialize_recursive_func) bt_ctf_field_variant_serialize_recursive;
+               BT_LOGD("Created CTF writer variant field object: addr=%p, ft-addr=%p",
+                       variant, type);
+       } else {
+               BT_LOGE_STR("Failed to allocate one variant field.");
+       }
+
+       return (void *) variant;
+}
+
+static
+struct bt_ctf_field *bt_ctf_field_array_create(struct bt_ctf_field_type *type)
+{
+       struct bt_field_common_array *array =
+               g_new0(struct bt_field_common_array, 1);
+       int ret;
+
+       BT_LOGD("Creating CTF writer array field object: ft-addr=%p", type);
+       BT_ASSERT(type);
+
+       if (!array) {
+               BT_LOGE_STR("Failed to allocate one array field.");
+               goto end;
+       }
+
+       ret = bt_field_common_array_initialize(BT_TO_COMMON(array),
+               (void *) type,
+               bt_field_common_array_destroy_recursive,
+               &bt_ctf_field_array_methods);
+       array->common.spec.writer.serialize_func =
+               (bt_ctf_field_serialize_recursive_func) bt_ctf_field_array_serialize_recursive;
+       if (ret) {
+               BT_PUT(array);
+               goto end;
+       }
+
+       BT_LOGD("Created CTF writer array field object: addr=%p, ft-addr=%p",
+               array, type);
+
+end:
+       return (void *) array;
+}
+
+static
+struct bt_ctf_field *bt_ctf_field_sequence_create(struct bt_ctf_field_type *type)
+{
+       struct bt_field_common_sequence *sequence = g_new0(
+               struct bt_field_common_sequence, 1);
+
+       BT_LOGD("Creating CTF writer sequence field object: ft-addr=%p", type);
+
+       if (sequence) {
+               bt_field_common_initialize(BT_TO_COMMON(sequence),
+                       (void *) type,
+                       bt_field_common_sequence_destroy_recursive,
+                       &bt_ctf_field_sequence_methods);
+               sequence->common.spec.writer.serialize_func =
+                       (bt_ctf_field_serialize_recursive_func) bt_ctf_field_sequence_serialize_recursive;
+               BT_LOGD("Created CTF writer sequence field object: addr=%p, ft-addr=%p",
+                       sequence, type);
+       } else {
+               BT_LOGE_STR("Failed to allocate one sequence field.");
+       }
+
+       return (void *) sequence;
+}
+
+static
+struct bt_ctf_field *bt_ctf_field_string_create(struct bt_ctf_field_type *type)
+{
+       struct bt_field_common_string *string = g_new0(
+               struct bt_field_common_string, 1);
+
+       BT_LOGD("Creating CTF writer string field object: ft-addr=%p", type);
+
+       if (string) {
+               bt_field_common_initialize(BT_TO_COMMON(string),
+                       (void *) type,
+                       bt_field_common_string_destroy,
+                       &bt_ctf_field_string_methods);
+               string->common.spec.writer.serialize_func =
+                       (bt_ctf_field_serialize_recursive_func) bt_ctf_field_string_serialize;
+               BT_LOGD("Created CTF writer string field object: addr=%p, ft-addr=%p",
+                       string, type);
+       } else {
+               BT_LOGE_STR("Failed to allocate one string field.");
+       }
+
+       return (void *) string;
+}
index 3d99b63973ae0a0632c79b7fda525d642ec73539..29af02ca51e41a1c895a4cd2723eea6c1194cf73 100644 (file)
@@ -28,6 +28,7 @@
 
 #include <glib.h>
 #include <babeltrace/ctf-writer/functor-internal.h>
+#include <babeltrace/ctf-ir/utils-internal.h>
 
 BT_HIDDEN
 void value_exists(gpointer element, gpointer search_query)
index ce6b96b34d3ca9dedc7f92c74b3a44c7df77a318..e2f3bb6a77a7e1e7e697e998c6c28b407c96b32c 100644 (file)
  * SOFTWARE.
  */
 
+#define BT_LOG_TAG "CTF-WRITER-SERIALIZE"
+#include <babeltrace/lib-logging-internal.h>
+
 #include <stdlib.h>
 #include <stdio.h>
 #include <stdint.h>
-#include <babeltrace/ctf-ir/field-types.h>
-#include <babeltrace/ctf-ir/field-types-internal.h>
-#include <babeltrace/ctf-ir/fields.h>
-#include <babeltrace/ctf-ir/fields-internal.h>
+#include <babeltrace/ctf-writer/fields.h>
+#include <babeltrace/ctf-writer/field-types.h>
 #include <babeltrace/ctf-writer/serialize-internal.h>
+#include <babeltrace/ctf-ir/utils-internal.h>
+#include <babeltrace/ctf-ir/fields-internal.h>
+#include <babeltrace/ctf-ir/field-types-internal.h>
 #include <babeltrace/align-internal.h>
 #include <babeltrace/mmap-align-internal.h>
 #include <babeltrace/endian-internal.h>
@@ -43,7 +47,6 @@
 #include <babeltrace/compat/fcntl-internal.h>
 #include <babeltrace/types.h>
 #include <babeltrace/common-internal.h>
-#include <babeltrace/assert-internal.h>
 #include <glib.h>
 
 #if (FLT_RADIX != 2)
@@ -61,16 +64,16 @@ union intval {
  * optimisation.
  */
 static
-int aligned_integer_write(struct bt_stream_pos *pos,
-               union intval value, unsigned int alignment, unsigned int size,
-               bt_bool is_signed, enum bt_byte_order byte_order)
+int aligned_integer_write(struct bt_ctf_stream_pos *pos, union intval value,
+               unsigned int alignment, unsigned int size, bt_bool is_signed,
+               enum bt_ctf_byte_order byte_order)
 {
        bt_bool rbo = (byte_order != BT_MY_BYTE_ORDER); /* reverse byte order */
 
-       if (!bt_stream_pos_align(pos, alignment))
+       if (!bt_ctf_stream_pos_align(pos, alignment))
                return -EFAULT;
 
-       if (!bt_stream_pos_access_ok(pos, size))
+       if (!bt_ctf_stream_pos_access_ok(pos, size))
                return -EFAULT;
 
        BT_ASSERT(!(pos->offset % CHAR_BIT));
@@ -80,7 +83,7 @@ int aligned_integer_write(struct bt_stream_pos *pos,
                {
                        uint8_t v = value.unsignd;
 
-                       memcpy(bt_stream_pos_get_addr(pos), &v, sizeof(v));
+                       memcpy(bt_ctf_stream_pos_get_addr(pos), &v, sizeof(v));
                        break;
                }
                case 16:
@@ -89,7 +92,7 @@ int aligned_integer_write(struct bt_stream_pos *pos,
 
                        if (rbo)
                                v = GUINT16_SWAP_LE_BE(v);
-                       memcpy(bt_stream_pos_get_addr(pos), &v, sizeof(v));
+                       memcpy(bt_ctf_stream_pos_get_addr(pos), &v, sizeof(v));
                        break;
                }
                case 32:
@@ -98,7 +101,7 @@ int aligned_integer_write(struct bt_stream_pos *pos,
 
                        if (rbo)
                                v = GUINT32_SWAP_LE_BE(v);
-                       memcpy(bt_stream_pos_get_addr(pos), &v, sizeof(v));
+                       memcpy(bt_ctf_stream_pos_get_addr(pos), &v, sizeof(v));
                        break;
                }
                case 64:
@@ -107,7 +110,7 @@ int aligned_integer_write(struct bt_stream_pos *pos,
 
                        if (rbo)
                                v = GUINT64_SWAP_LE_BE(v);
-                       memcpy(bt_stream_pos_get_addr(pos), &v, sizeof(v));
+                       memcpy(bt_ctf_stream_pos_get_addr(pos), &v, sizeof(v));
                        break;
                }
                default:
@@ -119,7 +122,7 @@ int aligned_integer_write(struct bt_stream_pos *pos,
                {
                        uint8_t v = value.signd;
 
-                       memcpy(bt_stream_pos_get_addr(pos), &v, sizeof(v));
+                       memcpy(bt_ctf_stream_pos_get_addr(pos), &v, sizeof(v));
                        break;
                }
                case 16:
@@ -128,7 +131,7 @@ int aligned_integer_write(struct bt_stream_pos *pos,
 
                        if (rbo)
                                v = GUINT16_SWAP_LE_BE(v);
-                       memcpy(bt_stream_pos_get_addr(pos), &v, sizeof(v));
+                       memcpy(bt_ctf_stream_pos_get_addr(pos), &v, sizeof(v));
                        break;
                }
                case 32:
@@ -137,7 +140,7 @@ int aligned_integer_write(struct bt_stream_pos *pos,
 
                        if (rbo)
                                v = GUINT32_SWAP_LE_BE(v);
-                       memcpy(bt_stream_pos_get_addr(pos), &v, sizeof(v));
+                       memcpy(bt_ctf_stream_pos_get_addr(pos), &v, sizeof(v));
                        break;
                }
                case 64:
@@ -146,7 +149,7 @@ int aligned_integer_write(struct bt_stream_pos *pos,
 
                        if (rbo)
                                v = GUINT64_SWAP_LE_BE(v);
-                       memcpy(bt_stream_pos_get_addr(pos), &v, sizeof(v));
+                       memcpy(bt_ctf_stream_pos_get_addr(pos), &v, sizeof(v));
                        break;
                }
                default:
@@ -154,15 +157,15 @@ int aligned_integer_write(struct bt_stream_pos *pos,
                }
        }
 
-       if (!bt_stream_pos_move(pos, size))
+       if (!bt_ctf_stream_pos_move(pos, size))
                return -EFAULT;
        return 0;
 }
 
 static
-int integer_write(struct bt_stream_pos *pos, union intval value,
+int integer_write(struct bt_ctf_stream_pos *pos, union intval value,
        unsigned int alignment, unsigned int size, bt_bool is_signed,
-       enum bt_byte_order byte_order)
+       enum bt_ctf_byte_order byte_order)
 {
        if (!(alignment % CHAR_BIT)
            && !(size % CHAR_BIT)) {
@@ -170,14 +173,14 @@ int integer_write(struct bt_stream_pos *pos, union intval value,
                        size, is_signed, byte_order);
        }
 
-       if (!bt_stream_pos_align(pos, alignment))
+       if (!bt_ctf_stream_pos_align(pos, alignment))
                return -EFAULT;
 
-       if (!bt_stream_pos_access_ok(pos, size))
+       if (!bt_ctf_stream_pos_access_ok(pos, size))
                return -EFAULT;
 
        if (!is_signed) {
-               if (byte_order == BT_BYTE_ORDER_LITTLE_ENDIAN)
+               if (byte_order == BT_CTF_BYTE_ORDER_LITTLE_ENDIAN)
                        bt_bitfield_write_le(mmap_align_addr(pos->base_mma) +
                                pos->mmap_base_offset, unsigned char,
                                pos->offset, size, value.unsignd);
@@ -186,7 +189,7 @@ int integer_write(struct bt_stream_pos *pos, union intval value,
                                pos->mmap_base_offset, unsigned char,
                                pos->offset, size, value.unsignd);
        } else {
-               if (byte_order == BT_BYTE_ORDER_LITTLE_ENDIAN)
+               if (byte_order == BT_CTF_BYTE_ORDER_LITTLE_ENDIAN)
                        bt_bitfield_write_le(mmap_align_addr(pos->base_mma) +
                                pos->mmap_base_offset, unsigned char,
                                pos->offset, size, value.signd);
@@ -196,46 +199,48 @@ int integer_write(struct bt_stream_pos *pos, union intval value,
                                pos->offset, size, value.signd);
        }
 
-       if (!bt_stream_pos_move(pos, size))
+       if (!bt_ctf_stream_pos_move(pos, size))
                return -EFAULT;
        return 0;
 }
 
 BT_HIDDEN
-int bt_field_integer_write(struct bt_field_integer *int_field,
-               struct bt_stream_pos *pos,
-               enum bt_byte_order native_byte_order)
+int bt_ctf_field_integer_write(struct bt_field_common *field,
+               struct bt_ctf_stream_pos *pos,
+               enum bt_ctf_byte_order native_byte_order)
 {
-       struct bt_field_type *type = int_field->parent.type;
-       struct bt_field_type_integer *int_type = (void *) type;
-       enum bt_byte_order byte_order;
+       struct bt_field_type_common_integer *int_type =
+               BT_FROM_COMMON(field->type);
+       struct bt_field_common_integer *int_field = BT_FROM_COMMON(field);
+       enum bt_ctf_byte_order byte_order;
        union intval value;
 
-       byte_order = int_type->user_byte_order;
+       byte_order = (int) int_type->user_byte_order;
        if (byte_order == BT_BYTE_ORDER_NATIVE) {
                byte_order = native_byte_order;
        }
 
        value.signd = int_field->payload.signd;
        value.unsignd = int_field->payload.unsignd;
-       return integer_write(pos, value, type->alignment,
+       return integer_write(pos, value, int_type->common.alignment,
                int_type->size, int_type->is_signed,
                byte_order);
 }
 
 BT_HIDDEN
-int bt_field_floating_point_write(
-               struct bt_field_floating_point *flt_field,
-               struct bt_stream_pos *pos,
-               enum bt_byte_order native_byte_order)
+int bt_ctf_field_floating_point_write(
+               struct bt_field_common *field,
+               struct bt_ctf_stream_pos *pos,
+               enum bt_ctf_byte_order native_byte_order)
 {
-       struct bt_field_type *type = flt_field->parent.type;
-       struct bt_field_type_floating_point *flt_type = (void *) type;
-       enum bt_byte_order byte_order;
+       struct bt_field_type_common_floating_point *flt_type =
+               BT_FROM_COMMON(field->type);
+       struct bt_field_common_floating_point *flt_field = BT_FROM_COMMON(field);
+       enum bt_ctf_byte_order byte_order;
        union intval value;
        unsigned int size;
 
-       byte_order = flt_type->user_byte_order;
+       byte_order = (int) flt_type->user_byte_order;
        if (byte_order == BT_BYTE_ORDER_NATIVE) {
                byte_order = native_byte_order;
        }
@@ -262,12 +267,12 @@ int bt_field_floating_point_write(
                return -EINVAL;
        }
 
-       return integer_write(pos, value, type->alignment, size, BT_FALSE,
-               byte_order);
+       return integer_write(pos, value, flt_type->common.alignment,
+               size, BT_FALSE, byte_order);
 }
 
 BT_HIDDEN
-void bt_stream_pos_packet_seek(struct bt_stream_pos *pos, size_t index,
+void bt_ctf_stream_pos_packet_seek(struct bt_ctf_stream_pos *pos, size_t index,
        int whence)
 {
        int ret;
diff --git a/lib/ctf-writer/stream-class.c b/lib/ctf-writer/stream-class.c
new file mode 100644 (file)
index 0000000..80c2a54
--- /dev/null
@@ -0,0 +1,626 @@
+/*
+ * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ * Copyright 2017-2018 Philippe Proulx <pproulx@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#define BT_LOG_TAG "CTF-WRITER-STREAM-CLASS"
+#include <babeltrace/lib-logging-internal.h>
+
+#include <babeltrace/ref.h>
+#include <babeltrace/ctf-writer/writer-internal.h>
+#include <babeltrace/ctf-writer/stream-class-internal.h>
+#include <babeltrace/ctf-writer/field-types-internal.h>
+#include <babeltrace/ctf-writer/event-internal.h>
+#include <babeltrace/ctf-writer/event.h>
+#include <babeltrace/ctf-writer/trace.h>
+#include <babeltrace/compiler-internal.h>
+#include <babeltrace/assert-internal.h>
+#include <babeltrace/assert-pre-internal.h>
+#include <inttypes.h>
+
+static
+int init_event_header(struct bt_ctf_stream_class *stream_class)
+{
+       int ret = 0;
+       struct bt_ctf_field_type *event_header_type =
+               bt_ctf_field_type_structure_create();
+       struct bt_ctf_field_type *_uint32_t =
+               get_field_type(FIELD_TYPE_ALIAS_UINT32_T);
+       struct bt_ctf_field_type *_uint64_t =
+               get_field_type(FIELD_TYPE_ALIAS_UINT64_T);
+
+       if (!event_header_type) {
+               BT_LOGE_STR("Cannot create empty structure field type.");
+               ret = -1;
+               goto end;
+       }
+
+       ret = bt_ctf_field_type_structure_add_field(event_header_type,
+               _uint32_t, "id");
+       if (ret) {
+               BT_LOGE_STR("Cannot add `id` field to event header field type.");
+               goto end;
+       }
+
+       ret = bt_ctf_field_type_structure_add_field(event_header_type,
+               _uint64_t, "timestamp");
+       if (ret) {
+               BT_LOGE_STR("Cannot add `timestamp` field to event header field type.");
+               goto end;
+       }
+
+       bt_put(stream_class->common.event_header_field_type);
+       stream_class->common.event_header_field_type =
+               (void *) event_header_type;
+       event_header_type = NULL;
+
+end:
+       if (ret) {
+               bt_put(event_header_type);
+       }
+
+       bt_put(_uint32_t);
+       bt_put(_uint64_t);
+       return ret;
+}
+
+static
+int init_packet_context(struct bt_ctf_stream_class *stream_class)
+{
+       int ret = 0;
+       struct bt_ctf_field_type *packet_context_type =
+               bt_ctf_field_type_structure_create();
+       struct bt_ctf_field_type *_uint64_t =
+               get_field_type(FIELD_TYPE_ALIAS_UINT64_T);
+       struct bt_ctf_field_type *ts_begin_end_uint64_t;
+
+       if (!packet_context_type) {
+               BT_LOGE_STR("Cannot create empty structure field type.");
+               ret = -1;
+               goto end;
+       }
+
+       ts_begin_end_uint64_t = bt_ctf_field_type_copy(_uint64_t);
+       if (!ts_begin_end_uint64_t) {
+               BT_LOGE_STR("Cannot copy integer field type for `timestamp_begin` and `timestamp_end` fields.");
+               ret = -1;
+               goto end;
+       }
+
+       /*
+        * We create a stream packet context as proposed in the CTF
+        * specification.
+        */
+       ret = bt_ctf_field_type_structure_add_field(packet_context_type,
+               ts_begin_end_uint64_t, "timestamp_begin");
+       if (ret) {
+               BT_LOGE_STR("Cannot add `timestamp_begin` field to event header field type.");
+               goto end;
+       }
+
+       ret = bt_ctf_field_type_structure_add_field(packet_context_type,
+               ts_begin_end_uint64_t, "timestamp_end");
+       if (ret) {
+               BT_LOGE_STR("Cannot add `timestamp_end` field to event header field type.");
+               goto end;
+       }
+
+       ret = bt_ctf_field_type_structure_add_field(packet_context_type,
+               _uint64_t, "content_size");
+       if (ret) {
+               BT_LOGE_STR("Cannot add `content_size` field to event header field type.");
+               goto end;
+       }
+
+       ret = bt_ctf_field_type_structure_add_field(packet_context_type,
+               _uint64_t, "packet_size");
+       if (ret) {
+               BT_LOGE_STR("Cannot add `packet_size` field to event header field type.");
+               goto end;
+       }
+
+       ret = bt_ctf_field_type_structure_add_field(packet_context_type,
+               _uint64_t, "events_discarded");
+       if (ret) {
+               BT_LOGE_STR("Cannot add `events_discarded` field to event header field type.");
+               goto end;
+       }
+
+       bt_put(stream_class->common.packet_context_field_type);
+       stream_class->common.packet_context_field_type =
+               (void *) packet_context_type;
+       packet_context_type = NULL;
+
+end:
+       if (ret) {
+               bt_put(packet_context_type);
+               goto end;
+       }
+
+       bt_put(_uint64_t);
+       bt_put(ts_begin_end_uint64_t);
+       return ret;
+}
+
+static
+void bt_ctf_stream_class_destroy(struct bt_object *obj)
+{
+       struct bt_ctf_stream_class *stream_class;
+
+       stream_class = (void *) obj;
+       BT_LOGD("Destroying CTF writer stream class: addr=%p, name=\"%s\", id=%" PRId64,
+               stream_class, bt_ctf_stream_class_get_name(stream_class),
+               bt_ctf_stream_class_get_id(stream_class));
+       bt_stream_class_common_finalize(BT_TO_COMMON(stream_class));
+       bt_put(stream_class->clock);
+       g_free(stream_class);
+}
+
+struct bt_ctf_stream_class *bt_ctf_stream_class_create(const char *name)
+{
+       struct bt_ctf_stream_class *stream_class;
+       int ret;
+
+       BT_LOGD("Creating CTF writer stream class object: name=\"%s\"", name);
+       stream_class = g_new0(struct bt_ctf_stream_class, 1);
+       if (!stream_class) {
+               BT_LOGE_STR("Failed to allocate one CTF writer stream class.");
+               goto error;
+       }
+
+       ret = bt_stream_class_common_initialize(BT_TO_COMMON(stream_class),
+               name, bt_ctf_stream_class_destroy);
+       if (ret) {
+               /* bt_stream_class_common_initialize() logs errors */
+               goto error;
+       }
+
+       ret = init_event_header(stream_class);
+       if (ret) {
+               BT_LOGE_STR("Cannot initialize stream class's event header field type.");
+               goto error;
+       }
+
+       ret = init_packet_context(stream_class);
+       if (ret) {
+               BT_LOGE_STR("Cannot initialize stream class's packet context field type.");
+               goto error;
+       }
+
+       BT_LOGD("Created CTF writer stream class object: addr=%p, name=\"%s\"",
+               stream_class, name);
+       return stream_class;
+
+error:
+       BT_PUT(stream_class);
+       return stream_class;
+}
+
+static
+int try_map_clock_class(struct bt_ctf_stream_class *stream_class,
+               struct bt_ctf_field_type *parent_ft, const char *field_name)
+{
+       struct bt_ctf_clock_class *mapped_clock_class = NULL;
+       int ret = 0;
+       struct bt_ctf_field_type *ft =
+               bt_ctf_field_type_structure_get_field_type_by_name(parent_ft,
+                       field_name);
+
+       BT_ASSERT(stream_class->clock);
+
+       if (!ft) {
+               /* Field does not exist: not an error */
+               goto end;
+       }
+
+       BT_ASSERT(((struct bt_field_type_common *) ft)->id ==
+               BT_CTF_FIELD_TYPE_ID_INTEGER);
+       mapped_clock_class =
+               bt_ctf_field_type_integer_get_mapped_clock_class(ft);
+       if (!mapped_clock_class) {
+               struct bt_ctf_field_type *ft_copy;
+
+               if (!stream_class->clock) {
+                       BT_LOGW("Cannot automatically set field's type mapped clock class: stream class's clock is not set: "
+                               "stream-class-addr=%p, stream-class-name=\"%s\", "
+                               "stream-class-id=%" PRId64 ", ft-addr=%p",
+                               stream_class,
+                               bt_ctf_stream_class_get_name(stream_class),
+                               bt_ctf_stream_class_get_id(stream_class), ft);
+                       ret = -1;
+                       goto end;
+               }
+
+               ft_copy = bt_ctf_field_type_copy(ft);
+               if (!ft_copy) {
+                       BT_LOGE("Failed to copy integer field type: ft-addr=%p",
+                               ft);
+               }
+
+               ret = bt_field_type_common_integer_set_mapped_clock_class_no_check_frozen(
+                       (void *) ft_copy,
+                       BT_TO_COMMON(stream_class->clock->clock_class));
+               BT_ASSERT(ret == 0);
+
+               ret = bt_field_type_common_structure_replace_field(
+                       (void *) parent_ft, field_name, (void *) ft_copy);
+               bt_put(ft_copy);
+               BT_LOGV("Automatically mapped field type to stream class's clock class: "
+                       "stream-class-addr=%p, stream-class-name=\"%s\", "
+                       "stream-class-id=%" PRId64 ", ft-addr=%p, "
+                       "ft-copy-addr=%p",
+                       stream_class,
+                       bt_ctf_stream_class_get_name(stream_class),
+                       bt_ctf_stream_class_get_id(stream_class), ft, ft_copy);
+       }
+
+end:
+       bt_put(ft);
+       bt_put(mapped_clock_class);
+       return ret;
+}
+
+BT_HIDDEN
+int bt_ctf_stream_class_map_clock_class(
+               struct bt_ctf_stream_class *stream_class,
+               struct bt_ctf_field_type *packet_context_type,
+               struct bt_ctf_field_type *event_header_type)
+{
+       int ret = 0;
+
+       BT_ASSERT(stream_class);
+
+       if (!stream_class->clock) {
+               /* No clock class to map to */
+               goto end;
+       }
+
+       if (packet_context_type) {
+               if (try_map_clock_class(stream_class, packet_context_type,
+                               "timestamp_begin")) {
+                       BT_LOGE_STR("Cannot automatically set stream class's packet context field type's `timestamp_begin` field's mapped clock class.");
+                       ret = -1;
+                       goto end;
+               }
+
+               if (try_map_clock_class(stream_class, packet_context_type,
+                               "timestamp_end")) {
+                       BT_LOGE_STR("Cannot automatically set stream class's packet context field type's `timestamp_end` field's mapped clock class.");
+                       ret = -1;
+                       goto end;
+               }
+       }
+
+       if (event_header_type) {
+               if (try_map_clock_class(stream_class, event_header_type,
+                               "timestamp")) {
+                       BT_LOGE_STR("Cannot automatically set stream class's event header field type's `timestamp` field's mapped clock class.");
+                       ret = -1;
+                       goto end;
+               }
+       }
+
+end:
+       return ret;
+}
+
+struct bt_ctf_clock *bt_ctf_stream_class_get_clock(
+               struct bt_ctf_stream_class *stream_class)
+{
+       struct bt_ctf_clock *clock = NULL;
+
+       if (!stream_class) {
+               BT_LOGW_STR("Invalid parameter: stream class is NULL.");
+               goto end;
+       }
+
+       if (!stream_class->clock) {
+               BT_LOGV("Stream class has no clock: "
+                       "addr=%p, name=\"%s\", id=%" PRId64,
+                       stream_class,
+                       bt_ctf_stream_class_get_name(stream_class),
+                       bt_ctf_stream_class_get_id(stream_class));
+               goto end;
+       }
+
+       clock = bt_get(stream_class->clock);
+
+end:
+       return clock;
+}
+
+int bt_ctf_stream_class_set_clock(
+               struct bt_ctf_stream_class *stream_class,
+               struct bt_ctf_clock *clock)
+{
+       int ret = 0;
+
+       if (!stream_class || !clock) {
+               BT_LOGW("Invalid parameter: stream class or clock is NULL: "
+                       "stream-class-addr=%p, clock-addr=%p",
+                       stream_class, clock);
+               ret = -1;
+               goto end;
+       }
+
+       if (stream_class->common.frozen) {
+               BT_LOGW("Invalid parameter: stream class is frozen: "
+                       "addr=%p, name=\"%s\", id=%" PRId64,
+                       stream_class,
+                       bt_ctf_stream_class_get_name(stream_class),
+                       bt_ctf_stream_class_get_id(stream_class));
+               ret = -1;
+               goto end;
+       }
+
+       /* Replace the current clock of this stream class. */
+       bt_put(stream_class->clock);
+       stream_class->clock = bt_get(clock);
+       BT_LOGV("Set stream class's clock: "
+               "addr=%p, name=\"%s\", id=%" PRId64 ", "
+               "clock-addr=%p, clock-name=\"%s\"",
+               stream_class,
+               bt_ctf_stream_class_get_name(stream_class),
+               bt_ctf_stream_class_get_id(stream_class),
+               stream_class->clock,
+               bt_ctf_clock_get_name(stream_class->clock));
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+int bt_ctf_stream_class_serialize(struct bt_ctf_stream_class *stream_class,
+               struct metadata_context *context)
+{
+       int ret = 0;
+       size_t i;
+       struct bt_ctf_trace *trace;
+       struct bt_ctf_field_type *packet_header_type = NULL;
+
+       BT_LOGD("Serializing stream class's metadata: "
+               "stream-class-addr=%p, stream-class-name=\"%s\", "
+               "stream-class-id=%" PRId64 ", metadata-context-addr=%p",
+               stream_class,
+               bt_ctf_stream_class_get_name(stream_class),
+               bt_ctf_stream_class_get_id(stream_class), context);
+       g_string_assign(context->field_name, "");
+       context->current_indentation_level = 1;
+       if (!stream_class->common.id_set) {
+               BT_LOGW_STR("Stream class's ID is not set.");
+               ret = -1;
+               goto end;
+       }
+
+       g_string_append(context->string, "stream {\n");
+
+       /*
+        * The reference to the trace is only borrowed since the
+        * serialization of the stream class might have been triggered
+        * by the trace's destruction. In such a case, the trace's
+        * reference count would, unexepectedly, go through the sequence
+        * 1 -> 0 -> 1 -> 0 -> ..., provoking an endless loop of destruction
+        * and serialization.
+        */
+       trace = BT_FROM_COMMON(bt_stream_class_common_borrow_trace(
+               BT_TO_COMMON(stream_class)));
+       BT_ASSERT(trace);
+       packet_header_type = bt_ctf_trace_get_packet_header_field_type(trace);
+       trace = NULL;
+       if (packet_header_type) {
+               struct bt_ctf_field_type *stream_id_type;
+
+               stream_id_type =
+                       bt_ctf_field_type_structure_get_field_type_by_name(
+                               packet_header_type, "stream_id");
+               if (stream_id_type) {
+                       /*
+                        * Only set the stream's id if the trace's packet header
+                        * contains a stream_id field. This field is only
+                        * needed if the trace contains only one stream
+                        * class.
+                        */
+                       g_string_append_printf(context->string,
+                               "\tid = %" PRId64 ";\n",
+                               stream_class->common.id);
+               }
+               bt_put(stream_id_type);
+       }
+       if (stream_class->common.event_header_field_type) {
+               BT_LOGD_STR("Serializing stream class's event header field type's metadata.");
+               g_string_append(context->string, "\tevent.header := ");
+               ret = bt_ctf_field_type_serialize_recursive(
+                       (void *) stream_class->common.event_header_field_type,
+                       context);
+               if (ret) {
+                       BT_LOGW("Cannot serialize stream class's event header field type's metadata: "
+                               "ret=%d", ret);
+                       goto end;
+               }
+               g_string_append(context->string, ";");
+       }
+
+
+       if (stream_class->common.packet_context_field_type) {
+               BT_LOGD_STR("Serializing stream class's packet context field type's metadata.");
+               g_string_append(context->string, "\n\n\tpacket.context := ");
+               ret = bt_ctf_field_type_serialize_recursive(
+                       (void *) stream_class->common.packet_context_field_type,
+                       context);
+               if (ret) {
+                       BT_LOGW("Cannot serialize stream class's packet context field type's metadata: "
+                               "ret=%d", ret);
+                       goto end;
+               }
+               g_string_append(context->string, ";");
+       }
+
+       if (stream_class->common.event_context_field_type) {
+               BT_LOGD_STR("Serializing stream class's event context field type's metadata.");
+               g_string_append(context->string, "\n\n\tevent.context := ");
+               ret = bt_ctf_field_type_serialize_recursive(
+                       (void *) stream_class->common.event_context_field_type,
+                       context);
+               if (ret) {
+                       BT_LOGW("Cannot serialize stream class's event context field type's metadata: "
+                               "ret=%d", ret);
+                       goto end;
+               }
+               g_string_append(context->string, ";");
+       }
+
+       g_string_append(context->string, "\n};\n\n");
+
+       for (i = 0; i < stream_class->common.event_classes->len; i++) {
+               struct bt_ctf_event_class *event_class =
+                       stream_class->common.event_classes->pdata[i];
+
+               ret = bt_ctf_event_class_serialize(event_class, context);
+               if (ret) {
+                       BT_LOGW("Cannot serialize event class's metadata: "
+                               "event-class-addr=%p, event-class-name=\"%s\", "
+                               "event-class-id=%" PRId64,
+                               event_class,
+                               bt_ctf_event_class_get_name(event_class),
+                               bt_ctf_event_class_get_id(event_class));
+                       goto end;
+               }
+       }
+
+end:
+       bt_put(packet_header_type);
+       context->current_indentation_level = 0;
+       return ret;
+}
+
+struct bt_ctf_trace *bt_ctf_stream_class_get_trace(
+               struct bt_ctf_stream_class *stream_class)
+{
+       return BT_FROM_COMMON(bt_stream_class_common_get_trace(
+               BT_TO_COMMON(stream_class)));
+}
+
+const char *bt_ctf_stream_class_get_name(
+               struct bt_ctf_stream_class *stream_class)
+{
+       return bt_stream_class_common_get_name(BT_TO_COMMON(stream_class));
+}
+
+int bt_ctf_stream_class_set_name(
+               struct bt_ctf_stream_class *stream_class, const char *name)
+{
+       return bt_stream_class_common_set_name(BT_TO_COMMON(stream_class),
+               name);
+}
+
+int64_t bt_ctf_stream_class_get_id(
+               struct bt_ctf_stream_class *stream_class)
+{
+       return bt_stream_class_common_get_id(BT_TO_COMMON(stream_class));
+}
+
+int bt_ctf_stream_class_set_id(
+               struct bt_ctf_stream_class *stream_class, uint64_t id)
+{
+       return bt_stream_class_common_set_id(BT_TO_COMMON(stream_class), id);
+}
+
+struct bt_ctf_field_type *bt_ctf_stream_class_get_packet_context_type(
+               struct bt_ctf_stream_class *stream_class)
+{
+       return BT_FROM_COMMON(
+               bt_stream_class_common_get_packet_context_field_type(
+                       BT_TO_COMMON(stream_class)));
+}
+
+int bt_ctf_stream_class_set_packet_context_type(
+               struct bt_ctf_stream_class *stream_class,
+               struct bt_ctf_field_type *packet_context_type)
+{
+       return bt_stream_class_common_set_packet_context_field_type(
+               BT_TO_COMMON(stream_class), (void *) packet_context_type);
+}
+
+struct bt_ctf_field_type *
+bt_ctf_stream_class_get_event_header_type(
+               struct bt_ctf_stream_class *stream_class)
+{
+       return BT_FROM_COMMON(
+               bt_stream_class_common_get_event_header_field_type(
+                       BT_TO_COMMON(stream_class)));
+}
+
+int bt_ctf_stream_class_set_event_header_type(
+               struct bt_ctf_stream_class *stream_class,
+               struct bt_ctf_field_type *event_header_type)
+{
+       return bt_stream_class_common_set_event_header_field_type(
+               BT_TO_COMMON(stream_class), (void *) event_header_type);
+}
+
+struct bt_ctf_field_type *
+bt_ctf_stream_class_get_event_context_type(
+               struct bt_ctf_stream_class *stream_class)
+{
+       return BT_FROM_COMMON(
+               bt_stream_class_common_get_event_context_field_type(
+                       BT_TO_COMMON(stream_class)));
+}
+
+int bt_ctf_stream_class_set_event_context_type(
+               struct bt_ctf_stream_class *stream_class,
+               struct bt_ctf_field_type *event_context_type)
+{
+       return bt_stream_class_common_set_event_context_field_type(
+               BT_TO_COMMON(stream_class), (void *) event_context_type);
+}
+
+int64_t bt_ctf_stream_class_get_event_class_count(
+               struct bt_ctf_stream_class *stream_class)
+{
+       return bt_stream_class_common_get_event_class_count(
+               BT_TO_COMMON(stream_class));
+}
+
+struct bt_ctf_event_class *bt_ctf_stream_class_get_event_class_by_index(
+               struct bt_ctf_stream_class *stream_class, uint64_t index)
+{
+       return BT_FROM_COMMON(
+               bt_stream_class_common_get_event_class_by_index(
+                       BT_TO_COMMON(stream_class), index));
+}
+
+struct bt_ctf_event_class *bt_ctf_stream_class_get_event_class_by_id(
+               struct bt_ctf_stream_class *stream_class, uint64_t id)
+{
+       return BT_FROM_COMMON(
+               bt_stream_class_common_get_event_class_by_id(
+                       BT_TO_COMMON(stream_class), id));
+}
+
+int bt_ctf_stream_class_add_event_class(
+               struct bt_ctf_stream_class *stream_class,
+               struct bt_ctf_event_class *event_class)
+{
+       return bt_stream_class_common_add_event_class(
+               BT_TO_COMMON(stream_class), BT_TO_COMMON(event_class),
+               (bt_validation_flag_copy_field_type_func) bt_ctf_field_type_copy);
+}
diff --git a/lib/ctf-writer/stream.c b/lib/ctf-writer/stream.c
new file mode 100644 (file)
index 0000000..aa6a525
--- /dev/null
@@ -0,0 +1,1953 @@
+/*
+ * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ * Copyright 2017-2018 Philippe Proulx <pproulx@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#define BT_LOG_TAG "CTF-WRITER-STREAM"
+#include <babeltrace/lib-logging-internal.h>
+
+#include <babeltrace/ref.h>
+#include <babeltrace/ctf-ir/event-class-internal.h>
+#include <babeltrace/ctf-writer/writer-internal.h>
+#include <babeltrace/ctf-writer/stream.h>
+#include <babeltrace/ctf-writer/stream-internal.h>
+#include <babeltrace/ctf-writer/stream-class-internal.h>
+#include <babeltrace/ctf-writer/field-types.h>
+#include <babeltrace/ctf-writer/fields-internal.h>
+#include <babeltrace/ctf-writer/trace-internal.h>
+#include <babeltrace/ctf-writer/event-internal.h>
+#include <babeltrace/compiler-internal.h>
+#include <babeltrace/assert-internal.h>
+#include <babeltrace/assert-pre-internal.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <inttypes.h>
+
+static
+void bt_ctf_stream_destroy(struct bt_object *obj);
+
+static
+int try_set_structure_field_integer(struct bt_ctf_field *, char *, uint64_t);
+
+static
+int set_integer_field_value(struct bt_ctf_field* field, uint64_t value)
+{
+       int ret = 0;
+       struct bt_ctf_field_type *field_type = NULL;
+
+       if (!field) {
+               BT_LOGW_STR("Invalid parameter: field is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       field_type = bt_ctf_field_get_type(field);
+       BT_ASSERT(field_type);
+
+       if (bt_ctf_field_type_get_type_id(field_type) !=
+                       BT_CTF_FIELD_TYPE_ID_INTEGER) {
+               /* Not an integer and the value is unset, error. */
+               BT_LOGW("Invalid parameter: field's type is not an integer field type: "
+                       "field-addr=%p, ft-addr=%p, ft-id=%s",
+                       field, field_type,
+                       bt_common_field_type_id_string((int)
+                               bt_ctf_field_type_get_type_id(field_type)));
+               ret = -1;
+               goto end;
+       }
+
+       if (bt_ctf_field_type_integer_is_signed(field_type)) {
+               ret = bt_ctf_field_integer_signed_set_value(field, (int64_t) value);
+               if (ret) {
+                       /* Value is out of range, error. */
+                       BT_LOGW("Cannot set signed integer field's value: "
+                               "addr=%p, value=%" PRId64,
+                               field, (int64_t) value);
+                       goto end;
+               }
+       } else {
+               ret = bt_ctf_field_integer_unsigned_set_value(field, value);
+               if (ret) {
+                       /* Value is out of range, error. */
+                       BT_LOGW("Cannot set unsigned integer field's value: "
+                               "addr=%p, value=%" PRIu64,
+                               field, value);
+                       goto end;
+               }
+       }
+end:
+       bt_put(field_type);
+       return ret;
+}
+
+static
+int set_packet_header_magic(struct bt_ctf_stream *stream)
+{
+       int ret = 0;
+       struct bt_ctf_field *magic_field = bt_ctf_field_structure_get_field_by_name(
+               stream->packet_header, "magic");
+       const uint32_t magic_value = 0xc1fc1fc1;
+
+       BT_ASSERT(stream);
+
+       if (!magic_field) {
+               /* No magic field found. Not an error, skip. */
+               BT_LOGV("No field named `magic` in packet header: skipping: "
+                       "stream-addr=%p, stream-name=\"%s\"",
+                       stream, bt_ctf_stream_get_name(stream));
+               goto end;
+       }
+
+       ret = bt_ctf_field_integer_unsigned_set_value(magic_field,
+               (uint64_t) magic_value);
+
+       if (ret) {
+               BT_LOGW("Cannot set packet header field's `magic` integer field's value: "
+                       "stream-addr=%p, stream-name=\"%s\", field-addr=%p, value=%" PRIu64,
+                       stream, bt_ctf_stream_get_name(stream),
+                       magic_field, (uint64_t) magic_value);
+       } else {
+               BT_LOGV("Set packet header field's `magic` field's value: "
+                       "stream-addr=%p, stream-name=\"%s\", field-addr=%p, value=%" PRIu64,
+                       stream, bt_ctf_stream_get_name(stream),
+                       magic_field, (uint64_t) magic_value);
+       }
+end:
+       bt_put(magic_field);
+       return ret;
+}
+
+static
+int set_packet_header_uuid(struct bt_ctf_stream *stream)
+{
+       int ret = 0;
+       int64_t i;
+       struct bt_ctf_trace *trace = NULL;
+       struct bt_ctf_field *uuid_field = bt_ctf_field_structure_get_field_by_name(
+               stream->packet_header, "uuid");
+
+       BT_ASSERT(stream);
+
+       if (!uuid_field) {
+               /* No uuid field found. Not an error, skip. */
+               BT_LOGV("No field named `uuid` in packet header: skipping: "
+                       "stream-addr=%p, stream-name=\"%s\"",
+                       stream, bt_ctf_stream_get_name(stream));
+               goto end;
+       }
+
+       trace = (struct bt_ctf_trace *) bt_object_get_parent(stream);
+       for (i = 0; i < 16; i++) {
+               struct bt_ctf_field *uuid_element =
+                       bt_ctf_field_array_get_field(uuid_field, i);
+
+               ret = bt_ctf_field_integer_unsigned_set_value(
+                       uuid_element, (uint64_t) trace->common.uuid[i]);
+               bt_put(uuid_element);
+               if (ret) {
+                       BT_LOGW("Cannot set integer field's value (for `uuid` packet header field): "
+                               "stream-addr=%p, stream-name=\"%s\", field-addr=%p, "
+                               "value=%" PRIu64 ", index=%" PRId64,
+                               stream, bt_ctf_stream_get_name(stream),
+                               uuid_element, (uint64_t) trace->common.uuid[i], i);
+                       goto end;
+               }
+       }
+
+       BT_LOGV("Set packet header field's `uuid` field's value: "
+               "stream-addr=%p, stream-name=\"%s\", field-addr=%p",
+               stream, bt_ctf_stream_get_name(stream), uuid_field);
+
+end:
+       bt_put(uuid_field);
+       BT_PUT(trace);
+       return ret;
+}
+static
+int set_packet_header_stream_id(struct bt_ctf_stream *stream)
+{
+       int ret = 0;
+       uint32_t stream_id;
+       struct bt_ctf_field *stream_id_field =
+               bt_ctf_field_structure_get_field_by_name(
+                       stream->packet_header, "stream_id");
+
+       if (!stream_id_field) {
+               /* No stream_id field found. Not an error, skip. */
+               BT_LOGV("No field named `stream_id` in packet header: skipping: "
+                       "stream-addr=%p, stream-name=\"%s\"",
+                       stream, bt_ctf_stream_get_name(stream));
+               goto end;
+       }
+
+       stream_id = stream->common.stream_class->id;
+       ret = bt_ctf_field_integer_unsigned_set_value(stream_id_field,
+               (uint64_t) stream_id);
+       if (ret) {
+               BT_LOGW("Cannot set packet header field's `stream_id` integer field's value: "
+                       "stream-addr=%p, stream-name=\"%s\", field-addr=%p, value=%" PRIu64,
+                       stream, bt_ctf_stream_get_name(stream),
+                       stream_id_field, (uint64_t) stream_id);
+       } else {
+               BT_LOGV("Set packet header field's `stream_id` field's value: "
+                       "stream-addr=%p, stream-name=\"%s\", field-addr=%p, value=%" PRIu64,
+                       stream, bt_ctf_stream_get_name(stream),
+                       stream_id_field, (uint64_t) stream_id);
+       }
+
+end:
+       bt_put(stream_id_field);
+       return ret;
+}
+
+static
+int auto_populate_packet_header(struct bt_ctf_stream *stream)
+{
+       int ret = 0;
+
+       if (!stream->packet_header) {
+               goto end;
+       }
+
+       ret = set_packet_header_magic(stream);
+       if (ret) {
+               BT_LOGW("Cannot set packet header's magic number field: "
+                       "stream-addr=%p, stream-name=\"%s\"",
+                       stream, bt_ctf_stream_get_name(stream));
+               goto end;
+       }
+
+       ret = set_packet_header_uuid(stream);
+       if (ret) {
+               BT_LOGW("Cannot set packet header's UUID field: "
+                       "stream-addr=%p, stream-name=\"%s\"",
+                       stream, bt_ctf_stream_get_name(stream));
+               goto end;
+       }
+
+       ret = set_packet_header_stream_id(stream);
+       if (ret) {
+               BT_LOGW("Cannot set packet header's stream class ID field: "
+                       "stream-addr=%p, stream-name=\"%s\"",
+                       stream, bt_ctf_stream_get_name(stream));
+               goto end;
+       }
+
+       BT_LOGV("Automatically populated stream's packet header's known fields: "
+               "stream-addr=%p, stream-name=\"%s\"",
+               stream, bt_ctf_stream_get_name(stream));
+
+end:
+       return ret;
+}
+
+static
+int set_packet_context_packet_size(struct bt_ctf_stream *stream)
+{
+       int ret = 0;
+       struct bt_ctf_field *field = bt_ctf_field_structure_get_field_by_name(
+               stream->packet_context, "packet_size");
+
+       BT_ASSERT(stream);
+
+       if (!field) {
+               /* No packet size field found. Not an error, skip. */
+               BT_LOGV("No field named `packet_size` in packet context: skipping: "
+                       "stream-addr=%p, stream-name=\"%s\"",
+                       stream, bt_ctf_stream_get_name(stream));
+               goto end;
+       }
+
+       ret = bt_ctf_field_integer_unsigned_set_value(field,
+               stream->pos.packet_size);
+       if (ret) {
+               BT_LOGW("Cannot set packet context field's `packet_size` integer field's value: "
+                       "stream-addr=%p, stream-name=\"%s\", field-addr=%p, value=%" PRIu64,
+                       stream, bt_ctf_stream_get_name(stream),
+                       field, stream->pos.packet_size);
+       } else {
+               BT_LOGV("Set packet context field's `packet_size` field's value: "
+                       "stream-addr=%p, stream-name=\"%s\", field-addr=%p, value=%" PRIu64,
+                       stream, bt_ctf_stream_get_name(stream),
+                       field, stream->pos.packet_size);
+       }
+
+end:
+       bt_put(field);
+       return ret;
+}
+
+static
+int set_packet_context_content_size(struct bt_ctf_stream *stream)
+{
+       int ret = 0;
+       struct bt_ctf_field *field = bt_ctf_field_structure_get_field_by_name(
+               stream->packet_context, "content_size");
+
+       BT_ASSERT(stream);
+
+       if (!field) {
+               /* No content size field found. Not an error, skip. */
+               BT_LOGV("No field named `content_size` in packet context: skipping: "
+                       "stream-addr=%p, stream-name=\"%s\"",
+                       stream, bt_ctf_stream_get_name(stream));
+               goto end;
+       }
+
+       ret = bt_ctf_field_integer_unsigned_set_value(field,
+               stream->pos.offset);
+       if (ret) {
+               BT_LOGW("Cannot set packet context field's `content_size` integer field's value: "
+                       "stream-addr=%p, stream-name=\"%s\", field-addr=%p, value=%" PRId64,
+                       stream, bt_ctf_stream_get_name(stream),
+                       field, stream->pos.offset);
+       } else {
+               BT_LOGV("Set packet context field's `content_size` field's value: "
+                       "stream-addr=%p, stream-name=\"%s\", field-addr=%p, value=%" PRId64,
+                       stream, bt_ctf_stream_get_name(stream),
+                       field, stream->pos.offset);
+       }
+
+end:
+       bt_put(field);
+       return ret;
+}
+
+static
+int set_packet_context_events_discarded(struct bt_ctf_stream *stream)
+{
+       int ret = 0;
+       struct bt_ctf_field *field = bt_ctf_field_structure_get_field_by_name(
+               stream->packet_context, "events_discarded");
+
+       BT_ASSERT(stream);
+
+       if (!field) {
+               /* No discarded events count field found. Not an error, skip. */
+               BT_LOGV("No field named `events_discarded` in packet context: skipping: "
+                       "stream-addr=%p, stream-name=\"%s\"",
+                       stream, bt_ctf_stream_get_name(stream));
+               goto end;
+       }
+
+       /*
+        * If the field is set by the user, make sure that the value is
+        * greater than or equal to the stream's current count of
+        * discarded events. We do not allow wrapping here. If it's
+        * valid, update the stream's current count.
+        */
+       if (bt_ctf_field_is_set_recursive(field)) {
+               uint64_t user_val;
+
+               ret = bt_ctf_field_integer_unsigned_get_value(field,
+                       &user_val);
+               if (ret) {
+                       BT_LOGW("Cannot get packet context `events_discarded` field's unsigned value: "
+                               "stream-addr=%p, stream-name=\"%s\", field-addr=%p",
+                               stream, bt_ctf_stream_get_name(stream), field);
+                       goto end;
+               }
+
+               if (user_val < stream->discarded_events) {
+                       BT_LOGW("Invalid packet context `events_discarded` field's unsigned value: "
+                               "value is lesser than the stream's current discarded events count: "
+                               "stream-addr=%p, stream-name=\"%s\", field-addr=%p, "
+                               "value=%" PRIu64 ", "
+                               "stream-discarded-events-count=%" PRIu64,
+                               stream, bt_ctf_stream_get_name(stream), field,
+                               user_val, stream->discarded_events);
+                       goto end;
+               }
+
+               stream->discarded_events = user_val;
+       } else {
+               ret = bt_ctf_field_integer_unsigned_set_value(field,
+                       stream->discarded_events);
+               if (ret) {
+                       BT_LOGW("Cannot set packet context field's `events_discarded` integer field's value: "
+                               "stream-addr=%p, stream-name=\"%s\", field-addr=%p, value=%" PRIu64,
+                               stream, bt_ctf_stream_get_name(stream),
+                               field, stream->discarded_events);
+               } else {
+                       BT_LOGV("Set packet context field's `events_discarded` field's value: "
+                               "stream-addr=%p, stream-name=\"%s\", field-addr=%p, value=%" PRIu64,
+                               stream, bt_ctf_stream_get_name(stream),
+                               field, stream->discarded_events);
+               }
+       }
+
+end:
+       bt_put(field);
+       return ret;
+}
+
+static
+void update_clock_value(uint64_t *val, uint64_t new_val,
+               unsigned int new_val_size)
+{
+       const uint64_t pow2 = 1ULL << new_val_size;
+       const uint64_t mask = pow2 - 1;
+       uint64_t val_masked;
+
+#ifdef BT_LOG_ENABLED_VERBOSE
+       uint64_t old_val = *val;
+#endif
+
+       if (new_val_size == 64) {
+               *val = new_val;
+               goto end;
+       }
+
+       val_masked = *val & mask;
+
+       if (new_val < val_masked) {
+               /* Wrapped once */
+               new_val |= pow2;
+       }
+
+       *val &= ~mask;
+       *val |= new_val;
+
+end:
+       BT_LOGV("Updated clock value: old-val=%" PRIu64 ", new-val=%" PRIu64,
+               old_val, *val);
+       return;
+}
+
+static
+int visit_field_update_clock_value(struct bt_ctf_field *field, uint64_t *val)
+{
+       int ret = 0;
+       struct bt_field_common *field_common = (void *) field;
+
+       if (!field) {
+               goto end;
+       }
+
+       switch (bt_ctf_field_get_type_id(field)) {
+       case BT_CTF_FIELD_TYPE_ID_INTEGER:
+       {
+               struct bt_ctf_clock_class *cc =
+                       bt_ctf_field_type_integer_get_mapped_clock_class(
+                               (void *) field_common->type);
+               int val_size;
+               uint64_t uval;
+
+               if (!cc) {
+                       goto end;
+               }
+
+               bt_put(cc);
+               val_size = bt_ctf_field_type_integer_get_size(
+                       (void *) field_common->type);
+               BT_ASSERT(val_size >= 1);
+
+               if (bt_ctf_field_type_integer_is_signed(
+                               (void *) field_common->type)) {
+                       int64_t ival;
+
+                       ret = bt_ctf_field_integer_signed_get_value(field, &ival);
+                       uval = (uint64_t) ival;
+               } else {
+                       ret = bt_ctf_field_integer_unsigned_get_value(field, &uval);
+               }
+
+               if (ret) {
+                       /* Not set */
+                       goto end;
+               }
+
+               update_clock_value(val, uval, val_size);
+               break;
+       }
+       case BT_CTF_FIELD_TYPE_ID_ENUM:
+       {
+               struct bt_ctf_field *int_field =
+                       bt_ctf_field_enumeration_get_container(field);
+
+               BT_ASSERT(int_field);
+               ret = visit_field_update_clock_value(int_field, val);
+               bt_put(int_field);
+               break;
+       }
+       case BT_CTF_FIELD_TYPE_ID_ARRAY:
+       {
+               uint64_t i;
+               int64_t len = bt_ctf_field_type_array_get_length(
+                       (void *) field_common->type);
+
+               BT_ASSERT(len >= 0);
+
+               for (i = 0; i < len; i++) {
+                       struct bt_ctf_field *elem_field =
+                               bt_ctf_field_array_get_field(field, i);
+
+                       BT_ASSERT(elem_field);
+                       ret = visit_field_update_clock_value(elem_field, val);
+                       bt_put(elem_field);
+                       if (ret) {
+                               goto end;
+                       }
+               }
+               break;
+       }
+       case BT_CTF_FIELD_TYPE_ID_SEQUENCE:
+       {
+               uint64_t i;
+               int64_t len = bt_field_common_sequence_get_int_length(
+                       (void *) field);
+
+               if (len < 0) {
+                       ret = -1;
+                       goto end;
+               }
+
+               for (i = 0; i < len; i++) {
+                       struct bt_ctf_field *elem_field =
+                               bt_ctf_field_sequence_get_field(field, i);
+
+                       BT_ASSERT(elem_field);
+                       ret = visit_field_update_clock_value(elem_field, val);
+                       bt_put(elem_field);
+                       if (ret) {
+                               goto end;
+                       }
+               }
+               break;
+       }
+       case BT_CTF_FIELD_TYPE_ID_STRUCT:
+       {
+               uint64_t i;
+               int64_t len = bt_ctf_field_type_structure_get_field_count(
+                       (void *) field_common->type);
+
+               BT_ASSERT(len >= 0);
+
+               for (i = 0; i < len; i++) {
+                       struct bt_ctf_field *member_field =
+                               bt_ctf_field_structure_get_field_by_index(field, i);
+
+                       BT_ASSERT(member_field);
+                       ret = visit_field_update_clock_value(member_field, val);
+                       bt_put(member_field);
+                       if (ret) {
+                               goto end;
+                       }
+               }
+               break;
+       }
+       case BT_CTF_FIELD_TYPE_ID_VARIANT:
+       {
+               struct bt_ctf_field *cur_field =
+                       bt_ctf_field_variant_get_current_field(field);
+
+               if (!cur_field) {
+                       ret = -1;
+                       goto end;
+               }
+
+               ret = visit_field_update_clock_value(cur_field, val);
+               bt_put(cur_field);
+               break;
+       }
+       default:
+               break;
+       }
+
+end:
+       return ret;
+}
+
+int visit_event_update_clock_value(struct bt_ctf_event *event, uint64_t *val)
+{
+       int ret = 0;
+       struct bt_ctf_field *field;
+
+       field = bt_ctf_event_get_header(event);
+       ret = visit_field_update_clock_value(field, val);
+       bt_put(field);
+       if (ret) {
+               BT_LOGW_STR("Cannot automatically update clock value in "
+                       "event's header.");
+               goto end;
+       }
+
+       field = bt_ctf_event_get_stream_event_context(event);
+       ret = visit_field_update_clock_value(field, val);
+       bt_put(field);
+       if (ret) {
+               BT_LOGW_STR("Cannot automatically update clock value in "
+                       "event's stream event context.");
+               goto end;
+       }
+
+       field = bt_ctf_event_get_context(event);
+       ret = visit_field_update_clock_value(field, val);
+       bt_put(field);
+       if (ret) {
+               BT_LOGW_STR("Cannot automatically update clock value in "
+                       "event's context.");
+               goto end;
+       }
+
+       field = bt_ctf_event_get_payload_field(event);
+       ret = visit_field_update_clock_value(field, val);
+       bt_put(field);
+       if (ret) {
+               BT_LOGW_STR("Cannot automatically update clock value in "
+                       "event's payload.");
+               goto end;
+       }
+
+end:
+       return ret;
+}
+
+static
+int set_packet_context_timestamps(struct bt_ctf_stream *stream)
+{
+       int ret = 0;
+       uint64_t val;
+       uint64_t cur_clock_value;
+       uint64_t init_clock_value = 0;
+       struct bt_ctf_field *ts_begin_field = bt_ctf_field_structure_get_field_by_name(
+               stream->packet_context, "timestamp_begin");
+       struct bt_ctf_field *ts_end_field = bt_ctf_field_structure_get_field_by_name(
+               stream->packet_context, "timestamp_end");
+       struct bt_field_common *packet_context =
+               (void *) stream->packet_context;
+       uint64_t i;
+       int64_t len;
+
+       if (ts_begin_field && bt_ctf_field_is_set_recursive(ts_begin_field)) {
+               /* Use provided `timestamp_begin` value as starting value */
+               ret = bt_ctf_field_integer_unsigned_get_value(ts_begin_field, &val);
+               BT_ASSERT(ret == 0);
+               init_clock_value = val;
+       } else if (stream->last_ts_end != -1ULL) {
+               /* Use last packet's ending timestamp as starting value */
+               init_clock_value = stream->last_ts_end;
+       }
+
+       cur_clock_value = init_clock_value;
+
+       if (stream->last_ts_end != -1ULL &&
+                       cur_clock_value < stream->last_ts_end) {
+               BT_LOGW("Packet's initial timestamp is less than previous "
+                       "packet's final timestamp: "
+                       "stream-addr=%p, stream-name=\"%s\", "
+                       "cur-packet-ts-begin=%" PRIu64 ", "
+                       "prev-packet-ts-end=%" PRIu64,
+                       stream, bt_ctf_stream_get_name(stream),
+                       cur_clock_value, stream->last_ts_end);
+               ret = -1;
+               goto end;
+       }
+
+       /*
+        * Visit all the packet context fields, followed by all the
+        * fields of all the events, in order, updating our current
+        * clock value as we visit.
+        *
+        * While visiting the packet context fields, do not consider
+        * `timestamp_begin` and `timestamp_end` because this function's
+        * purpose is to set them anyway. Also do not consider
+        * `packet_size`, `content_size`, `events_discarded`, and
+        * `packet_seq_num` if they are not set because those are
+        * autopopulating fields.
+        */
+       len = bt_ctf_field_type_structure_get_field_count(
+               (void *) packet_context->type);
+       BT_ASSERT(len >= 0);
+
+       for (i = 0; i < len; i++) {
+               const char *member_name;
+               struct bt_ctf_field *member_field;
+
+               ret = bt_ctf_field_type_structure_get_field_by_index(
+                       (void *) packet_context->type, &member_name, NULL, i);
+               BT_ASSERT(ret == 0);
+
+               if (strcmp(member_name, "timestamp_begin") == 0 ||
+                               strcmp(member_name, "timestamp_end") == 0) {
+                       continue;
+               }
+
+               member_field = bt_ctf_field_structure_get_field_by_index(
+                       stream->packet_context, i);
+               BT_ASSERT(member_field);
+
+               if (strcmp(member_name, "packet_size") == 0 &&
+                               !bt_ctf_field_is_set_recursive(member_field)) {
+                       bt_put(member_field);
+                       continue;
+               }
+
+               if (strcmp(member_name, "content_size") == 0 &&
+                               !bt_ctf_field_is_set_recursive(member_field)) {
+                       bt_put(member_field);
+                       continue;
+               }
+
+               if (strcmp(member_name, "events_discarded") == 0 &&
+                               !bt_ctf_field_is_set_recursive(member_field)) {
+                       bt_put(member_field);
+                       continue;
+               }
+
+               if (strcmp(member_name, "packet_seq_num") == 0 &&
+                               !bt_ctf_field_is_set_recursive(member_field)) {
+                       bt_put(member_field);
+                       continue;
+               }
+
+               ret = visit_field_update_clock_value(member_field,
+                       &cur_clock_value);
+               bt_put(member_field);
+               if (ret) {
+                       BT_LOGW("Cannot automatically update clock value "
+                               "in stream's packet context: "
+                               "stream-addr=%p, stream-name=\"%s\", "
+                               "field-name=\"%s\"",
+                               stream, bt_ctf_stream_get_name(stream),
+                               member_name);
+                       goto end;
+               }
+       }
+
+       for (i = 0; i < stream->events->len; i++) {
+               struct bt_ctf_event *event = g_ptr_array_index(stream->events, i);
+
+               BT_ASSERT(event);
+               ret = visit_event_update_clock_value(event, &cur_clock_value);
+               if (ret) {
+                       BT_LOGW("Cannot automatically update clock value "
+                               "in stream's packet context: "
+                               "stream-addr=%p, stream-name=\"%s\", "
+                               "index=%" PRIu64 ", event-addr=%p, "
+                               "event-class-id=%" PRId64 ", "
+                               "event-class-name=\"%s\"",
+                               stream, bt_ctf_stream_get_name(stream),
+                               i, event,
+                               bt_event_class_common_get_id(event->common.class),
+                               bt_event_class_common_get_name(event->common.class));
+                       goto end;
+               }
+       }
+
+       /*
+        * Everything is visited, thus the current clock value
+        * corresponds to the ending timestamp. Validate this value
+        * against the provided value of `timestamp_end`, if any,
+        * otherwise set it.
+        */
+       if (ts_end_field && bt_ctf_field_is_set_recursive(ts_end_field)) {
+               ret = bt_ctf_field_integer_unsigned_get_value(ts_end_field, &val);
+               BT_ASSERT(ret == 0);
+
+               if (val < cur_clock_value) {
+                       BT_LOGW("Packet's final timestamp is less than "
+                               "computed packet's final timestamp: "
+                               "stream-addr=%p, stream-name=\"%s\", "
+                               "cur-packet-ts-end=%" PRIu64 ", "
+                               "computed-packet-ts-end=%" PRIu64,
+                               stream, bt_ctf_stream_get_name(stream),
+                               val, cur_clock_value);
+                       ret = -1;
+                       goto end;
+               }
+
+               stream->last_ts_end = val;
+       }
+
+       if (ts_end_field && !bt_ctf_field_is_set_recursive(ts_end_field)) {
+               ret = set_integer_field_value(ts_end_field, cur_clock_value);
+               BT_ASSERT(ret == 0);
+               stream->last_ts_end = cur_clock_value;
+       }
+
+       if (!ts_end_field) {
+               stream->last_ts_end = cur_clock_value;
+       }
+
+       /* Set `timestamp_begin` field to initial clock value */
+       if (ts_begin_field && !bt_ctf_field_is_set_recursive(ts_begin_field)) {
+               ret = set_integer_field_value(ts_begin_field, init_clock_value);
+               BT_ASSERT(ret == 0);
+       }
+
+end:
+       bt_put(ts_begin_field);
+       bt_put(ts_end_field);
+       return ret;
+}
+
+static
+int auto_populate_packet_context(struct bt_ctf_stream *stream, bool set_ts)
+{
+       int ret = 0;
+
+       if (!stream->packet_context) {
+               goto end;
+       }
+
+       ret = set_packet_context_packet_size(stream);
+       if (ret) {
+               BT_LOGW("Cannot set packet context's packet size field: "
+                       "stream-addr=%p, stream-name=\"%s\"",
+                       stream, bt_ctf_stream_get_name(stream));
+               goto end;
+       }
+
+       ret = set_packet_context_content_size(stream);
+       if (ret) {
+               BT_LOGW("Cannot set packet context's content size field: "
+                       "stream-addr=%p, stream-name=\"%s\"",
+                       stream, bt_ctf_stream_get_name(stream));
+               goto end;
+       }
+
+       if (set_ts) {
+               ret = set_packet_context_timestamps(stream);
+               if (ret) {
+                       BT_LOGW("Cannot set packet context's timestamp fields: "
+                               "stream-addr=%p, stream-name=\"%s\"",
+                               stream, bt_ctf_stream_get_name(stream));
+                       goto end;
+               }
+       }
+
+       ret = set_packet_context_events_discarded(stream);
+       if (ret) {
+               BT_LOGW("Cannot set packet context's discarded events count field: "
+                       "stream-addr=%p, stream-name=\"%s\"",
+                       stream, bt_ctf_stream_get_name(stream));
+               goto end;
+       }
+
+       BT_LOGV("Automatically populated stream's packet context's known fields: "
+               "stream-addr=%p, stream-name=\"%s\"",
+               stream, bt_ctf_stream_get_name(stream));
+
+end:
+       return ret;
+}
+
+static
+void release_event(struct bt_ctf_event *event)
+{
+       if (bt_object_get_ref_count(event)) {
+               /*
+                * The event is being orphaned, but it must guarantee the
+                * existence of its event class for the duration of its
+                * lifetime.
+                */
+               bt_get(event->common.class);
+               BT_PUT(event->common.base.parent);
+       } else {
+               bt_object_release(event);
+       }
+}
+
+static
+int create_stream_file(struct bt_ctf_writer *writer,
+               struct bt_ctf_stream *stream)
+{
+       int fd;
+       GString *filename = g_string_new(NULL);
+       int64_t stream_class_id;
+       char *file_path = NULL;
+
+       BT_LOGD("Creating stream file: writer-addr=%p, stream-addr=%p, "
+               "stream-name=\"%s\", stream-class-addr=%p, stream-class-name=\"%s\"",
+               writer, stream, bt_ctf_stream_get_name(stream),
+               stream->common.stream_class,
+               stream->common.stream_class->name->str);
+
+       if (stream->common.name && stream->common.name->len > 0) {
+               /* Use stream name's base name as prefix */
+               gchar *basename = g_path_get_basename(stream->common.name->str);
+
+               BT_ASSERT(basename);
+
+               if (strcmp(basename, G_DIR_SEPARATOR_S) == 0) {
+                       g_string_assign(filename, "stream");
+               } else {
+                       g_string_assign(filename, basename);
+               }
+
+               g_free(basename);
+               goto append_ids;
+       }
+
+       if (stream->common.stream_class->name &&
+                       stream->common.stream_class->name->len > 0) {
+               /* Use stream class name's base name as prefix */
+               gchar *basename =
+                       g_path_get_basename(
+                               stream->common.stream_class->name->str);
+
+               BT_ASSERT(basename);
+
+               if (strcmp(basename, G_DIR_SEPARATOR_S) == 0) {
+                       g_string_assign(filename, "stream");
+               } else {
+                       g_string_assign(filename, basename);
+               }
+
+               g_free(basename);
+               goto append_ids;
+       }
+
+       /* Default to using `stream-` as prefix */
+       g_string_assign(filename, "stream");
+
+append_ids:
+       stream_class_id = bt_stream_class_common_get_id(stream->common.stream_class);
+       BT_ASSERT(stream_class_id >= 0);
+       BT_ASSERT(stream->common.id >= 0);
+       g_string_append_printf(filename, "-%" PRId64 "-%" PRId64,
+               stream_class_id, stream->common.id);
+
+       file_path = g_build_filename(writer->path->str, filename->str, NULL);
+       if (file_path == NULL) {
+               fd = -1;
+               goto end;
+       }
+
+       fd = open(file_path,
+               O_RDWR | O_CREAT | O_TRUNC,
+               S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
+       g_free(file_path);
+       if (fd < 0) {
+               BT_LOGW_ERRNO("Failed to open stream file for writing",
+                       ": file_path=\"%s\", filename=\"%s\", ret=%d",
+                       file_path, filename->str, fd);
+               goto end;
+       }
+
+       BT_LOGD("Created stream file for writing: "
+               "stream-addr=%p, stream-name=\"%s\", "
+               "filename=\"%s\", fd=%d", stream, bt_ctf_stream_get_name(stream),
+               filename->str, fd);
+
+end:
+       g_string_free(filename, TRUE);
+       return fd;
+}
+
+static
+void set_stream_fd(struct bt_ctf_stream *stream, int fd)
+{
+       (void) bt_ctf_stream_pos_init(&stream->pos, fd, O_RDWR);
+       stream->pos.fd = fd;
+}
+
+BT_HIDDEN
+struct bt_ctf_stream *bt_ctf_stream_create_with_id(
+               struct bt_ctf_stream_class *stream_class,
+               const char *name, uint64_t id)
+{
+       int ret;
+       int fd;
+       struct bt_ctf_stream *stream = NULL;
+       struct bt_ctf_trace *trace = NULL;
+       struct bt_ctf_writer *writer = NULL;
+
+       BT_LOGD("Creating CTF writer stream object: stream-class-addr=%p, "
+               "stream-class-name=\"%s\", stream-name=\"%s\", "
+               "stream-id=%" PRIu64,
+               stream_class, bt_ctf_stream_class_get_name(stream_class),
+               name, id);
+       stream = g_new0(struct bt_ctf_stream, 1);
+       if (!stream) {
+               BT_LOGE_STR("Failed to allocate one stream.");
+               goto error;
+       }
+
+       if (id == -1ULL) {
+               id = stream_class->next_stream_id;
+       }
+
+       ret = bt_stream_common_initialize(BT_TO_COMMON(stream),
+               BT_TO_COMMON(stream_class), name, id, bt_ctf_stream_destroy);
+       if (ret) {
+               /* bt_stream_common_initialize() logs errors */
+               goto error;
+       }
+
+       trace = BT_FROM_COMMON(bt_stream_class_common_borrow_trace(
+               BT_TO_COMMON(stream_class)));
+       if (!trace) {
+               BT_LOGW("Invalid parameter: cannot create stream from a stream class which is not part of trace: "
+                       "stream-class-addr=%p, stream-class-name=\"%s\", "
+                       "stream-name=\"%s\"",
+                       stream_class, bt_ctf_stream_class_get_name(stream_class),
+                       name);
+               goto error;
+       }
+
+       stream->pos.fd = -1;
+       writer = (struct bt_ctf_writer *) bt_object_get_parent(trace);
+       stream->last_ts_end = -1ULL;
+       BT_LOGD("CTF writer stream object belongs writer's trace: "
+               "writer-addr=%p", writer);
+       BT_ASSERT(writer);
+
+       if (stream_class->common.packet_context_field_type) {
+               BT_LOGD("Creating stream's packet context field: "
+                       "ft-addr=%p",
+                       stream_class->common.packet_context_field_type);
+               stream->packet_context = bt_ctf_field_create(
+                       (void *) stream_class->common.packet_context_field_type);
+               if (!stream->packet_context) {
+                       BT_LOGW_STR("Cannot create stream's packet context field.");
+                       goto error;
+               }
+
+               /* Initialize events_discarded */
+               ret = try_set_structure_field_integer(
+                       stream->packet_context, "events_discarded", 0);
+               if (ret < 0) {
+                       BT_LOGW("Cannot set `events_discarded` field in packet context: "
+                               "ret=%d, packet-context-field-addr=%p",
+                               ret, stream->packet_context);
+                       goto error;
+               }
+       }
+
+       stream->events = g_ptr_array_new_with_free_func(
+               (GDestroyNotify) release_event);
+       if (!stream->events) {
+               BT_LOGE_STR("Failed to allocate a GPtrArray.");
+               goto error;
+       }
+
+       if (trace->common.packet_header_field_type) {
+               BT_LOGD("Creating stream's packet header field: "
+                       "ft-addr=%p", trace->common.packet_header_field_type);
+               stream->packet_header =
+                       bt_ctf_field_create(
+                               (void *) trace->common.packet_header_field_type);
+               if (!stream->packet_header) {
+                       BT_LOGW_STR("Cannot create stream's packet header field.");
+                       goto error;
+               }
+       }
+
+       /*
+        * Attempt to populate the default trace packet header fields
+        * (magic, uuid and stream_id). This will _not_ fail shall the
+        * fields not be found or be of an incompatible type; they will
+        * simply not be populated automatically. The user will have to
+        * make sure to set the trace packet header fields himself
+        * before flushing.
+        */
+       ret = auto_populate_packet_header(stream);
+       if (ret) {
+               BT_LOGW_STR("Cannot automatically populate the stream's packet header.");
+               goto error;
+       }
+
+       /* Create file associated with this stream */
+       fd = create_stream_file(writer, stream);
+       if (fd < 0) {
+               BT_LOGW_STR("Cannot create stream file.");
+               goto error;
+       }
+
+       set_stream_fd(stream, fd);
+
+       /* Freeze the writer */
+       BT_LOGD_STR("Freezing stream's CTF writer.");
+       bt_ctf_writer_freeze(writer);
+
+       /* Add this stream to the trace's streams */
+       g_ptr_array_add(trace->common.streams, stream);
+       stream_class->next_stream_id++;
+       BT_LOGD("Created stream object: addr=%p", stream);
+       goto end;
+
+error:
+       BT_PUT(stream);
+
+end:
+       bt_put(writer);
+       return stream;
+}
+
+struct bt_ctf_stream *bt_ctf_stream_create(
+               struct bt_ctf_stream_class *stream_class,
+               const char *name, uint64_t id_param)
+{
+       return bt_ctf_stream_create_with_id(stream_class,
+               name, id_param);
+}
+
+int bt_ctf_stream_get_discarded_events_count(
+               struct bt_ctf_stream *stream, uint64_t *count)
+{
+       int ret = 0;
+
+       if (!stream) {
+               BT_LOGW_STR("Invalid parameter: stream is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       if (!count) {
+               BT_LOGW_STR("Invalid parameter: count is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       if (stream->pos.fd < 0) {
+               BT_LOGW("Invalid parameter: stream is not a CTF writer stream: "
+                       "stream-addr=%p, stream-name=\"%s\"",
+                       stream, bt_ctf_stream_get_name(stream));
+               ret = -1;
+               goto end;
+       }
+
+       *count = (uint64_t) stream->discarded_events;
+
+end:
+       return ret;
+}
+
+static
+int set_packet_context_events_discarded_field(struct bt_ctf_stream *stream,
+       uint64_t count)
+{
+       int ret = 0;
+       struct bt_ctf_field *events_discarded_field = NULL;
+
+       if (!stream->packet_context) {
+               goto end;
+       }
+
+       events_discarded_field = bt_ctf_field_structure_get_field_by_name(
+               stream->packet_context, "events_discarded");
+       if (!events_discarded_field) {
+               goto end;
+       }
+
+       ret = bt_ctf_field_integer_unsigned_set_value(
+               events_discarded_field, count);
+       if (ret) {
+               BT_LOGW("Cannot set packet context's `events_discarded` field: "
+                       "field-addr=%p, value=%" PRIu64,
+                       events_discarded_field, count);
+               goto end;
+       }
+
+end:
+       bt_put(events_discarded_field);
+       return ret;
+}
+
+void bt_ctf_stream_append_discarded_events(struct bt_ctf_stream *stream,
+               uint64_t event_count)
+{
+       int ret;
+       uint64_t new_count;
+       struct bt_ctf_field *events_discarded_field = NULL;
+
+       if (!stream) {
+               BT_LOGW_STR("Invalid parameter: stream is NULL.");
+               goto end;
+       }
+
+       BT_LOGV("Appending discarded events to stream: "
+               "stream-addr=%p, stream-name=\"%s\", append-count=%" PRIu64,
+               stream, bt_ctf_stream_get_name(stream), event_count);
+
+       if (!stream->packet_context) {
+               BT_LOGW_STR("Invalid parameter: stream has no packet context field.");
+               goto end;
+       }
+
+       if (stream->pos.fd < 0) {
+               BT_LOGW_STR("Invalid parameter: stream is not a CTF writer stream.");
+               goto end;
+       }
+
+       events_discarded_field = bt_ctf_field_structure_get_field_by_name(
+               stream->packet_context, "events_discarded");
+       if (!events_discarded_field) {
+               BT_LOGW_STR("No field named `events_discarded` in stream's packet context.");
+               goto end;
+       }
+
+       new_count = stream->discarded_events + event_count;
+       if (new_count < stream->discarded_events) {
+               BT_LOGW("New discarded events count is less than the stream's current discarded events count: "
+                       "cur-count=%" PRIu64 ", new-count=%" PRIu64,
+                       stream->discarded_events, new_count);
+               goto end;
+       }
+
+       ret = set_packet_context_events_discarded_field(stream, new_count);
+       if (ret) {
+               /* set_packet_context_events_discarded_field() logs errors */
+               goto end;
+       }
+
+       stream->discarded_events = new_count;
+       BT_LOGV("Appended discarded events to stream: "
+               "stream-addr=%p, stream-name=\"%s\", append-count=%" PRIu64,
+               stream, bt_ctf_stream_get_name(stream), event_count);
+
+end:
+       bt_put(events_discarded_field);
+}
+
+static int auto_populate_event_header(struct bt_ctf_stream *stream,
+               struct bt_ctf_event *event)
+{
+       int ret = 0;
+       struct bt_ctf_field *id_field = NULL, *timestamp_field = NULL;
+       struct bt_ctf_clock_class *mapped_clock_class = NULL;
+       struct bt_ctf_stream_class *stream_class =
+               BT_FROM_COMMON(bt_stream_common_borrow_class(
+                       BT_TO_COMMON(stream)));
+       int64_t event_class_id;
+
+       BT_ASSERT(event);
+
+       if (!event->common.header_field) {
+               goto end;
+       }
+
+       if (event->common.frozen) {
+               BT_LOGW_STR("Cannot populate event header field: event is frozen.");
+               ret = -1;
+               goto end;
+       }
+
+       BT_LOGV("Automatically populating event's header field: "
+               "stream-addr=%p, stream-name=\"%s\", event-addr=%p",
+               stream, bt_ctf_stream_get_name(stream), event);
+
+       id_field = bt_ctf_field_structure_get_field_by_name(
+               (void *) event->common.header_field, "id");
+       event_class_id = bt_event_class_common_get_id(event->common.class);
+       BT_ASSERT(event_class_id >= 0);
+
+       if (id_field && bt_ctf_field_get_type_id(id_field) == BT_CTF_FIELD_TYPE_ID_INTEGER) {
+               ret = set_integer_field_value(id_field, event_class_id);
+               if (ret) {
+                       BT_LOGW("Cannot set event header's `id` field's value: "
+                               "addr=%p, value=%" PRIu64, id_field,
+                               event_class_id);
+                       goto end;
+               }
+       }
+
+       /*
+        * The conditions to automatically set the timestamp are:
+        *
+        * 1. The event header field "timestamp" exists and is an
+        *    integer field.
+        * 2. This stream's class has a registered clock (set with
+        *    bt_ctf_stream_class_set_clock()).
+        * 3. The "timestamp" field is not set.
+        */
+       timestamp_field = bt_ctf_field_structure_get_field_by_name(
+                       (void *) event->common.header_field, "timestamp");
+       if (timestamp_field && stream_class->clock &&
+                       bt_ctf_field_get_type_id(id_field) == BT_CTF_FIELD_TYPE_ID_INTEGER &&
+                       !bt_ctf_field_is_set_recursive(timestamp_field)) {
+               mapped_clock_class =
+                       bt_ctf_field_type_integer_get_mapped_clock_class(
+                               (void *) ((struct bt_field_common *) timestamp_field)->type);
+               if (mapped_clock_class) {
+                       uint64_t timestamp;
+
+                       BT_ASSERT(mapped_clock_class ==
+                               stream_class->clock->clock_class);
+                       ret = bt_ctf_clock_get_value(
+                               stream_class->clock,
+                               &timestamp);
+                       BT_ASSERT(ret == 0);
+                       ret = set_integer_field_value(timestamp_field,
+                                       timestamp);
+                       if (ret) {
+                               BT_LOGW("Cannot set event header's `timestamp` field's value: "
+                                       "addr=%p, value=%" PRIu64,
+                                       timestamp_field, timestamp);
+                               goto end;
+                       }
+               }
+       }
+
+       BT_LOGV("Automatically populated event's header field: "
+               "stream-addr=%p, stream-name=\"%s\", event-addr=%p",
+               stream, bt_ctf_stream_get_name(stream), event);
+
+end:
+       bt_put(id_field);
+       bt_put(timestamp_field);
+       bt_put(mapped_clock_class);
+       return ret;
+}
+
+int bt_ctf_stream_append_event(struct bt_ctf_stream *stream,
+               struct bt_ctf_event *event)
+{
+       int ret = 0;
+
+       if (!stream) {
+               BT_LOGW_STR("Invalid parameter: stream is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       if (!event) {
+               BT_LOGW_STR("Invalid parameter: event is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       if (stream->pos.fd < 0) {
+               BT_LOGW_STR("Invalid parameter: stream is not a CTF writer stream.");
+               ret = -1;
+               goto end;
+       }
+
+       BT_LOGV("Appending event to stream: "
+               "stream-addr=%p, stream-name=\"%s\", event-addr=%p, "
+               "event-class-name=\"%s\", event-class-id=%" PRId64,
+               stream, bt_ctf_stream_get_name(stream), event,
+               bt_event_class_common_get_name(
+                       bt_event_common_borrow_class(BT_TO_COMMON(event))),
+               bt_event_class_common_get_id(
+                       bt_event_common_borrow_class(BT_TO_COMMON(event))));
+
+       /*
+        * The event is not supposed to have a parent stream at this
+        * point. The only other way an event can have a parent stream
+        * is if it was assigned when setting a packet to the event,
+        * in which case the packet's stream is not a writer stream,
+        * and thus the user is trying to append an event which belongs
+        * to another stream.
+        */
+       if (event->common.base.parent) {
+               ret = -1;
+               goto end;
+       }
+
+       bt_object_set_parent(event, stream);
+       BT_LOGV_STR("Automatically populating the header of the event to append.");
+       ret = auto_populate_event_header(stream, event);
+       if (ret) {
+               /* auto_populate_event_header() reports errors */
+               goto error;
+       }
+
+       /* Make sure the various scopes of the event are set */
+       BT_LOGV_STR("Validating event to append.");
+       ret = bt_event_common_validate(BT_TO_COMMON(event));
+       if (ret) {
+               goto error;
+       }
+
+       /* Save the new event and freeze it */
+       BT_LOGV_STR("Freezing the event to append.");
+       bt_event_common_freeze(BT_TO_COMMON(event));
+       g_ptr_array_add(stream->events, event);
+
+       /*
+        * Event had to hold a reference to its event class as long as it wasn't
+        * part of the same trace hierarchy. From now on, the event and its
+        * class share the same lifetime guarantees and the reference is no
+        * longer needed.
+        */
+       BT_LOGV_STR("Putting the event's class.");
+       bt_put(event->common.class);
+       BT_LOGV("Appended event to stream: "
+               "stream-addr=%p, stream-name=\"%s\", event-addr=%p, "
+               "event-class-name=\"%s\", event-class-id=%" PRId64,
+               stream, bt_ctf_stream_get_name(stream), event,
+               bt_event_class_common_get_name(
+                       bt_event_common_borrow_class(BT_TO_COMMON(event))),
+               bt_event_class_common_get_id(
+                       bt_event_common_borrow_class(BT_TO_COMMON(event))));
+
+end:
+       return ret;
+
+error:
+       /*
+        * Orphan the event; we were not successful in associating it to
+        * a stream.
+        */
+       bt_object_set_parent(event, NULL);
+
+       return ret;
+}
+
+struct bt_ctf_field *bt_ctf_stream_get_packet_context(struct bt_ctf_stream *stream)
+{
+       struct bt_ctf_field *packet_context = NULL;
+
+       if (!stream) {
+               BT_LOGW_STR("Invalid parameter: stream is NULL.");
+               goto end;
+       }
+
+       if (stream->pos.fd < 0) {
+               BT_LOGW("Invalid parameter: stream is not a CTF writer stream: "
+                       "stream-addr=%p, stream-name=\"%s\"", stream,
+                       bt_ctf_stream_get_name(stream));
+               goto end;
+       }
+
+       packet_context = stream->packet_context;
+       if (packet_context) {
+               bt_get(packet_context);
+       }
+end:
+       return packet_context;
+}
+
+int bt_ctf_stream_set_packet_context(struct bt_ctf_stream *stream,
+               struct bt_ctf_field *field)
+{
+       int ret = 0;
+       struct bt_ctf_field_type *field_type;
+
+       if (!stream) {
+               BT_LOGW_STR("Invalid parameter: stream is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       if (stream->pos.fd < 0) {
+               BT_LOGW_STR("Invalid parameter: stream is not a CTF writer stream.");
+               ret = -1;
+               goto end;
+       }
+
+       field_type = bt_ctf_field_get_type(field);
+       if (bt_field_type_common_compare((void *) field_type,
+                       stream->common.stream_class->packet_context_field_type)) {
+               BT_LOGW("Invalid parameter: packet context's field type is different from the stream's packet context field type: "
+                       "stream-addr=%p, stream-name=\"%s\", "
+                       "packet-context-field-addr=%p, "
+                       "packet-context-ft-addr=%p",
+                       stream, bt_ctf_stream_get_name(stream),
+                       field, field_type);
+               ret = -1;
+               goto end;
+       }
+
+       bt_put(field_type);
+       bt_put(stream->packet_context);
+       stream->packet_context = bt_get(field);
+       BT_LOGV("Set stream's packet context field: "
+               "stream-addr=%p, stream-name=\"%s\", "
+               "packet-context-field-addr=%p",
+               stream, bt_ctf_stream_get_name(stream), field);
+end:
+       return ret;
+}
+
+struct bt_ctf_field *bt_ctf_stream_get_packet_header(struct bt_ctf_stream *stream)
+{
+       struct bt_ctf_field *packet_header = NULL;
+
+       if (!stream) {
+               BT_LOGW_STR("Invalid parameter: stream is NULL.");
+               goto end;
+       }
+
+       if (stream->pos.fd < 0) {
+               BT_LOGW("Invalid parameter: stream is not a CTF writer stream: "
+                       "stream-addr=%p, stream-name=\"%s\"", stream,
+                       bt_ctf_stream_get_name(stream));
+               goto end;
+       }
+
+       packet_header = stream->packet_header;
+       if (packet_header) {
+               bt_get(packet_header);
+       }
+end:
+       return packet_header;
+}
+
+int bt_ctf_stream_set_packet_header(struct bt_ctf_stream *stream,
+               struct bt_ctf_field *field)
+{
+       int ret = 0;
+       struct bt_ctf_trace *trace = NULL;
+       struct bt_ctf_field_type *field_type = NULL;
+
+       if (!stream) {
+               BT_LOGW_STR("Invalid parameter: stream is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       if (stream->pos.fd < 0) {
+               BT_LOGW_STR("Invalid parameter: stream is not a CTF writer stream.");
+               ret = -1;
+               goto end;
+       }
+
+       trace = (struct bt_ctf_trace *) bt_object_get_parent(stream);
+
+       if (!field) {
+               if (trace->common.packet_header_field_type) {
+                       BT_LOGW("Invalid parameter: setting no packet header but packet header field type is not NULL: "
+                               "stream-addr=%p, stream-name=\"%s\", "
+                               "packet-header-field-addr=%p, "
+                               "expected-ft-addr=%p",
+                               stream, bt_ctf_stream_get_name(stream),
+                               field, trace->common.packet_header_field_type);
+                       ret = -1;
+                       goto end;
+               }
+
+               goto skip_validation;
+       }
+
+       field_type = bt_ctf_field_get_type(field);
+       BT_ASSERT(field_type);
+
+       if (bt_field_type_common_compare((void *) field_type,
+                       trace->common.packet_header_field_type)) {
+               BT_LOGW("Invalid parameter: packet header's field type is different from the stream's packet header field type: "
+                       "stream-addr=%p, stream-name=\"%s\", "
+                       "packet-header-field-addr=%p, "
+                       "packet-header-ft-addr=%p",
+                       stream, bt_ctf_stream_get_name(stream),
+                       field, field_type);
+               ret = -1;
+               goto end;
+       }
+
+skip_validation:
+       bt_put(stream->packet_header);
+       stream->packet_header = bt_get(field);
+       BT_LOGV("Set stream's packet header field: "
+               "stream-addr=%p, stream-name=\"%s\", "
+               "packet-header-field-addr=%p",
+               stream, bt_ctf_stream_get_name(stream), field);
+end:
+       BT_PUT(trace);
+       bt_put(field_type);
+       return ret;
+}
+
+static
+void reset_structure_field(struct bt_ctf_field *structure, const char *name)
+{
+       struct bt_ctf_field *member;
+
+       member = bt_ctf_field_structure_get_field_by_name(structure, name);
+       if (member) {
+               (void) bt_field_common_reset_recursive((void *) member);
+               bt_put(member);
+       }
+}
+
+int bt_ctf_stream_flush(struct bt_ctf_stream *stream)
+{
+       int ret = 0;
+       size_t i;
+       struct bt_ctf_stream_pos packet_context_pos;
+       struct bt_ctf_trace *trace;
+       enum bt_ctf_byte_order native_byte_order;
+       bool has_packet_size = false;
+
+       if (!stream) {
+               BT_LOGW_STR("Invalid parameter: stream is NULL.");
+               ret = -1;
+               goto end_no_stream;
+       }
+
+       if (stream->pos.fd < 0) {
+               BT_LOGW_STR("Invalid parameter: stream is not a CTF writer stream.");
+               ret = -1;
+               goto end;
+       }
+
+       if (stream->packet_context) {
+               struct bt_ctf_field *packet_size_field;
+
+               packet_size_field = bt_ctf_field_structure_get_field_by_name(
+                               stream->packet_context, "packet_size");
+               has_packet_size = (packet_size_field != NULL);
+               bt_put(packet_size_field);
+       }
+
+       if (stream->flushed_packet_count == 1) {
+               if (!stream->packet_context) {
+                       BT_LOGW_STR("Cannot flush a stream which has no packet context field more than once.");
+                       ret = -1;
+                       goto end;
+               }
+
+               if (!has_packet_size) {
+                       BT_LOGW_STR("Cannot flush a stream which has no packet context's `packet_size` field more than once.");
+                       ret = -1;
+                       goto end;
+               }
+       }
+
+       BT_LOGV("Flushing stream's current packet: stream-addr=%p, "
+               "stream-name=\"%s\", packet-index=%u", stream,
+               bt_ctf_stream_get_name(stream), stream->flushed_packet_count);
+       trace = BT_FROM_COMMON(bt_stream_class_common_borrow_trace(
+               stream->common.stream_class));
+       BT_ASSERT(trace);
+       native_byte_order = bt_ctf_trace_get_native_byte_order(trace);
+
+       ret = auto_populate_packet_header(stream);
+       if (ret) {
+               BT_LOGW_STR("Cannot automatically populate the stream's packet header field.");
+               ret = -1;
+               goto end;
+       }
+
+       ret = auto_populate_packet_context(stream, true);
+       if (ret) {
+               BT_LOGW_STR("Cannot automatically populate the stream's packet context field.");
+               ret = -1;
+               goto end;
+       }
+
+       /* mmap the next packet */
+       BT_LOGV("Seeking to the next packet: pos-offset=%" PRId64,
+               stream->pos.offset);
+       bt_ctf_stream_pos_packet_seek(&stream->pos, 0, SEEK_CUR);
+       BT_ASSERT(stream->pos.packet_size % 8 == 0);
+
+       if (stream->packet_header) {
+               BT_LOGV_STR("Serializing packet header field.");
+               ret = bt_ctf_field_serialize_recursive(stream->packet_header,
+                       &stream->pos, native_byte_order);
+               if (ret) {
+                       BT_LOGW("Cannot serialize stream's packet header field: "
+                               "field-addr=%p", stream->packet_header);
+                       goto end;
+               }
+       }
+
+       if (stream->packet_context) {
+               /* Write packet context */
+               memcpy(&packet_context_pos, &stream->pos,
+                       sizeof(packet_context_pos));
+               BT_LOGV_STR("Serializing packet context field.");
+               ret = bt_ctf_field_serialize_recursive(stream->packet_context,
+                       &stream->pos, native_byte_order);
+               if (ret) {
+                       BT_LOGW("Cannot serialize stream's packet context field: "
+                               "field-addr=%p", stream->packet_context);
+                       goto end;
+               }
+       }
+
+       BT_LOGV("Serializing events: count=%u", stream->events->len);
+
+       for (i = 0; i < stream->events->len; i++) {
+               struct bt_ctf_event *event = g_ptr_array_index(
+                       stream->events, i);
+               struct bt_ctf_event_class *event_class =
+                       BT_FROM_COMMON(bt_event_common_borrow_class(
+                               BT_TO_COMMON(event)));
+
+               BT_LOGV("Serializing event: index=%zu, event-addr=%p, "
+                       "event-class-name=\"%s\", event-class-id=%" PRId64 ", "
+                       "pos-offset=%" PRId64 ", packet-size=%" PRIu64,
+                       i, event, bt_ctf_event_class_get_name(event_class),
+                       bt_ctf_event_class_get_id(event_class),
+                       stream->pos.offset, stream->pos.packet_size);
+
+               /* Write event header */
+               if (event->common.header_field) {
+                       BT_LOGV_STR("Serializing event's header field.");
+                       ret = bt_ctf_field_serialize_recursive(
+                               (void *) event->common.header_field,
+                               &stream->pos, native_byte_order);
+                       if (ret) {
+                               BT_LOGW("Cannot serialize event's header field: "
+                                       "field-addr=%p",
+                                       event->common.header_field);
+                               goto end;
+                       }
+               }
+
+               /* Write stream event context */
+               if (event->common.stream_event_context_field) {
+                       BT_LOGV_STR("Serializing event's stream event context field.");
+                       ret = bt_ctf_field_serialize_recursive(
+                               (void *) event->common.stream_event_context_field,
+                               &stream->pos, native_byte_order);
+                       if (ret) {
+                               BT_LOGW("Cannot serialize event's stream event context field: "
+                                       "field-addr=%p",
+                                       event->common.stream_event_context_field);
+                               goto end;
+                       }
+               }
+
+               /* Write event content */
+               ret = bt_ctf_event_serialize(event,
+                       &stream->pos, native_byte_order);
+               if (ret) {
+                       /* bt_ctf_event_serialize() logs errors */
+                       goto end;
+               }
+       }
+
+       if (!has_packet_size && stream->pos.offset % 8 != 0) {
+               BT_LOGW("Stream's packet context field type has no `packet_size` field, "
+                       "but current content size is not a multiple of 8 bits: "
+                       "content-size=%" PRId64 ", "
+                       "packet-size=%" PRIu64,
+                       stream->pos.offset,
+                       stream->pos.packet_size);
+               ret = -1;
+               goto end;
+       }
+
+       BT_ASSERT(stream->pos.packet_size % 8 == 0);
+
+       /*
+        * Remove extra padding bytes.
+        */
+       stream->pos.packet_size = (stream->pos.offset + 7) & ~7;
+
+       if (stream->packet_context) {
+               /*
+                * The whole packet is serialized at this point. Make sure that,
+                * if `packet_size` is missing, the current content size is
+                * equal to the current packet size.
+                */
+               struct bt_ctf_field *field = bt_ctf_field_structure_get_field_by_name(
+                       stream->packet_context, "content_size");
+
+               bt_put(field);
+               if (!field) {
+                       if (stream->pos.offset != stream->pos.packet_size) {
+                               BT_LOGW("Stream's packet context's `content_size` field is missing, "
+                                       "but current packet's content size is not equal to its packet size: "
+                                       "content-size=%" PRId64 ", "
+                                       "packet-size=%" PRIu64,
+                                       stream->pos.offset,
+                                       stream->pos.packet_size);
+                               ret = -1;
+                               goto end;
+                       }
+               }
+
+               /*
+                * Overwrite the packet context now that the stream
+                * position's packet and content sizes have the correct
+                * values.
+                *
+                * Copy base_mma as the packet may have been remapped
+                * (e.g. when a packet is resized).
+                */
+               packet_context_pos.base_mma = stream->pos.base_mma;
+               ret = auto_populate_packet_context(stream, false);
+               if (ret) {
+                       BT_LOGW_STR("Cannot automatically populate the stream's packet context field.");
+                       ret = -1;
+                       goto end;
+               }
+
+               BT_LOGV("Rewriting (serializing) packet context field.");
+               ret = bt_ctf_field_serialize_recursive(stream->packet_context,
+                       &packet_context_pos, native_byte_order);
+               if (ret) {
+                       BT_LOGW("Cannot serialize stream's packet context field: "
+                               "field-addr=%p", stream->packet_context);
+                       goto end;
+               }
+       }
+
+       g_ptr_array_set_size(stream->events, 0);
+       stream->flushed_packet_count++;
+       stream->size += stream->pos.packet_size / CHAR_BIT;
+
+end:
+       /* Reset automatically-set fields. */
+       if (stream->packet_context) {
+               reset_structure_field(stream->packet_context, "timestamp_begin");
+               reset_structure_field(stream->packet_context, "timestamp_end");
+               reset_structure_field(stream->packet_context, "packet_size");
+               reset_structure_field(stream->packet_context, "content_size");
+               reset_structure_field(stream->packet_context, "events_discarded");
+       }
+
+       if (ret < 0) {
+               /*
+                * We failed to write the packet. Its size is therefore set to 0
+                * to ensure the next mapping is done in the same place rather
+                * than advancing by "stream->pos.packet_size", which would
+                * leave a corrupted packet in the trace.
+                */
+               stream->pos.packet_size = 0;
+       } else {
+               BT_LOGV("Flushed stream's current packet: content-size=%" PRId64 ", "
+                       "packet-size=%" PRIu64,
+                       stream->pos.offset, stream->pos.packet_size);
+       }
+
+end_no_stream:
+       return ret;
+}
+
+static
+void bt_ctf_stream_destroy(struct bt_object *obj)
+{
+       struct bt_ctf_stream *stream = (void *) obj;
+
+       BT_LOGD("Destroying CTF writer stream object: addr=%p, name=\"%s\"",
+               stream, bt_ctf_stream_get_name(stream));
+
+       bt_stream_common_finalize(BT_TO_COMMON(stream));
+       (void) bt_ctf_stream_pos_fini(&stream->pos);
+
+       if (stream->pos.fd >= 0) {
+               int ret;
+
+               /*
+                * Truncate the file's size to the minimum required to fit the
+                * last packet as we might have grown it too much on the last
+                * mmap.
+                */
+               do {
+                       ret = ftruncate(stream->pos.fd, stream->size);
+               } while (ret == -1 && errno == EINTR);
+               if (ret) {
+                       BT_LOGE_ERRNO("Failed to truncate stream file",
+                               ": ret=%d, size=%" PRIu64,
+                               ret, (uint64_t) stream->size);
+               }
+
+               if (close(stream->pos.fd)) {
+                       BT_LOGE_ERRNO("Failed to close stream file",
+                               ": ret=%d", ret);
+               }
+       }
+
+       if (stream->events) {
+               BT_LOGD_STR("Putting events.");
+               g_ptr_array_free(stream->events, TRUE);
+       }
+
+       BT_LOGD_STR("Putting packet header field.");
+       bt_put(stream->packet_header);
+       BT_LOGD_STR("Putting packet context field.");
+       bt_put(stream->packet_context);
+       g_free(stream);
+}
+
+static
+int _set_structure_field_integer(struct bt_ctf_field *structure, char *name,
+               uint64_t value, bt_bool force)
+{
+       int ret = 0;
+       struct bt_ctf_field_type *field_type = NULL;
+       struct bt_ctf_field *integer;
+
+       BT_ASSERT(structure);
+       BT_ASSERT(name);
+
+       integer = bt_ctf_field_structure_get_field_by_name(structure, name);
+       if (!integer) {
+               /* Field not found, not an error. */
+               BT_LOGV("Field not found: struct-field-addr=%p, "
+                       "name=\"%s\", force=%d", structure, name, force);
+               goto end;
+       }
+
+       /* Make sure the payload has not already been set. */
+       if (!force && bt_ctf_field_is_set_recursive(integer)) {
+               /* Payload already set, not an error */
+               BT_LOGV("Field's payload is already set: struct-field-addr=%p, "
+                       "name=\"%s\", force=%d", structure, name, force);
+               goto end;
+       }
+
+       field_type = bt_ctf_field_get_type(integer);
+       BT_ASSERT(field_type);
+       if (bt_ctf_field_type_get_type_id(field_type) != BT_CTF_FIELD_TYPE_ID_INTEGER) {
+               /*
+                * The user most likely meant for us to populate this field
+                * automatically. However, we can only do this if the field
+                * is an integer. Return an error.
+                */
+               BT_LOGW("Invalid parameter: field's type is not an integer field type: "
+                       "field-addr=%p, ft-addr=%p, ft-id=%s",
+                       integer, field_type,
+                       bt_common_field_type_id_string((int)
+                               bt_ctf_field_type_get_type_id(field_type)));
+               ret = -1;
+               goto end;
+       }
+
+       if (bt_ctf_field_type_integer_is_signed(field_type)) {
+               ret = bt_ctf_field_integer_signed_set_value(integer,
+                       (int64_t) value);
+       } else {
+               ret = bt_ctf_field_integer_unsigned_set_value(integer, value);
+       }
+       ret = !ret ? 1 : ret;
+end:
+       bt_put(integer);
+       bt_put(field_type);
+       return ret;
+}
+
+/*
+ * Returns the following codes:
+ * 1 if the field was found and set,
+ * 0 if nothing was done (field not found, or was already set),
+ * <0 if an error was encoutered
+ */
+static
+int try_set_structure_field_integer(struct bt_ctf_field *structure, char *name,
+               uint64_t value)
+{
+       return _set_structure_field_integer(structure, name, value, BT_FALSE);
+}
+
+struct bt_ctf_stream_class *bt_ctf_stream_get_class(
+               struct bt_ctf_stream *stream)
+{
+       return BT_FROM_COMMON(bt_stream_common_get_class(BT_TO_COMMON(stream)));
+}
+
+const char *bt_ctf_stream_get_name(struct bt_ctf_stream *stream)
+{
+       return bt_stream_common_get_name(BT_TO_COMMON(stream));
+}
+
+int64_t bt_ctf_stream_get_id(struct bt_ctf_stream *stream)
+{
+       return bt_stream_common_get_id(BT_TO_COMMON(stream));
+}
diff --git a/lib/ctf-writer/trace.c b/lib/ctf-writer/trace.c
new file mode 100644 (file)
index 0000000..1e0a32e
--- /dev/null
@@ -0,0 +1,509 @@
+/*
+ * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ * Copyright 2017-2018 Philippe Proulx <pproulx@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#define BT_LOG_TAG "CTF-WRITER-TRACE"
+#include <babeltrace/lib-logging-internal.h>
+
+#include <babeltrace/ctf-ir/trace-internal.h>
+#include <babeltrace/ctf-ir/clock-class.h>
+#include <babeltrace/ctf-writer/clock-internal.h>
+#include <babeltrace/ctf-writer/trace-internal.h>
+#include <babeltrace/ctf-writer/stream-class-internal.h>
+#include <babeltrace/ctf-writer/writer-internal.h>
+#include <babeltrace/ctf-writer/field-types-internal.h>
+
+#define DEFAULT_IDENTIFIER_SIZE                128
+#define DEFAULT_METADATA_STRING_SIZE   4096
+
+static
+void bt_ctf_trace_destroy(struct bt_object *obj)
+{
+       struct bt_ctf_trace *trace = (void *) obj;
+
+       BT_LOGD("Destroying CTF writer trace object: addr=%p, name=\"%s\"",
+               trace, bt_ctf_trace_get_name(trace));
+       bt_trace_common_finalize(BT_TO_COMMON(trace));
+       g_free(trace);
+}
+
+BT_HIDDEN
+struct bt_ctf_trace *bt_ctf_trace_create(void)
+{
+       struct bt_ctf_trace *trace = NULL;
+       int ret;
+
+       BT_LOGD_STR("Creating CTF writer trace object.");
+       trace = g_new0(struct bt_ctf_trace, 1);
+       if (!trace) {
+               BT_LOGE_STR("Failed to allocate one CTF writer trace.");
+               goto error;
+       }
+
+       ret = bt_trace_common_initialize(BT_TO_COMMON(trace),
+               bt_ctf_trace_destroy);
+       if (ret) {
+               /* bt_trace_common_initialize() logs errors */
+               goto error;
+       }
+
+       BT_LOGD("Created CTF writer trace object: addr=%p", trace);
+       return trace;
+
+error:
+       BT_PUT(trace);
+       return trace;
+}
+
+const unsigned char *bt_ctf_trace_get_uuid(struct bt_ctf_trace *trace)
+{
+       return bt_trace_common_get_uuid(BT_TO_COMMON(trace));
+}
+
+int bt_ctf_trace_set_uuid(struct bt_ctf_trace *trace,
+               const unsigned char *uuid)
+{
+       return bt_trace_common_set_uuid(BT_TO_COMMON(trace), uuid);
+}
+
+int bt_ctf_trace_set_environment_field(struct bt_ctf_trace *trace,
+               const char *name, struct bt_value *value)
+{
+       return bt_trace_common_set_environment_field(BT_TO_COMMON(trace),
+               name, value);
+}
+
+int bt_ctf_trace_set_environment_field_string(struct bt_ctf_trace *trace,
+               const char *name, const char *value)
+{
+       return bt_trace_common_set_environment_field_string(BT_TO_COMMON(trace),
+               name, value);
+}
+
+int bt_ctf_trace_set_environment_field_integer(
+               struct bt_ctf_trace *trace, const char *name, int64_t value)
+{
+       return bt_trace_common_set_environment_field_integer(
+               BT_TO_COMMON(trace), name, value);
+}
+
+int64_t bt_ctf_trace_get_environment_field_count(struct bt_ctf_trace *trace)
+{
+       return bt_trace_common_get_environment_field_count(BT_TO_COMMON(trace));
+}
+
+const char *
+bt_ctf_trace_get_environment_field_name_by_index(struct bt_ctf_trace *trace,
+               uint64_t index)
+{
+       return bt_trace_common_get_environment_field_name_by_index(
+               BT_TO_COMMON(trace), index);
+}
+
+struct bt_value *bt_ctf_trace_get_environment_field_value_by_index(
+               struct bt_ctf_trace *trace, uint64_t index)
+{
+       return bt_trace_common_get_environment_field_value_by_index(
+               BT_TO_COMMON(trace), index);
+}
+
+struct bt_value *bt_ctf_trace_get_environment_field_value_by_name(
+               struct bt_ctf_trace *trace, const char *name)
+{
+       return bt_trace_common_get_environment_field_value_by_name(
+               BT_TO_COMMON(trace), name);
+}
+
+int bt_ctf_trace_add_clock_class(struct bt_ctf_trace *trace,
+               struct bt_ctf_clock_class *clock_class)
+{
+       return bt_trace_common_add_clock_class(BT_TO_COMMON(trace),
+               (void *) clock_class);
+}
+
+int64_t bt_ctf_trace_get_clock_class_count(struct bt_ctf_trace *trace)
+{
+       return bt_trace_common_get_clock_class_count(BT_TO_COMMON(trace));
+}
+
+struct bt_ctf_clock_class *bt_ctf_trace_get_clock_class_by_index(
+               struct bt_ctf_trace *trace, uint64_t index)
+{
+       return (void *) bt_trace_common_get_clock_class_by_index(
+               BT_TO_COMMON(trace), index);
+}
+
+static
+int map_clock_classes_func(struct bt_stream_class_common *stream_class,
+               struct bt_field_type_common *packet_context_type,
+               struct bt_field_type_common *event_header_type)
+{
+       int ret = bt_ctf_stream_class_map_clock_class(
+               BT_FROM_COMMON(stream_class),
+               BT_FROM_COMMON(packet_context_type),
+               BT_FROM_COMMON(event_header_type));
+
+       if (ret) {
+               BT_LOGW_STR("Cannot automatically map selected stream class's field types to stream class's clock's class.");
+       }
+
+       return ret;
+}
+
+int bt_ctf_trace_add_stream_class(struct bt_ctf_trace *trace,
+               struct bt_ctf_stream_class *stream_class)
+{
+       int ret = 0;
+       struct bt_clock_class *expected_clock_class = NULL;
+
+       if (!trace) {
+               BT_LOGW_STR("Invalid parameter: trace is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       if (!stream_class) {
+               BT_LOGW_STR("Invalid parameter: stream class is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       if (stream_class->clock) {
+               struct bt_ctf_clock_class *stream_clock_class =
+                       stream_class->clock->clock_class;
+
+               /*
+                * Make sure this clock was also added to the
+                * trace (potentially through its CTF writer
+                * owner).
+                */
+               size_t i;
+
+               for (i = 0; i < trace->common.clock_classes->len; i++) {
+                       if (trace->common.clock_classes->pdata[i] ==
+                                       stream_clock_class) {
+                               /* Found! */
+                               break;
+                       }
+               }
+
+               if (i == trace->common.clock_classes->len) {
+                       /* Not found */
+                       BT_LOGW("Stream class's clock's class is not part of the trace: "
+                               "clock-class-addr=%p, clock-class-name=\"%s\"",
+                               stream_clock_class,
+                               bt_clock_class_get_name(
+                                       BT_TO_COMMON(stream_clock_class)));
+                       ret = -1;
+                       goto end;
+               }
+
+               if (stream_class->common.clock_class &&
+                               stream_class->common.clock_class !=
+                               BT_TO_COMMON(stream_class->clock->clock_class)) {
+                       /*
+                        * Stream class already has an expected clock
+                        * class, but it does not match its clock's
+                        * class.
+                        */
+                       BT_LOGW("Invalid parameter: stream class's clock's "
+                               "class does not match stream class's "
+                               "expected clock class: "
+                               "stream-class-addr=%p, "
+                               "stream-class-id=%" PRId64 ", "
+                               "stream-class-name=\"%s\", "
+                               "expected-clock-class-addr=%p, "
+                               "expected-clock-class-name=\"%s\"",
+                               stream_class,
+                               bt_ctf_stream_class_get_id(stream_class),
+                               bt_ctf_stream_class_get_name(stream_class),
+                               stream_class->common.clock_class,
+                               bt_clock_class_get_name(stream_class->common.clock_class));
+               } else if (!stream_class->common.clock_class) {
+                       /*
+                        * Set expected clock class to stream class's
+                        * clock's class.
+                        */
+                       expected_clock_class =
+                               BT_TO_COMMON(stream_class->clock->clock_class);
+               }
+       }
+
+
+       ret = bt_trace_common_add_stream_class(BT_TO_COMMON(trace),
+               BT_TO_COMMON(stream_class),
+               (bt_validation_flag_copy_field_type_func) bt_ctf_field_type_copy,
+               expected_clock_class, map_clock_classes_func,
+               false);
+
+end:
+       return ret;
+}
+
+int64_t bt_ctf_trace_get_stream_count(struct bt_ctf_trace *trace)
+{
+       return bt_trace_common_get_stream_count(BT_TO_COMMON(trace));
+}
+
+struct bt_ctf_stream *bt_ctf_trace_get_stream_by_index(
+               struct bt_ctf_trace *trace, uint64_t index)
+{
+       return BT_FROM_COMMON(bt_trace_common_get_stream_by_index(
+               BT_TO_COMMON(trace), index));
+}
+
+int64_t bt_ctf_trace_get_stream_class_count(struct bt_ctf_trace *trace)
+{
+       return bt_trace_common_get_stream_class_count(BT_TO_COMMON(trace));
+}
+
+struct bt_ctf_stream_class *bt_ctf_trace_get_stream_class_by_index(
+               struct bt_ctf_trace *trace, uint64_t index)
+{
+       return BT_FROM_COMMON(bt_trace_common_get_stream_class_by_index(
+               BT_TO_COMMON(trace), index));
+}
+
+struct bt_ctf_stream_class *bt_ctf_trace_get_stream_class_by_id(
+               struct bt_ctf_trace *trace, uint64_t id)
+{
+       return BT_FROM_COMMON(
+               bt_trace_common_get_stream_class_by_id(
+                       BT_TO_COMMON(trace), id));
+}
+
+struct bt_ctf_clock_class *bt_ctf_trace_get_clock_class_by_name(
+               struct bt_ctf_trace *trace, const char *name)
+{
+       return BT_FROM_COMMON(
+               bt_trace_common_get_clock_class_by_name(BT_TO_COMMON(trace),
+                       name));
+}
+
+static
+int append_trace_metadata(struct bt_ctf_trace *trace,
+               struct metadata_context *context)
+{
+       unsigned char *uuid = trace->common.uuid;
+       int ret = 0;
+
+       if (trace->common.native_byte_order == BT_BYTE_ORDER_NATIVE ||
+                       trace->common.native_byte_order == BT_BYTE_ORDER_UNSPECIFIED) {
+               BT_LOGW("Invalid parameter: trace's byte order cannot be BT_CTF_BYTE_ORDER_NATIVE or BT_CTF_BYTE_ORDER_UNSPECIFIED at this point; "
+                       "set it with bt_ctf_trace_set_native_byte_order(): "
+                       "addr=%p, name=\"%s\"",
+                       trace, bt_ctf_trace_get_name(trace));
+               ret = -1;
+               goto end;
+       }
+
+       g_string_append(context->string, "trace {\n");
+       g_string_append(context->string, "\tmajor = 1;\n");
+       g_string_append(context->string, "\tminor = 8;\n");
+       BT_ASSERT(trace->common.native_byte_order == BT_BYTE_ORDER_LITTLE_ENDIAN ||
+               trace->common.native_byte_order == BT_BYTE_ORDER_BIG_ENDIAN ||
+               trace->common.native_byte_order == BT_BYTE_ORDER_NETWORK);
+
+       if (trace->common.uuid_set) {
+               g_string_append_printf(context->string,
+                       "\tuuid = \"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\";\n",
+                       uuid[0], uuid[1], uuid[2], uuid[3],
+                       uuid[4], uuid[5], uuid[6], uuid[7],
+                       uuid[8], uuid[9], uuid[10], uuid[11],
+                       uuid[12], uuid[13], uuid[14], uuid[15]);
+       }
+
+       g_string_append_printf(context->string, "\tbyte_order = %s;\n",
+               get_byte_order_string(trace->common.native_byte_order));
+
+       if (trace->common.packet_header_field_type) {
+               g_string_append(context->string, "\tpacket.header := ");
+               context->current_indentation_level++;
+               g_string_assign(context->field_name, "");
+               BT_LOGD_STR("Serializing trace's packet header field type's metadata.");
+               ret = bt_ctf_field_type_serialize_recursive(
+                       (void *) trace->common.packet_header_field_type,
+                       context);
+               if (ret) {
+                       goto end;
+               }
+               context->current_indentation_level--;
+       }
+
+       g_string_append(context->string, ";\n};\n\n");
+end:
+       return ret;
+}
+
+static
+void append_env_metadata(struct bt_ctf_trace *trace,
+               struct metadata_context *context)
+{
+       int64_t i;
+       int64_t env_size;
+
+       env_size = bt_attributes_get_count(trace->common.environment);
+       if (env_size <= 0) {
+               return;
+       }
+
+       g_string_append(context->string, "env {\n");
+
+       for (i = 0; i < env_size; i++) {
+               struct bt_value *env_field_value_obj = NULL;
+               const char *entry_name;
+
+               entry_name = bt_attributes_get_field_name(
+                       trace->common.environment, i);
+               env_field_value_obj = bt_attributes_get_field_value(
+                       trace->common.environment, i);
+
+               BT_ASSERT(entry_name);
+               BT_ASSERT(env_field_value_obj);
+
+               switch (bt_value_get_type(env_field_value_obj)) {
+               case BT_VALUE_TYPE_INTEGER:
+               {
+                       int ret;
+                       int64_t int_value;
+
+                       ret = bt_value_integer_get(env_field_value_obj,
+                               &int_value);
+                       BT_ASSERT(ret == 0);
+                       g_string_append_printf(context->string,
+                               "\t%s = %" PRId64 ";\n", entry_name,
+                               int_value);
+                       break;
+               }
+               case BT_VALUE_TYPE_STRING:
+               {
+                       int ret;
+                       const char *str_value;
+                       char *escaped_str = NULL;
+
+                       ret = bt_value_string_get(env_field_value_obj,
+                               &str_value);
+                       BT_ASSERT(ret == 0);
+                       escaped_str = g_strescape(str_value, NULL);
+                       if (!escaped_str) {
+                               BT_LOGE("Cannot escape string: string=\"%s\"",
+                                       str_value);
+                               goto loop_next;
+                       }
+
+                       g_string_append_printf(context->string,
+                               "\t%s = \"%s\";\n", entry_name, escaped_str);
+                       free(escaped_str);
+                       break;
+               }
+               default:
+                       goto loop_next;
+               }
+
+loop_next:
+               BT_PUT(env_field_value_obj);
+       }
+
+       g_string_append(context->string, "};\n\n");
+}
+
+char *bt_ctf_trace_get_metadata_string(struct bt_ctf_trace *trace)
+{
+       char *metadata = NULL;
+       struct metadata_context *context = NULL;
+       int err = 0;
+       size_t i;
+
+       if (!trace) {
+               BT_LOGW_STR("Invalid parameter: trace is NULL.");
+               goto end;
+       }
+
+       context = g_new0(struct metadata_context, 1);
+       if (!context) {
+               BT_LOGE_STR("Failed to allocate one metadata context.");
+               goto end;
+       }
+
+       context->field_name = g_string_sized_new(DEFAULT_IDENTIFIER_SIZE);
+       context->string = g_string_sized_new(DEFAULT_METADATA_STRING_SIZE);
+       g_string_append(context->string, "/* CTF 1.8 */\n\n");
+       if (append_trace_metadata(trace, context)) {
+               /* append_trace_metadata() logs errors */
+               goto error;
+       }
+       append_env_metadata(trace, context);
+       g_ptr_array_foreach(trace->common.clock_classes,
+               (GFunc) bt_ctf_clock_class_serialize, context);
+
+       for (i = 0; i < trace->common.stream_classes->len; i++) {
+               /* bt_stream_class_serialize() logs details */
+               err = bt_ctf_stream_class_serialize(
+                       trace->common.stream_classes->pdata[i], context);
+               if (err) {
+                       /* bt_stream_class_serialize() logs errors */
+                       goto error;
+               }
+       }
+
+       metadata = context->string->str;
+
+error:
+       g_string_free(context->string, err ? TRUE : FALSE);
+       g_string_free(context->field_name, TRUE);
+       g_free(context);
+
+end:
+       return metadata;
+}
+
+enum bt_ctf_byte_order bt_ctf_trace_get_native_byte_order(
+               struct bt_ctf_trace *trace)
+{
+       return (int) bt_trace_common_get_native_byte_order(BT_TO_COMMON(trace));
+}
+
+int bt_ctf_trace_set_native_byte_order(struct bt_ctf_trace *trace,
+               enum bt_ctf_byte_order byte_order)
+{
+       return bt_trace_common_set_native_byte_order(BT_TO_COMMON(trace),
+               (int) byte_order, false);
+}
+
+struct bt_ctf_field_type *bt_ctf_trace_get_packet_header_field_type(
+               struct bt_ctf_trace *trace)
+{
+       return BT_FROM_COMMON(bt_trace_common_get_packet_header_field_type(
+               BT_TO_COMMON(trace)));
+}
+
+int bt_ctf_trace_set_packet_header_field_type(struct bt_ctf_trace *trace,
+               struct bt_ctf_field_type *packet_header_type)
+{
+       return bt_trace_common_set_packet_header_field_type(BT_TO_COMMON(trace),
+               (void *) packet_header_type);
+}
+
+const char *bt_ctf_trace_get_name(struct bt_ctf_trace *trace)
+{
+       return bt_trace_common_get_name(BT_TO_COMMON(trace));
+}
index a4ad7fe852bc46ec32a3fbae0e85ad9f1e60a792..b51dd7fff7244dd4329f5f2b9c68f1accd2a97c4 100644 (file)
 #include <babeltrace/lib-logging-internal.h>
 
 #include <babeltrace/ctf-writer/clock-internal.h>
-#include <babeltrace/ctf-writer/writer-internal.h>
-#include <babeltrace/ctf-ir/field-types-internal.h>
-#include <babeltrace/ctf-ir/fields-internal.h>
+#include <babeltrace/ctf-writer/field-types-internal.h>
+#include <babeltrace/ctf-writer/fields-internal.h>
 #include <babeltrace/ctf-writer/functor-internal.h>
-#include <babeltrace/ctf-ir/stream-class-internal.h>
-#include <babeltrace/ctf-ir/stream-internal.h>
-#include <babeltrace/ctf-ir/trace-internal.h>
+#include <babeltrace/ctf-writer/stream-class-internal.h>
+#include <babeltrace/ctf-writer/stream-internal.h>
+#include <babeltrace/ctf-writer/trace-internal.h>
+#include <babeltrace/ctf-writer/writer-internal.h>
 #include <babeltrace/ref.h>
 #include <babeltrace/endian-internal.h>
 #include <babeltrace/compiler-internal.h>
@@ -54,43 +54,42 @@ static
 void bt_ctf_writer_destroy(struct bt_object *obj);
 
 static
-int init_trace_packet_header(struct bt_trace *trace)
+int init_trace_packet_header(struct bt_ctf_trace *trace)
 {
        int ret = 0;
-       struct bt_field *magic = NULL, *uuid_array = NULL;
-       struct bt_field_type *_uint32_t =
+       struct bt_ctf_field_type *_uint32_t =
                get_field_type(FIELD_TYPE_ALIAS_UINT32_T);
-       struct bt_field_type *_uint8_t =
+       struct bt_ctf_field_type *_uint8_t =
                get_field_type(FIELD_TYPE_ALIAS_UINT8_T);
-       struct bt_field_type *trace_packet_header_type =
-               bt_field_type_structure_create();
-       struct bt_field_type *uuid_array_type =
-               bt_field_type_array_create(_uint8_t, 16);
+       struct bt_ctf_field_type *trace_packet_header_type =
+               bt_ctf_field_type_structure_create();
+       struct bt_ctf_field_type *uuid_array_type =
+               bt_ctf_field_type_array_create(_uint8_t, 16);
 
        if (!trace_packet_header_type || !uuid_array_type) {
                ret = -1;
                goto end;
        }
 
-       ret = bt_field_type_structure_add_field(trace_packet_header_type,
+       ret = bt_ctf_field_type_structure_add_field(trace_packet_header_type,
                _uint32_t, "magic");
        if (ret) {
                goto end;
        }
 
-       ret = bt_field_type_structure_add_field(trace_packet_header_type,
+       ret = bt_ctf_field_type_structure_add_field(trace_packet_header_type,
                uuid_array_type, "uuid");
        if (ret) {
                goto end;
        }
 
-       ret = bt_field_type_structure_add_field(trace_packet_header_type,
+       ret = bt_ctf_field_type_structure_add_field(trace_packet_header_type,
                _uint32_t, "stream_id");
        if (ret) {
                goto end;
        }
 
-       ret = bt_trace_set_packet_header_type(trace,
+       ret = bt_ctf_trace_set_packet_header_field_type(trace,
                trace_packet_header_type);
        if (ret) {
                goto end;
@@ -99,8 +98,6 @@ end:
        bt_put(uuid_array_type);
        bt_put(_uint32_t);
        bt_put(_uint8_t);
-       bt_put(magic);
-       bt_put(uuid_array);
        bt_put(trace_packet_header_type);
        return ret;
 }
@@ -129,7 +126,7 @@ struct bt_ctf_writer *bt_ctf_writer_create(const char *path)
                goto error_destroy;
        }
 
-       writer->trace = bt_trace_create();
+       writer->trace = bt_ctf_trace_create();
        if (!writer->trace) {
                goto error_destroy;
        }
@@ -146,17 +143,16 @@ struct bt_ctf_writer *bt_ctf_writer_create(const char *path)
                goto error_destroy;
        }
 
-       ret = bt_trace_set_uuid(writer->trace, uuid);
+       ret = bt_ctf_trace_set_uuid(writer->trace, uuid);
        if (ret) {
                goto error_destroy;
        }
 
-       writer->trace->is_created_by_writer = 1;
        bt_object_set_parent(writer->trace, writer);
        bt_put(writer->trace);
 
        /* Default to little-endian */
-       ret = bt_ctf_writer_set_byte_order(writer, BT_BYTE_ORDER_NATIVE);
+       ret = bt_ctf_writer_set_byte_order(writer, BT_CTF_BYTE_ORDER_NATIVE);
        BT_ASSERT(ret == 0);
 
        /* Create trace directory if necessary and open a metadata file */
@@ -203,9 +199,9 @@ void bt_ctf_writer_destroy(struct bt_object *obj)
        g_free(writer);
 }
 
-struct bt_trace *bt_ctf_writer_get_trace(struct bt_ctf_writer *writer)
+struct bt_ctf_trace *bt_ctf_writer_get_trace(struct bt_ctf_writer *writer)
 {
-       struct bt_trace *trace = NULL;
+       struct bt_ctf_trace *trace = NULL;
 
        if (!writer) {
                goto end;
@@ -217,10 +213,10 @@ end:
        return trace;
 }
 
-struct bt_stream *bt_ctf_writer_create_stream(struct bt_ctf_writer *writer,
-               struct bt_stream_class *stream_class)
+struct bt_ctf_stream *bt_ctf_writer_create_stream(struct bt_ctf_writer *writer,
+               struct bt_ctf_stream_class *stream_class)
 {
-       struct bt_stream *stream = NULL;
+       struct bt_ctf_stream *stream = NULL;
        int stream_class_count;
        bt_bool stream_class_found = BT_FALSE;
        int i;
@@ -230,14 +226,14 @@ struct bt_stream *bt_ctf_writer_create_stream(struct bt_ctf_writer *writer,
        }
 
        /* Make sure the stream class is part of the writer's trace */
-       stream_class_count = bt_trace_get_stream_class_count(writer->trace);
+       stream_class_count = bt_ctf_trace_get_stream_class_count(writer->trace);
        if (stream_class_count < 0) {
                goto error;
        }
 
        for (i = 0; i < stream_class_count; i++) {
-               struct bt_stream_class *existing_stream_class =
-                       bt_trace_get_stream_class_by_index(
+               struct bt_ctf_stream_class *existing_stream_class =
+                       bt_ctf_trace_get_stream_class_by_index(
                                writer->trace, i);
 
                if (existing_stream_class == stream_class) {
@@ -252,7 +248,7 @@ struct bt_stream *bt_ctf_writer_create_stream(struct bt_ctf_writer *writer,
        }
 
        if (!stream_class_found) {
-               int ret = bt_trace_add_stream_class(writer->trace,
+               int ret = bt_ctf_trace_add_stream_class(writer->trace,
                        stream_class);
 
                if (ret) {
@@ -260,7 +256,7 @@ struct bt_stream *bt_ctf_writer_create_stream(struct bt_ctf_writer *writer,
                }
        }
 
-       stream = bt_stream_create(stream_class, NULL);
+       stream = bt_ctf_stream_create_with_id(stream_class, NULL, -1ULL);
        if (!stream) {
                goto error;
        }
@@ -282,7 +278,7 @@ int bt_ctf_writer_add_environment_field(struct bt_ctf_writer *writer,
                goto end;
        }
 
-       ret = bt_trace_set_environment_field_string(writer->trace,
+       ret = bt_ctf_trace_set_environment_field_string(writer->trace,
                name, value);
 end:
        return ret;
@@ -297,7 +293,7 @@ int bt_ctf_writer_add_environment_field_int64(struct bt_ctf_writer *writer,
                goto end;
        }
 
-       ret = bt_trace_set_environment_field_integer(writer->trace, name,
+       ret = bt_ctf_trace_set_environment_field_integer(writer->trace, name,
                value);
 end:
        return ret;
@@ -312,7 +308,7 @@ int bt_ctf_writer_add_clock(struct bt_ctf_writer *writer,
                goto end;
        }
 
-       ret = bt_trace_add_clock_class(writer->trace, clock->clock_class);
+       ret = bt_ctf_trace_add_clock_class(writer->trace, clock->clock_class);
 end:
        return ret;
 }
@@ -325,7 +321,7 @@ char *bt_ctf_writer_get_metadata_string(struct bt_ctf_writer *writer)
                goto end;
        }
 
-       metadata_string = bt_trace_get_metadata_string(
+       metadata_string = bt_ctf_trace_get_metadata_string(
                writer->trace);
 end:
        return metadata_string;
@@ -340,7 +336,7 @@ void bt_ctf_writer_flush_metadata(struct bt_ctf_writer *writer)
                goto end;
        }
 
-       metadata_string = bt_trace_get_metadata_string(
+       metadata_string = bt_ctf_trace_get_metadata_string(
                writer->trace);
        if (!metadata_string) {
                goto end;
@@ -367,7 +363,7 @@ end:
 }
 
 int bt_ctf_writer_set_byte_order(struct bt_ctf_writer *writer,
-               enum bt_byte_order byte_order)
+               enum bt_ctf_byte_order byte_order)
 {
        int ret = 0;
 
@@ -376,28 +372,80 @@ int bt_ctf_writer_set_byte_order(struct bt_ctf_writer *writer,
                goto end;
        }
 
-       if (byte_order == BT_BYTE_ORDER_NATIVE) {
-               byte_order = BT_MY_BYTE_ORDER;
+       if (byte_order == BT_CTF_BYTE_ORDER_NATIVE) {
+               byte_order = (int) BT_MY_BYTE_ORDER;
        }
 
-       ret = bt_trace_set_native_byte_order(writer->trace,
+       ret = bt_ctf_trace_set_native_byte_order(writer->trace,
                byte_order);
 end:
        return ret;
 }
 
-void bt_ctf_writer_get(struct bt_ctf_writer *writer)
+BT_HIDDEN
+void bt_ctf_writer_freeze(struct bt_ctf_writer *writer)
 {
-       bt_get(writer);
+       writer->frozen = 1;
 }
 
-void bt_ctf_writer_put(struct bt_ctf_writer *writer)
+static
+const unsigned int field_type_aliases_alignments[] = {
+       [FIELD_TYPE_ALIAS_UINT5_T] = 1,
+       [FIELD_TYPE_ALIAS_UINT8_T ... FIELD_TYPE_ALIAS_UINT16_T] = 8,
+       [FIELD_TYPE_ALIAS_UINT27_T] = 1,
+       [FIELD_TYPE_ALIAS_UINT32_T ... FIELD_TYPE_ALIAS_UINT64_T] = 8,
+};
+
+static
+const unsigned int field_type_aliases_sizes[] = {
+       [FIELD_TYPE_ALIAS_UINT5_T] = 5,
+       [FIELD_TYPE_ALIAS_UINT8_T] = 8,
+       [FIELD_TYPE_ALIAS_UINT16_T] = 16,
+       [FIELD_TYPE_ALIAS_UINT27_T] = 27,
+       [FIELD_TYPE_ALIAS_UINT32_T] = 32,
+       [FIELD_TYPE_ALIAS_UINT64_T] = 64,
+};
+
+BT_HIDDEN
+struct bt_ctf_field_type *get_field_type(enum field_type_alias alias)
 {
-       bt_put(writer);
+       int ret;
+       unsigned int alignment, size;
+       struct bt_ctf_field_type *field_type = NULL;
+
+       if (alias >= NR_FIELD_TYPE_ALIAS) {
+               goto end;
+       }
+
+       alignment = field_type_aliases_alignments[alias];
+       size = field_type_aliases_sizes[alias];
+       field_type = bt_ctf_field_type_integer_create(size);
+       ret = bt_ctf_field_type_set_alignment(field_type, alignment);
+       if (ret) {
+               BT_PUT(field_type);
+       }
+end:
+       return field_type;
 }
 
 BT_HIDDEN
-void bt_ctf_writer_freeze(struct bt_ctf_writer *writer)
+const char *get_byte_order_string(enum bt_byte_order byte_order)
 {
-       writer->frozen = 1;
+       const char *string;
+
+       switch (byte_order) {
+       case BT_BYTE_ORDER_LITTLE_ENDIAN:
+               string = "le";
+               break;
+       case BT_BYTE_ORDER_BIG_ENDIAN:
+               string = "be";
+               break;
+       case BT_BYTE_ORDER_NATIVE:
+               string = "native";
+               break;
+       default:
+               abort();
+       }
+
+       return string;
 }
index b98121a1d596a65f06854b10b2318bde390d563d..28ad724d935d2b8972e4aa951ffc3b5cbaa9488b 100644 (file)
@@ -78,7 +78,7 @@ struct stream_state {
 };
 
 static
-void stream_destroy_listener(struct bt_stream *stream, void *data)
+void stream_destroy_listener(struct bt_stream_common *stream, void *data)
 {
        struct bt_notification_iterator_private_connection *iterator = data;
 
@@ -184,7 +184,7 @@ void bt_private_connection_notification_iterator_destroy(struct bt_object *obj)
                        BT_ASSERT(stream_gptr);
 
                        BT_LOGD_STR("Removing stream's destroy listener for notification iterator.");
-                       bt_stream_remove_destroy_listener(
+                       bt_stream_common_remove_destroy_listener(
                                (void *) stream_gptr, stream_destroy_listener,
                                iterator);
                }
index b42801d741393e5381e2a4472979351980b5e039..065df3038d69f7993b69a15f7536b1505d775ffb 100644 (file)
@@ -76,7 +76,7 @@ bt_bool validate_clock_classes(struct bt_notification_event *notif)
        struct bt_stream_class *stream_class = NULL;
        struct bt_trace *trace = NULL;
 
-       event_class = bt_event_borrow_event_class(notif->event);
+       event_class = bt_event_borrow_class(notif->event);
        BT_ASSERT(event_class);
        stream_class = bt_event_class_borrow_stream_class(event_class);
        BT_ASSERT(stream_class);
@@ -158,7 +158,7 @@ static inline bool event_has_trace(struct bt_event *event)
        struct bt_event_class *event_class;
        struct bt_stream_class *stream_class;
 
-       event_class = bt_event_borrow_event_class(event);
+       event_class = bt_event_borrow_class(event);
        BT_ASSERT(event_class);
        stream_class = bt_event_class_borrow_stream_class(event_class);
        BT_ASSERT(stream_class);
@@ -185,7 +185,7 @@ struct bt_notification *bt_notification_event_create(struct bt_event *event,
        }
 
        BT_ASSERT(cc_prio_map);
-       event_class = bt_event_borrow_event_class(event);
+       event_class = bt_event_borrow_class(event);
        BT_ASSERT(event_class);
        BT_LOGD("Creating event notification object: "
                "event-addr=%p, event-class-addr=%p, "
index 0bbfa8ea1ebb45e1da30f45b851473d66dd2a608..3a6b32376c1f1e71a94ad2365337052c6c2f9196 100644 (file)
@@ -74,7 +74,7 @@ struct bt_notification *bt_notification_packet_begin_create(
        BT_ASSERT_PRE_NON_NULL(packet, "Packet");
        stream = bt_packet_borrow_stream(packet);
        BT_ASSERT(stream);
-       stream_class = bt_stream_borrow_stream_class(stream);
+       stream_class = bt_stream_borrow_class(stream);
        BT_ASSERT(stream_class);
        BT_LOGD("Creating packet beginning notification object: "
                "packet-addr=%p, stream-addr=%p, stream-name=\"%s\", "
@@ -130,7 +130,7 @@ struct bt_notification *bt_notification_packet_end_create(
        BT_ASSERT_PRE_NON_NULL(packet, "Packet");
        stream = bt_packet_borrow_stream(packet);
        BT_ASSERT(stream);
-       stream_class = bt_stream_borrow_stream_class(stream);
+       stream_class = bt_stream_borrow_class(stream);
        BT_ASSERT(stream_class);
        BT_LOGD("Creating packet end notification object: "
                "packet-addr=%p, stream-addr=%p, stream-name=\"%s\", "
index af6156333141a4f5a13e125c517f721217db3a56..84ee483a900361dd00cd1f552b091308ce8e1855 100644 (file)
@@ -55,9 +55,7 @@ struct bt_notification *bt_notification_stream_end_create(
        struct bt_stream_class *stream_class;
 
        BT_ASSERT_PRE_NON_NULL(stream, "Stream");
-       BT_ASSERT_PRE(stream->pos.fd < 0,
-               "Stream is a CTF writer stream: %!+s", stream);
-       stream_class = bt_stream_borrow_stream_class(stream);
+       stream_class = bt_stream_borrow_class(stream);
        BT_ASSERT(stream_class);
        BT_LOGD("Creating stream end notification object: "
                "stream-addr=%p, stream-name=\"%s\", "
@@ -123,9 +121,7 @@ struct bt_notification *bt_notification_stream_begin_create(
        struct bt_stream_class *stream_class;
 
        BT_ASSERT_PRE_NON_NULL(stream, "Stream");
-       BT_ASSERT_PRE(stream->pos.fd < 0,
-               "Stream is a CTF writer stream: %!+s", stream);
-       stream_class = bt_stream_borrow_stream_class(stream);
+       stream_class = bt_stream_borrow_class(stream);
        BT_ASSERT(stream_class);
        BT_LOGD("Creating stream beginning notification object: "
                "stream-addr=%p, stream-name=\"%s\", "
index 65d3313892dcfd4bbf7dffbe69f2c1ff1a4a39a3..d50d9770d38a888b0f6fc2ecd0d8ddffc89a5967 100644 (file)
@@ -20,6 +20,8 @@
  * SOFTWARE.
  */
 
+#define BT_LOG_TAG "LIB-LOGGING"
+
 #include <stdarg.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <babeltrace/ctf-ir/clock-class-internal.h>
 #include <babeltrace/ctf-ir/clock-value-internal.h>
 #include <babeltrace/ctf-ir/field-path-internal.h>
+#include <babeltrace/ctf-ir/utils-internal.h>
+#include <babeltrace/ctf-writer/field-types-internal.h>
+#include <babeltrace/ctf-writer/fields-internal.h>
+#include <babeltrace/ctf-writer/event-internal.h>
+#include <babeltrace/ctf-writer/stream-class-internal.h>
+#include <babeltrace/ctf-writer/stream-internal.h>
+#include <babeltrace/ctf-writer/trace-internal.h>
+#include <babeltrace/ctf-writer/clock-internal.h>
+#include <babeltrace/ctf-writer/writer-internal.h>
 #include <babeltrace/graph/clock-class-priority-map-internal.h>
 #include <babeltrace/graph/component-class-internal.h>
 #include <babeltrace/graph/component-class-sink-colander-internal.h>
@@ -64,8 +75,6 @@
 #include <babeltrace/graph/port-internal.h>
 #include <babeltrace/plugin/plugin-internal.h>
 #include <babeltrace/plugin/plugin-so-internal.h>
-#include <babeltrace/ctf-writer/writer-internal.h>
-#include <babeltrace/ctf-writer/clock-internal.h>
 
 #define LIB_LOGGING_BUF_SIZE   (4096 * 4)
 
@@ -112,6 +121,8 @@ static char __thread lib_logging_buf[LIB_LOGGING_BUF_SIZE];
                strcat(tmp_prefix, (_prefix2));                         \
        } while (0)
 
+typedef void (*format_func)(char **, bool, const char *, void *);
+
 static inline void format_component(char **buf_ch, bool extended,
                const char *prefix, struct bt_component *component);
 
@@ -127,11 +138,11 @@ static inline void format_ref_count(char **buf_ch, bool extended,
        BUF_APPEND(", %sref-count=%lu", prefix, obj->ref_count.count);
 }
 
-static inline void format_field_type(char **buf_ch, bool extended,
-               const char *prefix, struct bt_field_type *field_type)
+static inline void format_field_type_common(char **buf_ch, bool extended,
+               const char *prefix, struct bt_field_type_common *field_type)
 {
        BUF_APPEND(", %stype-id=%s, %salignment=%u",
-               PRFIELD(bt_field_type_id_string(field_type->id)),
+               PRFIELD(bt_common_field_type_id_string(field_type->id)),
                PRFIELD(field_type->alignment));
 
        if (extended) {
@@ -147,35 +158,38 @@ static inline void format_field_type(char **buf_ch, bool extended,
        switch (field_type->id) {
        case BT_FIELD_TYPE_ID_INTEGER:
        {
-               struct bt_field_type_integer *integer = (void *) field_type;
+               struct bt_field_type_common_integer *integer =
+                       BT_FROM_COMMON(field_type);
 
                BUF_APPEND(", %ssize=%u, %sis-signed=%d, %sbyte-order=%s, "
                        "%sbase=%d, %sencoding=%s, "
                        "%smapped-clock-class-addr=%p",
                        PRFIELD(integer->size), PRFIELD(integer->is_signed),
-                       PRFIELD(bt_byte_order_string(integer->user_byte_order)),
+                       PRFIELD(bt_common_byte_order_string(integer->user_byte_order)),
                        PRFIELD(integer->base),
-                       PRFIELD(bt_string_encoding_string(integer->encoding)),
-                       PRFIELD(integer->mapped_clock));
+                       PRFIELD(bt_common_string_encoding_string(integer->encoding)),
+                       PRFIELD(integer->mapped_clock_class));
 
-               if (integer->mapped_clock) {
+               if (integer->mapped_clock_class) {
                        BUF_APPEND(", %smapped-clock-class-name=\"%s\"",
-                               PRFIELD(bt_clock_class_get_name(integer->mapped_clock)));
+                               PRFIELD(bt_clock_class_get_name(integer->mapped_clock_class)));
                }
                break;
        }
        case BT_FIELD_TYPE_ID_FLOAT:
        {
-               struct bt_field_type_floating_point *flt = (void *) field_type;
+               struct bt_field_type_common_floating_point *flt =
+                       BT_FROM_COMMON(field_type);
 
                BUF_APPEND(", %sexp-dig=%u, %smant-dig=%u, %sbyte-order=%s",
                        PRFIELD(flt->exp_dig), PRFIELD(flt->mant_dig),
-                       PRFIELD(bt_byte_order_string(flt->user_byte_order)));
+                       PRFIELD(bt_common_byte_order_string(flt->user_byte_order)));
                break;
        }
        case BT_FIELD_TYPE_ID_ENUM:
        {
-               struct bt_field_type_enumeration *enm = (void *) field_type;
+               struct bt_field_type_common_enumeration *enm =
+                       BT_FROM_COMMON(field_type);
 
                BUF_APPEND(", %smapping-count=%u",
                        PRFIELD(enm->entries->len));
@@ -183,15 +197,17 @@ static inline void format_field_type(char **buf_ch, bool extended,
        }
        case BT_FIELD_TYPE_ID_STRING:
        {
-               struct bt_field_type_string *str = (void *) field_type;
+               struct bt_field_type_common_string *str =
+                       BT_FROM_COMMON(field_type);
 
                BUF_APPEND(", %sencoding=%s",
-                       PRFIELD(bt_string_encoding_string(str->encoding)));
+                       PRFIELD(bt_common_string_encoding_string(str->encoding)));
                break;
        }
        case BT_FIELD_TYPE_ID_STRUCT:
        {
-               struct bt_field_type_structure *structure = (void *) field_type;
+               struct bt_field_type_common_structure *structure =
+                       BT_FROM_COMMON(field_type);
 
                BUF_APPEND(", %sfield-count=%u",
                        PRFIELD(structure->fields->len));
@@ -199,21 +215,23 @@ static inline void format_field_type(char **buf_ch, bool extended,
        }
        case BT_FIELD_TYPE_ID_SEQUENCE:
        {
-               struct bt_field_type_sequence *seq = (void *) field_type;
+               struct bt_field_type_common_sequence *seq =
+                       BT_FROM_COMMON(field_type);
 
                BUF_APPEND(", %slength-ft-addr=\"%s\", %selem-ft-addr=%p",
                        PRFIELD(seq->length_field_name->str),
-                       PRFIELD(seq->element_type));
+                       PRFIELD(seq->element_ft));
                break;
        }
        case BT_FIELD_TYPE_ID_VARIANT:
        {
-               struct bt_field_type_variant *variant = (void *) field_type;
+               struct bt_field_type_common_variant *variant =
+                       BT_FROM_COMMON(field_type);
 
                BUF_APPEND(", %stag-name=\"%s\", %stag-ft-addr=%p, "
                        "%sfield-count=%u",
                        PRFIELD(variant->tag_name->str),
-                       PRFIELD(variant->tag), PRFIELD(variant->fields->len));
+                       PRFIELD(variant->tag_ft), PRFIELD(variant->fields->len));
                break;
        }
        default:
@@ -221,11 +239,26 @@ static inline void format_field_type(char **buf_ch, bool extended,
        }
 }
 
-static inline void format_field_integer_extended(char **buf_ch,
-               const char *prefix, struct bt_field *field)
+static inline void format_field_type(char **buf_ch, bool extended,
+               const char *prefix, struct bt_field_type *field_type)
+{
+       format_field_type_common(buf_ch, extended, prefix,
+               (void *) field_type);
+}
+
+static inline void format_writer_field_type(char **buf_ch, bool extended,
+               const char *prefix, struct bt_ctf_field_type *field_type)
+{
+       format_field_type_common(buf_ch, extended, prefix,
+               (void *) field_type);
+}
+
+static inline void format_field_common_integer_extended(char **buf_ch,
+               const char *prefix, struct bt_field_common *field)
 {
-       struct bt_field_integer *integer = (void *) field;
-       struct bt_field_type_integer *field_type = (void *) field->type;
+       struct bt_field_common_integer *integer = BT_FROM_COMMON(field);
+       struct bt_field_type_common_integer *field_type =
+               BT_FROM_COMMON(field->type);
        const char *fmt = NULL;
 
        if (field_type->base == 8) {
@@ -249,8 +282,8 @@ static inline void format_field_integer_extended(char **buf_ch,
        }
 }
 
-static inline void format_field(char **buf_ch, bool extended,
-               const char *prefix, struct bt_field *field)
+static inline void format_field_common(char **buf_ch, bool extended,
+               const char *prefix, struct bt_field_common *field)
 {
        BUF_APPEND(", %sis-set=%d", PRFIELD(field->payload_set));
 
@@ -260,7 +293,7 @@ static inline void format_field(char **buf_ch, bool extended,
 
        BUF_APPEND(", %stype-addr=%p, %stype-id=%s",
                PRFIELD(field->type),
-               PRFIELD(bt_field_type_id_string(field->type->id)));
+               PRFIELD(bt_common_field_type_id_string(field->type->id)));
 
        if (!extended || field->type->id == BT_FIELD_TYPE_ID_UNKNOWN ||
                        !field->payload_set) {
@@ -270,29 +303,32 @@ static inline void format_field(char **buf_ch, bool extended,
        switch (field->type->id) {
        case BT_FIELD_TYPE_ID_INTEGER:
        {
-               format_field_integer_extended(buf_ch, prefix, field);
+               format_field_common_integer_extended(buf_ch, prefix, field);
                break;
        }
        case BT_FIELD_TYPE_ID_FLOAT:
        {
-               struct bt_field_floating_point *flt = (void *) field;
+               struct bt_field_common_floating_point *flt =
+                       BT_FROM_COMMON(field);
 
                BUF_APPEND(", %svalue=%f", PRFIELD(flt->payload));
                break;
        }
        case BT_FIELD_TYPE_ID_ENUM:
        {
-               struct bt_field_enumeration *enm = (void *) field;
+               struct bt_field_common_enumeration *enm =
+                       BT_FROM_COMMON(field);
 
                if (enm->payload) {
-                       format_field_integer_extended(buf_ch, prefix,
+                       format_field_common_integer_extended(buf_ch, prefix,
                                enm->payload);
                }
                break;
        }
        case BT_FIELD_TYPE_ID_STRING:
        {
-               struct bt_field_string *str = (void *) field;
+               struct bt_field_common_string *str =
+                       BT_FROM_COMMON(field);
 
                BT_ASSERT(str->payload);
                BUF_APPEND(", %spartial-value=\"%.32s\"",
@@ -301,14 +337,16 @@ static inline void format_field(char **buf_ch, bool extended,
        }
        case BT_FIELD_TYPE_ID_SEQUENCE:
        {
-               struct bt_field_sequence *seq = (void *) field;
+               struct bt_field_common_sequence *seq =
+                       BT_FROM_COMMON(field);
 
                BUF_APPEND(", %slength-field-addr=%p", PRFIELD(seq->length));
                break;
        }
        case BT_FIELD_TYPE_ID_VARIANT:
        {
-               struct bt_field_variant *variant = (void *) field;
+               struct bt_field_common_variant *variant =
+                       BT_FROM_COMMON(field);
 
                BUF_APPEND(", %stag-field-addr=%p, %svalue-field-addr=%p",
                        PRFIELD(variant->tag), PRFIELD(variant->payload));
@@ -319,6 +357,18 @@ static inline void format_field(char **buf_ch, bool extended,
        }
 }
 
+static inline void format_field(char **buf_ch, bool extended,
+               const char *prefix, struct bt_field *field)
+{
+       format_field_common(buf_ch, extended, prefix, (void *) field);
+}
+
+static inline void format_writer_field(char **buf_ch, bool extended,
+               const char *prefix, struct bt_ctf_field *field)
+{
+       format_field_common(buf_ch, extended, prefix, (void *) field);
+}
+
 static inline void format_field_path(char **buf_ch, bool extended,
                const char *prefix, struct bt_field_path *field_path)
 {
@@ -331,7 +381,7 @@ static inline void format_field_path(char **buf_ch, bool extended,
                return;
        }
 
-       BUF_APPEND(", %spath=[%s", PRFIELD(bt_scope_string(field_path->root)));
+       BUF_APPEND(", %spath=[%s", PRFIELD(bt_common_scope_string(field_path->root)));
 
        for (i = 0; i < field_path->indexes->len; i++) {
                int index = g_array_index(field_path->indexes, int, i);
@@ -342,8 +392,8 @@ static inline void format_field_path(char **buf_ch, bool extended,
        BUF_APPEND("%s", "]");
 }
 
-static inline void format_trace(char **buf_ch, bool extended,
-               const char *prefix, struct bt_trace *trace)
+static inline void format_trace_common(char **buf_ch, bool extended,
+               const char *prefix, struct bt_trace_common *trace)
 {
        if (trace->name) {
                BUF_APPEND(", %sname=\"%s\"", PRFIELD(trace->name->str));
@@ -353,27 +403,41 @@ static inline void format_trace(char **buf_ch, bool extended,
                return;
        }
 
-       BUF_APPEND(", %sis-frozen=%d, %sis-static=%d",
-               PRFIELD(trace->frozen), PRFIELD(trace->is_static));
+       BUF_APPEND(", %sis-frozen=%d", PRFIELD(trace->frozen));
 
        if (trace->uuid_set) {
                BUF_APPEND_UUID(trace->uuid);
        }
 
        BUF_APPEND(", %sclock-class-count=%u, %sstream-class-count=%u, "
-               "%sstream-count=%u, %sis-ctf-writer-trace=%d, "
-               "%spacket-header-ft-addr=%p",
-               PRFIELD(trace->clocks->len),
+               "%sstream-count=%u, %spacket-header-ft-addr=%p",
+               PRFIELD(trace->clock_classes->len),
                PRFIELD(trace->stream_classes->len),
                PRFIELD(trace->streams->len),
-               PRFIELD(trace->is_created_by_writer),
-               PRFIELD(trace->packet_header_type));
+               PRFIELD(trace->packet_header_field_type));
 }
 
-static inline void format_stream_class(char **buf_ch, bool extended,
-               const char *prefix, struct bt_stream_class *stream_class)
+static inline void format_trace(char **buf_ch, bool extended,
+               const char *prefix, struct bt_trace *trace)
 {
-       struct bt_trace *trace;
+       format_trace_common(buf_ch, extended, prefix, BT_TO_COMMON(trace));
+
+       if (extended) {
+               BUF_APPEND(", %sis-static=%d", PRFIELD(trace->is_static));
+       }
+}
+
+static inline void format_writer_trace(char **buf_ch, bool extended,
+               const char *prefix, struct bt_ctf_trace *trace)
+{
+       format_trace_common(buf_ch, extended, prefix, BT_TO_COMMON(trace));
+}
+
+static inline void format_stream_class_common(char **buf_ch, bool extended,
+               const char *prefix, struct bt_stream_class_common *stream_class,
+               format_func trace_format_func)
+{
+       struct bt_trace_common *trace;
        char tmp_prefix[64];
 
        if (stream_class->id_set) {
@@ -389,35 +453,51 @@ static inline void format_stream_class(char **buf_ch, bool extended,
        }
 
        BUF_APPEND(", %sis-frozen=%d", PRFIELD(stream_class->frozen));
-
-       if (stream_class->clock) {
-               BUF_APPEND(", %sctf-writer-clock-addr=%p, "
-                       "%sctf-writer-clock-name=\"%s\"",
-                       PRFIELD(stream_class->clock),
-                       PRFIELD(bt_clock_class_get_name(stream_class->clock->clock_class)));
-       }
-
        BUF_APPEND(", %sevent-class-count=%u, %spacket-context-ft-addr=%p, "
                "%sevent-header-ft-addr=%p, %sevent-context-ft-addr=%p",
                PRFIELD(stream_class->event_classes->len),
-               PRFIELD(stream_class->packet_context_type),
-               PRFIELD(stream_class->event_header_type),
-               PRFIELD(stream_class->event_context_type));
-       trace = bt_stream_class_borrow_trace(stream_class);
+               PRFIELD(stream_class->packet_context_field_type),
+               PRFIELD(stream_class->event_header_field_type),
+               PRFIELD(stream_class->event_context_field_type));
+       trace = bt_stream_class_common_borrow_trace(stream_class);
        if (!trace) {
                return;
        }
 
        BUF_APPEND(", %strace-addr=%p", PRFIELD(trace));
        SET_TMP_PREFIX("trace-");
-       format_trace(buf_ch, false, tmp_prefix, trace);
+       trace_format_func(buf_ch, false, tmp_prefix, trace);
 }
 
-static inline void format_event_class(char **buf_ch, bool extended,
-               const char *prefix, struct bt_event_class *event_class)
+static inline void format_stream_class(char **buf_ch, bool extended,
+               const char *prefix, struct bt_stream_class *stream_class)
 {
-       struct bt_stream_class *stream_class;
-       struct bt_trace *trace;
+       format_stream_class_common(buf_ch, extended, prefix,
+               BT_TO_COMMON(stream_class), (format_func) format_trace);
+}
+
+static inline void format_writer_stream_class(char **buf_ch, bool extended,
+               const char *prefix, struct bt_ctf_stream_class *stream_class)
+{
+       format_stream_class_common(buf_ch, extended, prefix,
+               BT_TO_COMMON(stream_class), (format_func) format_writer_trace);
+
+       if (extended && stream_class->clock) {
+               BUF_APPEND(", %sctf-writer-clock-addr=%p, "
+                       "%sctf-writer-clock-name=\"%s\"",
+                       PRFIELD(stream_class->clock),
+                       PRFIELD(bt_clock_class_get_name(
+                               BT_TO_COMMON(stream_class->clock->clock_class))));
+       }
+}
+
+static inline void format_event_class_common(char **buf_ch, bool extended,
+               const char *prefix, struct bt_event_class_common *event_class,
+               format_func format_stream_class_func,
+               format_func format_trace_func)
+{
+       struct bt_stream_class_common *stream_class;
+       struct bt_trace_common *trace;
        char tmp_prefix[64];
 
        BUF_APPEND(", %sid=%" PRId64, PRFIELD(event_class->id));
@@ -432,7 +512,7 @@ static inline void format_event_class(char **buf_ch, bool extended,
 
        BUF_APPEND(", %sis-frozen=%d, %slog-level=%s",
                PRFIELD(event_class->frozen),
-               PRFIELD(bt_event_class_log_level_string(event_class->log_level)));
+               PRFIELD(bt_common_event_class_log_level_string(event_class->log_level)));
 
        if (event_class->emf_uri) {
                BUF_APPEND(", %semf-uri=\"%s\"",
@@ -440,32 +520,51 @@ static inline void format_event_class(char **buf_ch, bool extended,
        }
 
        BUF_APPEND(", %scontext-ft-addr=%p, %spayload-ft-addr=%p",
-               PRFIELD(event_class->context),
-               PRFIELD(event_class->fields));
+               PRFIELD(event_class->context_field_type),
+               PRFIELD(event_class->payload_field_type));
 
-       stream_class = bt_event_class_borrow_stream_class(event_class);
+       stream_class = bt_event_class_common_borrow_stream_class(event_class);
        if (!stream_class) {
                return;
        }
 
        BUF_APPEND(", %sstream-class-addr=%p", PRFIELD(stream_class));
        SET_TMP_PREFIX("stream-class-");
-       format_stream_class(buf_ch, false, tmp_prefix, stream_class);
-       trace = bt_stream_class_borrow_trace(stream_class);
+       format_stream_class_func(buf_ch, false, tmp_prefix, stream_class);
+       trace = bt_stream_class_common_borrow_trace(stream_class);
        if (!trace) {
                return;
        }
 
        BUF_APPEND(", %strace-addr=%p", PRFIELD(trace));
        SET_TMP_PREFIX("trace-");
-       format_trace(buf_ch, false, tmp_prefix, trace);
+       format_trace_func(buf_ch, false, tmp_prefix, trace);
 }
 
-static inline void format_stream(char **buf_ch, bool extended,
-               const char *prefix, struct bt_stream *stream)
+static inline void format_event_class(char **buf_ch, bool extended,
+               const char *prefix, struct bt_event_class *event_class)
 {
-       struct bt_stream_class *stream_class;
-       struct bt_trace *trace;
+       format_event_class_common(buf_ch, extended, prefix,
+               BT_TO_COMMON(event_class), (format_func) format_stream_class,
+               (format_func) format_trace);
+}
+
+static inline void format_writer_event_class(char **buf_ch, bool extended,
+               const char *prefix, struct bt_ctf_event_class *event_class)
+{
+       format_event_class_common(buf_ch, extended, prefix,
+               BT_TO_COMMON(event_class),
+               (format_func) format_writer_stream_class,
+               (format_func) format_writer_trace);
+}
+
+static inline void format_stream_common(char **buf_ch, bool extended,
+               const char *prefix, struct bt_stream_common *stream,
+               format_func format_stream_class_func,
+               format_func format_trace_func)
+{
+       struct bt_stream_class_common *stream_class;
+       struct bt_trace_common *trace;
        char tmp_prefix[64];
 
        BUF_APPEND(", %sid=%" PRId64, PRFIELD(stream->id));
@@ -474,55 +573,66 @@ static inline void format_stream(char **buf_ch, bool extended,
                BUF_APPEND(", %sname=\"%s\"", PRFIELD(stream->name->str));
        }
 
-       BUF_APPEND(", %sis-ctf-writer-stream=%d",
-               PRFIELD(stream->pos.fd != -1));
-
        if (!extended) {
                return;
        }
 
-       if (stream->pos.fd != -1) {
-               BUF_APPEND(", %sheader-field-addr=%p, %scontext-field-addr=%p"
-                       ", %sfd=%d, %smmap-offset=%zu, "
-                       "%smmap-base-offset=%zu, %spacket-size=%" PRIu64 ", "
-                       "%soffset=%" PRId64 ", %sevent-count=%u, "
-                       "%sflushed-packet-count=%u, "
-                       "%sdiscarded-event-count=%" PRIu64 ", "
-                       "%ssize=%" PRIu64 ", %slast-ts-end=%" PRIu64,
-                       PRFIELD(stream->packet_header),
-                       PRFIELD(stream->packet_context),
-                       PRFIELD(stream->pos.fd),
-                       PRFIELD((size_t) stream->pos.mmap_offset),
-                       PRFIELD((size_t) stream->pos.mmap_base_offset),
-                       PRFIELD(stream->pos.packet_size),
-                       PRFIELD(stream->pos.offset),
-                       PRFIELD(stream->events->len),
-                       PRFIELD(stream->flushed_packet_count),
-                       PRFIELD(stream->discarded_events),
-                       PRFIELD(stream->size), PRFIELD(stream->last_ts_end));
-       }
-
-       stream_class = bt_stream_borrow_stream_class(stream);
+       stream_class = bt_stream_common_borrow_class(stream);
        if (!stream_class) {
                return;
        }
 
        BUF_APPEND(", %sstream-class-addr=%p", PRFIELD(stream_class));
        SET_TMP_PREFIX("stream-class-");
-       format_stream_class(buf_ch, false, tmp_prefix, stream_class);
-       trace = bt_stream_class_borrow_trace(stream_class);
+       format_stream_class_func(buf_ch, false, tmp_prefix, stream_class);
+       trace = bt_stream_class_common_borrow_trace(stream_class);
        if (!trace) {
                return;
        }
 
-       trace = (struct bt_trace *) bt_object_borrow_parent(stream);
+       trace = (void *) bt_object_borrow_parent(stream);
        if (!trace) {
                return;
        }
 
        BUF_APPEND(", %strace-addr=%p", PRFIELD(trace));
        SET_TMP_PREFIX("trace-");
-       format_trace(buf_ch, false, tmp_prefix, trace);
+       format_trace_common(buf_ch, false, tmp_prefix, trace);
+}
+
+static inline void format_stream(char **buf_ch, bool extended,
+               const char *prefix, struct bt_stream *stream)
+{
+       format_stream_common(buf_ch, extended, prefix, BT_TO_COMMON(stream),
+               (format_func) format_stream_class,
+               (format_func) format_trace);
+}
+
+static inline void format_writer_stream(char **buf_ch, bool extended,
+               const char *prefix, struct bt_ctf_stream *stream)
+{
+       format_stream_common(buf_ch, extended, prefix, BT_TO_COMMON(stream),
+               (format_func) format_writer_stream_class,
+               (format_func) format_writer_trace);
+
+       BUF_APPEND(", %sheader-field-addr=%p, %scontext-field-addr=%p"
+               ", %sfd=%d, %smmap-offset=%zu, "
+               "%smmap-base-offset=%zu, %spacket-size=%" PRIu64 ", "
+               "%soffset=%" PRId64 ", %sevent-count=%u, "
+               "%sflushed-packet-count=%u, "
+               "%sdiscarded-event-count=%" PRIu64 ", "
+               "%ssize=%" PRIu64 ", %slast-ts-end=%" PRIu64,
+               PRFIELD(stream->packet_header),
+               PRFIELD(stream->packet_context),
+               PRFIELD(stream->pos.fd),
+               PRFIELD((size_t) stream->pos.mmap_offset),
+               PRFIELD((size_t) stream->pos.mmap_base_offset),
+               PRFIELD(stream->pos.packet_size),
+               PRFIELD(stream->pos.offset),
+               PRFIELD(stream->events->len),
+               PRFIELD(stream->flushed_packet_count),
+               PRFIELD(stream->discarded_events),
+               PRFIELD(stream->size), PRFIELD(stream->last_ts_end));
 }
 
 static inline void format_packet(char **buf_ch, bool extended,
@@ -559,13 +669,14 @@ static inline void format_packet(char **buf_ch, bool extended,
        format_trace(buf_ch, false, tmp_prefix, trace);
 }
 
-static inline void format_event(char **buf_ch, bool extended,
-               const char *prefix, struct bt_event *event)
+static inline void format_event_common(char **buf_ch, bool extended,
+               const char *prefix, struct bt_event_common *event,
+               format_func format_event_class_func,
+               format_func format_stream_class_func,
+               format_func format_trace_func)
 {
-       struct bt_trace *trace;
-       struct bt_stream_class *stream_class;
-       struct bt_packet *packet;
-       struct bt_stream *stream;
+       struct bt_trace_common *trace;
+       struct bt_stream_class_common *stream_class;
        char tmp_prefix[64];
 
        if (!extended) {
@@ -574,30 +685,48 @@ static inline void format_event(char **buf_ch, bool extended,
 
        BUF_APPEND(", %sis-frozen=%d, %sheader-field-addr=%p, "
                "%sstream-context-field-addr=%p, "
-               "%scontext-field-addr=%p, %spayload-field-addr=%p, "
-               "%sclock-value-count=%u",
+               "%scontext-field-addr=%p, %spayload-field-addr=%p, ",
                PRFIELD(event->frozen),
-               PRFIELD(event->event_header),
-               PRFIELD(event->stream_event_context),
-               PRFIELD(event->context_payload),
-               PRFIELD(event->fields_payload),
-               PRFIELD(g_hash_table_size(event->clock_values)));
-       BUF_APPEND(", %sevent-class-addr=%p", PRFIELD(event->event_class));
+               PRFIELD(event->header_field),
+               PRFIELD(event->stream_event_context_field),
+               PRFIELD(event->context_field),
+               PRFIELD(event->payload_field));
+       BUF_APPEND(", %sevent-class-addr=%p", PRFIELD(event->class));
        SET_TMP_PREFIX("event-class-");
-       format_event_class(buf_ch, false, tmp_prefix, event->event_class);
-       stream_class = bt_event_class_borrow_stream_class(event->event_class);
+       format_event_class_func(buf_ch, false, tmp_prefix, event->class);
+       stream_class = bt_event_class_common_borrow_stream_class(event->class);
        if (stream_class) {
                BUF_APPEND(", %sstream-class-addr=%p", PRFIELD(stream_class));
                SET_TMP_PREFIX("stream-class-");
-               format_stream_class(buf_ch, false, tmp_prefix, stream_class);
+               format_stream_class_func(buf_ch, false, tmp_prefix,
+                       stream_class);
 
-               trace = bt_stream_class_borrow_trace(stream_class);
+               trace = bt_stream_class_common_borrow_trace(stream_class);
                if (trace) {
                        BUF_APPEND(", %strace-addr=%p", PRFIELD(trace));
                        SET_TMP_PREFIX("trace-");
-                       format_trace(buf_ch, false, tmp_prefix, trace);
+                       format_trace_func(buf_ch, false, tmp_prefix, trace);
                }
        }
+}
+
+static inline void format_event(char **buf_ch, bool extended,
+               const char *prefix, struct bt_event *event)
+{
+       struct bt_packet *packet;
+       struct bt_stream *stream;
+       char tmp_prefix[64];
+
+       format_event_common(buf_ch, extended, prefix, BT_TO_COMMON(event),
+               (format_func) format_event_class,
+               (format_func) format_stream_class, (format_func) format_trace);
+
+       if (!extended) {
+               return;
+       }
+
+       BUF_APPEND(", %sclock-value-count=%u",
+               PRFIELD(g_hash_table_size(event->clock_values)));
 
        packet = bt_event_borrow_packet(event);
        if (!packet) {
@@ -617,6 +746,15 @@ static inline void format_event(char **buf_ch, bool extended,
        format_stream(buf_ch, false, tmp_prefix, stream);
 }
 
+static inline void format_writer_event(char **buf_ch, bool extended,
+               const char *prefix, struct bt_event *event)
+{
+       format_event_common(buf_ch, extended, prefix, BT_TO_COMMON(event),
+               (format_func) format_writer_event_class,
+               (format_func) format_writer_stream_class,
+               (format_func) format_writer_trace);
+}
+
 static inline void format_clock_class(char **buf_ch, bool extended,
                const char *prefix, struct bt_clock_class *clock_class)
 {
@@ -1071,6 +1209,41 @@ static inline void format_ctf_writer(char **buf_ch, bool extended,
        /* TODO */
 }
 
+static inline void format_stream_class_common_common(char **buf_ch,
+               bool extended, const char *prefix,
+               struct bt_stream_class_common *stream_class)
+{
+       format_stream_class_common(buf_ch, extended, prefix, stream_class,
+               (format_func) format_trace_common);
+}
+
+static inline void format_event_class_common_common(char **buf_ch,
+               bool extended, const char *prefix,
+               struct bt_event_class_common *event_class)
+{
+       format_event_class_common(buf_ch, extended, prefix, event_class,
+               (format_func) format_stream_class_common,
+               (format_func) format_trace_common);
+}
+
+static inline void format_event_common_common(char **buf_ch,
+               bool extended, const char *prefix,
+               struct bt_event_common *event)
+{
+       format_event_common(buf_ch, extended, prefix, event,
+               (format_func) format_event_class_common,
+               (format_func) format_stream_class_common,
+               (format_func) format_trace_common);
+}
+
+static inline void format_stream_common_common(char **buf_ch, bool extended,
+               const char *prefix, struct bt_stream_common *stream)
+{
+       format_stream_common(buf_ch, extended, prefix, stream,
+               (format_func) format_stream_class_common,
+               (format_func) format_trace_common);
+}
+
 static inline void handle_conversion_specifier_bt(void *priv_data,
                char **buf_ch, size_t avail_size,
                const char **out_fmt_ch, va_list *args)
@@ -1080,6 +1253,11 @@ static inline void handle_conversion_specifier_bt(void *priv_data,
        char prefix[64];
        char *prefix_ch = prefix;
        void *obj;
+       enum {
+               CAT_DEFAULT,
+               CAT_WRITER,
+               CAT_COMMON,
+       } cat = CAT_DEFAULT;
 
        /* skip "%!" */
        fmt_ch += 2;
@@ -1108,6 +1286,14 @@ static inline void handle_conversion_specifier_bt(void *priv_data,
                fmt_ch++;
        }
 
+       if (*fmt_ch == 'w') {
+               cat = CAT_WRITER;
+               fmt_ch++;
+       } else if (*fmt_ch == '_') {
+               cat = CAT_COMMON;
+               fmt_ch++;
+       }
+
        obj = va_arg(*args, void *);
        BUF_APPEND("%saddr=%p", prefix, obj);
 
@@ -1115,75 +1301,133 @@ static inline void handle_conversion_specifier_bt(void *priv_data,
                goto update_fmt;
        }
 
-       switch (*fmt_ch) {
-       case 'r':
-               format_ref_count(buf_ch, extended, prefix, obj);
-               break;
-       case 'F':
-               format_field_type(buf_ch, extended, prefix, obj);
-               break;
-       case 'f':
-               format_field(buf_ch, extended, prefix, obj);
-               break;
-       case 'P':
-               format_field_path(buf_ch, extended, prefix, obj);
-               break;
-       case 'E':
-               format_event_class(buf_ch, extended, prefix, obj);
-               break;
-       case 'e':
-               format_event(buf_ch, extended, prefix, obj);
-               break;
-       case 'S':
-               format_stream_class(buf_ch, extended, prefix, obj);
-               break;
-       case 's':
-               format_stream(buf_ch, extended, prefix, obj);
-               break;
-       case 'a':
-               format_packet(buf_ch, extended, prefix, obj);
-               break;
-       case 't':
-               format_trace(buf_ch, extended, prefix, obj);
-               break;
-       case 'K':
-               format_clock_class(buf_ch, extended, prefix, obj);
-               break;
-       case 'k':
-               format_clock_value(buf_ch, extended, prefix, obj);
-               break;
-       case 'v':
-               format_value(buf_ch, extended, prefix, obj);
-               break;
-       case 'n':
-               format_notification(buf_ch, extended, prefix, obj);
-               break;
-       case 'i':
-               format_notification_iterator(buf_ch, extended, prefix, obj);
-               break;
-       case 'C':
-               format_component_class(buf_ch, extended, prefix, obj);
-               break;
-       case 'c':
-               format_component(buf_ch, extended, prefix, obj);
-               break;
-       case 'p':
-               format_port(buf_ch, extended, prefix, obj);
-               break;
-       case 'x':
-               format_connection(buf_ch, extended, prefix, obj);
-               break;
-       case 'u':
-               format_plugin(buf_ch, extended, prefix, obj);
+       switch (cat) {
+       case CAT_DEFAULT:
+               switch (*fmt_ch) {
+               case 'r':
+                       format_ref_count(buf_ch, extended, prefix, obj);
+                       break;
+               case 'F':
+                       format_field_type(buf_ch, extended, prefix, obj);
+                       break;
+               case 'f':
+                       format_field(buf_ch, extended, prefix, obj);
+                       break;
+               case 'P':
+                       format_field_path(buf_ch, extended, prefix, obj);
+                       break;
+               case 'E':
+                       format_event_class(buf_ch, extended, prefix, obj);
+                       break;
+               case 'e':
+                       format_event(buf_ch, extended, prefix, obj);
+                       break;
+               case 'S':
+                       format_stream_class(buf_ch, extended, prefix, obj);
+                       break;
+               case 's':
+                       format_stream(buf_ch, extended, prefix, obj);
+                       break;
+               case 'a':
+                       format_packet(buf_ch, extended, prefix, obj);
+                       break;
+               case 't':
+                       format_trace(buf_ch, extended, prefix, obj);
+                       break;
+               case 'K':
+                       format_clock_class(buf_ch, extended, prefix, obj);
+                       break;
+               case 'k':
+                       format_clock_value(buf_ch, extended, prefix, obj);
+                       break;
+               case 'v':
+                       format_value(buf_ch, extended, prefix, obj);
+                       break;
+               case 'n':
+                       format_notification(buf_ch, extended, prefix, obj);
+                       break;
+               case 'i':
+                       format_notification_iterator(buf_ch, extended, prefix, obj);
+                       break;
+               case 'C':
+                       format_component_class(buf_ch, extended, prefix, obj);
+                       break;
+               case 'c':
+                       format_component(buf_ch, extended, prefix, obj);
+                       break;
+               case 'p':
+                       format_port(buf_ch, extended, prefix, obj);
+                       break;
+               case 'x':
+                       format_connection(buf_ch, extended, prefix, obj);
+                       break;
+               case 'u':
+                       format_plugin(buf_ch, extended, prefix, obj);
+                       break;
+               case 'g':
+                       format_graph(buf_ch, extended, prefix, obj);
+                       break;
+               default:
+                       abort();
+               }
                break;
-       case 'g':
-               format_graph(buf_ch, extended, prefix, obj);
+       case CAT_WRITER:
+               switch (*fmt_ch) {
+               case 'F':
+                       format_writer_field_type(buf_ch, extended, prefix, obj);
+                       break;
+               case 'f':
+                       format_writer_field(buf_ch, extended, prefix, obj);
+                       break;
+               case 'E':
+                       format_writer_event_class(buf_ch, extended, prefix, obj);
+                       break;
+               case 'e':
+                       format_writer_event(buf_ch, extended, prefix, obj);
+                       break;
+               case 'S':
+                       format_writer_stream_class(buf_ch, extended, prefix, obj);
+                       break;
+               case 's':
+                       format_writer_stream(buf_ch, extended, prefix, obj);
+                       break;
+               case 't':
+                       format_writer_trace(buf_ch, extended, prefix, obj);
+                       break;
+               case 'w':
+                       format_ctf_writer(buf_ch, extended, prefix, obj);
+                       break;
+               default:
+                       abort();
+               }
                break;
-       case 'w':
-               format_ctf_writer(buf_ch, extended, prefix, obj);
+       case CAT_COMMON:
+               switch (*fmt_ch) {
+               case 'F':
+                       format_field_type_common(buf_ch, extended, prefix, obj);
+                       break;
+               case 'f':
+                       format_field_common(buf_ch, extended, prefix, obj);
+                       break;
+               case 'E':
+                       format_event_class_common_common(buf_ch, extended, prefix, obj);
+                       break;
+               case 'e':
+                       format_event_common_common(buf_ch, extended, prefix, obj);
+                       break;
+               case 'S':
+                       format_stream_class_common_common(buf_ch, extended, prefix, obj);
+                       break;
+               case 's':
+                       format_stream_common_common(buf_ch, extended, prefix, obj);
+                       break;
+               case 't':
+                       format_trace_common(buf_ch, extended, prefix, obj);
+                       break;
+               default:
+                       abort();
+               }
                break;
-       default:
-               abort();
        }
 
 update_fmt:
index be2de4e7a86409f198aa1f968e25491a095499c9..04acb6ec3cdf14b02c5cf3f877c100a5e7ffb169 100644 (file)
@@ -1,7 +1,8 @@
-SUBDIRS = libctfcopytrace ctf text utils
+SUBDIRS = ctf text utils
+#libctfcopytrace
 
 if ENABLE_DEBUG_INFO
-SUBDIRS += lttng-utils
+#SUBDIRS += lttng-utils
 endif
 
 noinst_HEADERS = plugins-common.h
index 110f9bbece4ec7bba6864fbe10ca7733de693eb0..e2141a27f8ba715364964dee7118d6da6bda33cc 100644 (file)
@@ -1,4 +1,5 @@
-SUBDIRS = common fs-src fs-sink lttng-live
+SUBDIRS = common fs-src
+# fs-sink lttng-live
 
 noinst_HEADERS = print.h
 
@@ -14,10 +15,11 @@ babeltrace_plugin_ctf_la_LDFLAGS = \
 
 babeltrace_plugin_ctf_la_LIBADD = \
        fs-src/libbabeltrace-plugin-ctf-fs.la \
-       lttng-live/libbabeltrace-plugin-ctf-lttng-live.la \
-       fs-sink/libbabeltrace-plugin-ctf-writer.la \
        common/libbabeltrace-plugin-ctf-common.la
 
+#      lttng-live/libbabeltrace-plugin-ctf-lttng-live.la \
+#      fs-sink/libbabeltrace-plugin-ctf-writer.la
+
 if !ENABLE_BUILT_IN_PLUGINS
 babeltrace_plugin_ctf_la_LIBADD += \
        $(top_builddir)/lib/libbabeltrace.la \
index ac6ce1a042180fefb6aaf0ab8c107a7d035b32c9..7ccfab0e64ab3d988c686c289f44414150cdc6f2 100644 (file)
@@ -35,8 +35,8 @@
 #include <babeltrace/assert-internal.h>
 #include <string.h>
 #include <babeltrace/bitfield-internal.h>
+#include <babeltrace/common-internal.h>
 #include <babeltrace/babeltrace.h>
-#include <babeltrace/ctf-ir/field-types-internal.h>
 #include <babeltrace/ref.h>
 #include <babeltrace/align-internal.h>
 #include <glib.h>
@@ -249,7 +249,7 @@ int64_t get_compound_field_type_length(struct bt_btr *btr,
                BT_LOGW("Cannot get field type's field count: btr-addr=%p, "
                        "ft-addr=%p, ft-id=%s",
                        btr, field_type,
-                       bt_field_type_id_string(
+                       bt_common_field_type_id_string(
                                bt_field_type_get_type_id(field_type)));
                length = BT_BTR_STATUS_ERROR;
        }
@@ -270,7 +270,7 @@ int stack_push(struct stack *stack, struct bt_field_type *base_type,
        BT_LOGV("Pushing field type on stack: stack-addr=%p, "
                "ft-addr=%p, ft-id=%s, base-length=%zu, "
                "stack-size-before=%u, stack-size-after=%u",
-               stack, base_type, bt_field_type_id_string(
+               stack, base_type, bt_common_field_type_id_string(
                        bt_field_type_get_type_id(base_type)),
                base_len, stack->entries->len, stack->entries->len + 1);
        entry = g_new0(struct stack_entry, 1);
@@ -300,7 +300,7 @@ int stack_push_with_len(struct bt_btr *btr,
        if (base_len < 0) {
                BT_LOGW("Cannot get compound field type's field count: "
                        "btr-addr=%p, ft-addr=%p, ft-id=%s",
-                       btr, base_type, bt_field_type_id_string(
+                       btr, base_type, bt_common_field_type_id_string(
                                bt_field_type_get_type_id(base_type)));
                ret = BT_BTR_STATUS_ERROR;
                goto end;
@@ -438,7 +438,7 @@ int get_basic_field_type_size(struct bt_btr *btr,
        {
                struct bt_field_type *int_type;
 
-               int_type = bt_field_type_enumeration_get_container_type(
+               int_type = bt_field_type_enumeration_get_container_field_type(
                        field_type);
                BT_ASSERT(int_type);
                size = get_basic_field_type_size(btr, int_type);
@@ -524,7 +524,7 @@ enum bt_btr_status read_unsigned_bitfield(const uint8_t *buf, size_t at,
 
        BT_LOGV("Read unsigned bit array: cur=%zu, size=%" PRId64 ", "
                "bo=%s, val=%" PRIu64, at, field_size,
-               bt_byte_order_string(bo), *v);
+               bt_common_byte_order_string(bo), *v);
        return status;
 }
 
@@ -549,7 +549,7 @@ enum bt_btr_status read_signed_bitfield(const uint8_t *buf, size_t at,
 
        BT_LOGV("Read signed bit array: cur=%zu, size=%" PRId64 ", "
                "bo=%s, val=%" PRId64, at, field_size,
-               bt_byte_order_string(bo), *v);
+               bt_common_byte_order_string(bo), *v);
        return status;
 }
 
@@ -599,8 +599,8 @@ end:
        if (status < 0) {
                BT_LOGW("Cannot read bit array: two different byte orders not at a byte boundary: "
                        "btr-addr=%p, last-bo=%s, next-bo=%s",
-                       btr, bt_byte_order_string(btr->last_bo),
-                       bt_byte_order_string(next_bo));
+                       btr, bt_common_byte_order_string(btr->last_bo),
+                       bt_common_byte_order_string(next_bo));
        }
 
        return status;
@@ -796,7 +796,7 @@ enum bt_btr_status read_basic_enum_and_call_cb(struct bt_btr *btr,
        struct bt_field_type *int_field_type;
        enum bt_btr_status status = BT_BTR_STATUS_OK;
 
-       int_field_type = bt_field_type_enumeration_get_container_type(
+       int_field_type = bt_field_type_enumeration_get_container_field_type(
                btr->cur_basic_field_type);
        BT_ASSERT(int_field_type);
        status = read_basic_int_and_call(btr, buf, at,
@@ -1119,7 +1119,7 @@ enum bt_btr_status read_basic_begin_state(struct bt_btr *btr)
                BT_LOGF("Unknown basic field type ID: "
                        "btr-addr=%p, ft-addr=%p, ft-id=%s",
                        btr, btr->cur_basic_field_type,
-                       bt_field_type_id_string(
+                       bt_common_field_type_id_string(
                                bt_field_type_get_type_id(
                                        btr->cur_basic_field_type)));
                abort();
@@ -1152,7 +1152,7 @@ enum bt_btr_status read_basic_continue_state(struct bt_btr *btr)
                BT_LOGF("Unknown basic field type ID: "
                        "btr-addr=%p, ft-addr=%p, ft-id=%s",
                        btr, btr->cur_basic_field_type,
-                       bt_field_type_id_string(
+                       bt_common_field_type_id_string(
                                bt_field_type_get_type_id(
                                        btr->cur_basic_field_type)));
                abort();
@@ -1184,7 +1184,7 @@ enum bt_btr_status align_type_state(struct bt_btr *btr,
                BT_LOGW("Cannot get field type's alignment: "
                        "btr-addr=%p, ft-addr=%p, ft-id=%s",
                        btr, field_type,
-                       bt_field_type_id_string(
+                       bt_common_field_type_id_string(
                                bt_field_type_get_type_id(field_type)));
                status = BT_BTR_STATUS_ERROR;
                goto end;
@@ -1294,12 +1294,12 @@ enum bt_btr_status next_field_state(struct bt_btr *btr)
                break;
        case BT_FIELD_TYPE_ID_ARRAY:
                next_field_type =
-                       bt_field_type_array_get_element_type(
+                       bt_field_type_array_get_element_field_type(
                                top->base_type);
                break;
        case BT_FIELD_TYPE_ID_SEQUENCE:
                next_field_type =
-                       bt_field_type_sequence_get_element_type(
+                       bt_field_type_sequence_get_element_field_type(
                                top->base_type);
                break;
        case BT_FIELD_TYPE_ID_VARIANT:
@@ -1317,7 +1317,7 @@ enum bt_btr_status next_field_state(struct bt_btr *btr)
                        "btr-addr=%p, base-ft-addr=%p, base-ft-id=%s, "
                        "index=%" PRId64,
                        btr, top->base_type,
-                       bt_field_type_id_string(
+                       bt_common_field_type_id_string(
                                bt_field_type_get_type_id(top->base_type)),
                        top->index);
                status = BT_BTR_STATUS_ERROR;
index ee6e116669b59c81c3f7f29520452a0b8b42fff5..388c76f926e89560984357ddf85e2a65f2d3182d 100644 (file)
 #include <glib.h>
 #include <inttypes.h>
 #include <errno.h>
+#include <babeltrace/common-internal.h>
 #include <babeltrace/compat/uuid-internal.h>
 #include <babeltrace/endian-internal.h>
 #include <babeltrace/babeltrace.h>
-#include <babeltrace/ctf-ir/field-types-internal.h>
 
 #include "scanner.h"
 #include "parser.h"
@@ -2195,10 +2195,10 @@ int visit_enum_decl_entry(struct ctx *ctx, struct ctf_node *enumerator,
        }
 
        if (is_signed) {
-               ret = bt_field_type_enumeration_add_mapping_signed(enum_decl,
+               ret = bt_field_type_enumeration_signed_add_mapping(enum_decl,
                        effective_label, start, end);
        } else {
-               ret = bt_field_type_enumeration_add_mapping_unsigned(enum_decl,
+               ret = bt_field_type_enumeration_unsigned_add_mapping(enum_decl,
                        effective_label, (uint64_t) start, (uint64_t) end);
        }
        if (ret) {
@@ -2300,7 +2300,7 @@ int visit_enum_decl(struct ctx *ctx, const char *name,
                if (!bt_field_type_is_integer(integer_decl)) {
                        BT_LOGE("Container field type for enumeration field type is not an integer field type: "
                                "ft-id=%s",
-                               bt_field_type_id_string(
+                               bt_common_field_type_id_string(
                                        bt_field_type_get_type_id(integer_decl)));
                        ret = -EINVAL;
                        goto error;
@@ -3328,7 +3328,7 @@ int visit_event_decl_entry(struct ctx *ctx, struct ctf_node *node,
                        }
 
                        BT_ASSERT(decl);
-                       ret = bt_event_class_set_context_type(
+                       ret = bt_event_class_set_context_field_type(
                                event_class, decl);
                        BT_PUT(decl);
                        if (ret) {
@@ -3358,7 +3358,7 @@ int visit_event_decl_entry(struct ctx *ctx, struct ctf_node *node,
                        }
 
                        BT_ASSERT(decl);
-                       ret = bt_event_class_set_payload_type(
+                       ret = bt_event_class_set_payload_field_type(
                                event_class, decl);
                        BT_PUT(decl);
                        if (ret) {
@@ -3565,7 +3565,7 @@ int reset_event_decl_types(struct ctx *ctx,
        int ret = 0;
 
        /* Context type. */
-       ret = bt_event_class_set_context_type(event_class, NULL);
+       ret = bt_event_class_set_context_field_type(event_class, NULL);
        if (ret) {
                BT_LOGE("Cannot reset initial event class's context field type: "
                        "event-name=\"%s\"",
@@ -3574,7 +3574,7 @@ int reset_event_decl_types(struct ctx *ctx,
        }
 
        /* Event payload. */
-       ret = bt_event_class_set_payload_type(event_class, NULL);
+       ret = bt_event_class_set_payload_field_type(event_class, NULL);
        if (ret) {
                BT_LOGE("Cannot reset initial event class's payload field type: "
                        "event-name=\"%s\"",
@@ -3592,21 +3592,21 @@ int reset_stream_decl_types(struct ctx *ctx,
        int ret = 0;
 
        /* Packet context. */
-       ret = bt_stream_class_set_packet_context_type(stream_class, NULL);
+       ret = bt_stream_class_set_packet_context_field_type(stream_class, NULL);
        if (ret) {
                BT_LOGE_STR("Cannot reset initial stream class's packet context field type.");
                goto end;
        }
 
        /* Event header. */
-       ret = bt_stream_class_set_event_header_type(stream_class, NULL);
+       ret = bt_stream_class_set_event_header_field_type(stream_class, NULL);
        if (ret) {
                BT_LOGE_STR("Cannot reset initial stream class's event header field type.");
                goto end;
        }
 
        /* Event context. */
-       ret = bt_stream_class_set_event_context_type(stream_class, NULL);
+       ret = bt_stream_class_set_event_context_field_type(stream_class, NULL);
        if (ret) {
                BT_LOGE_STR("Cannot reset initial stream class's event context field type.");
                goto end;
@@ -3621,7 +3621,7 @@ struct bt_stream_class *create_reset_stream_class(struct ctx *ctx)
        int ret;
        struct bt_stream_class *stream_class;
 
-       stream_class = bt_stream_class_create_empty(NULL);
+       stream_class = bt_stream_class_create(NULL);
        if (!stream_class) {
                BT_LOGE_STR("Cannot create empty stream class.");
                goto error;
@@ -4105,7 +4105,7 @@ int visit_stream_decl_entry(struct ctx *ctx, struct ctf_node *node,
                                goto error;
                        }
 
-                       ret = bt_stream_class_set_event_header_type(
+                       ret = bt_stream_class_set_event_header_field_type(
                                stream_class, decl);
                        BT_PUT(decl);
                        if (ret) {
@@ -4136,7 +4136,7 @@ int visit_stream_decl_entry(struct ctx *ctx, struct ctf_node *node,
 
                        BT_ASSERT(decl);
 
-                       ret = bt_stream_class_set_event_context_type(
+                       ret = bt_stream_class_set_event_context_field_type(
                                stream_class, decl);
                        BT_PUT(decl);
                        if (ret) {
@@ -4182,7 +4182,7 @@ int visit_stream_decl_entry(struct ctx *ctx, struct ctf_node *node,
                                goto error;
                        }
 
-                       ret = bt_stream_class_set_packet_context_type(
+                       ret = bt_stream_class_set_packet_context_field_type(
                                stream_class, decl);
                        BT_PUT(decl);
                        if (ret) {
@@ -4266,7 +4266,7 @@ int visit_stream_decl(struct ctx *ctx, struct ctf_node *node)
                _BT_FIELD_TYPE_INIT(packet_header_decl);
 
                packet_header_decl =
-                       bt_trace_get_packet_header_type(ctx->trace);
+                       bt_trace_get_packet_header_field_type(ctx->trace);
                if (!packet_header_decl) {
                        _BT_LOGE_NODE(node,
                                "Stream class has a `id` attribute, "
@@ -4474,7 +4474,7 @@ int visit_trace_decl_entry(struct ctx *ctx, struct ctf_node *node, int *set)
                        }
 
                        BT_ASSERT(packet_header_decl);
-                       ret = bt_trace_set_packet_header_type(ctx->trace,
+                       ret = bt_trace_set_packet_header_field_type(ctx->trace,
                                packet_header_decl);
                        BT_PUT(packet_header_decl);
                        if (ret) {
@@ -5336,7 +5336,7 @@ struct ctf_visitor_generate_ir *ctf_visitor_generate_ir_create(
        }
 
        /* Set packet header to NULL to override the default one */
-       ret = bt_trace_set_packet_header_type(trace, NULL);
+       ret = bt_trace_set_packet_header_field_type(trace, NULL);
        if (ret) {
                BT_LOGE_STR("Cannot reset initial trace's packet header field type.");
                goto error;
index e596b532666e2c0ddd696a8da45256910b037ad6..642f9931cb2bf48e22562f4e4d1940a9974b26c7 100644 (file)
@@ -34,8 +34,7 @@
 #include <babeltrace/assert-internal.h>
 #include <string.h>
 #include <babeltrace/babeltrace.h>
-#include <babeltrace/ctf-ir/field-types-internal.h>
-#include <babeltrace/ctf-ir/field-path-internal.h>
+#include <babeltrace/common-internal.h>
 #include <glib.h>
 #include <stdlib.h>
 
@@ -691,7 +690,7 @@ enum bt_notif_iter_status read_packet_header_begin_state(
        }
 
        /* Packet header type is common to the whole trace. */
-       packet_header_type = bt_trace_get_packet_header_type(
+       packet_header_type = bt_trace_get_packet_header_field_type(
                        notit->meta.trace);
        if (!packet_header_type) {
                notit->state = STATE_AFTER_TRACE_PACKET_HEADER;
@@ -761,7 +760,7 @@ create_stream_class_field_path_cache_entry(
                goto end;
        }
 
-       event_header = bt_stream_class_get_event_header_type(stream_class);
+       event_header = bt_stream_class_get_event_header_field_type(stream_class);
        if (event_header && bt_field_type_is_structure(event_header)) {
                int i, count;
 
@@ -800,7 +799,7 @@ create_stream_class_field_path_cache_entry(
                }
        }
 
-       packet_context = bt_stream_class_get_packet_context_type(
+       packet_context = bt_stream_class_get_packet_context_field_type(
                        stream_class);
        if (packet_context && bt_field_type_is_structure(packet_context)) {
                int i, count;
@@ -910,7 +909,7 @@ enum bt_notif_iter_status set_current_stream_class(
        notit->cur_sc_field_path_cache = NULL;
 
        /* Is there any "stream_id" field in the packet header? */
-       packet_header_type = bt_trace_get_packet_header_type(
+       packet_header_type = bt_trace_get_packet_header_field_type(
                notit->meta.trace);
        if (!packet_header_type) {
                /*
@@ -937,7 +936,7 @@ enum bt_notif_iter_status set_current_stream_class(
                stream_id_field = bt_field_structure_get_field_by_name(
                                notit->dscopes.trace_packet_header, "stream_id");
                BT_ASSERT(stream_id_field);
-               ret = bt_field_unsigned_integer_get_value(
+               ret = bt_field_integer_unsigned_get_value(
                                stream_id_field, &stream_id);
                BT_ASSERT(!ret);
                BT_PUT(stream_id_field);
@@ -1044,7 +1043,7 @@ enum bt_notif_iter_status read_packet_context_begin_state(
        struct bt_field_type *packet_context_type;
 
        BT_ASSERT(notit->meta.stream_class);
-       packet_context_type = bt_stream_class_get_packet_context_type(
+       packet_context_type = bt_stream_class_get_packet_context_field_type(
                notit->meta.stream_class);
        if (!packet_context_type) {
                BT_LOGV("No packet packet context field type in stream class: continuing: "
@@ -1111,7 +1110,7 @@ enum bt_notif_iter_status set_current_packet_content_sizes(
        content_size_field = bt_field_structure_get_field_by_name(
                notit->dscopes.stream_packet_context, "content_size");
        if (packet_size_field) {
-               int ret = bt_field_unsigned_integer_get_value(
+               int ret = bt_field_integer_unsigned_get_value(
                        packet_size_field, &packet_size);
 
                BT_ASSERT(ret == 0);
@@ -1133,7 +1132,7 @@ enum bt_notif_iter_status set_current_packet_content_sizes(
        }
 
        if (content_size_field) {
-               int ret = bt_field_unsigned_integer_get_value(
+               int ret = bt_field_integer_unsigned_get_value(
                        content_size_field, &content_size);
 
                BT_ASSERT(ret == 0);
@@ -1218,7 +1217,7 @@ enum bt_notif_iter_status read_event_header_begin_state(
                }
        }
 
-       event_header_type = bt_stream_class_get_event_header_type(
+       event_header_type = bt_stream_class_get_event_header_field_type(
                notit->meta.stream_class);
        if (!event_header_type) {
                notit->state = STATE_AFTER_STREAM_EVENT_HEADER;
@@ -1278,7 +1277,7 @@ enum bt_notif_iter_status set_current_event_class(struct bt_notif_iter *notit)
        uint64_t event_id = -1ULL;
        int ret;
 
-       event_header_type = bt_stream_class_get_event_header_type(
+       event_header_type = bt_stream_class_get_event_header_field_type(
                notit->meta.stream_class);
        if (!event_header_type) {
                /*
@@ -1327,7 +1326,7 @@ enum bt_notif_iter_status set_current_event_class(struct bt_notif_iter *notit)
                }
 
                if (bt_field_is_integer(v_struct_id_field)) {
-                       ret = bt_field_unsigned_integer_get_value(
+                       ret = bt_field_integer_unsigned_get_value(
                                v_struct_id_field, &event_id);
                        if (ret) {
                                BT_LOGV("Cannot get value of unsigned integer field (`id`): continuing: "
@@ -1356,7 +1355,7 @@ end_v_field_type:
                }
 
                if (bt_field_is_integer(id_field)) {
-                       ret_get_value = bt_field_unsigned_integer_get_value(
+                       ret_get_value = bt_field_integer_unsigned_get_value(
                                id_field, &event_id);
                } else if (bt_field_is_enumeration(id_field)) {
                        struct bt_field *container;
@@ -1364,7 +1363,7 @@ end_v_field_type:
                        container = bt_field_enumeration_get_container(
                                id_field);
                        BT_ASSERT(container);
-                       ret_get_value = bt_field_unsigned_integer_get_value(
+                       ret_get_value = bt_field_integer_unsigned_get_value(
                                container, &event_id);
                        BT_PUT(container);
                }
@@ -1446,8 +1445,9 @@ enum bt_notif_iter_status read_stream_event_context_begin_state(
        enum bt_notif_iter_status status = BT_NOTIF_ITER_STATUS_OK;
        struct bt_field_type *stream_event_context_type;
 
-       stream_event_context_type = bt_stream_class_get_event_context_type(
-               notit->meta.stream_class);
+       stream_event_context_type =
+               bt_stream_class_get_event_context_field_type(
+                       notit->meta.stream_class);
        if (!stream_event_context_type) {
                notit->state = STATE_DSCOPE_EVENT_CONTEXT_BEGIN;
                goto end;
@@ -1497,7 +1497,7 @@ enum bt_notif_iter_status read_event_context_begin_state(
        enum bt_notif_iter_status status = BT_NOTIF_ITER_STATUS_OK;
        struct bt_field_type *event_context_type;
 
-       event_context_type = bt_event_class_get_context_type(
+       event_context_type = bt_event_class_get_context_field_type(
                notit->meta.event_class);
        if (!event_context_type) {
                notit->state = STATE_DSCOPE_EVENT_PAYLOAD_BEGIN;
@@ -1548,7 +1548,7 @@ enum bt_notif_iter_status read_event_payload_begin_state(
        enum bt_notif_iter_status status = BT_NOTIF_ITER_STATUS_OK;
        struct bt_field_type *event_payload_type;
 
-       event_payload_type = bt_event_class_get_payload_type(
+       event_payload_type = bt_event_class_get_payload_field_type(
                notit->meta.event_class);
        if (!event_payload_type) {
                notit->state = STATE_EMIT_NOTIF_EVENT;
@@ -1833,7 +1833,7 @@ struct bt_field *get_next_field(struct bt_notif_iter *notit)
                BT_LOGF("Unknown base field type ID: "
                        "notit-addr=%p, ft-addr=%p, ft-id=%s",
                        notit, base_type,
-                       bt_field_type_id_string(
+                       bt_common_field_type_id_string(
                                bt_field_type_get_type_id(base_type)));
                abort();
        }
@@ -1859,7 +1859,7 @@ void update_clock_state(uint64_t *state,
        requested_new_value_size =
                        bt_field_type_integer_get_size(value_type);
        BT_ASSERT(requested_new_value_size > 0);
-       ret = bt_field_unsigned_integer_get_value(value_field,
+       ret = bt_field_integer_unsigned_get_value(value_field,
                        &requested_new_value);
        BT_ASSERT(!ret);
 
@@ -1956,7 +1956,7 @@ enum bt_btr_status btr_unsigned_int_common(uint64_t value,
                "notit-addr=%p, btr-addr=%p, ft-addr=%p, "
                "ft-id=%s, value=%" PRIu64,
                notit, notit->btr, type,
-               bt_field_type_id_string(
+               bt_common_field_type_id_string(
                        bt_field_type_get_type_id(type)),
                value);
 
@@ -1984,13 +1984,13 @@ enum bt_btr_status btr_unsigned_int_common(uint64_t value,
                BT_LOGF("Unexpected field type ID: "
                        "notit-addr=%p, ft-addr=%p, ft-id=%s",
                        notit, type,
-                       bt_field_type_id_string(
+                       bt_common_field_type_id_string(
                                bt_field_type_get_type_id(type)));
                abort();
        }
 
        BT_ASSERT(int_field);
-       ret = bt_field_unsigned_integer_set_value(int_field, value);
+       ret = bt_field_integer_unsigned_set_value(int_field, value);
        BT_ASSERT(ret == 0);
        stack_top(notit->stack)->index++;
        *out_int_field = int_field;
@@ -2013,7 +2013,7 @@ enum bt_btr_status btr_timestamp_end_cb(void *value,
                "notit-addr=%p, btr-addr=%p, ft-addr=%p, "
                "ft-id=%s",
                notit, notit->btr, type,
-               bt_field_type_id_string(
+               bt_common_field_type_id_string(
                        bt_field_type_get_type_id(type)));
        status = btr_unsigned_int_common(*((uint64_t *) value), type, data,
                        &field);
@@ -2036,7 +2036,7 @@ enum bt_btr_status btr_unsigned_int_cb(uint64_t value,
                "notit-addr=%p, btr-addr=%p, ft-addr=%p, "
                "ft-id=%s, value=%" PRIu64,
                notit, notit->btr, type,
-               bt_field_type_id_string(
+               bt_common_field_type_id_string(
                        bt_field_type_get_type_id(type)),
                value);
        override = g_hash_table_lookup(notit->field_overrides, type);
@@ -2072,7 +2072,7 @@ enum bt_btr_status btr_signed_int_cb(int64_t value,
                "notit-addr=%p, btr-addr=%p, ft-addr=%p, "
                "ft-id=%s, value=%" PRId64,
                notit, notit->btr, type,
-               bt_field_type_id_string(
+               bt_common_field_type_id_string(
                        bt_field_type_get_type_id(type)),
                value);
 
@@ -2100,13 +2100,13 @@ enum bt_btr_status btr_signed_int_cb(int64_t value,
                BT_LOGF("Unexpected field type ID: "
                        "notit-addr=%p, ft-addr=%p, ft-id=%s",
                        notit, type,
-                       bt_field_type_id_string(
+                       bt_common_field_type_id_string(
                                bt_field_type_get_type_id(type)));
                abort();
        }
 
        BT_ASSERT(int_field);
-       ret = bt_field_signed_integer_set_value(int_field, value);
+       ret = bt_field_integer_signed_set_value(int_field, value);
        BT_ASSERT(!ret);
        stack_top(notit->stack)->index++;
        status = update_clock(notit, int_field);
@@ -2131,7 +2131,7 @@ enum bt_btr_status btr_floating_point_cb(double value,
                "notit-addr=%p, btr-addr=%p, ft-addr=%p, "
                "ft-id=%s, value=%f",
                notit, notit->btr, type,
-               bt_field_type_id_string(
+               bt_common_field_type_id_string(
                        bt_field_type_get_type_id(type)),
                value);
 
@@ -2165,7 +2165,7 @@ enum bt_btr_status btr_string_begin_cb(
                "notit-addr=%p, btr-addr=%p, ft-addr=%p, "
                "ft-id=%s",
                notit, notit->btr, type,
-               bt_field_type_id_string(
+               bt_common_field_type_id_string(
                        bt_field_type_get_type_id(type)));
 
        /* Create next field */
@@ -2222,7 +2222,7 @@ enum bt_btr_status btr_string_cb(const char *value,
                "notit-addr=%p, btr-addr=%p, ft-addr=%p, "
                "ft-id=%s, string-length=%zu",
                notit, notit->btr, type,
-               bt_field_type_id_string(
+               bt_common_field_type_id_string(
                        bt_field_type_get_type_id(type)),
                len);
 
@@ -2254,7 +2254,7 @@ enum bt_btr_status btr_string_end_cb(
                "notit-addr=%p, btr-addr=%p, ft-addr=%p, "
                "ft-id=%s",
                notit, notit->btr, type,
-               bt_field_type_id_string(
+               bt_common_field_type_id_string(
                        bt_field_type_get_type_id(type)));
 
        /* Pop string field */
@@ -2277,7 +2277,7 @@ enum bt_btr_status btr_compound_begin_cb(
                "notit-addr=%p, btr-addr=%p, ft-addr=%p, "
                "ft-id=%s",
                notit, notit->btr, type,
-               bt_field_type_id_string(
+               bt_common_field_type_id_string(
                        bt_field_type_get_type_id(type)));
 
        /* Create field */
@@ -2298,7 +2298,7 @@ enum bt_btr_status btr_compound_begin_cb(
                        BT_LOGE("Cannot create compound field: "
                                "notit-addr=%p, ft-addr=%p, ft-id=%s",
                                notit, type,
-                               bt_field_type_id_string(
+                               bt_common_field_type_id_string(
                                        bt_field_type_get_type_id(type)));
                        status = BT_BTR_STATUS_ERROR;
                        goto end;
@@ -2319,7 +2319,7 @@ enum bt_btr_status btr_compound_begin_cb(
                BT_LOGE("Cannot push compound field onto the stack: "
                        "notit-addr=%p, ft-addr=%p, ft-id=%s, ret=%d",
                        notit, type,
-                       bt_field_type_id_string(
+                       bt_common_field_type_id_string(
                                bt_field_type_get_type_id(type)),
                        ret);
                status = BT_BTR_STATUS_ERROR;
@@ -2341,7 +2341,7 @@ enum bt_btr_status btr_compound_end_cb(
                "notit-addr=%p, btr-addr=%p, ft-addr=%p, "
                "ft-id=%s",
                notit, notit->btr, type,
-               bt_field_type_id_string(
+               bt_common_field_type_id_string(
                        bt_field_type_get_type_id(type)));
        BT_ASSERT(!stack_empty(notit->stack));
 
@@ -2396,7 +2396,7 @@ struct bt_field *resolve_field(struct bt_notif_iter *notit,
        default:
                BT_LOGF("Cannot resolve field path: unknown scope: "
                        "notit-addr=%p, root-scope=%s",
-                       notit, bt_scope_string(
+                       notit, bt_common_scope_string(
                                bt_field_path_get_root_scope(path)));
                abort();
        }
@@ -2404,7 +2404,7 @@ struct bt_field *resolve_field(struct bt_notif_iter *notit,
        if (!field) {
                BT_LOGW("Cannot resolve field path: root field not found: "
                        "notit-addr=%p, root-scope=%s",
-                       notit, bt_scope_string(
+                       notit, bt_common_scope_string(
                                bt_field_path_get_root_scope(path)));
                goto end;
        }
@@ -2434,7 +2434,7 @@ struct bt_field *resolve_field(struct bt_notif_iter *notit,
                        BT_LOGW("Cannot find next field: "
                                "notit-addr=%p, ft-addr=%p, ft-id=%s, index=%d",
                                notit, field_type,
-                               bt_field_type_id_string(
+                               bt_common_field_type_id_string(
                                        bt_field_type_get_type_id(field_type)),
                                index);
                        goto end;
@@ -2469,7 +2469,7 @@ int64_t btr_get_sequence_length_cb(struct bt_field_type *type, void *data)
                goto end;
        }
 
-       iret = bt_field_unsigned_integer_get_value(length_field, &length);
+       iret = bt_field_integer_unsigned_get_value(length_field, &length);
        if (iret) {
                BT_LOGE("Cannot get value of sequence length field: "
                        "notit-addr=%p, field-addr=%p",
@@ -2660,7 +2660,7 @@ struct bt_event *create_event(struct bt_notif_iter *notit)
                goto error;
        }
 
-       ret = bt_event_set_event_context(event,
+       ret = bt_event_set_context(event,
                notit->dscopes.event_context);
        if (ret) {
                BT_LOGE("Cannot set event's stream event context field: "
@@ -2674,7 +2674,7 @@ struct bt_event *create_event(struct bt_notif_iter *notit)
                goto error;
        }
 
-       ret = bt_event_set_event_payload(event,
+       ret = bt_event_set_payload(event,
                notit->dscopes.event_payload);
        if (ret) {
                BT_LOGE("Cannot set event's payload field: "
@@ -2741,7 +2741,7 @@ uint64_t get_cur_stream_instance_id(struct bt_notif_iter *notit)
                goto end;
        }
 
-       ret = bt_field_unsigned_integer_get_value(stream_instance_id_field,
+       ret = bt_field_integer_unsigned_get_value(stream_instance_id_field,
                &stream_instance_id);
        if (ret) {
                stream_instance_id = -1ULL;
@@ -3007,7 +3007,7 @@ void init_trace_field_path_cache(struct bt_trace *trace,
        int i, count;
        struct bt_field_type *packet_header = NULL;
 
-       packet_header = bt_trace_get_packet_header_type(trace);
+       packet_header = bt_trace_get_packet_header_field_type(trace);
        if (!packet_header) {
                goto end;
        }
index 02c488c5058e0aaf06c6ae02a74c608182ce6a3d..70261f91682262923a791cef822bbb9c1b8507ea 100644 (file)
@@ -46,7 +46,7 @@ struct bt_stream_class *ctf_utils_stream_class_from_packet_header(
                goto single_stream_class;
        }
 
-       ret = bt_field_unsigned_integer_get_value(stream_id_field,
+       ret = bt_field_integer_unsigned_get_value(stream_id_field,
                &stream_id);
        if (ret) {
                stream_id = -1ULL;
index e31f1787280b8c47a19c26a611ff73097bf004a6..9053b2f7614b3013b602f45751711424a6beb39b 100644 (file)
@@ -629,12 +629,12 @@ int init_index_entry(struct ctf_fs_ds_index_entry *entry,
        BT_ASSERT(packet_size >= 0);
        entry->packet_size = packet_size;
 
-       ret = bt_field_unsigned_integer_get_value(timestamp_begin,
+       ret = bt_field_integer_unsigned_get_value(timestamp_begin,
                        &entry->timestamp_begin);
        if (ret) {
                goto end;
        }
-       ret = bt_field_unsigned_integer_get_value(timestamp_end,
+       ret = bt_field_integer_unsigned_get_value(timestamp_end,
                        &entry->timestamp_end);
        if (ret) {
                goto end;
index 8395c81b0225eca494fac4a5e9d5f2e3e3757c95..4d8fea746860c437cc1bb61e16c325439fda9b18 100644 (file)
@@ -431,7 +431,7 @@ uint64_t get_packet_header_stream_instance_id(struct ctf_fs_trace *ctf_fs_trace,
                goto end;
        }
 
-       ret = bt_field_unsigned_integer_get_value(stream_instance_id_field,
+       ret = bt_field_integer_unsigned_get_value(stream_instance_id_field,
                &stream_instance_id);
        if (ret) {
                stream_instance_id = -1ULL;
@@ -474,7 +474,7 @@ uint64_t get_packet_context_timestamp_begin_ns(
                goto end;
        }
 
-       ret = bt_field_unsigned_integer_get_value(timestamp_begin_field,
+       ret = bt_field_integer_unsigned_get_value(timestamp_begin_field,
                &timestamp_begin_raw_value);
        if (ret) {
                goto end;
@@ -893,12 +893,14 @@ int create_ds_file_groups(struct ctf_fs_trace *ctf_fs_trace)
                }
 
                if (ds_file_group->stream_id == -1ULL) {
-                       /* No stream ID */
+                       /* No stream ID: use 0 */
                        ds_file_group->stream = bt_stream_create(
-                               ds_file_group->stream_class, name->str);
+                               ds_file_group->stream_class, name->str,
+                               ctf_fs_trace->next_stream_id);
+                       ctf_fs_trace->next_stream_id++;
                } else {
                        /* Specific stream ID */
-                       ds_file_group->stream = bt_stream_create_with_id(
+                       ds_file_group->stream = bt_stream_create(
                                ds_file_group->stream_class, name->str,
                                ds_file_group->stream_id);
                }
index d8fc7f43ee626fc0504e6df8b371ec78733a8c44..1124a0f39a7184a302fc93aee2393799690f4111 100644 (file)
@@ -87,6 +87,9 @@ struct ctf_fs_trace {
 
        /* Owned by this */
        GString *name;
+
+       /* Next automatic stream ID when not provided by packet header */
+       uint64_t next_stream_id;
 };
 
 struct ctf_fs_ds_file_group {
index cb894ddd0e9c55f93646b9935bf6532864900c4a..ee97583f8bdef23b8a9591f881be37f58529cc35 100644 (file)
@@ -53,6 +53,7 @@ BT_PLUGIN_SOURCE_COMPONENT_CLASS_NOTIFICATION_ITERATOR_INIT_METHOD(fs,
 BT_PLUGIN_SOURCE_COMPONENT_CLASS_NOTIFICATION_ITERATOR_FINALIZE_METHOD(fs,
        ctf_fs_iterator_finalize);
 
+#if 0
 /* ctf.fs sink */
 BT_PLUGIN_SINK_COMPONENT_CLASS(fs, writer_run);
 BT_PLUGIN_SINK_COMPONENT_CLASS_INIT_METHOD(fs, writer_component_init);
@@ -78,3 +79,4 @@ BT_PLUGIN_SOURCE_COMPONENT_CLASS_NOTIFICATION_ITERATOR_INIT_METHOD_WITH_ID(
        auto, lttng_live, lttng_live_iterator_init);
 BT_PLUGIN_SOURCE_COMPONENT_CLASS_NOTIFICATION_ITERATOR_FINALIZE_METHOD_WITH_ID(
        auto, lttng_live, lttng_live_iterator_finalize);
+#endif
index 3dc5f3be6ea463446d81e61adbec8423181f9ed9..36047924c63638c72fd445c9c876c29e67775777 100644 (file)
@@ -1,6 +1,7 @@
 AM_CPPFLAGS += -I$(top_srcdir)/plugins
 
-SUBDIRS = pretty dmesg .
+SUBDIRS = pretty .
+# dmesg
 
 plugindir = "$(PLUGINSDIR)"
 plugin_LTLIBRARIES = babeltrace-plugin-text.la
@@ -11,8 +12,9 @@ babeltrace_plugin_text_la_LDFLAGS = \
        -avoid-version -module
 
 babeltrace_plugin_text_la_LIBADD = \
-       pretty/libbabeltrace-plugin-text-pretty-cc.la \
-       dmesg/libbabeltrace-plugin-text-dmesg-cc.la
+       pretty/libbabeltrace-plugin-text-pretty-cc.la
+
+#      dmesg/libbabeltrace-plugin-text-dmesg-cc.la
 
 if !ENABLE_BUILT_IN_PLUGINS
 babeltrace_plugin_text_la_LIBADD += \
index 58a7f8f75f46172a154fbd77fd45dad478e122ae..2188f95644d891d2145445311a53e088387dbc25 100644 (file)
@@ -42,6 +42,7 @@ BT_PLUGIN_SINK_COMPONENT_CLASS_PORT_CONNECTED_METHOD(pretty,
 BT_PLUGIN_SINK_COMPONENT_CLASS_DESCRIPTION(pretty,
        "Pretty-print notifications (`text` format of Babeltrace 1).");
 
+#if 0
 /* dmesg source */
 BT_PLUGIN_SOURCE_COMPONENT_CLASS(dmesg, dmesg_notif_iter_next);
 BT_PLUGIN_SOURCE_COMPONENT_CLASS_DESCRIPTION(dmesg,
@@ -52,3 +53,4 @@ BT_PLUGIN_SOURCE_COMPONENT_CLASS_NOTIFICATION_ITERATOR_INIT_METHOD(dmesg,
        dmesg_notif_iter_init);
 BT_PLUGIN_SOURCE_COMPONENT_CLASS_NOTIFICATION_ITERATOR_FINALIZE_METHOD(dmesg,
        dmesg_notif_iter_finalize);
+#endif
index 821f03470861693f1078e96d9dc7168cfdf89d2c..4b05ede282763ae7c13363377358550b5624006a 100644 (file)
@@ -591,18 +591,18 @@ enum bt_component_status print_integer(struct pretty_component *pretty,
                ret = BT_COMPONENT_STATUS_ERROR;
                goto end;
        }
-       signedness = bt_ctf_field_type_integer_get_signed(field_type);
+       signedness = bt_field_type_integer_is_signed(field_type);
        if (signedness < 0) {
                ret = BT_COMPONENT_STATUS_ERROR;
                goto end;
        }
        if (!signedness) {
-               if (bt_field_unsigned_integer_get_value(field, &v.u) < 0) {
+               if (bt_field_integer_unsigned_get_value(field, &v.u) < 0) {
                        ret = BT_COMPONENT_STATUS_ERROR;
                        goto end;
                }
        } else {
-               if (bt_field_signed_integer_get_value(field, &v.s) < 0) {
+               if (bt_field_integer_signed_get_value(field, &v.s) < 0) {
                        ret = BT_COMPONENT_STATUS_ERROR;
                        goto end;
                }
@@ -803,7 +803,7 @@ enum bt_component_status print_enum(struct pretty_component *pretty,
                ret = BT_COMPONENT_STATUS_ERROR;
                goto end;
        }
-       is_signed = bt_ctf_field_type_integer_get_signed(container_field_type);
+       is_signed = bt_field_type_integer_is_signed(container_field_type);
        if (is_signed < 0) {
                ret = BT_COMPONENT_STATUS_ERROR;
                goto end;
@@ -811,22 +811,22 @@ enum bt_component_status print_enum(struct pretty_component *pretty,
        if (is_signed) {
                int64_t value;
 
-               if (bt_field_signed_integer_get_value(container_field,
+               if (bt_field_integer_signed_get_value(container_field,
                                &value)) {
                        ret = BT_COMPONENT_STATUS_ERROR;
                        goto end;
                }
-               iter = bt_field_type_enumeration_find_mappings_by_signed_value(
+               iter = bt_field_type_enumeration_signed_find_mappings_by_value(
                                enumeration_field_type, value);
        } else {
                uint64_t value;
 
-               if (bt_field_unsigned_integer_get_value(container_field,
+               if (bt_field_integer_unsigned_get_value(container_field,
                                &value)) {
                        ret = BT_COMPONENT_STATUS_ERROR;
                        goto end;
                }
-               iter = bt_field_type_enumeration_find_mappings_by_unsigned_value(
+               iter = bt_field_type_enumeration_unsigned_find_mappings_by_value(
                                enumeration_field_type, value);
        }
        g_string_append(pretty->string, "( ");
@@ -844,7 +844,7 @@ enum bt_component_status print_enum(struct pretty_component *pretty,
        for (;;) {
                const char *mapping_name;
 
-               if (bt_field_type_enumeration_mapping_iterator_get_signed(
+               if (bt_field_type_enumeration_mapping_iterator_signed_get(
                                iter, &mapping_name, NULL, NULL) < 0) {
                        ret = BT_COMPONENT_STATUS_ERROR;
                        goto end;
@@ -1023,7 +1023,7 @@ enum bt_component_status print_array(struct pretty_component *pretty,
                ret = BT_COMPONENT_STATUS_ERROR;
                goto end;
        }
-       field_type = bt_field_type_array_get_element_type(array_type);
+       field_type = bt_field_type_array_get_element_field_type(array_type);
        if (!field_type) {
                ret = BT_COMPONENT_STATUS_ERROR;
                goto end;
@@ -1140,11 +1140,11 @@ enum bt_component_status print_sequence(struct pretty_component *pretty,
                ret = BT_COMPONENT_STATUS_ERROR;
                goto end;
        }
-       if (bt_field_unsigned_integer_get_value(length_field, &len) < 0) {
+       if (bt_field_integer_unsigned_get_value(length_field, &len) < 0) {
                ret = BT_COMPONENT_STATUS_ERROR;
                goto end;
        }
-       field_type = bt_field_type_sequence_get_element_type(seq_type);
+       field_type = bt_field_type_sequence_get_element_field_type(seq_type);
        if (!field_type) {
                ret = BT_COMPONENT_STATUS_ERROR;
                goto end;
@@ -1245,7 +1245,7 @@ enum bt_component_status print_variant(struct pretty_component *pretty,
                }
 
                iter_ret =
-                       bt_field_type_enumeration_mapping_iterator_get_signed(
+                       bt_field_type_enumeration_mapping_iterator_signed_get(
                                iter, &tag_choice, NULL, NULL);
                if (iter_ret) {
                        bt_put(iter);
@@ -1277,9 +1277,9 @@ enum bt_component_status print_field(struct pretty_component *pretty,
 
        type_id = bt_field_get_type_id(field);
        switch (type_id) {
-       case CTF_TYPE_INTEGER:
+       case BT_CTF_FIELD_TYPE_ID_INTEGER:
                return print_integer(pretty, field);
-       case CTF_TYPE_FLOAT:
+       case BT_CTF_FIELD_TYPE_ID_FLOAT:
        {
                double v;
 
@@ -1295,9 +1295,9 @@ enum bt_component_status print_field(struct pretty_component *pretty,
                }
                return BT_COMPONENT_STATUS_OK;
        }
-       case CTF_TYPE_ENUM:
+       case BT_CTF_FIELD_TYPE_ID_ENUM:
                return print_enum(pretty, field);
-       case CTF_TYPE_STRING:
+       case BT_CTF_FIELD_TYPE_ID_STRING:
        {
                const char *str;
 
@@ -1315,14 +1315,14 @@ enum bt_component_status print_field(struct pretty_component *pretty,
                }
                return BT_COMPONENT_STATUS_OK;
        }
-       case CTF_TYPE_STRUCT:
+       case BT_CTF_FIELD_TYPE_ID_STRUCT:
                return print_struct(pretty, field, print_names, filter_fields,
                                filter_array_len);
-       case CTF_TYPE_VARIANT:
+       case BT_CTF_FIELD_TYPE_ID_VARIANT:
                return print_variant(pretty, field, print_names);
-       case CTF_TYPE_ARRAY:
+       case BT_CTF_FIELD_TYPE_ID_ARRAY:
                return print_array(pretty, field, print_names);
-       case CTF_TYPE_SEQUENCE:
+       case BT_CTF_FIELD_TYPE_ID_SEQUENCE:
                return print_sequence(pretty, field, print_names);
        default:
                // TODO: log instead
@@ -1422,7 +1422,7 @@ enum bt_component_status print_event_context(struct pretty_component *pretty,
        enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
        struct bt_field *main_field = NULL;
 
-       main_field = bt_event_get_event_context(event);
+       main_field = bt_event_get_context(event);
        if (!main_field) {
                goto end;
        }
@@ -1447,7 +1447,7 @@ enum bt_component_status print_event_payload(struct pretty_component *pretty,
        enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
        struct bt_field *main_field = NULL;
 
-       main_field = bt_event_get_event_payload(event);
+       main_field = bt_event_get_payload(event);
        if (!main_field) {
                goto end;
        }
index 3872c4dcaddba6b81d8aa052edb5fc44ee1f9209..b99ab20694e165ccbd9d7e8f18fe5c2428bb4d82 100644 (file)
@@ -1,6 +1,7 @@
 AM_CPPFLAGS += -I$(top_srcdir)/plugins
 
-SUBDIRS = dummy counter trimmer muxer .
+SUBDIRS = dummy counter muxer .
+# trimmer
 
 plugindir = "$(PLUGINSDIR)"
 plugin_LTLIBRARIES = babeltrace-plugin-utils.la
@@ -11,14 +12,16 @@ babeltrace_plugin_utils_la_LDFLAGS = \
        -avoid-version -module
 babeltrace_plugin_utils_la_LIBADD = \
        dummy/libbabeltrace-plugin-dummy-cc.la \
-       counter/libbabeltrace-plugin-counter-cc.la \
-       trimmer/libbabeltrace-plugin-trimmer.la \
-       muxer/libbabeltrace-plugin-muxer.la
+       muxer/libbabeltrace-plugin-muxer.la \
+       counter/libbabeltrace-plugin-counter-cc.la
+
+#      trimmer/libbabeltrace-plugin-trimmer.la
 
 if !ENABLE_BUILT_IN_PLUGINS
 babeltrace_plugin_utils_la_LIBADD += \
        $(top_builddir)/lib/libbabeltrace.la \
-       $(top_builddir)/plugins/libctfcopytrace/libctfcopytrace.la \
        $(top_builddir)/common/libbabeltrace-common.la \
        $(top_builddir)/logging/libbabeltrace-logging.la
+
+#      $(top_builddir)/plugins/libctfcopytrace/libctfcopytrace.la
 endif
index 50dabf5cc3b2771d6f23b40b2d99ad1ff55990f6..6a87a5f664c79fe0d2c56072be4580011ca5c69d 100644 (file)
@@ -54,6 +54,7 @@ BT_PLUGIN_SINK_COMPONENT_CLASS_PORT_CONNECTED_METHOD(counter,
 BT_PLUGIN_SINK_COMPONENT_CLASS_DESCRIPTION(counter,
        "Count notifications and print the results.");
 
+#if 0
 /* flt.utils.trimmer */
 BT_PLUGIN_FILTER_COMPONENT_CLASS(trimmer, trimmer_iterator_next);
 BT_PLUGIN_FILTER_COMPONENT_CLASS_DESCRIPTION(trimmer,
@@ -64,6 +65,7 @@ BT_PLUGIN_FILTER_COMPONENT_CLASS_NOTIFICATION_ITERATOR_INIT_METHOD(trimmer,
        trimmer_iterator_init);
 BT_PLUGIN_FILTER_COMPONENT_CLASS_NOTIFICATION_ITERATOR_FINALIZE_METHOD(trimmer,
        trimmer_iterator_finalize);
+#endif
 
 /* flt.utils.muxer */
 BT_PLUGIN_FILTER_COMPONENT_CLASS(muxer, muxer_notif_iter_next);
index 71225bfd426f2013297cfaaed27951b4fc270b56..f88cecd533cd15158ff0edde557d939af89f3e8d 100644 (file)
@@ -34,7 +34,7 @@
 #include "tap/tap.h"
 
 static
-struct bt_field_type *get_good_packet_header_type(void)
+struct bt_field_type *get_good_packet_header_field_type(void)
 {
        /*
        Generated by bt-ctfirtg using the following input:
@@ -143,7 +143,7 @@ struct bt_field_type *get_good_packet_header_type(void)
        assert(ret == 0);
        root_magic = bt_field_type_integer_create(32);
        assert(root_magic);
-       ret = bt_ctf_field_type_integer_set_signed(root_magic, 0);
+       ret = bt_field_type_integer_set_is_signed(root_magic, 0);
        assert(ret == 0);
        ret = bt_field_type_integer_set_base(root_magic, 10);
        assert(ret == 0);
@@ -157,7 +157,7 @@ struct bt_field_type *get_good_packet_header_type(void)
        assert(ret == 0);
        root_uuid_elem = bt_field_type_integer_create(8);
        assert(root_uuid_elem);
-       ret = bt_ctf_field_type_integer_set_signed(root_uuid_elem, 0);
+       ret = bt_field_type_integer_set_is_signed(root_uuid_elem, 0);
        assert(ret == 0);
        ret = bt_field_type_integer_set_base(root_uuid_elem, 10);
        assert(ret == 0);
@@ -173,7 +173,7 @@ struct bt_field_type *get_good_packet_header_type(void)
        assert(ret == 0);
        root_stream_id = bt_field_type_integer_create(32);
        assert(root_stream_id);
-       ret = bt_ctf_field_type_integer_set_signed(root_stream_id, 0);
+       ret = bt_field_type_integer_set_is_signed(root_stream_id, 0);
        assert(ret == 0);
        ret = bt_field_type_integer_set_base(root_stream_id, 10);
        assert(ret == 0);
@@ -197,7 +197,7 @@ struct bt_field_type *get_good_packet_header_type(void)
        assert(ret == 0);
        root_iron_dust = bt_field_type_integer_create(23);
        assert(root_iron_dust);
-       ret = bt_ctf_field_type_integer_set_signed(root_iron_dust, 0);
+       ret = bt_field_type_integer_set_is_signed(root_iron_dust, 0);
        assert(ret == 0);
        ret = bt_field_type_integer_set_base(root_iron_dust, 10);
        assert(ret == 0);
@@ -211,7 +211,7 @@ struct bt_field_type *get_good_packet_header_type(void)
        assert(ret == 0);
        root_iron_parallel_int = bt_field_type_integer_create(10);
        assert(root_iron_parallel_int);
-       ret = bt_ctf_field_type_integer_set_signed(root_iron_parallel_int, 0);
+       ret = bt_field_type_integer_set_is_signed(root_iron_parallel_int, 0);
        assert(ret == 0);
        ret = bt_field_type_integer_set_base(root_iron_parallel_int, 10);
        assert(ret == 0);
@@ -223,11 +223,11 @@ struct bt_field_type *get_good_packet_header_type(void)
        assert(ret == 0);
        root_iron_parallel = bt_field_type_enumeration_create(root_iron_parallel_int);
        assert(root_iron_parallel);
-       ret = bt_ctf_field_type_enumeration_add_mapping(root_iron_parallel, "RED", 0, 0);
+       ret = bt_field_type_enumeration_unsigned_add_mapping(root_iron_parallel, "RED", 0, 0);
        assert(ret == 0);
-       ret = bt_ctf_field_type_enumeration_add_mapping(root_iron_parallel, "BLUE", 1, 1);
+       ret = bt_field_type_enumeration_unsigned_add_mapping(root_iron_parallel, "BLUE", 1, 1);
        assert(ret == 0);
-       ret = bt_ctf_field_type_enumeration_add_mapping(root_iron_parallel, "YELLOW", 2, 2);
+       ret = bt_field_type_enumeration_unsigned_add_mapping(root_iron_parallel, "YELLOW", 2, 2);
        assert(ret == 0);
        ret = bt_field_type_structure_add_field(root_iron, root_iron_parallel, "parallel");
        assert(ret == 0);
@@ -237,7 +237,7 @@ struct bt_field_type *get_good_packet_header_type(void)
        assert(ret == 0);
        root_iron_fire_word = bt_field_type_integer_create(17);
        assert(root_iron_fire_word);
-       ret = bt_ctf_field_type_integer_set_signed(root_iron_fire_word, 0);
+       ret = bt_field_type_integer_set_is_signed(root_iron_fire_word, 0);
        assert(ret == 0);
        ret = bt_field_type_integer_set_base(root_iron_fire_word, 10);
        assert(ret == 0);
@@ -265,7 +265,7 @@ struct bt_field_type *get_good_packet_header_type(void)
        assert(ret == 0);
        root_iron_fire_keen_elem_BLUE_elem = bt_field_type_integer_create(5);
        assert(root_iron_fire_keen_elem_BLUE_elem);
-       ret = bt_ctf_field_type_integer_set_signed(root_iron_fire_keen_elem_BLUE_elem, 0);
+       ret = bt_field_type_integer_set_is_signed(root_iron_fire_keen_elem_BLUE_elem, 0);
        assert(ret == 0);
        ret = bt_field_type_integer_set_base(root_iron_fire_keen_elem_BLUE_elem, 10);
        assert(ret == 0);
@@ -311,7 +311,7 @@ struct bt_field_type *get_good_packet_header_type(void)
        assert(ret == 0);
        root_serious = bt_field_type_integer_create(1);
        assert(root_serious);
-       ret = bt_ctf_field_type_integer_set_signed(root_serious, 0);
+       ret = bt_field_type_integer_set_is_signed(root_serious, 0);
        assert(ret == 0);
        ret = bt_field_type_integer_set_base(root_serious, 10);
        assert(ret == 0);
@@ -352,7 +352,7 @@ struct bt_field_type *get_good_packet_header_type(void)
 }
 
 static
-struct bt_field_type *get_good_packet_context_type(void)
+struct bt_field_type *get_good_packet_context_field_type(void)
 {
        /*
        Generated by bt-ctfirtg using the following input:
@@ -449,7 +449,7 @@ struct bt_field_type *get_good_packet_context_type(void)
        assert(ret == 0);
        root_placid = bt_field_type_integer_create(32);
        assert(root_placid);
-       ret = bt_ctf_field_type_integer_set_signed(root_placid, 0);
+       ret = bt_field_type_integer_set_is_signed(root_placid, 0);
        assert(ret == 0);
        ret = bt_field_type_integer_set_base(root_placid, 10);
        assert(ret == 0);
@@ -469,7 +469,7 @@ struct bt_field_type *get_good_packet_context_type(void)
        assert(ret == 0);
        root_serious = bt_field_type_integer_create(11);
        assert(root_serious);
-       ret = bt_ctf_field_type_integer_set_signed(root_serious, 0);
+       ret = bt_field_type_integer_set_is_signed(root_serious, 0);
        assert(ret == 0);
        ret = bt_field_type_integer_set_base(root_serious, 10);
        assert(ret == 0);
@@ -497,7 +497,7 @@ struct bt_field_type *get_good_packet_context_type(void)
        assert(ret == 0);
        root_clover_oval = bt_field_type_integer_create(17);
        assert(root_clover_oval);
-       ret = bt_ctf_field_type_integer_set_signed(root_clover_oval, 0);
+       ret = bt_field_type_integer_set_is_signed(root_clover_oval, 0);
        assert(ret == 0);
        ret = bt_field_type_integer_set_base(root_clover_oval, 10);
        assert(ret == 0);
@@ -521,7 +521,7 @@ struct bt_field_type *get_good_packet_context_type(void)
        assert(ret == 0);
        root_clover_whole_RED = bt_field_type_integer_create(44);
        assert(root_clover_whole_RED);
-       ret = bt_ctf_field_type_integer_set_signed(root_clover_whole_RED, 0);
+       ret = bt_field_type_integer_set_is_signed(root_clover_whole_RED, 0);
        assert(ret == 0);
        ret = bt_field_type_integer_set_base(root_clover_whole_RED, 10);
        assert(ret == 0);
@@ -543,7 +543,7 @@ struct bt_field_type *get_good_packet_context_type(void)
        assert(ret == 0);
        root_clover_egg_elem = bt_field_type_integer_create(55);
        assert(root_clover_egg_elem);
-       ret = bt_ctf_field_type_integer_set_signed(root_clover_egg_elem, 0);
+       ret = bt_field_type_integer_set_is_signed(root_clover_egg_elem, 0);
        assert(ret == 0);
        ret = bt_field_type_integer_set_base(root_clover_egg_elem, 10);
        assert(ret == 0);
@@ -559,7 +559,7 @@ struct bt_field_type *get_good_packet_context_type(void)
        assert(ret == 0);
        root_clover_square_int = bt_field_type_integer_create(12);
        assert(root_clover_square_int);
-       ret = bt_ctf_field_type_integer_set_signed(root_clover_square_int, 0);
+       ret = bt_field_type_integer_set_is_signed(root_clover_square_int, 0);
        assert(ret == 0);
        ret = bt_field_type_integer_set_base(root_clover_square_int, 10);
        assert(ret == 0);
@@ -571,15 +571,15 @@ struct bt_field_type *get_good_packet_context_type(void)
        assert(ret == 0);
        root_clover_square = bt_field_type_enumeration_create(root_clover_square_int);
        assert(root_clover_square);
-       ret = bt_ctf_field_type_enumeration_add_mapping(root_clover_square, "YOUNG", 0, 0);
+       ret = bt_field_type_enumeration_unsigned_add_mapping(root_clover_square, "YOUNG", 0, 0);
        assert(ret == 0);
-       ret = bt_ctf_field_type_enumeration_add_mapping(root_clover_square, "OLD", 1, 1);
+       ret = bt_field_type_enumeration_unsigned_add_mapping(root_clover_square, "OLD", 1, 1);
        assert(ret == 0);
        ret = bt_field_type_structure_add_field(root_clover, root_clover_square, "square");
        assert(ret == 0);
        root_clover_useful_elem = bt_field_type_integer_create(2);
        assert(root_clover_useful_elem);
-       ret = bt_ctf_field_type_integer_set_signed(root_clover_useful_elem, 0);
+       ret = bt_field_type_integer_set_is_signed(root_clover_useful_elem, 0);
        assert(ret == 0);
        ret = bt_field_type_integer_set_base(root_clover_useful_elem, 10);
        assert(ret == 0);
@@ -628,7 +628,7 @@ struct bt_field_type *get_good_packet_context_type(void)
 
 
 static
-struct bt_field_type *get_good_event_header_type(void)
+struct bt_field_type *get_good_event_header_field_type(void)
 {
        /*
        Generated by bt-ctfirtg using the following input:
@@ -700,7 +700,7 @@ struct bt_field_type *get_good_event_header_type(void)
        assert(ret == 0);
        root_id = bt_field_type_integer_create(17);
        assert(root_id);
-       ret = bt_ctf_field_type_integer_set_signed(root_id, 0);
+       ret = bt_field_type_integer_set_is_signed(root_id, 0);
        assert(ret == 0);
        ret = bt_field_type_integer_set_base(root_id, 10);
        assert(ret == 0);
@@ -714,7 +714,7 @@ struct bt_field_type *get_good_event_header_type(void)
        assert(ret == 0);
        root_timestamp = bt_field_type_integer_create(64);
        assert(root_timestamp);
-       ret = bt_ctf_field_type_integer_set_signed(root_timestamp, 0);
+       ret = bt_field_type_integer_set_is_signed(root_timestamp, 0);
        assert(ret == 0);
        ret = bt_field_type_integer_set_base(root_timestamp, 10);
        assert(ret == 0);
@@ -732,7 +732,7 @@ struct bt_field_type *get_good_event_header_type(void)
        assert(ret == 0);
        root_action_special = bt_field_type_integer_create(17);
        assert(root_action_special);
-       ret = bt_ctf_field_type_integer_set_signed(root_action_special, 0);
+       ret = bt_field_type_integer_set_is_signed(root_action_special, 0);
        assert(ret == 0);
        ret = bt_field_type_integer_set_base(root_action_special, 10);
        assert(ret == 0);
@@ -760,7 +760,7 @@ struct bt_field_type *get_good_event_header_type(void)
        assert(ret == 0);
        root_action_grandiose_elem = bt_field_type_integer_create(3);
        assert(root_action_grandiose_elem);
-       ret = bt_ctf_field_type_integer_set_signed(root_action_grandiose_elem, 0);
+       ret = bt_field_type_integer_set_is_signed(root_action_grandiose_elem, 0);
        assert(ret == 0);
        ret = bt_field_type_integer_set_base(root_action_grandiose_elem, 10);
        assert(ret == 0);
@@ -790,7 +790,7 @@ struct bt_field_type *get_good_event_header_type(void)
        assert(ret == 0);
        root_fruit_apple_elem = bt_field_type_integer_create(5);
        assert(root_fruit_apple_elem);
-       ret = bt_ctf_field_type_integer_set_signed(root_fruit_apple_elem, 0);
+       ret = bt_field_type_integer_set_is_signed(root_fruit_apple_elem, 0);
        assert(ret == 0);
        ret = bt_field_type_integer_set_base(root_fruit_apple_elem, 10);
        assert(ret == 0);
@@ -826,7 +826,7 @@ struct bt_field_type *get_good_event_header_type(void)
 }
 
 static
-struct bt_field_type *get_good_stream_event_context_type(void)
+struct bt_field_type *get_good_stream_event_context_field_type(void)
 {
        /*
        Generated by bt-ctfirtg using the following input:
@@ -917,7 +917,7 @@ struct bt_field_type *get_good_stream_event_context_type(void)
        assert(ret == 0);
        root_face_magic = bt_field_type_integer_create(23);
        assert(root_face_magic);
-       ret = bt_ctf_field_type_integer_set_signed(root_face_magic, 0);
+       ret = bt_field_type_integer_set_is_signed(root_face_magic, 0);
        assert(ret == 0);
        ret = bt_field_type_integer_set_base(root_face_magic, 10);
        assert(ret == 0);
@@ -941,7 +941,7 @@ struct bt_field_type *get_good_stream_event_context_type(void)
        assert(ret == 0);
        root_cats = bt_field_type_integer_create(5);
        assert(root_cats);
-       ret = bt_ctf_field_type_integer_set_signed(root_cats, 0);
+       ret = bt_field_type_integer_set_is_signed(root_cats, 0);
        assert(ret == 0);
        ret = bt_field_type_integer_set_base(root_cats, 10);
        assert(ret == 0);
@@ -967,7 +967,7 @@ struct bt_field_type *get_good_stream_event_context_type(void)
        assert(ret == 0);
        root_stream_id = bt_field_type_integer_create(9);
        assert(root_stream_id);
-       ret = bt_ctf_field_type_integer_set_signed(root_stream_id, 0);
+       ret = bt_field_type_integer_set_is_signed(root_stream_id, 0);
        assert(ret == 0);
        ret = bt_field_type_integer_set_base(root_stream_id, 10);
        assert(ret == 0);
@@ -999,7 +999,7 @@ struct bt_field_type *get_good_stream_event_context_type(void)
 }
 
 static
-struct bt_field_type *get_good_event_context_type(void)
+struct bt_field_type *get_good_event_context_field_type(void)
 {
        /*
        Generated by bt-ctfirtg using the following input:
@@ -1115,7 +1115,7 @@ struct bt_field_type *get_good_event_context_type(void)
        assert(ret == 0);
        root_film = bt_field_type_integer_create(19);
        assert(root_film);
-       ret = bt_ctf_field_type_integer_set_signed(root_film, 0);
+       ret = bt_field_type_integer_set_is_signed(root_film, 0);
        assert(ret == 0);
        ret = bt_field_type_integer_set_base(root_film, 10);
        assert(ret == 0);
@@ -1157,7 +1157,7 @@ struct bt_field_type *get_good_event_context_type(void)
        assert(ret == 0);
        root_berry_third = bt_field_type_integer_create(18);
        assert(root_berry_third);
-       ret = bt_ctf_field_type_integer_set_signed(root_berry_third, 0);
+       ret = bt_field_type_integer_set_is_signed(root_berry_third, 0);
        assert(ret == 0);
        ret = bt_field_type_integer_set_base(root_berry_third, 10);
        assert(ret == 0);
@@ -1189,7 +1189,7 @@ struct bt_field_type *get_good_event_context_type(void)
        assert(ret == 0);
        root_cats = bt_field_type_integer_create(55);
        assert(root_cats);
-       ret = bt_ctf_field_type_integer_set_signed(root_cats, 0);
+       ret = bt_field_type_integer_set_is_signed(root_cats, 0);
        assert(ret == 0);
        ret = bt_field_type_integer_set_base(root_cats, 10);
        assert(ret == 0);
@@ -1288,7 +1288,7 @@ struct bt_field_type *get_good_event_context_type(void)
 }
 
 static
-struct bt_field_type *get_good_event_payload_type(void)
+struct bt_field_type *get_good_event_payload_field_type(void)
 {
        /*
        Generated by bt-ctfirtg using the following input:
@@ -1413,7 +1413,7 @@ struct bt_field_type *get_good_event_payload_type(void)
        assert(ret == 0);
        root_splendid = bt_field_type_integer_create(12);
        assert(root_splendid);
-       ret = bt_ctf_field_type_integer_set_signed(root_splendid, 0);
+       ret = bt_field_type_integer_set_is_signed(root_splendid, 0);
        assert(ret == 0);
        ret = bt_field_type_integer_set_base(root_splendid, 10);
        assert(ret == 0);
@@ -1572,26 +1572,26 @@ struct bt_field_type *get_child_ft(struct bt_field_type *parent_ft,
        struct bt_field_type *ft = NULL;
 
        switch (bt_field_type_get_type_id(parent_ft)) {
-       case CTF_TYPE_STRUCT:
+       case BT_FIELD_TYPE_ID_STRUCT:
                ft = bt_field_type_structure_get_field_type_by_name(
                        parent_ft, name);
                break;
 
-       case CTF_TYPE_VARIANT:
+       case BT_FIELD_TYPE_ID_VARIANT:
                ft = bt_field_type_variant_get_field_type_by_name(
                        parent_ft, name);
                break;
 
-       case CTF_TYPE_ARRAY:
-               ft = bt_field_type_array_get_element_type(parent_ft);
+       case BT_FIELD_TYPE_ID_ARRAY:
+               ft = bt_field_type_array_get_element_field_type(parent_ft);
                break;
 
-       case CTF_TYPE_SEQUENCE:
-               ft = bt_field_type_sequence_get_element_type(parent_ft);
+       case BT_FIELD_TYPE_ID_SEQUENCE:
+               ft = bt_field_type_sequence_get_element_field_type(parent_ft);
                break;
 
-       case CTF_TYPE_ENUM:
-               ft = bt_field_type_enumeration_get_container_type(
+       case BT_FIELD_TYPE_ID_ENUM:
+               ft = bt_field_type_enumeration_get_container_field_type(
                        parent_ft);
                break;
 
@@ -1724,17 +1724,17 @@ void validate_test_pass(struct bt_trace *trace)
        ec = bt_stream_class_get_event_class_by_index(sc, 0);
        assert(ec);
 
-       ph = bt_trace_get_packet_header_type(trace);
+       ph = bt_trace_get_packet_header_field_type(trace);
        ok(ph, "Trace packet header still exists after successful validation");
-       pc = bt_stream_class_get_packet_context_type(sc);
+       pc = bt_stream_class_get_packet_context_field_type(sc);
        ok(pc, "Stream packet context still exists after successful validation");
-       eh = bt_stream_class_get_event_header_type(sc);
+       eh = bt_stream_class_get_event_header_field_type(sc);
        ok(eh, "Stream event header still exists after successful validation");
-       sec = bt_stream_class_get_event_context_type(sc);
+       sec = bt_stream_class_get_event_context_field_type(sc);
        ok(sec, "Stream event context still exists after successful validation");
-       ectx = bt_event_class_get_context_type(ec);
+       ectx = bt_event_class_get_context_field_type(ec);
        ok(ectx, "Event context still exists after successful validation");
-       ep = bt_event_class_get_payload_type(ec);
+       ep = bt_event_class_get_payload_field_type(ec);
        ok(ep, "Event payload still exists after successful validation");
 
        /* trace.packet.header.iron.fire.keen */
@@ -1750,7 +1750,7 @@ void validate_test_pass(struct bt_trace *trace)
                BT_SCOPE_TRACE_PACKET_HEADER, 3, 2, FIELD_PATH_END),
                "trace.packet.header.iron.fire.keen.[element] has the correct field path");
        ft_target = get_ft(ph, "iron", "parallel", NULL);
-       ft_tag = bt_field_type_variant_get_tag_type(ft_src);
+       ft_tag = bt_field_type_variant_get_tag_field_type(ft_src);
        ok(ft_tag == ft_target,
                "trace.packet.header.iron.fire.keen.[element] has the correct tag type");
        BT_PUT(ft_src);
@@ -1791,7 +1791,7 @@ void validate_test_pass(struct bt_trace *trace)
                BT_SCOPE_TRACE_PACKET_HEADER, 3, 2, FIELD_PATH_END),
                "stream.packet.context.clover.whole has the correct field path");
        ft_target = get_ft(ph, "iron", "parallel", NULL);
-       ft_tag = bt_field_type_variant_get_tag_type(ft_src);
+       ft_tag = bt_field_type_variant_get_tag_field_type(ft_src);
        ok(ft_tag == ft_target,
                "stream.packet.context.clover.whole has the correct tag type");
        BT_PUT(ft_src);
@@ -2076,30 +2076,30 @@ void test_pass(void)
        ec = bt_event_class_create("oh_what_an_event_class");
        assert(ec);
 
-       ph = get_good_packet_header_type();
+       ph = get_good_packet_header_field_type();
        assert(ph);
-       pc = get_good_packet_context_type();
+       pc = get_good_packet_context_field_type();
        assert(pc);
-       eh = get_good_event_header_type();
+       eh = get_good_event_header_field_type();
        assert(eh);
-       sec = get_good_stream_event_context_type();
+       sec = get_good_stream_event_context_field_type();
        assert(sec);
-       ectx = get_good_event_context_type();
+       ectx = get_good_event_context_field_type();
        assert(ec);
-       ep = get_good_event_payload_type();
+       ep = get_good_event_payload_field_type();
        assert(ep);
 
-       ret = bt_trace_set_packet_header_type(trace, ph);
+       ret = bt_trace_set_packet_header_field_type(trace, ph);
        assert(ret == 0);
-       ret = bt_stream_class_set_packet_context_type(sc, pc);
+       ret = bt_stream_class_set_packet_context_field_type(sc, pc);
        assert(ret == 0);
-       ret = bt_stream_class_set_event_header_type(sc, eh);
+       ret = bt_stream_class_set_event_header_field_type(sc, eh);
        assert(ret == 0);
-       ret = bt_stream_class_set_event_context_type(sc, sec);
+       ret = bt_stream_class_set_event_context_field_type(sc, sec);
        assert(ret == 0);
-       ret = bt_event_class_set_context_type(ec, ectx);
+       ret = bt_event_class_set_context_field_type(ec, ectx);
        assert(ret == 0);
-       ret = bt_event_class_set_payload_type(ec, ep);
+       ret = bt_event_class_set_payload_field_type(ec, ep);
        assert(ret == 0);
 
        ret = bt_stream_class_add_event_class(sc, ec);
@@ -2123,42 +2123,40 @@ void test_pass(void)
 }
 
 static
-struct bt_event *create_event_with_context_and_payload(
-               struct bt_field_type *ectx, struct bt_field_type *ep)
+int try_add_event_class_to_trace(struct bt_field_type *ectx,
+               struct bt_field_type *ep)
 {
        int ret;
+       struct bt_trace *trace;
        struct bt_stream_class *sc;
        struct bt_event_class *ec;
-       struct bt_event *event;
 
+       trace = bt_trace_create();
+       assert(trace);
        sc = bt_stream_class_create("sc");
        assert(sc);
        ec = bt_event_class_create("ec");
        assert(ec);
 
        if (ectx) {
-               ret = bt_event_class_set_context_type(ec, ectx);
+               ret = bt_event_class_set_context_field_type(ec, ectx);
                assert(ret == 0);
        }
 
        if (ep) {
-               ret = bt_event_class_set_payload_type(ec, ep);
+               ret = bt_event_class_set_payload_field_type(ec, ep);
                assert(ret == 0);
        }
 
        ret = bt_stream_class_add_event_class(sc, ec);
        assert(ret == 0);
-
-       /* Validation happens here */
-       event = bt_event_create(ec);
-
+       ret = bt_trace_add_stream_class(trace, sc);
        BT_PUT(ec);
        BT_PUT(sc);
-
-       return event;
+       BT_PUT(trace);
+       return ret;
 }
 
-
 static
 struct bt_field_type *test_fail_unavailable_root_get_event_payload(void)
 {
@@ -2193,7 +2191,7 @@ struct bt_field_type *test_fail_unavailable_root_get_event_payload(void)
        assert(ret == 0);
        root_a = bt_field_type_integer_create(32);
        assert(root_a);
-       ret = bt_ctf_field_type_integer_set_signed(root_a, 0);
+       ret = bt_field_type_integer_set_is_signed(root_a, 0);
        assert(ret == 0);
        ret = bt_field_type_integer_set_base(root_a, 10);
        assert(ret == 0);
@@ -2232,15 +2230,13 @@ static
 void test_fail_unavailable_root(void)
 {
        struct bt_field_type *ep;
-       struct bt_event *event;
 
        ep = test_fail_unavailable_root_get_event_payload();
        assert(ep);
-       event = create_event_with_context_and_payload(NULL, ep);
-       ok(!event, "Sequence FT with length in unavailable root is invalid");
+       ok(try_add_event_class_to_trace(NULL, ep),
+               "Sequence FT with length in unavailable root is invalid");
 
        BT_PUT(ep);
-       BT_PUT(event);
 }
 
 static
@@ -2277,7 +2273,7 @@ struct bt_field_type *test_fail_target_is_root_get_event_payload(void)
        assert(ret == 0);
        root_a = bt_field_type_integer_create(32);
        assert(root_a);
-       ret = bt_ctf_field_type_integer_set_signed(root_a, 0);
+       ret = bt_field_type_integer_set_is_signed(root_a, 0);
        assert(ret == 0);
        ret = bt_field_type_integer_set_base(root_a, 10);
        assert(ret == 0);
@@ -2316,15 +2312,12 @@ static
 void test_fail_target_is_root(void)
 {
        struct bt_field_type *ep;
-       struct bt_event *event;
 
        ep = test_fail_target_is_root_get_event_payload();
        assert(ep);
-       event = create_event_with_context_and_payload(NULL, ep);
-       ok(!event, "Sequence FT with root as its length is invalid");
-
+       ok(try_add_event_class_to_trace(NULL, ep),
+               "Sequence FT with root as its length is invalid");
        BT_PUT(ep);
-       BT_PUT(event);
 }
 
 static
@@ -2365,7 +2358,7 @@ struct bt_field_type *test_fail_target_is_after_source_get_ep(void)
        assert(ret == 0);
        root_a = bt_field_type_integer_create(32);
        assert(root_a);
-       ret = bt_ctf_field_type_integer_set_signed(root_a, 0);
+       ret = bt_field_type_integer_set_is_signed(root_a, 0);
        assert(ret == 0);
        ret = bt_field_type_integer_set_base(root_a, 10);
        assert(ret == 0);
@@ -2393,7 +2386,7 @@ struct bt_field_type *test_fail_target_is_after_source_get_ep(void)
        assert(ret == 0);
        root_d = bt_field_type_integer_create(17);
        assert(root_d);
-       ret = bt_ctf_field_type_integer_set_signed(root_d, 0);
+       ret = bt_field_type_integer_set_is_signed(root_d, 0);
        assert(ret == 0);
        ret = bt_field_type_integer_set_base(root_d, 10);
        assert(ret == 0);
@@ -2419,15 +2412,12 @@ static
 void test_fail_target_is_after_source(void)
 {
        struct bt_field_type *ep;
-       struct bt_event *event;
 
        ep = test_fail_target_is_after_source_get_ep();
        assert(ep);
-       event = create_event_with_context_and_payload(NULL, ep);
-       ok(!event, "Sequence FT with length after it is invalid");
-
+       ok(try_add_event_class_to_trace(NULL, ep),
+               "Sequence FT with length after it is invalid");
        BT_PUT(ep);
-       BT_PUT(event);
 }
 
 static
@@ -2472,7 +2462,7 @@ struct bt_field_type *test_fail_target_is_ancestor_of_source_get_ep(void)
        assert(ret == 0);
        root_a = bt_field_type_integer_create(32);
        assert(root_a);
-       ret = bt_ctf_field_type_integer_set_signed(root_a, 0);
+       ret = bt_field_type_integer_set_is_signed(root_a, 0);
        assert(ret == 0);
        ret = bt_field_type_integer_set_base(root_a, 10);
        assert(ret == 0);
@@ -2506,7 +2496,7 @@ struct bt_field_type *test_fail_target_is_ancestor_of_source_get_ep(void)
        assert(ret == 0);
        root_d = bt_field_type_integer_create(17);
        assert(root_d);
-       ret = bt_ctf_field_type_integer_set_signed(root_d, 0);
+       ret = bt_field_type_integer_set_is_signed(root_d, 0);
        assert(ret == 0);
        ret = bt_field_type_integer_set_base(root_d, 10);
        assert(ret == 0);
@@ -2533,15 +2523,12 @@ static
 void test_fail_target_is_ancestor_of_source(void)
 {
        struct bt_field_type *ep;
-       struct bt_event *event;
 
        ep = test_fail_target_is_ancestor_of_source_get_ep();
        assert(ep);
-       event = create_event_with_context_and_payload(NULL, ep);
-       ok(!event, "Sequence FT with ancestor as its length is invalid");
-
+       ok(try_add_event_class_to_trace(NULL, ep),
+               "Sequence FT with ancestor as its length is invalid");
        BT_PUT(ep);
-       BT_PUT(event);
 }
 
 static
@@ -2582,7 +2569,7 @@ struct bt_field_type *test_fail_target_is_source_get_event_payload(void)
        assert(ret == 0);
        root_a = bt_field_type_integer_create(32);
        assert(root_a);
-       ret = bt_ctf_field_type_integer_set_signed(root_a, 0);
+       ret = bt_field_type_integer_set_is_signed(root_a, 0);
        assert(ret == 0);
        ret = bt_field_type_integer_set_base(root_a, 10);
        assert(ret == 0);
@@ -2610,7 +2597,7 @@ struct bt_field_type *test_fail_target_is_source_get_event_payload(void)
        assert(ret == 0);
        root_d = bt_field_type_integer_create(17);
        assert(root_d);
-       ret = bt_ctf_field_type_integer_set_signed(root_d, 0);
+       ret = bt_field_type_integer_set_is_signed(root_d, 0);
        assert(ret == 0);
        ret = bt_field_type_integer_set_base(root_d, 10);
        assert(ret == 0);
@@ -2636,15 +2623,12 @@ static
 void test_fail_target_is_source(void)
 {
        struct bt_field_type *ep;
-       struct bt_event *event;
 
        ep = test_fail_target_is_source_get_event_payload();
        assert(ep);
-       event = create_event_with_context_and_payload(NULL, ep);
-       ok(!event, "Sequence FT with itself as its length is invalid");
-
+       ok(try_add_event_class_to_trace(NULL, ep),
+               "Sequence FT with itself as its length is invalid");
        BT_PUT(ep);
-       BT_PUT(event);
 }
 
 static
@@ -2686,7 +2670,7 @@ struct bt_field_type *test_fail_variant_tag_is_not_enum_get_ep(void)
        assert(ret == 0);
        root_a = bt_field_type_integer_create(32);
        assert(root_a);
-       ret = bt_ctf_field_type_integer_set_signed(root_a, 0);
+       ret = bt_field_type_integer_set_is_signed(root_a, 0);
        assert(ret == 0);
        ret = bt_field_type_integer_set_base(root_a, 10);
        assert(ret == 0);
@@ -2716,7 +2700,7 @@ struct bt_field_type *test_fail_variant_tag_is_not_enum_get_ep(void)
        assert(ret == 0);
        root_d = bt_field_type_integer_create(17);
        assert(root_d);
-       ret = bt_ctf_field_type_integer_set_signed(root_d, 0);
+       ret = bt_field_type_integer_set_is_signed(root_d, 0);
        assert(ret == 0);
        ret = bt_field_type_integer_set_base(root_d, 10);
        assert(ret == 0);
@@ -2742,15 +2726,12 @@ static
 void test_fail_variant_tag_is_not_enum(void)
 {
        struct bt_field_type *ep;
-       struct bt_event *event;
 
        ep = test_fail_variant_tag_is_not_enum_get_ep();
        assert(ep);
-       event = create_event_with_context_and_payload(NULL, ep);
-       ok(!event, "Variant FT with non-enum FT as its tag FT is invalid");
-
+       ok(try_add_event_class_to_trace(NULL, ep),
+               "Variant FT with non-enum FT as its tag FT is invalid");
        BT_PUT(ep);
-       BT_PUT(event);
 }
 
 static
@@ -2799,7 +2780,7 @@ struct bt_field_type *test_fail_variant_tag_mismatch_mappings_get_ep(void)
        assert(ret == 0);
        root_a_int = bt_field_type_integer_create(16);
        assert(root_a_int);
-       ret = bt_ctf_field_type_integer_set_signed(root_a_int, 0);
+       ret = bt_field_type_integer_set_is_signed(root_a_int, 0);
        assert(ret == 0);
        ret = bt_field_type_integer_set_base(root_a_int, 10);
        assert(ret == 0);
@@ -2811,11 +2792,11 @@ struct bt_field_type *test_fail_variant_tag_mismatch_mappings_get_ep(void)
        assert(ret == 0);
        root_a = bt_field_type_enumeration_create(root_a_int);
        assert(root_a);
-       ret = bt_ctf_field_type_enumeration_add_mapping(root_a, "GLASS", 0, 0);
+       ret = bt_field_type_enumeration_unsigned_add_mapping(root_a, "GLASS", 0, 0);
        assert(ret == 0);
-       ret = bt_ctf_field_type_enumeration_add_mapping(root_a, "OF", 1, 1);
+       ret = bt_field_type_enumeration_unsigned_add_mapping(root_a, "OF", 1, 1);
        assert(ret == 0);
-       ret = bt_ctf_field_type_enumeration_add_mapping(root_a, "WATER", 2, 2);
+       ret = bt_field_type_enumeration_unsigned_add_mapping(root_a, "WATER", 2, 2);
        assert(ret == 0);
        ret = bt_field_type_structure_add_field(root, root_a, "a");
        assert(ret == 0);
@@ -2829,7 +2810,7 @@ struct bt_field_type *test_fail_variant_tag_mismatch_mappings_get_ep(void)
        assert(ret == 0);
        root_b_OF = bt_field_type_integer_create(2);
        assert(root_b_OF);
-       ret = bt_ctf_field_type_integer_set_signed(root_b_OF, 0);
+       ret = bt_field_type_integer_set_is_signed(root_b_OF, 0);
        assert(ret == 0);
        ret = bt_field_type_integer_set_base(root_b_OF, 10);
        assert(ret == 0);
@@ -2864,15 +2845,12 @@ static
 void test_fail_variant_tag_mismatch_mappings(void)
 {
        struct bt_field_type *ep;
-       struct bt_event *event;
 
        ep = test_fail_variant_tag_mismatch_mappings_get_ep();
        assert(ep);
-       event = create_event_with_context_and_payload(NULL, ep);
-       ok(event, "Variant FT with mismatching tag FT is valid");
-
+       ok(try_add_event_class_to_trace(NULL, ep) == 0,
+               "Variant FT with mismatching tag FT is valid");
        BT_PUT(ep);
-       BT_PUT(event);
 }
 
 static
@@ -2939,15 +2917,12 @@ static
 void test_fail_sequence_tag_is_not_int(void)
 {
        struct bt_field_type *ep;
-       struct bt_event *event;
 
        ep = test_fail_sequence_tag_is_not_int_get_ep();
        assert(ep);
-       event = create_event_with_context_and_payload(NULL, ep);
-       ok(!event, "Sequence FT with non-enum length FT is invalid");
-
+       ok(try_add_event_class_to_trace(NULL, ep),
+               "Sequence FT with non-enum length FT is invalid");
        BT_PUT(ep);
-       BT_PUT(event);
 }
 
 static
index cb91ac51b0d74991d9cc2ceec2de72c83ae17e3c..2398d4e3245b2bbf6867e4c93e7bbea47c8264c7 100644 (file)
@@ -291,26 +291,26 @@ void init_static_data(void)
        assert(empty_struct_ft);
        trace = bt_trace_create();
        assert(trace);
-       ret = bt_trace_set_packet_header_type(trace, empty_struct_ft);
+       ret = bt_trace_set_packet_header_field_type(trace, empty_struct_ft);
        assert(ret == 0);
        src_empty_cc_prio_map = bt_clock_class_priority_map_create();
        assert(src_empty_cc_prio_map);
        src_stream_class = bt_stream_class_create("my-stream-class");
        assert(src_stream_class);
-       ret = bt_stream_class_set_packet_context_type(src_stream_class,
+       ret = bt_stream_class_set_packet_context_field_type(src_stream_class,
                empty_struct_ft);
        assert(ret == 0);
-       ret = bt_stream_class_set_event_header_type(src_stream_class,
+       ret = bt_stream_class_set_event_header_field_type(src_stream_class,
                empty_struct_ft);
        assert(ret == 0);
-       ret = bt_stream_class_set_event_context_type(src_stream_class,
+       ret = bt_stream_class_set_event_context_field_type(src_stream_class,
                empty_struct_ft);
        assert(ret == 0);
        src_event_class = bt_event_class_create("my-event-class");
-       ret = bt_event_class_set_context_type(src_event_class,
+       ret = bt_event_class_set_context_field_type(src_event_class,
                empty_struct_ft);
        assert(ret == 0);
-       ret = bt_event_class_set_context_type(src_event_class,
+       ret = bt_event_class_set_payload_field_type(src_event_class,
                empty_struct_ft);
        assert(ret == 0);
        ret = bt_stream_class_add_event_class(src_stream_class,
@@ -318,9 +318,9 @@ void init_static_data(void)
        assert(ret == 0);
        ret = bt_trace_add_stream_class(trace, src_stream_class);
        assert(ret == 0);
-       src_stream1 = bt_stream_create(src_stream_class, "stream-1");
+       src_stream1 = bt_stream_create(src_stream_class, "stream-1", 0);
        assert(src_stream1);
-       src_stream2 = bt_stream_create(src_stream_class, "stream-2");
+       src_stream2 = bt_stream_create(src_stream_class, "stream-2", 1);
        assert(src_stream2);
        src_stream1_packet1 = bt_packet_create(src_stream1);
        assert(src_stream1_packet1);
index 5709b2eca70c5050a0164af87dbc4e38d49162a5..9e9260bb36340e330fc70ac81d74508938b84efa 100644 (file)
  */
 
 #include "tap/tap.h"
-#include <babeltrace/ctf-writer/writer.h>
-#include <babeltrace/ctf-writer/stream.h>
 #include <babeltrace/ctf-writer/clock.h>
-#include <babeltrace/ctf-ir/trace.h>
+#include <babeltrace/ctf-writer/event.h>
+#include <babeltrace/ctf-writer/fields.h>
 #include <babeltrace/ctf-writer/stream-class.h>
-#include <babeltrace/ctf-ir/stream.h>
-#include <babeltrace/ctf-ir/fields.h>
+#include <babeltrace/ctf-writer/stream.h>
+#include <babeltrace/ctf-writer/trace.h>
+#include <babeltrace/ctf-writer/writer.h>
+#include <babeltrace/ctf-ir/clock-class.h>
 #include <babeltrace/ctf-ir/event.h>
 #include <babeltrace/ctf-ir/event-class.h>
+#include <babeltrace/ctf-ir/fields.h>
+#include <babeltrace/ctf-ir/stream-class.h>
+#include <babeltrace/ctf-ir/stream.h>
+#include <babeltrace/ctf-ir/trace.h>
 #include <babeltrace/object-internal.h>
 #include <babeltrace/compat/stdlib-internal.h>
 #include <assert.h>
@@ -37,7 +42,6 @@
 #define NR_TESTS 41
 
 struct user {
-       struct bt_ctf_writer *writer;
        struct bt_trace *tc;
        struct bt_stream_class *sc;
        struct bt_event_class *ec;
@@ -45,7 +49,16 @@ struct user {
        struct bt_event *event;
 };
 
-const char *user_names[] = {
+struct writer_user {
+       struct bt_ctf_writer *writer;
+       struct bt_ctf_trace *tc;
+       struct bt_ctf_stream_class *sc;
+       struct bt_ctf_event_class *ec;
+       struct bt_ctf_stream *stream;
+       struct bt_ctf_event *event;
+};
+
+const char *writer_user_names[] = {
        "writer",
        "trace",
        "stream class",
@@ -54,7 +67,8 @@ const char *user_names[] = {
        "event",
 };
 
-static const size_t USER_NR_ELEMENTS = sizeof(struct user) / sizeof(void *);
+static const size_t WRITER_USER_NR_ELEMENTS =
+       sizeof(struct writer_user) / sizeof(void *);
 
 /**
  * Returns a structure containing the following fields:
@@ -116,6 +130,60 @@ error:
        goto end;
 }
 
+static struct bt_ctf_field_type *create_writer_integer_struct(void)
+{
+       int ret;
+       struct bt_ctf_field_type *structure = NULL;
+       struct bt_ctf_field_type *ui8 = NULL, *ui16 = NULL, *ui32 = NULL;
+
+       structure = bt_ctf_field_type_structure_create();
+       if (!structure) {
+               goto error;
+       }
+
+       ui8 = bt_ctf_field_type_integer_create(8);
+       if (!ui8) {
+               diag("Failed to create uint8_t type");
+               goto error;
+       }
+       ret = bt_ctf_field_type_structure_add_field(structure, ui8,
+                       "payload_8");
+       if (ret) {
+               diag("Failed to add uint8_t to structure");
+               goto error;
+       }
+       ui16 = bt_ctf_field_type_integer_create(16);
+       if (!ui16) {
+               diag("Failed to create uint16_t type");
+               goto error;
+       }
+       ret = bt_ctf_field_type_structure_add_field(structure, ui16,
+                       "payload_16");
+       if (ret) {
+               diag("Failed to add uint16_t to structure");
+               goto error;
+       }
+       ui32 = bt_ctf_field_type_integer_create(32);
+       if (!ui32) {
+               diag("Failed to create uint32_t type");
+               goto error;
+       }
+       ret = bt_ctf_field_type_structure_add_field(structure, ui32,
+                       "payload_32");
+       if (ret) {
+               diag("Failed to add uint32_t to structure");
+               goto error;
+       }
+end:
+       BT_PUT(ui8);
+       BT_PUT(ui16);
+       BT_PUT(ui32);
+       return structure;
+error:
+       BT_PUT(structure);
+       goto end;
+}
+
 /**
  * A simple event has the following payload:
  *     - uint8_t payload_8;
@@ -141,7 +209,7 @@ static struct bt_event_class *create_simple_event(const char *name)
                goto error;
        }
 
-       ret = bt_event_class_set_payload_type(event, payload);
+       ret = bt_event_class_set_payload_field_type(event, payload);
        if (ret) {
                diag("Failed to set simple event payload");
                goto error;
@@ -196,7 +264,7 @@ static struct bt_event_class *create_complex_event(const char *name)
                goto error;
        }
 
-       ret = bt_event_class_set_payload_type(event, outer);
+       ret = bt_event_class_set_payload_field_type(event, outer);
        if (ret) {
                diag("Failed to set complex event payload");
                goto error;
@@ -242,10 +310,10 @@ static void set_stream_class_field_types(
        assert(ret == 0);
        bt_put(ft);
 
-       ret = bt_stream_class_set_packet_context_type(stream_class,
+       ret = bt_stream_class_set_packet_context_field_type(stream_class,
                packet_context_type);
        assert(ret == 0);
-       ret = bt_stream_class_set_event_header_type(stream_class,
+       ret = bt_stream_class_set_event_header_field_type(stream_class,
                event_header_type);
        assert(ret == 0);
 
@@ -259,7 +327,7 @@ static struct bt_stream_class *create_sc1(void)
        struct bt_event_class *ec1 = NULL, *ec2 = NULL;
        struct bt_stream_class *sc1 = NULL, *ret_stream = NULL;
 
-       sc1 = bt_stream_class_create_empty("sc1");
+       sc1 = bt_stream_class_create("sc1");
        if (!sc1) {
                diag("Failed to create Stream Class");
                goto error;
@@ -310,7 +378,7 @@ static struct bt_stream_class *create_sc2(void)
        struct bt_event_class *ec3 = NULL;
        struct bt_stream_class *sc2 = NULL, *ret_stream = NULL;
 
-       sc2 = bt_stream_class_create_empty("sc2");
+       sc2 = bt_stream_class_create("sc2");
        if (!sc2) {
                diag("Failed to create Stream Class");
                goto error;
@@ -354,7 +422,7 @@ static void set_trace_packet_header(struct bt_trace *trace)
        assert(ret == 0);
        bt_put(ft);
 
-       ret = bt_trace_set_packet_header_type(trace,
+       ret = bt_trace_set_packet_header_field_type(trace,
                packet_header_type);
        assert(ret == 0);
 
@@ -565,11 +633,11 @@ static void test_example_scenario(void)
        BT_PUT(user_c.ec);
 }
 
-static void create_user_full(struct user *user)
+static void create_writer_user_full(struct writer_user *user)
 {
        gchar *trace_path;
-       struct bt_field_type *ft;
-       struct bt_field *field;
+       struct bt_ctf_field_type *ft;
+       struct bt_ctf_field *field;
        struct bt_ctf_clock *clock;
        int ret;
 
@@ -581,48 +649,48 @@ static void create_user_full(struct user *user)
        user->writer = bt_ctf_writer_create(trace_path);
        assert(user->writer);
        ret = bt_ctf_writer_set_byte_order(user->writer,
-               BT_BYTE_ORDER_LITTLE_ENDIAN);
+               BT_CTF_BYTE_ORDER_LITTLE_ENDIAN);
        assert(ret == 0);
        user->tc = bt_ctf_writer_get_trace(user->writer);
        assert(user->tc);
-       user->sc = bt_stream_class_create("sc");
+       user->sc = bt_ctf_stream_class_create("sc");
        assert(user->sc);
        clock = bt_ctf_clock_create("the_clock");
        assert(clock);
        ret = bt_ctf_writer_add_clock(user->writer, clock);
        assert(!ret);
-       ret = bt_stream_class_set_clock(user->sc, clock);
+       ret = bt_ctf_stream_class_set_clock(user->sc, clock);
        assert(!ret);
        BT_PUT(clock);
        user->stream = bt_ctf_writer_create_stream(user->writer, user->sc);
        assert(user->stream);
-       user->ec = bt_event_class_create("ec");
+       user->ec = bt_ctf_event_class_create("ec");
        assert(user->ec);
-       ft = create_integer_struct();
+       ft = create_writer_integer_struct();
        assert(ft);
-       ret = bt_event_class_set_payload_type(user->ec, ft);
+       ret = bt_ctf_event_class_set_payload_field_type(user->ec, ft);
        BT_PUT(ft);
        assert(!ret);
-       ret = bt_stream_class_add_event_class(user->sc, user->ec);
+       ret = bt_ctf_stream_class_add_event_class(user->sc, user->ec);
        assert(!ret);
-       user->event = bt_event_create(user->ec);
+       user->event = bt_ctf_event_create(user->ec);
        assert(user->event);
-       field = bt_event_get_payload(user->event, "payload_8");
+       field = bt_ctf_event_get_payload(user->event, "payload_8");
        assert(field);
-       ret = bt_field_unsigned_integer_set_value(field, 10);
+       ret = bt_ctf_field_integer_unsigned_set_value(field, 10);
        assert(!ret);
        BT_PUT(field);
-       field = bt_event_get_payload(user->event, "payload_16");
+       field = bt_ctf_event_get_payload(user->event, "payload_16");
        assert(field);
-       ret = bt_field_unsigned_integer_set_value(field, 20);
+       ret = bt_ctf_field_integer_unsigned_set_value(field, 20);
        assert(!ret);
        BT_PUT(field);
-       field = bt_event_get_payload(user->event, "payload_32");
+       field = bt_ctf_event_get_payload(user->event, "payload_32");
        assert(field);
-       ret = bt_field_unsigned_integer_set_value(field, 30);
+       ret = bt_ctf_field_integer_unsigned_set_value(field, 30);
        assert(!ret);
        BT_PUT(field);
-       ret = bt_stream_append_event(user->stream, user->event);
+       ret = bt_ctf_stream_append_event(user->stream, user->event);
        assert(!ret);
        recursive_rmdir(trace_path);
        g_free(trace_path);
@@ -639,16 +707,16 @@ static void test_put_order_swap(size_t *array, size_t a, size_t b)
 static void test_put_order_put_objects(size_t *array, size_t size)
 {
        size_t i;
-       struct user user = { 0 };
+       struct writer_user user = { 0 };
        void **objects = (void *) &user;
 
-       create_user_full(&user);
+       create_writer_user_full(&user);
        printf("# ");
 
        for (i = 0; i < size; ++i) {
                void *obj = objects[array[i]];
 
-               printf("%s", user_names[array[i]]);
+               printf("%s", writer_user_names[array[i]]);
                BT_PUT(obj);
 
                if (i < size - 1) {
@@ -679,14 +747,15 @@ static void test_put_order_permute(size_t *array, int k, size_t size)
 static void test_put_order(void)
 {
        size_t i;
-       size_t array[USER_NR_ELEMENTS];
+       size_t array[WRITER_USER_NR_ELEMENTS];
 
        /* Initialize array of indexes */
-       for (i = 0; i < USER_NR_ELEMENTS; ++i) {
+       for (i = 0; i < WRITER_USER_NR_ELEMENTS; ++i) {
                array[i] = i;
        }
 
-       test_put_order_permute(array, USER_NR_ELEMENTS, USER_NR_ELEMENTS);
+       test_put_order_permute(array, WRITER_USER_NR_ELEMENTS,
+               WRITER_USER_NR_ELEMENTS);
 }
 
 /**
index 1653cd6184bfe25600095e324ee2a24a00db952d..5601809136548b4c0af5f9107435af9545950c8f 100644 (file)
@@ -26,9 +26,7 @@
 #include <babeltrace/ctf-writer/event-types.h>
 #include <babeltrace/ctf-writer/event-fields.h>
 #include <babeltrace/ctf-writer/stream-class.h>
-#include <babeltrace/ctf-ir/packet.h>
-#include <babeltrace/ctf-ir/clock-class.h>
-#include <babeltrace/ctf-ir/trace.h>
+#include <babeltrace/ctf-writer/trace.h>
 #include <babeltrace/ref.h>
 #include <babeltrace/ctf/events.h>
 #include <babeltrace/values.h>
@@ -59,7 +57,7 @@
 #define DEFAULT_CLOCK_TIME 0
 #define DEFAULT_CLOCK_VALUE 0
 
-#define NR_TESTS 476
+#define NR_TESTS 347
 
 struct bt_utsname {
        char sysname[BABELTRACE_HOST_NAME_MAX];
@@ -98,7 +96,6 @@ static
 void validate_trace(char *parser_path, char *trace_path)
 {
        int ret = 0;
-       gchar *standard_error = NULL;
        gint exit_status;
        char *argv[] = {parser_path, trace_path, "-o", "dummy", NULL};
 
@@ -114,7 +111,7 @@ void validate_trace(char *parser_path, char *trace_path)
                        NULL,
                        NULL,
                        NULL,
-                       &standard_error,
+                       NULL,
                        &exit_status,
                        NULL)) {
                diag("Failed to spawn babeltrace.");
@@ -131,60 +128,58 @@ void validate_trace(char *parser_path, char *trace_path)
 
        if (ret != 0) {
                diag("Babeltrace returned an error.");
-               diag_multiline(standard_error);
                goto result;
        }
 
 result:
        ok(ret == 0, "Babeltrace could read the resulting trace");
-       g_free(standard_error);
 }
 
 static
-void append_simple_event(struct bt_stream_class *stream_class,
-               struct bt_stream *stream, struct bt_ctf_clock *clock)
+void append_simple_event(struct bt_ctf_stream_class *stream_class,
+               struct bt_ctf_stream *stream, struct bt_ctf_clock *clock)
 {
        /* Create and add a simple event class */
-       struct bt_event_class *simple_event_class =
-               bt_event_class_create("Simple Event");
-       struct bt_field_type *uint_12_type =
-               bt_field_type_integer_create(12);
-       struct bt_field_type *int_64_type =
-               bt_field_type_integer_create(64);
-       struct bt_field_type *float_type =
-               bt_field_type_floating_point_create();
-       struct bt_field_type *enum_type;
-       struct bt_field_type *enum_type_unsigned =
-               bt_field_type_enumeration_create(uint_12_type);
-       struct bt_field_type *event_context_type =
-               bt_field_type_structure_create();
-       struct bt_field_type *event_payload_type = NULL;
-       struct bt_field_type *returned_type;
-       struct bt_event *simple_event;
-       struct bt_field *integer_field;
-       struct bt_field *float_field;
-       struct bt_field *enum_field;
-       struct bt_field *enum_field_unsigned;
-       struct bt_field *enum_container_field;
+       struct bt_ctf_event_class *simple_event_class =
+               bt_ctf_event_class_create("Simple Event");
+       struct bt_ctf_field_type *uint_12_type =
+               bt_ctf_field_type_integer_create(12);
+       struct bt_ctf_field_type *int_64_type =
+               bt_ctf_field_type_integer_create(64);
+       struct bt_ctf_field_type *float_type =
+               bt_ctf_field_type_floating_point_create();
+       struct bt_ctf_field_type *enum_type;
+       struct bt_ctf_field_type *enum_type_unsigned =
+               bt_ctf_field_type_enumeration_create(uint_12_type);
+       struct bt_ctf_field_type *event_context_type =
+               bt_ctf_field_type_structure_create();
+       struct bt_ctf_field_type *event_payload_type = NULL;
+       struct bt_ctf_field_type *returned_type;
+       struct bt_ctf_event *simple_event;
+       struct bt_ctf_field *integer_field;
+       struct bt_ctf_field *float_field;
+       struct bt_ctf_field *enum_field;
+       struct bt_ctf_field *enum_field_unsigned;
+       struct bt_ctf_field *enum_container_field;
        const char *mapping_name_test = "truie";
        const double double_test_value = 3.1415;
-       struct bt_field *enum_container_field_unsigned;
+       struct bt_ctf_field *enum_container_field_unsigned;
        const char *mapping_name_negative_test = "negative_value";
        const char *ret_char;
        double ret_double;
        int64_t ret_range_start_int64_t, ret_range_end_int64_t;
        uint64_t ret_range_start_uint64_t, ret_range_end_uint64_t;
-       struct bt_event_class *ret_event_class;
-       struct bt_field *packet_context;
-       struct bt_field *packet_context_field;
-       struct bt_field *stream_event_context;
-       struct bt_field *stream_event_context_field;
-       struct bt_field *event_context;
-       struct bt_field *event_context_field;
-       struct bt_field_type *ep_integer_field_type = NULL;
-       struct bt_field_type *ep_enum_field_type = NULL;
-       struct bt_field_type *ep_enum_field_unsigned_type = NULL;
-       struct bt_field_type_enumeration_mapping_iterator *iter = NULL;
+       struct bt_ctf_event_class *ret_event_class;
+       struct bt_ctf_field *packet_context;
+       struct bt_ctf_field *packet_context_field;
+       struct bt_ctf_field *stream_event_context;
+       struct bt_ctf_field *stream_event_context_field;
+       struct bt_ctf_field *event_context;
+       struct bt_ctf_field *event_context_field;
+       struct bt_ctf_field_type *ep_integer_field_type = NULL;
+       struct bt_ctf_field_type *ep_enum_field_type = NULL;
+       struct bt_ctf_field_type *ep_enum_field_unsigned_type = NULL;
+       struct bt_ctf_field_type_enumeration_mapping_iterator *iter = NULL;
        int ret;
 
        ok(uint_12_type, "Create an unsigned integer type");
@@ -192,290 +187,262 @@ void append_simple_event(struct bt_stream_class *stream_class,
        ok(!bt_ctf_field_type_integer_set_signed(int_64_type, 1),
                "Set signed 64 bit integer signedness to true");
        ok(int_64_type, "Create a signed integer type");
-       enum_type = bt_field_type_enumeration_create(int_64_type);
+       enum_type = bt_ctf_field_type_enumeration_create(int_64_type);
 
-       returned_type = bt_field_type_enumeration_get_container_type(enum_type);
-       ok(returned_type == int_64_type, "bt_field_type_enumeration_get_container_type returns the right type");
-       ok(!bt_field_type_enumeration_create(enum_type),
-               "bt_field_enumeration_type_create rejects non-integer container field types");
+       returned_type = bt_ctf_field_type_enumeration_get_container_field_type(enum_type);
+       ok(returned_type == int_64_type, "bt_ctf_field_type_enumeration_get_container_field_type returns the right type");
+       ok(!bt_ctf_field_type_enumeration_create(enum_type),
+               "bt_ctf_field_enumeration_type_create rejects non-integer container field types");
        bt_put(returned_type);
 
-       bt_field_type_set_alignment(float_type, 32);
-       ok(bt_field_type_get_alignment(float_type) == 32,
-               "bt_field_type_get_alignment returns a correct value");
+       bt_ctf_field_type_set_alignment(float_type, 32);
+       ok(bt_ctf_field_type_get_alignment(float_type) == 32,
+               "bt_ctf_field_type_get_alignment returns a correct value");
 
-       ok(bt_field_type_floating_point_set_exponent_digits(float_type, 11) == 0,
+       ok(bt_ctf_field_type_floating_point_set_exponent_digits(float_type, 11) == 0,
                "Set a floating point type's exponent digit count");
-       ok(bt_field_type_floating_point_set_mantissa_digits(float_type, 53) == 0,
+       ok(bt_ctf_field_type_floating_point_set_mantissa_digits(float_type, 53) == 0,
                "Set a floating point type's mantissa digit count");
 
-       ok(bt_field_type_floating_point_get_exponent_digits(float_type) == 11,
-               "bt_field_type_floating_point_get_exponent_digits returns the correct value");
-       ok(bt_field_type_floating_point_get_mantissa_digits(float_type) == 53,
-               "bt_field_type_floating_point_get_mantissa_digits returns the correct value");
+       ok(bt_ctf_field_type_floating_point_get_exponent_digits(float_type) == 11,
+               "bt_ctf_field_type_floating_point_get_exponent_digits returns the correct value");
+       ok(bt_ctf_field_type_floating_point_get_mantissa_digits(float_type) == 53,
+               "bt_ctf_field_type_floating_point_get_mantissa_digits returns the correct value");
 
        ok(bt_ctf_field_type_enumeration_add_mapping(enum_type,
                mapping_name_negative_test, -12345, 0) == 0,
-               "bt_field_type_enumeration_add_mapping accepts negative enumeration mappings");
+               "bt_ctf_field_type_enumeration_add_mapping accepts negative enumeration mappings");
        ok(bt_ctf_field_type_enumeration_add_mapping(enum_type,
                "escaping; \"test\"", 1, 1) == 0,
-               "bt_field_type_enumeration_add_mapping accepts enumeration mapping strings containing quotes");
+               "bt_ctf_field_type_enumeration_add_mapping accepts enumeration mapping strings containing quotes");
        ok(bt_ctf_field_type_enumeration_add_mapping(enum_type,
                "\tanother \'escaping\'\n test\"", 2, 4) == 0,
-               "bt_field_type_enumeration_add_mapping accepts enumeration mapping strings containing special characters");
+               "bt_ctf_field_type_enumeration_add_mapping accepts enumeration mapping strings containing special characters");
        ok(bt_ctf_field_type_enumeration_add_mapping(enum_type,
                "event clock int float", 5, 22) == 0,
                "Accept enumeration mapping strings containing reserved keywords");
        bt_ctf_field_type_enumeration_add_mapping(enum_type, mapping_name_test,
                42, 42);
        ok(bt_ctf_field_type_enumeration_add_mapping(enum_type, mapping_name_test,
-               43, 51) == 0, "bt_field_type_enumeration_add_mapping accepts duplicate mapping names");
+               43, 51) == 0, "bt_ctf_field_type_enumeration_add_mapping accepts duplicate mapping names");
        ok(bt_ctf_field_type_enumeration_add_mapping(enum_type, "something",
-               -500, -400) == 0, "bt_field_type_enumeration_add_mapping accepts overlapping enum entries");
+               -500, -400) == 0, "bt_ctf_field_type_enumeration_add_mapping accepts overlapping enum entries");
        ok(bt_ctf_field_type_enumeration_add_mapping(enum_type, mapping_name_test,
-               -54, -55), "bt_field_type_enumeration_add_mapping rejects mapping where end < start");
+               -54, -55), "bt_ctf_field_type_enumeration_add_mapping rejects mapping where end < start");
        bt_ctf_field_type_enumeration_add_mapping(enum_type, "another entry", -42000, -13000);
 
-       iter = bt_field_type_enumeration_find_mappings_by_signed_value(enum_type, -4200000);
-       ret = bt_field_type_enumeration_mapping_iterator_next(iter);
-       ok(iter && ret, "bt_field_type_enumeration_find_mappings_by_signed_value rejects non-mapped values");
-       BT_PUT(iter);
-
-       iter = bt_field_type_enumeration_find_mappings_by_signed_value(enum_type, 3);
-       ok(iter != NULL, "bt_field_type_enumeration_find_mappings_by_signed_value succeeds with mapped value");
-       ret = bt_field_type_enumeration_mapping_iterator_next(iter);
-       ok(!ret && bt_field_type_enumeration_mapping_iterator_get_signed(iter, NULL, NULL, NULL) == 0,
-               "bt_field_type_enumeration_mapping_iterator_get_signed handles mapped values correctly");
-       BT_PUT(iter);
-
-       ok(bt_event_class_add_field(simple_event_class, enum_type,
+       ok(bt_ctf_event_class_add_field(simple_event_class, enum_type,
                "enum_field") == 0, "Add signed enumeration field to event");
 
-       ok(bt_field_type_enumeration_get_mapping_signed(enum_type, 0, NULL,
+       ok(bt_ctf_field_type_enumeration_signed_get_mapping_by_index(enum_type, 0, NULL,
                &ret_range_start_int64_t, &ret_range_end_int64_t) == 0,
-               "bt_field_type_enumeration_get_mapping_signed handles a NULL string correctly");
-       ok(bt_field_type_enumeration_get_mapping_signed(enum_type, 0, &ret_char,
+               "bt_ctf_field_type_enumeration_signed_get_mapping_by_index handles a NULL string correctly");
+       ok(bt_ctf_field_type_enumeration_signed_get_mapping_by_index(enum_type, 0, &ret_char,
                NULL, &ret_range_end_int64_t) == 0,
-               "bt_field_type_enumeration_get_mapping_signed handles a NULL start correctly");
-       ok(bt_field_type_enumeration_get_mapping_signed(enum_type, 0, &ret_char,
+               "bt_ctf_field_type_enumeration_signed_get_mapping_by_index handles a NULL start correctly");
+       ok(bt_ctf_field_type_enumeration_signed_get_mapping_by_index(enum_type, 0, &ret_char,
                &ret_range_start_int64_t, NULL) == 0,
-               "bt_field_type_enumeration_get_mapping_signed handles a NULL end correctly");
+               "bt_ctf_field_type_enumeration_signed_get_mapping_by_index handles a NULL end correctly");
        /* Assumes entries are sorted by range_start values. */
-       ok(bt_field_type_enumeration_get_mapping_signed(enum_type, 6, &ret_char,
+       ok(bt_ctf_field_type_enumeration_signed_get_mapping_by_index(enum_type, 6, &ret_char,
                &ret_range_start_int64_t, &ret_range_end_int64_t) == 0,
-               "bt_field_type_enumeration_get_mapping_signed returns a value");
+               "bt_ctf_field_type_enumeration_signed_get_mapping_by_index returns a value");
        ok(!strcmp(ret_char, mapping_name_test),
-               "bt_field_type_enumeration_get_mapping_signed returns a correct mapping name");
+               "bt_ctf_field_type_enumeration_signed_get_mapping_by_index returns a correct mapping name");
        ok(ret_range_start_int64_t == 42,
-               "bt_field_type_enumeration_get_mapping_signed returns a correct mapping start");
+               "bt_ctf_field_type_enumeration_signed_get_mapping_by_index returns a correct mapping start");
        ok(ret_range_end_int64_t == 42,
-               "bt_field_type_enumeration_get_mapping_signed returns a correct mapping end");
+               "bt_ctf_field_type_enumeration_signed_get_mapping_by_index returns a correct mapping end");
 
-       ok(bt_field_type_enumeration_add_mapping_unsigned(enum_type_unsigned,
+       ok(bt_ctf_field_type_enumeration_unsigned_add_mapping(enum_type_unsigned,
                "escaping; \"test\"", 0, 0) == 0,
-               "bt_field_type_enumeration_add_mapping_unsigned accepts enumeration mapping strings containing quotes");
-       ok(bt_field_type_enumeration_add_mapping_unsigned(enum_type_unsigned,
+               "bt_ctf_field_type_enumeration_unsigned_add_mapping accepts enumeration mapping strings containing quotes");
+       ok(bt_ctf_field_type_enumeration_unsigned_add_mapping(enum_type_unsigned,
                "\tanother \'escaping\'\n test\"", 1, 4) == 0,
-               "bt_field_type_enumeration_add_mapping_unsigned accepts enumeration mapping strings containing special characters");
-       ok(bt_field_type_enumeration_add_mapping_unsigned(enum_type_unsigned,
+               "bt_ctf_field_type_enumeration_unsigned_add_mapping accepts enumeration mapping strings containing special characters");
+       ok(bt_ctf_field_type_enumeration_unsigned_add_mapping(enum_type_unsigned,
                "event clock int float", 5, 22) == 0,
-               "bt_field_type_enumeration_add_mapping_unsigned accepts enumeration mapping strings containing reserved keywords");
-       ok(bt_field_type_enumeration_add_mapping_unsigned(enum_type_unsigned, mapping_name_test,
-               42, 42) == 0, "bt_field_type_enumeration_add_mapping_unsigned accepts single-value ranges");
-       ok(bt_field_type_enumeration_add_mapping_unsigned(enum_type_unsigned, mapping_name_test,
-               43, 51) == 0, "bt_field_type_enumeration_add_mapping_unsigned accepts duplicate mapping names");
-       ok(bt_field_type_enumeration_add_mapping_unsigned(enum_type_unsigned, "something",
-               7, 8) == 0, "bt_field_type_enumeration_add_mapping_unsigned accepts overlapping enum entries");
-       ok(bt_field_type_enumeration_add_mapping_unsigned(enum_type_unsigned, mapping_name_test,
-               55, 54), "bt_field_type_enumeration_add_mapping_unsigned rejects mapping where end < start");
-       ok(bt_event_class_add_field(simple_event_class, enum_type_unsigned,
+               "bt_ctf_field_type_enumeration_unsigned_add_mapping accepts enumeration mapping strings containing reserved keywords");
+       ok(bt_ctf_field_type_enumeration_unsigned_add_mapping(enum_type_unsigned, mapping_name_test,
+               42, 42) == 0, "bt_ctf_field_type_enumeration_unsigned_add_mapping accepts single-value ranges");
+       ok(bt_ctf_field_type_enumeration_unsigned_add_mapping(enum_type_unsigned, mapping_name_test,
+               43, 51) == 0, "bt_ctf_field_type_enumeration_unsigned_add_mapping accepts duplicate mapping names");
+       ok(bt_ctf_field_type_enumeration_unsigned_add_mapping(enum_type_unsigned, "something",
+               7, 8) == 0, "bt_ctf_field_type_enumeration_unsigned_add_mapping accepts overlapping enum entries");
+       ok(bt_ctf_field_type_enumeration_unsigned_add_mapping(enum_type_unsigned, mapping_name_test,
+               55, 54), "bt_ctf_field_type_enumeration_unsigned_add_mapping rejects mapping where end < start");
+       ok(bt_ctf_event_class_add_field(simple_event_class, enum_type_unsigned,
                "enum_field_unsigned") == 0, "Add unsigned enumeration field to event");
 
-       ok(bt_field_type_enumeration_get_mapping_count(enum_type_unsigned) == 6,
-               "bt_field_type_enumeration_get_mapping_count returns the correct value");
+       ok(bt_ctf_field_type_enumeration_get_mapping_count(enum_type_unsigned) == 6,
+               "bt_ctf_field_type_enumeration_get_mapping_count returns the correct value");
 
-       ok(bt_field_type_enumeration_get_mapping_unsigned(enum_type_unsigned, 0, NULL,
+       ok(bt_ctf_field_type_enumeration_unsigned_get_mapping_by_index(enum_type_unsigned, 0, NULL,
                &ret_range_start_uint64_t, &ret_range_end_uint64_t) == 0,
-               "bt_field_type_enumeration_get_mapping_unsigned handles a NULL string correctly");
-       ok(bt_field_type_enumeration_get_mapping_unsigned(enum_type_unsigned, 0, &ret_char,
+               "bt_ctf_field_type_enumeration_unsigned_get_mapping_by_index handles a NULL string correctly");
+       ok(bt_ctf_field_type_enumeration_unsigned_get_mapping_by_index(enum_type_unsigned, 0, &ret_char,
                NULL, &ret_range_end_uint64_t) == 0,
-               "bt_field_type_enumeration_get_mapping_unsigned handles a NULL start correctly");
-       ok(bt_field_type_enumeration_get_mapping_unsigned(enum_type_unsigned, 0, &ret_char,
+               "bt_ctf_field_type_enumeration_unsigned_get_mapping_by_index handles a NULL start correctly");
+       ok(bt_ctf_field_type_enumeration_unsigned_get_mapping_by_index(enum_type_unsigned, 0, &ret_char,
                &ret_range_start_uint64_t, NULL) == 0,
-               "bt_field_type_enumeration_get_mapping_unsigned handles a NULL end correctly");
-       ok(bt_field_type_enumeration_get_mapping_unsigned(enum_type_unsigned, 4, &ret_char,
+               "bt_ctf_field_type_enumeration_unsigned_get_mapping_by_index handles a NULL end correctly");
+       ok(bt_ctf_field_type_enumeration_unsigned_get_mapping_by_index(enum_type_unsigned, 4, &ret_char,
                &ret_range_start_uint64_t, &ret_range_end_uint64_t) == 0,
-               "bt_field_type_enumeration_get_mapping_unsigned returns a value");
+               "bt_ctf_field_type_enumeration_unsigned_get_mapping_by_index returns a value");
        ok(!strcmp(ret_char, mapping_name_test),
-               "bt_field_type_enumeration_get_mapping_unsigned returns a correct mapping name");
+               "bt_ctf_field_type_enumeration_unsigned_get_mapping_by_index returns a correct mapping name");
        ok(ret_range_start_uint64_t == 42,
-               "bt_field_type_enumeration_get_mapping_unsigned returns a correct mapping start");
+               "bt_ctf_field_type_enumeration_unsigned_get_mapping_by_index returns a correct mapping start");
        ok(ret_range_end_uint64_t == 42,
-               "bt_field_type_enumeration_get_mapping_unsigned returns a correct mapping end");
+               "bt_ctf_field_type_enumeration_unsigned_get_mapping_by_index returns a correct mapping end");
 
-       bt_event_class_add_field(simple_event_class, uint_12_type,
+       bt_ctf_event_class_add_field(simple_event_class, uint_12_type,
                "integer_field");
-       bt_event_class_add_field(simple_event_class, float_type,
+       bt_ctf_event_class_add_field(simple_event_class, float_type,
                "float_field");
 
-       assert(!bt_event_class_set_id(simple_event_class, 13));
+       assert(!bt_ctf_event_class_set_id(simple_event_class, 13));
 
        /* Set an event context type which will contain a single integer. */
-       ok(!bt_field_type_structure_add_field(event_context_type, uint_12_type,
+       ok(!bt_ctf_field_type_structure_add_field(event_context_type, uint_12_type,
                "event_specific_context"),
                "Add event specific context field");
 
-       ok(bt_event_class_set_context_type(NULL, event_context_type) < 0,
-               "bt_event_class_set_context_type handles a NULL event class correctly");
-       ok(!bt_event_class_set_context_type(simple_event_class, event_context_type),
+       ok(bt_ctf_event_class_set_context_field_type(NULL, event_context_type) < 0,
+               "bt_ctf_event_class_set_context_field_type handles a NULL event class correctly");
+       ok(!bt_ctf_event_class_set_context_field_type(simple_event_class, event_context_type),
                "Set an event class' context type successfully");
-       returned_type = bt_event_class_get_context_type(simple_event_class);
+       returned_type = bt_ctf_event_class_get_context_field_type(simple_event_class);
        ok(returned_type == event_context_type,
-               "bt_event_class_get_context_type returns the appropriate type");
+               "bt_ctf_event_class_get_context_field_type returns the appropriate type");
        bt_put(returned_type);
 
-       ok(!bt_stream_class_add_event_class(stream_class, simple_event_class),
+       ok(!bt_ctf_stream_class_add_event_class(stream_class, simple_event_class),
                "Adding simple event class to stream class");
 
        /*
-        * bt_stream_class_add_event_class() copies the field types
+        * bt_ctf_stream_class_add_event_class() copies the field types
         * of simple_event_class, so we retrieve the new ones to create
         * the appropriate fields.
         */
        BT_PUT(event_context_type);
        BT_PUT(event_payload_type);
-       event_payload_type = bt_event_class_get_payload_type(
+       event_payload_type = bt_ctf_event_class_get_payload_field_type(
                simple_event_class);
        assert(event_payload_type);
-       event_context_type = bt_event_class_get_context_type(
+       event_context_type = bt_ctf_event_class_get_context_field_type(
                simple_event_class);
        assert(event_context_type);
        ep_integer_field_type =
-               bt_field_type_structure_get_field_type_by_name(
+               bt_ctf_field_type_structure_get_field_type_by_name(
                        event_payload_type, "integer_field");
        assert(ep_integer_field_type);
        ep_enum_field_type =
-               bt_field_type_structure_get_field_type_by_name(
+               bt_ctf_field_type_structure_get_field_type_by_name(
                        event_payload_type, "enum_field");
        assert(ep_enum_field_type);
        ep_enum_field_unsigned_type =
-               bt_field_type_structure_get_field_type_by_name(
+               bt_ctf_field_type_structure_get_field_type_by_name(
                        event_payload_type, "enum_field_unsigned");
        assert(ep_enum_field_unsigned_type);
 
-       ok(bt_stream_class_get_event_class_count(stream_class) == 1,
-               "bt_stream_class_get_event_class_count returns a correct number of event classes");
-       ret_event_class = bt_stream_class_get_event_class_by_index(stream_class, 0);
+       ok(bt_ctf_stream_class_get_event_class_count(stream_class) == 1,
+               "bt_ctf_stream_class_get_event_class_count returns a correct number of event classes");
+       ret_event_class = bt_ctf_stream_class_get_event_class_by_index(stream_class, 0);
        ok(ret_event_class == simple_event_class,
-               "bt_stream_class_get_event_class returns the correct event class");
+               "bt_ctf_stream_class_get_event_class returns the correct event class");
        bt_put(ret_event_class);
-       ok(!bt_stream_class_get_event_class_by_id(stream_class, 2),
-               "bt_stream_class_get_event_class_by_id returns NULL when the requested ID doesn't exist");
+       ok(!bt_ctf_stream_class_get_event_class_by_id(stream_class, 2),
+               "bt_ctf_stream_class_get_event_class_by_id returns NULL when the requested ID doesn't exist");
        ret_event_class =
-               bt_stream_class_get_event_class_by_id(stream_class, 13);
+               bt_ctf_stream_class_get_event_class_by_id(stream_class, 13);
        ok(ret_event_class == simple_event_class,
-               "bt_stream_class_get_event_class_by_id returns a correct event class");
+               "bt_ctf_stream_class_get_event_class_by_id returns a correct event class");
        bt_put(ret_event_class);
 
-       simple_event = bt_event_create(simple_event_class);
+       simple_event = bt_ctf_event_create(simple_event_class);
        ok(simple_event,
                "Instantiate an event containing a single integer field");
 
-       integer_field = bt_field_create(ep_integer_field_type);
-       bt_field_unsigned_integer_set_value(integer_field, 42);
-       ok(bt_event_set_payload(simple_event, "integer_field",
-               integer_field) == 0, "Use bt_event_set_payload to set a manually allocated field");
+       integer_field = bt_ctf_field_create(ep_integer_field_type);
+       bt_ctf_field_integer_unsigned_set_value(integer_field, 42);
+       ok(bt_ctf_event_set_payload(simple_event, "integer_field",
+               integer_field) == 0, "Use bt_ctf_event_set_payload to set a manually allocated field");
 
-       float_field = bt_event_get_payload(simple_event, "float_field");
-       bt_field_floating_point_set_value(float_field, double_test_value);
-       ok(!bt_field_floating_point_get_value(float_field, &ret_double),
-               "bt_field_floating_point_get_value returns a double value");
+       float_field = bt_ctf_event_get_payload(simple_event, "float_field");
+       bt_ctf_field_floating_point_set_value(float_field, double_test_value);
+       ok(!bt_ctf_field_floating_point_get_value(float_field, &ret_double),
+               "bt_ctf_field_floating_point_get_value returns a double value");
        ok(fabs(ret_double - double_test_value) <= DBL_EPSILON,
-               "bt_field_floating_point_get_value returns a correct value");
+               "bt_ctf_field_floating_point_get_value returns a correct value");
 
-       enum_field = bt_field_create(ep_enum_field_type);
+       enum_field = bt_ctf_field_create(ep_enum_field_type);
        assert(enum_field);
 
-       enum_container_field = bt_field_enumeration_get_container(enum_field);
-       ok(bt_field_signed_integer_set_value(
+       enum_container_field = bt_ctf_field_enumeration_get_container(enum_field);
+       ok(bt_ctf_field_integer_signed_set_value(
                enum_container_field, -42) == 0,
                "Set signed enumeration container value");
-       iter = bt_field_enumeration_get_mappings(enum_field);
-       ok(iter, "bt_field_enumeration_get_mappings returns an iterator to matching mappings");
-       ret = bt_field_type_enumeration_mapping_iterator_next(iter);
-       ok(!ret, "bt_field_enumeration_get_mappings returned a non-empty match");
-       ret = bt_field_type_enumeration_mapping_iterator_get_signed(iter, &ret_char, NULL, NULL);
-       ok(!ret && ret_char, "bt_field_type_enumeration_mapping_iterator_get_signed return a mapping name");
-       assert(ret_char);
-       ok(!strcmp(ret_char, mapping_name_negative_test),
-               "bt_field_enumeration_get_single_mapping_name returns the correct mapping name with an signed container");
-       ret = bt_event_set_payload(simple_event, "enum_field", enum_field);
+       ret = bt_ctf_event_set_payload(simple_event, "enum_field", enum_field);
        assert(!ret);
        BT_PUT(iter);
 
-       enum_field_unsigned = bt_field_create(ep_enum_field_unsigned_type);
+       enum_field_unsigned = bt_ctf_field_create(ep_enum_field_unsigned_type);
        assert(enum_field_unsigned);
-       enum_container_field_unsigned = bt_field_enumeration_get_container(
+       enum_container_field_unsigned = bt_ctf_field_enumeration_get_container(
                enum_field_unsigned);
-       ok(bt_field_unsigned_integer_set_value(
+       ok(bt_ctf_field_integer_unsigned_set_value(
                enum_container_field_unsigned, 42) == 0,
                "Set unsigned enumeration container value");
-       ret = bt_event_set_payload(simple_event, "enum_field_unsigned",
+       ret = bt_ctf_event_set_payload(simple_event, "enum_field_unsigned",
                enum_field_unsigned);
        assert(!ret);
-       iter = bt_field_enumeration_get_mappings(enum_field_unsigned);
-       assert(iter);
-       ret = bt_field_type_enumeration_mapping_iterator_next(iter);
-       assert(!ret);
-       (void) bt_field_type_enumeration_mapping_iterator_get_unsigned(iter, &ret_char, NULL, NULL);
-       ok(ret_char && !strcmp(ret_char, mapping_name_test),
-               "bt_field_type_enumeration_mapping_iterator_get_unsigned returns the correct mapping name with an unsigned container");
 
        ok(bt_ctf_clock_set_time(clock, current_time) == 0, "Set clock time");
 
        /* Populate stream event context */
        stream_event_context =
-               bt_event_get_stream_event_context(simple_event);
+               bt_ctf_event_get_stream_event_context(simple_event);
        assert(stream_event_context);
-       stream_event_context_field = bt_field_structure_get_field_by_name(
+       stream_event_context_field = bt_ctf_field_structure_get_field_by_name(
                stream_event_context, "common_event_context");
-       bt_field_unsigned_integer_set_value(stream_event_context_field, 42);
+       bt_ctf_field_integer_unsigned_set_value(stream_event_context_field, 42);
 
        /* Populate the event's context */
-       event_context = bt_event_get_event_context(simple_event);
+       event_context = bt_ctf_event_get_context(simple_event);
        ok(event_context,
-               "bt_event_get_event_context returns a field");
-       returned_type = bt_field_get_type(event_context);
+               "bt_ctf_event_get_context returns a field");
+       returned_type = bt_ctf_field_get_type(event_context);
        ok(returned_type == event_context_type,
-               "bt_event_get_event_context returns a field of the appropriate type");
-       event_context_field = bt_field_structure_get_field_by_name(event_context,
+               "bt_ctf_event_get_context returns a field of the appropriate type");
+       event_context_field = bt_ctf_field_structure_get_field_by_name(event_context,
                "event_specific_context");
-       ok(!bt_field_unsigned_integer_set_value(event_context_field, 1234),
+       ok(!bt_ctf_field_integer_unsigned_set_value(event_context_field, 1234),
                "Successfully set an event context's value");
-       ok(!bt_event_set_event_context(simple_event, event_context),
+       ok(!bt_ctf_event_set_context(simple_event, event_context),
                "Set an event context successfully");
 
-       ok(bt_stream_append_event(stream, simple_event) == 0,
+       ok(bt_ctf_stream_append_event(stream, simple_event) == 0,
                "Append simple event to trace stream");
 
-       packet_context = bt_stream_get_packet_context(stream);
+       packet_context = bt_ctf_stream_get_packet_context(stream);
        ok(packet_context,
-               "bt_stream_get_packet_context returns a packet context");
+               "bt_ctf_stream_get_packet_context returns a packet context");
 
-       packet_context_field = bt_field_structure_get_field_by_name(packet_context,
+       packet_context_field = bt_ctf_field_structure_get_field_by_name(packet_context,
                "packet_size");
        ok(packet_context_field,
                "Packet context contains the default packet_size field.");
        bt_put(packet_context_field);
-       packet_context_field = bt_field_structure_get_field_by_name(packet_context,
+       packet_context_field = bt_ctf_field_structure_get_field_by_name(packet_context,
                "custom_packet_context_field");
-       ok(bt_field_unsigned_integer_set_value(packet_context_field, 8) == 0,
+       ok(bt_ctf_field_integer_unsigned_set_value(packet_context_field, 8) == 0,
                "Custom packet context field value successfully set.");
 
-       ok(bt_stream_set_packet_context(stream, packet_context) == 0,
+       ok(bt_ctf_stream_set_packet_context(stream, packet_context) == 0,
                "Successfully set a stream's packet context");
 
-       ok(bt_stream_flush(stream) == 0,
+       ok(bt_ctf_stream_flush(stream) == 0,
                "Flush trace stream with one event");
 
        bt_put(simple_event_class);
@@ -507,10 +474,10 @@ void append_simple_event(struct bt_stream_class *stream_class,
 }
 
 static
-void append_complex_event(struct bt_stream_class *stream_class,
-               struct bt_stream *stream, struct bt_ctf_clock *clock)
+void append_complex_event(struct bt_ctf_stream_class *stream_class,
+               struct bt_ctf_stream *stream, struct bt_ctf_clock *clock)
 {
-       int i, ret;
+       int i;
        struct event_class_attrs_counts ;
        const char *complex_test_event_string = "Complex Test Event";
        const char *test_string_1 = "Test ";
@@ -518,29 +485,29 @@ void append_complex_event(struct bt_stream_class *stream_class,
        const char *test_string_3 = "abcdefghi";
        const char *test_string_4 = "abcd\0efg\0hi";
        const char *test_string_cat = "Test string abcdeefg";
-       struct bt_field_type *uint_35_type =
-               bt_field_type_integer_create(35);
-       struct bt_field_type *int_16_type =
-               bt_field_type_integer_create(16);
-       struct bt_field_type *uint_3_type =
-               bt_field_type_integer_create(3);
-       struct bt_field_type *enum_variant_type =
-               bt_field_type_enumeration_create(uint_3_type);
-       struct bt_field_type *variant_type =
-               bt_field_type_variant_create(enum_variant_type,
+       struct bt_ctf_field_type *uint_35_type =
+               bt_ctf_field_type_integer_create(35);
+       struct bt_ctf_field_type *int_16_type =
+               bt_ctf_field_type_integer_create(16);
+       struct bt_ctf_field_type *uint_3_type =
+               bt_ctf_field_type_integer_create(3);
+       struct bt_ctf_field_type *enum_variant_type =
+               bt_ctf_field_type_enumeration_create(uint_3_type);
+       struct bt_ctf_field_type *variant_type =
+               bt_ctf_field_type_variant_create(enum_variant_type,
                        "variant_selector");
-       struct bt_field_type *string_type =
-               bt_field_type_string_create();
-       struct bt_field_type *sequence_type;
-       struct bt_field_type *array_type;
-       struct bt_field_type *inner_structure_type =
-               bt_field_type_structure_create();
-       struct bt_field_type *complex_structure_type =
-               bt_field_type_structure_create();
-       struct bt_field_type *ret_field_type;
-       struct bt_event_class *event_class;
-       struct bt_event *event;
-       struct bt_field *uint_35_field, *int_16_field, *a_string_field,
+       struct bt_ctf_field_type *string_type =
+               bt_ctf_field_type_string_create();
+       struct bt_ctf_field_type *sequence_type;
+       struct bt_ctf_field_type *array_type;
+       struct bt_ctf_field_type *inner_structure_type =
+               bt_ctf_field_type_structure_create();
+       struct bt_ctf_field_type *complex_structure_type =
+               bt_ctf_field_type_structure_create();
+       struct bt_ctf_field_type *ret_field_type;
+       struct bt_ctf_event_class *event_class;
+       struct bt_ctf_event *event;
+       struct bt_ctf_field *uint_35_field, *int_16_field, *a_string_field,
                *inner_structure_field, *complex_structure_field,
                *a_sequence_field, *enum_variant_field, *enum_container_field,
                *variant_field, *an_array_field, *stream_event_ctx_field,
@@ -548,47 +515,46 @@ void append_complex_event(struct bt_stream_class *stream_class,
        uint64_t ret_unsigned_int;
        int64_t ret_signed_int;
        const char *ret_string;
-       struct bt_stream_class *ret_stream_class;
-       struct bt_event_class *ret_event_class;
-       struct bt_field *packet_context, *packet_context_field;
-       struct bt_field_type_enumeration_mapping_iterator *iter = NULL;
-
-       ok(bt_field_type_set_alignment(int_16_type, 0),
-               "bt_field_type_set_alignment handles 0-alignment correctly");
-       ok(bt_field_type_set_alignment(int_16_type, 3),
-               "bt_field_type_set_alignment handles wrong alignment correctly (3)");
-       ok(bt_field_type_set_alignment(int_16_type, 24),
-               "bt_field_type_set_alignment handles wrong alignment correctly (24)");
-       ok(!bt_field_type_set_alignment(int_16_type, 4),
-               "bt_field_type_set_alignment handles correct alignment correctly (4)");
-       ok(!bt_field_type_set_alignment(int_16_type, 32),
+       struct bt_ctf_stream_class *ret_stream_class;
+       struct bt_ctf_event_class *ret_event_class;
+       struct bt_ctf_field *packet_context, *packet_context_field;
+
+       ok(bt_ctf_field_type_set_alignment(int_16_type, 0),
+               "bt_ctf_field_type_set_alignment handles 0-alignment correctly");
+       ok(bt_ctf_field_type_set_alignment(int_16_type, 3),
+               "bt_ctf_field_type_set_alignment handles wrong alignment correctly (3)");
+       ok(bt_ctf_field_type_set_alignment(int_16_type, 24),
+               "bt_ctf_field_type_set_alignment handles wrong alignment correctly (24)");
+       ok(!bt_ctf_field_type_set_alignment(int_16_type, 4),
+               "bt_ctf_field_type_set_alignment handles correct alignment correctly (4)");
+       ok(!bt_ctf_field_type_set_alignment(int_16_type, 32),
                "Set alignment of signed 16 bit integer to 32");
        ok(!bt_ctf_field_type_integer_set_signed(int_16_type, 1),
                "Set integer signedness to true");
-       ok(!bt_field_type_integer_set_base(uint_35_type,
-               BT_INTEGER_BASE_HEXADECIMAL),
+       ok(!bt_ctf_field_type_integer_set_base(uint_35_type,
+               BT_CTF_INTEGER_BASE_HEXADECIMAL),
                "Set signed 16 bit integer base to hexadecimal");
 
-       array_type = bt_field_type_array_create(int_16_type, ARRAY_TEST_LENGTH);
-       sequence_type = bt_field_type_sequence_create(int_16_type,
+       array_type = bt_ctf_field_type_array_create(int_16_type, ARRAY_TEST_LENGTH);
+       sequence_type = bt_ctf_field_type_sequence_create(int_16_type,
                "seq_len");
 
-       ret_field_type = bt_field_type_array_get_element_type(
+       ret_field_type = bt_ctf_field_type_array_get_element_field_type(
                array_type);
        ok(ret_field_type == int_16_type,
-               "bt_field_type_array_get_element_type returns the correct type");
+               "bt_ctf_field_type_array_get_element_field_type returns the correct type");
        bt_put(ret_field_type);
 
-       ok(bt_field_type_array_get_length(array_type) == ARRAY_TEST_LENGTH,
-               "bt_field_type_array_get_length returns the correct length");
+       ok(bt_ctf_field_type_array_get_length(array_type) == ARRAY_TEST_LENGTH,
+               "bt_ctf_field_type_array_get_length returns the correct length");
 
-       ok(bt_field_type_structure_add_field(inner_structure_type,
+       ok(bt_ctf_field_type_structure_add_field(inner_structure_type,
                inner_structure_type, "yes"), "Cannot add self to structure");
-       ok(!bt_field_type_structure_add_field(inner_structure_type,
+       ok(!bt_ctf_field_type_structure_add_field(inner_structure_type,
                uint_35_type, "seq_len"), "Add seq_len field to inner structure");
-       ok(!bt_field_type_structure_add_field(inner_structure_type,
+       ok(!bt_ctf_field_type_structure_add_field(inner_structure_type,
                sequence_type, "a_sequence"), "Add a_sequence field to inner structure");
-       ok(!bt_field_type_structure_add_field(inner_structure_type,
+       ok(!bt_ctf_field_type_structure_add_field(inner_structure_type,
                array_type, "an_array"), "Add an_array field to inner structure");
 
        bt_ctf_field_type_enumeration_add_mapping(enum_variant_type,
@@ -598,287 +564,251 @@ void append_complex_event(struct bt_stream_class *stream_class,
        bt_ctf_field_type_enumeration_add_mapping(enum_variant_type,
                "UINT35_TYPE", 2, 7);
 
-       iter = bt_field_type_enumeration_find_mappings_by_name(enum_variant_type, "INT16_TYPE");
-       ok(iter != NULL, "bt_field_type_enumeration_find_mappings_by_name returns a non-NULL iterator");
-       ret = bt_field_type_enumeration_mapping_iterator_next(iter);
-       ok(!ret, "bt_field_type_enumeration_find_mappings_by_name handles an existing mapping correctly");
-       ok(bt_field_type_enumeration_mapping_iterator_get_unsigned(iter, NULL, NULL, NULL) == 0,
-               "bt_field_type_enumeration_mapping_iterator_get_unsigned handles mapped values correctly");
-       BT_PUT(iter);
-
-       iter = bt_field_type_enumeration_find_mappings_by_unsigned_value(enum_variant_type, -42);
-       ret = bt_field_type_enumeration_mapping_iterator_next(iter);
-       ok(iter && ret, "bt_field_type_enumeration_find_mappings_by_unsigned_value handles invalid values correctly");
-       BT_PUT(iter);
-
-       iter = bt_field_type_enumeration_find_mappings_by_unsigned_value(enum_variant_type, 5);
-       ret = bt_field_type_enumeration_mapping_iterator_next(iter);
-       ok(iter != NULL && !ret, "bt_field_type_enumeration_find_mappings_by_unsigned_value handles valid values correctly");
-       BT_PUT(iter);
-
-       ok(bt_field_type_variant_add_field(variant_type, uint_3_type,
+       ok(bt_ctf_field_type_variant_add_field(variant_type, uint_3_type,
                "An unknown entry"), "Reject a variant field based on an unknown tag value");
-       ok(bt_field_type_variant_add_field(variant_type, uint_3_type,
+       ok(bt_ctf_field_type_variant_add_field(variant_type, uint_3_type,
                "UINT3_TYPE") == 0, "Add a field to a variant");
-       ok(!bt_field_type_variant_add_field(variant_type, int_16_type,
+       ok(!bt_ctf_field_type_variant_add_field(variant_type, int_16_type,
                "INT16_TYPE"), "Add INT16_TYPE field to variant");
-       ok(!bt_field_type_variant_add_field(variant_type, uint_35_type,
+       ok(!bt_ctf_field_type_variant_add_field(variant_type, uint_35_type,
                "UINT35_TYPE"), "Add UINT35_TYPE field to variant");
 
-       ret_field_type = bt_field_type_variant_get_tag_type(variant_type);
+       ret_field_type = bt_ctf_field_type_variant_get_tag_field_type(variant_type);
        ok(ret_field_type == enum_variant_type,
-               "bt_field_type_variant_get_tag_type returns a correct tag type");
+               "bt_ctf_field_type_variant_get_tag_field_type returns a correct tag type");
        bt_put(ret_field_type);
 
-       ret_string = bt_field_type_variant_get_tag_name(variant_type);
+       ret_string = bt_ctf_field_type_variant_get_tag_name(variant_type);
        ok(ret_string ? !strcmp(ret_string, "variant_selector") : 0,
-               "bt_field_type_variant_get_tag_name returns the correct variant tag name");
-       ret_field_type = bt_field_type_variant_get_field_type_by_name(
+               "bt_ctf_field_type_variant_get_tag_name returns the correct variant tag name");
+       ret_field_type = bt_ctf_field_type_variant_get_field_type_by_name(
                variant_type, "INT16_TYPE");
        ok(ret_field_type == int_16_type,
-               "bt_field_type_variant_get_field_type_by_name returns a correct field type");
+               "bt_ctf_field_type_variant_get_field_type_by_name returns a correct field type");
        bt_put(ret_field_type);
 
-       ok(bt_field_type_variant_get_field_count(variant_type) == 3,
-               "bt_field_type_variant_get_field_count returns the correct count");
+       ok(bt_ctf_field_type_variant_get_field_count(variant_type) == 3,
+               "bt_ctf_field_type_variant_get_field_count returns the correct count");
 
-       ok(bt_field_type_variant_get_field_by_index(variant_type, NULL, &ret_field_type, 0) == 0,
-               "bt_field_type_variant_get_field handles a NULL field name correctly");
+       ok(bt_ctf_field_type_variant_get_field_by_index(variant_type, NULL, &ret_field_type, 0) == 0,
+               "bt_ctf_field_type_variant_get_field handles a NULL field name correctly");
        bt_put(ret_field_type);
-       ok(bt_field_type_variant_get_field_by_index(variant_type, &ret_string, NULL, 0) == 0,
-               "bt_field_type_variant_get_field handles a NULL field type correctly");
-       ok(bt_field_type_variant_get_field_by_index(variant_type, &ret_string, &ret_field_type, 1) == 0,
-               "bt_field_type_variant_get_field returns a field");
+       ok(bt_ctf_field_type_variant_get_field_by_index(variant_type, &ret_string, NULL, 0) == 0,
+               "bt_ctf_field_type_variant_get_field handles a NULL field type correctly");
+       ok(bt_ctf_field_type_variant_get_field_by_index(variant_type, &ret_string, &ret_field_type, 1) == 0,
+               "bt_ctf_field_type_variant_get_field returns a field");
        ok(!strcmp("INT16_TYPE", ret_string),
-               "bt_field_type_variant_get_field returns a correct field name");
+               "bt_ctf_field_type_variant_get_field returns a correct field name");
        ok(ret_field_type == int_16_type,
-               "bt_field_type_variant_get_field returns a correct field type");
+               "bt_ctf_field_type_variant_get_field returns a correct field type");
        bt_put(ret_field_type);
 
-       ok(!bt_field_type_structure_add_field(complex_structure_type,
+       ok(!bt_ctf_field_type_structure_add_field(complex_structure_type,
                enum_variant_type, "variant_selector"),
                "Add variant_selector field to complex structure");
-       ok(!bt_field_type_structure_add_field(complex_structure_type,
+       ok(!bt_ctf_field_type_structure_add_field(complex_structure_type,
                string_type, "string"), "Add `string` field to complex structure");
-       ok(!bt_field_type_structure_add_field(complex_structure_type,
+       ok(!bt_ctf_field_type_structure_add_field(complex_structure_type,
                variant_type, "variant_value"),
                "Add variant_value field to complex structure");
-       ok(!bt_field_type_structure_add_field(complex_structure_type,
+       ok(!bt_ctf_field_type_structure_add_field(complex_structure_type,
                inner_structure_type, "inner_structure"),
                "Add inner_structure field to complex structure");
 
-       event_class = bt_event_class_create(complex_test_event_string);
+       event_class = bt_ctf_event_class_create(complex_test_event_string);
        ok(event_class, "Create an event class");
-       ok(bt_event_class_add_field(event_class, uint_35_type, ""),
+       ok(bt_ctf_event_class_add_field(event_class, uint_35_type, ""),
                "Reject addition of a field with an empty name to an event");
-       ok(bt_event_class_add_field(event_class, NULL, "an_integer"),
+       ok(bt_ctf_event_class_add_field(event_class, NULL, "an_integer"),
                "Reject addition of a field with a NULL type to an event");
-       ok(bt_event_class_add_field(event_class, uint_35_type,
+       ok(bt_ctf_event_class_add_field(event_class, uint_35_type,
                "int"),
                "Reject addition of a type with an illegal name to an event");
-       ok(bt_event_class_add_field(event_class, uint_35_type,
+       ok(bt_ctf_event_class_add_field(event_class, uint_35_type,
                "uint_35") == 0,
                "Add field of type unsigned integer to an event");
-       ok(bt_event_class_add_field(event_class, int_16_type,
+       ok(bt_ctf_event_class_add_field(event_class, int_16_type,
                "int_16") == 0, "Add field of type signed integer to an event");
-       ok(bt_event_class_add_field(event_class, complex_structure_type,
+       ok(bt_ctf_event_class_add_field(event_class, complex_structure_type,
                "complex_structure") == 0,
                "Add composite structure to an event");
 
-       ret_string = bt_event_class_get_name(event_class);
+       ret_string = bt_ctf_event_class_get_name(event_class);
        ok(!strcmp(ret_string, complex_test_event_string),
-               "bt_event_class_get_name returns a correct name");
-       ok(bt_event_class_get_id(event_class) < 0,
-               "bt_event_class_get_id returns a negative value when not set");
-       ok(bt_event_class_set_id(NULL, 42) < 0,
-               "bt_event_class_set_id handles NULL correctly");
-       ok(bt_event_class_set_id(event_class, 42) == 0,
+               "bt_ctf_event_class_get_name returns a correct name");
+       ok(bt_ctf_event_class_get_id(event_class) < 0,
+               "bt_ctf_event_class_get_id returns a negative value when not set");
+       ok(bt_ctf_event_class_set_id(NULL, 42) < 0,
+               "bt_ctf_event_class_set_id handles NULL correctly");
+       ok(bt_ctf_event_class_set_id(event_class, 42) == 0,
                "Set an event class' id");
-       ok(bt_event_class_get_id(event_class) == 42,
-               "bt_event_class_get_id returns the correct value");
+       ok(bt_ctf_event_class_get_id(event_class) == 42,
+               "bt_ctf_event_class_get_id returns the correct value");
 
        /* Test event class attributes */
-       ok(bt_event_class_get_log_level(event_class) == BT_EVENT_CLASS_LOG_LEVEL_UNSPECIFIED,
+       ok(bt_ctf_event_class_get_log_level(event_class) == BT_CTF_EVENT_CLASS_LOG_LEVEL_UNSPECIFIED,
                "event class has the expected initial log level");
-       ok(!bt_event_class_get_emf_uri(event_class),
+       ok(!bt_ctf_event_class_get_emf_uri(event_class),
                "as expected, event class has no initial EMF URI");
-       ok(bt_event_class_set_log_level(NULL, BT_EVENT_CLASS_LOG_LEVEL_INFO),
-               "bt_event_class_set_log_level handles a NULL event class correctly");
-       ok(bt_event_class_set_log_level(event_class, BT_EVENT_CLASS_LOG_LEVEL_UNKNOWN),
-               "bt_event_class_set_log_level handles an unknown log level correctly");
-       ok(!bt_event_class_set_log_level(event_class, BT_EVENT_CLASS_LOG_LEVEL_INFO),
-               "bt_event_class_set_log_level succeeds with a valid log level");
-       ok(bt_event_class_get_log_level(event_class) == BT_EVENT_CLASS_LOG_LEVEL_INFO,
-               "bt_event_class_get_log_level returns the expected log level");
-       ok(bt_event_class_set_emf_uri(NULL, "http://diamon.org/babeltrace/"),
-               "bt_event_class_set_emf_uri handles a NULL event class correctly");
-       ok(!bt_event_class_set_emf_uri(event_class, "http://diamon.org/babeltrace/"),
-               "bt_event_class_set_emf_uri succeeds with a valid EMF URI");
-       ok(strcmp(bt_event_class_get_emf_uri(event_class), "http://diamon.org/babeltrace/") == 0,
-               "bt_event_class_get_emf_uri returns the expected EMF URI");
-       ok(!bt_event_class_set_emf_uri(event_class, NULL),
-               "bt_event_class_set_emf_uri succeeds with NULL (to reset)");
-       ok(!bt_event_class_get_emf_uri(event_class),
+       ok(bt_ctf_event_class_set_log_level(NULL, BT_CTF_EVENT_CLASS_LOG_LEVEL_INFO),
+               "bt_ctf_event_class_set_log_level handles a NULL event class correctly");
+       ok(bt_ctf_event_class_set_log_level(event_class, BT_CTF_EVENT_CLASS_LOG_LEVEL_UNKNOWN),
+               "bt_ctf_event_class_set_log_level handles an unknown log level correctly");
+       ok(!bt_ctf_event_class_set_log_level(event_class, BT_CTF_EVENT_CLASS_LOG_LEVEL_INFO),
+               "bt_ctf_event_class_set_log_level succeeds with a valid log level");
+       ok(bt_ctf_event_class_get_log_level(event_class) == BT_CTF_EVENT_CLASS_LOG_LEVEL_INFO,
+               "bt_ctf_event_class_get_log_level returns the expected log level");
+       ok(bt_ctf_event_class_set_emf_uri(NULL, "http://diamon.org/babeltrace/"),
+               "bt_ctf_event_class_set_emf_uri handles a NULL event class correctly");
+       ok(!bt_ctf_event_class_set_emf_uri(event_class, "http://diamon.org/babeltrace/"),
+               "bt_ctf_event_class_set_emf_uri succeeds with a valid EMF URI");
+       ok(strcmp(bt_ctf_event_class_get_emf_uri(event_class), "http://diamon.org/babeltrace/") == 0,
+               "bt_ctf_event_class_get_emf_uri returns the expected EMF URI");
+       ok(!bt_ctf_event_class_set_emf_uri(event_class, NULL),
+               "bt_ctf_event_class_set_emf_uri succeeds with NULL (to reset)");
+       ok(!bt_ctf_event_class_get_emf_uri(event_class),
                "as expected, event class has no EMF URI after reset");
 
        /* Add event class to the stream class */
-       ok(bt_stream_class_add_event_class(stream_class, NULL),
+       ok(bt_ctf_stream_class_add_event_class(stream_class, NULL),
                "Reject addition of NULL event class to a stream class");
-       ok(bt_stream_class_add_event_class(stream_class,
+       ok(bt_ctf_stream_class_add_event_class(stream_class,
                event_class) == 0, "Add an event class to stream class");
 
-       ret_stream_class = bt_event_class_get_stream_class(event_class);
+       ret_stream_class = bt_ctf_event_class_get_stream_class(event_class);
        ok(ret_stream_class == stream_class,
-               "bt_event_class_get_stream_class returns the correct stream class");
+               "bt_ctf_event_class_get_stream_class returns the correct stream class");
        bt_put(ret_stream_class);
 
-       ok(bt_event_class_get_payload_type_field_count(event_class) == 3,
-               "bt_event_class_get_field_count returns a correct value");
-
-       ok(bt_event_class_get_payload_type_field_by_index(event_class, &ret_string,
-               NULL, 0) == 0,
-               "bt_event_class_get_field handles a NULL field type correctly");
-       ok(bt_event_class_get_payload_type_field_by_index(event_class, &ret_string,
-               &ret_field_type, 0) == 0,
-               "bt_event_class_get_field returns a field");
-       ok(bt_field_type_compare(ret_field_type, uint_35_type) == 0,
-               "bt_event_class_get_field returns a correct field type");
-       bt_put(ret_field_type);
-       ok(!strcmp(ret_string, "uint_35"),
-               "bt_event_class_get_field returns a correct field name");
        ok(bt_ctf_event_class_get_field_by_name(event_class, "truie") == NULL,
-               "bt_event_class_get_field_by_name handles an invalid field name correctly");
+               "bt_ctf_event_class_get_field_by_name handles an invalid field name correctly");
        ret_field_type = bt_ctf_event_class_get_field_by_name(event_class,
                "complex_structure");
-       ok(bt_field_type_compare(ret_field_type, complex_structure_type) == 0,
-               "bt_event_class_get_field_by_name returns a correct field type");
        bt_put(ret_field_type);
 
-       event = bt_event_create(event_class);
+       event = bt_ctf_event_create(event_class);
        ok(event, "Instanciate a complex event");
 
-       ret_event_class = bt_event_get_class(event);
+       ret_event_class = bt_ctf_event_get_class(event);
        ok(ret_event_class == event_class,
-               "bt_event_get_class returns the correct event class");
+               "bt_ctf_event_get_class returns the correct event class");
        bt_put(ret_event_class);
 
-       uint_35_field = bt_event_get_payload(event, "uint_35");
-       ok(uint_35_field, "Use bt_event_get_payload to get a field instance ");
-       bt_field_unsigned_integer_set_value(uint_35_field, 0x0DDF00D);
-       ok(bt_field_unsigned_integer_get_value(uint_35_field,
+       uint_35_field = bt_ctf_event_get_payload(event, "uint_35");
+       ok(uint_35_field, "Use bt_ctf_event_get_payload to get a field instance ");
+       bt_ctf_field_integer_unsigned_set_value(uint_35_field, 0x0DDF00D);
+       ok(bt_ctf_field_integer_unsigned_get_value(uint_35_field,
                &ret_unsigned_int) == 0,
-               "bt_field_unsigned_integer_get_value succeeds after setting a value");
+               "bt_ctf_field_integer_unsigned_get_value succeeds after setting a value");
        ok(ret_unsigned_int == 0x0DDF00D,
-               "bt_field_unsigned_integer_get_value returns the correct value");
+               "bt_ctf_field_integer_unsigned_get_value returns the correct value");
        bt_put(uint_35_field);
 
-       int_16_field = bt_event_get_payload(event, "int_16");
-       bt_field_signed_integer_set_value(int_16_field, -12345);
-       ok(bt_field_signed_integer_get_value(int_16_field,
+       int_16_field = bt_ctf_event_get_payload(event, "int_16");
+       bt_ctf_field_integer_signed_set_value(int_16_field, -12345);
+       ok(bt_ctf_field_integer_signed_get_value(int_16_field,
                &ret_signed_int) == 0,
-               "bt_field_signed_integer_get_value succeeds after setting a value");
+               "bt_ctf_field_integer_signed_get_value succeeds after setting a value");
        ok(ret_signed_int == -12345,
-               "bt_field_signed_integer_get_value returns the correct value");
+               "bt_ctf_field_integer_signed_get_value returns the correct value");
        bt_put(int_16_field);
 
-       complex_structure_field = bt_event_get_payload(event,
+       complex_structure_field = bt_ctf_event_get_payload(event,
                "complex_structure");
 
-       inner_structure_field = bt_field_structure_get_field_by_index(
+       inner_structure_field = bt_ctf_field_structure_get_field_by_index(
                complex_structure_field, 3);
-       ret_field_type = bt_field_get_type(inner_structure_field);
+       ret_field_type = bt_ctf_field_get_type(inner_structure_field);
        bt_put(inner_structure_field);
-       ok(bt_field_type_compare(ret_field_type, inner_structure_type) == 0,
-               "bt_field_structure_get_field_by_index returns a correct field");
        bt_put(ret_field_type);
 
-       inner_structure_field = bt_field_structure_get_field_by_name(
+       inner_structure_field = bt_ctf_field_structure_get_field_by_name(
                complex_structure_field, "inner_structure");
-       a_string_field = bt_field_structure_get_field_by_name(
+       a_string_field = bt_ctf_field_structure_get_field_by_name(
                complex_structure_field, "string");
-       enum_variant_field = bt_field_structure_get_field_by_name(
+       enum_variant_field = bt_ctf_field_structure_get_field_by_name(
                complex_structure_field, "variant_selector");
-       variant_field = bt_field_structure_get_field_by_name(
+       variant_field = bt_ctf_field_structure_get_field_by_name(
                complex_structure_field, "variant_value");
-       uint_35_field = bt_field_structure_get_field_by_name(
+       uint_35_field = bt_ctf_field_structure_get_field_by_name(
                inner_structure_field, "seq_len");
-       a_sequence_field = bt_field_structure_get_field_by_name(
+       a_sequence_field = bt_ctf_field_structure_get_field_by_name(
                inner_structure_field, "a_sequence");
-       an_array_field = bt_field_structure_get_field_by_name(
+       an_array_field = bt_ctf_field_structure_get_field_by_name(
                inner_structure_field, "an_array");
 
-       enum_container_field = bt_field_enumeration_get_container(
+       enum_container_field = bt_ctf_field_enumeration_get_container(
                enum_variant_field);
-       bt_field_unsigned_integer_set_value(enum_container_field, 1);
-       int_16_field = bt_field_variant_get_field(variant_field,
+       bt_ctf_field_integer_unsigned_set_value(enum_container_field, 1);
+       int_16_field = bt_ctf_field_variant_get_field(variant_field,
                enum_variant_field);
-       bt_field_signed_integer_set_value(int_16_field, -200);
+       bt_ctf_field_integer_signed_set_value(int_16_field, -200);
        bt_put(int_16_field);
-       bt_field_string_set_value(a_string_field,
+       bt_ctf_field_string_set_value(a_string_field,
                test_string_1);
-       ok(!bt_field_string_append(a_string_field, test_string_2),
-               "bt_field_string_append succeeds");
-       ok(!bt_field_string_append_len(a_string_field, test_string_3, 5),
-               "bt_field_string_append_len succeeds (append 5 characters)");
-       ok(!bt_field_string_append_len(a_string_field, &test_string_4[5], 3),
-               "bt_field_string_append_len succeeds (append 0 characters)");
-       ok(!bt_field_string_append_len(a_string_field, test_string_3, 0),
-               "bt_field_string_append_len succeeds (append 0 characters)");
-
-       ret_string = bt_field_string_get_value(a_string_field);
-       ok(ret_string, "bt_field_string_get_value returns a string");
+       ok(!bt_ctf_field_string_append(a_string_field, test_string_2),
+               "bt_ctf_field_string_append succeeds");
+       ok(!bt_ctf_field_string_append_len(a_string_field, test_string_3, 5),
+               "bt_ctf_field_string_append_len succeeds (append 5 characters)");
+       ok(!bt_ctf_field_string_append_len(a_string_field, &test_string_4[5], 3),
+               "bt_ctf_field_string_append_len succeeds (append 0 characters)");
+       ok(!bt_ctf_field_string_append_len(a_string_field, test_string_3, 0),
+               "bt_ctf_field_string_append_len succeeds (append 0 characters)");
+
+       ret_string = bt_ctf_field_string_get_value(a_string_field);
+       ok(ret_string, "bt_ctf_field_string_get_value returns a string");
        ok(ret_string ? !strcmp(ret_string, test_string_cat) : 0,
-               "bt_field_string_get_value returns a correct value");
-       bt_field_unsigned_integer_set_value(uint_35_field,
+               "bt_ctf_field_string_get_value returns a correct value");
+       bt_ctf_field_integer_unsigned_set_value(uint_35_field,
                SEQUENCE_TEST_LENGTH);
 
-       ret_field_type = bt_field_type_variant_get_field_type_from_tag(
+       ret_field_type = bt_ctf_field_type_variant_get_field_type_from_tag(
                variant_type, enum_variant_field);
        ok(ret_field_type == int_16_type,
-               "bt_field_type_variant_get_field_type_from_tag returns the correct field type");
+               "bt_ctf_field_type_variant_get_field_type_from_tag returns the correct field type");
 
-       ok(bt_field_sequence_set_length(a_sequence_field,
+       ok(bt_ctf_field_sequence_set_length(a_sequence_field,
                uint_35_field) == 0, "Set a sequence field's length");
-       ret_field = bt_field_sequence_get_length(a_sequence_field);
+       ret_field = bt_ctf_field_sequence_get_length(a_sequence_field);
        ok(ret_field == uint_35_field,
-               "bt_field_sequence_get_length returns the correct length field");
+               "bt_ctf_field_sequence_get_length returns the correct length field");
 
        for (i = 0; i < SEQUENCE_TEST_LENGTH; i++) {
-               int_16_field = bt_field_sequence_get_field(
+               int_16_field = bt_ctf_field_sequence_get_field(
                        a_sequence_field, i);
-               bt_field_signed_integer_set_value(int_16_field, 4 - i);
+               bt_ctf_field_integer_signed_set_value(int_16_field, 4 - i);
                bt_put(int_16_field);
        }
 
        for (i = 0; i < ARRAY_TEST_LENGTH; i++) {
-               int_16_field = bt_field_array_get_field(
+               int_16_field = bt_ctf_field_array_get_field(
                        an_array_field, i);
-               bt_field_signed_integer_set_value(int_16_field, i);
+               bt_ctf_field_integer_signed_set_value(int_16_field, i);
                bt_put(int_16_field);
        }
 
-       stream_event_ctx_field = bt_event_get_stream_event_context(event);
+       stream_event_ctx_field = bt_ctf_event_get_stream_event_context(event);
        assert(stream_event_ctx_field);
-       stream_event_ctx_int_field = bt_field_structure_get_field_by_name(
+       stream_event_ctx_int_field = bt_ctf_field_structure_get_field_by_name(
                stream_event_ctx_field, "common_event_context");
        BT_PUT(stream_event_ctx_field);
-       bt_field_unsigned_integer_set_value(stream_event_ctx_int_field, 17);
+       bt_ctf_field_integer_unsigned_set_value(stream_event_ctx_int_field, 17);
        BT_PUT(stream_event_ctx_int_field);
 
        bt_ctf_clock_set_time(clock, ++current_time);
-       ok(bt_stream_append_event(stream, event) == 0,
+       ok(bt_ctf_stream_append_event(stream, event) == 0,
                "Append a complex event to a stream");
 
        /*
         * Populate the custom packet context field with a dummy value
         * otherwise flush will fail.
         */
-       packet_context = bt_stream_get_packet_context(stream);
-       packet_context_field = bt_field_structure_get_field_by_name(packet_context,
+       packet_context = bt_ctf_stream_get_packet_context(stream);
+       packet_context_field = bt_ctf_field_structure_get_field_by_name(packet_context,
                "custom_packet_context_field");
-       bt_field_unsigned_integer_set_value(packet_context_field, 1);
+       bt_ctf_field_integer_unsigned_set_value(packet_context_field, 1);
 
-       ok(bt_stream_flush(stream) == 0,
+       ok(bt_ctf_stream_flush(stream) == 0,
                "Flush a stream containing a complex event");
 
        bt_put(uint_35_field);
@@ -908,740 +838,213 @@ void append_complex_event(struct bt_stream_class *stream_class,
        bt_put(event);
 }
 
-static
-void field_copy_tests_validate_same_type(struct bt_field *field,
-               struct bt_field_type *expected_type, const char *name)
-{
-       struct bt_field_type *copy_type;
-
-       copy_type = bt_field_get_type(field);
-       ok(copy_type == expected_type,
-               "bt_field_copy does not copy the type (%s)", name);
-       bt_put(copy_type);
-}
-
-static
-void field_copy_tests_validate_diff_ptrs(struct bt_field *field_a,
-               struct bt_field *field_b, const char *name)
-{
-       ok(field_a != field_b,
-               "bt_field_copy creates different pointers (%s)", name);
-}
-
-static
-void field_copy_tests()
-{
-       struct bt_field_type *len_type = NULL;
-       struct bt_field_type *fp_type = NULL;
-       struct bt_field_type *s_type = NULL;
-       struct bt_field_type *e_int_type = NULL;
-       struct bt_field_type *e_type = NULL;
-       struct bt_field_type *v_type = NULL;
-       struct bt_field_type *v_label1_type = NULL;
-       struct bt_field_type *v_label1_array_type = NULL;
-       struct bt_field_type *v_label2_type = NULL;
-       struct bt_field_type *v_label2_seq_type = NULL;
-       struct bt_field_type *strct_type = NULL;
-       struct bt_field *len = NULL;
-       struct bt_field *fp = NULL;
-       struct bt_field *s = NULL;
-       struct bt_field *e_int = NULL;
-       struct bt_field *e = NULL;
-       struct bt_field *v = NULL;
-       struct bt_field *v_selected = NULL;
-       struct bt_field *v_selected_cur = NULL;
-       struct bt_field *v_selected_0 = NULL;
-       struct bt_field *v_selected_1 = NULL;
-       struct bt_field *v_selected_2 = NULL;
-       struct bt_field *v_selected_3 = NULL;
-       struct bt_field *v_selected_4 = NULL;
-       struct bt_field *v_selected_5 = NULL;
-       struct bt_field *v_selected_6 = NULL;
-       struct bt_field *a = NULL;
-       struct bt_field *a_0 = NULL;
-       struct bt_field *a_1 = NULL;
-       struct bt_field *a_2 = NULL;
-       struct bt_field *a_3 = NULL;
-       struct bt_field *a_4 = NULL;
-       struct bt_field *strct = NULL;
-       struct bt_field *len_copy = NULL;
-       struct bt_field *fp_copy = NULL;
-       struct bt_field *s_copy = NULL;
-       struct bt_field *e_int_copy = NULL;
-       struct bt_field *e_copy = NULL;
-       struct bt_field *v_copy = NULL;
-       struct bt_field *v_selected_copy = NULL;
-       struct bt_field *v_selected_copy_len = NULL;
-       struct bt_field *v_selected_0_copy = NULL;
-       struct bt_field *v_selected_1_copy = NULL;
-       struct bt_field *v_selected_2_copy = NULL;
-       struct bt_field *v_selected_3_copy = NULL;
-       struct bt_field *v_selected_4_copy = NULL;
-       struct bt_field *v_selected_5_copy = NULL;
-       struct bt_field *v_selected_6_copy = NULL;
-       struct bt_field *a_copy = NULL;
-       struct bt_field *a_0_copy = NULL;
-       struct bt_field *a_1_copy = NULL;
-       struct bt_field *a_2_copy = NULL;
-       struct bt_field *a_3_copy = NULL;
-       struct bt_field *a_4_copy = NULL;
-       struct bt_field *strct_copy = NULL;
-       struct bt_field_type_enumeration_mapping_iterator *e_iter = NULL;
-       uint64_t uint64_t_val;
-       const char *str_val;
-       double double_val;
-       int ret;
-
-       /* create len type */
-       len_type = bt_field_type_integer_create(32);
-       assert(len_type);
-
-       /* create fp type */
-       fp_type = bt_field_type_floating_point_create();
-       assert(fp_type);
-
-       /* create s type */
-       s_type = bt_field_type_string_create();
-       assert(s_type);
-
-       /* create e_int type */
-       e_int_type = bt_field_type_integer_create(8);
-       assert(e_int_type);
-
-       /* create e type */
-       e_type = bt_field_type_enumeration_create(e_int_type);
-       assert(e_type);
-       ret = bt_ctf_field_type_enumeration_add_mapping(e_type, "LABEL1",
-               10, 15);
-       assert(!ret);
-       ret = bt_ctf_field_type_enumeration_add_mapping(e_type, "LABEL2",
-               23, 23);
-       assert(!ret);
-
-       /* create v_label1 type */
-       v_label1_type = bt_field_type_string_create();
-       assert(v_label1_type);
-
-       /* create v_label1_array type */
-       v_label1_array_type = bt_field_type_array_create(v_label1_type, 5);
-       assert(v_label1_array_type);
-
-       /* create v_label2 type */
-       v_label2_type = bt_field_type_integer_create(16);
-       assert(v_label2_type);
-
-       /* create v_label2_seq type */
-       v_label2_seq_type = bt_field_type_sequence_create(v_label2_type,
-               "len");
-       assert(v_label2_seq_type);
-
-       /* create v type */
-       v_type = bt_field_type_variant_create(e_type, "e");
-       assert(v_type);
-       ret = bt_field_type_variant_add_field(v_type, v_label1_array_type,
-               "LABEL1");
-       assert(!ret);
-       ret = bt_field_type_variant_add_field(v_type, v_label2_seq_type,
-               "LABEL2");
-       assert(!ret);
-
-       /* create strct type */
-       strct_type = bt_field_type_structure_create();
-       assert(strct_type);
-       ret = bt_field_type_structure_add_field(strct_type, len_type,
-               "len");
-       assert(!ret);
-       ret = bt_field_type_structure_add_field(strct_type, fp_type, "fp");
-       assert(!ret);
-       ret = bt_field_type_structure_add_field(strct_type, s_type, "s");
-       assert(!ret);
-       ret = bt_field_type_structure_add_field(strct_type, e_type, "e");
-       assert(!ret);
-       ret = bt_field_type_structure_add_field(strct_type, v_type, "v");
-       assert(!ret);
-       ret = bt_field_type_structure_add_field(strct_type,
-               v_label1_array_type, "a");
-       assert(!ret);
-
-       /* create strct */
-       strct = bt_field_create(strct_type);
-       assert(strct);
-
-       /* get len field */
-       len = bt_field_structure_get_field_by_name(strct, "len");
-       assert(len);
-
-       /* get fp field */
-       fp = bt_field_structure_get_field_by_name(strct, "fp");
-       assert(fp);
-
-       /* get s field */
-       s = bt_field_structure_get_field_by_name(strct, "s");
-       assert(s);
-
-       /* get e field */
-       e = bt_field_structure_get_field_by_name(strct, "e");
-       assert(e);
-
-       /* get e_int (underlying integer) */
-       e_int = bt_field_enumeration_get_container(e);
-       assert(e_int);
-
-       /* get v field */
-       v = bt_field_structure_get_field_by_name(strct, "v");
-       assert(v);
-
-       /* get a field */
-       a = bt_field_structure_get_field_by_name(strct, "a");
-       assert(a);
-
-       /* set len field */
-       ret = bt_field_unsigned_integer_set_value(len, 7);
-       assert(!ret);
-
-       /* set fp field */
-       ret = bt_field_floating_point_set_value(fp, 3.14);
-       assert(!ret);
-
-       /* set s field */
-       ret = bt_field_string_set_value(s, "btbt");
-       assert(!ret);
-
-       /* set e field (LABEL2) */
-       ret = bt_field_unsigned_integer_set_value(e_int, 23);
-       assert(!ret);
-
-       /* set v field */
-       v_selected = bt_field_variant_get_field(v, e);
-       assert(v_selected);
-       v_selected_cur = bt_field_variant_get_current_field(v);
-       ok(v_selected_cur == v_selected,
-               "bt_field_variant_get_current_field returns the current field");
-       bt_put(v_selected_cur);
-
-       /* set selected v field */
-       ret = bt_field_sequence_set_length(v_selected, len);
-       assert(!ret);
-       v_selected_0 = bt_field_sequence_get_field(v_selected, 0);
-       assert(v_selected_0);
-       ret = bt_field_unsigned_integer_set_value(v_selected_0, 7);
-       assert(!ret);
-       v_selected_1 = bt_field_sequence_get_field(v_selected, 1);
-       assert(v_selected_1);
-       ret = bt_field_unsigned_integer_set_value(v_selected_1, 6);
-       assert(!ret);
-       v_selected_2 = bt_field_sequence_get_field(v_selected, 2);
-       assert(v_selected_2);
-       ret = bt_field_unsigned_integer_set_value(v_selected_2, 5);
-       assert(!ret);
-       v_selected_3 = bt_field_sequence_get_field(v_selected, 3);
-       assert(v_selected_3);
-       ret = bt_field_unsigned_integer_set_value(v_selected_3, 4);
-       assert(!ret);
-       v_selected_4 = bt_field_sequence_get_field(v_selected, 4);
-       assert(v_selected_4);
-       ret = bt_field_unsigned_integer_set_value(v_selected_4, 3);
-       assert(!ret);
-       v_selected_5 = bt_field_sequence_get_field(v_selected, 5);
-       assert(v_selected_5);
-       ret = bt_field_unsigned_integer_set_value(v_selected_5, 2);
-       assert(!ret);
-       v_selected_6 = bt_field_sequence_get_field(v_selected, 6);
-       assert(v_selected_6);
-       ret = bt_field_unsigned_integer_set_value(v_selected_6, 1);
-       assert(!ret);
-
-       /* set a field */
-       a_0 = bt_field_array_get_field(a, 0);
-       assert(a_0);
-       ret = bt_field_string_set_value(a_0, "a_0");
-       assert(!ret);
-       a_1 = bt_field_array_get_field(a, 1);
-       assert(a_1);
-       ret = bt_field_string_set_value(a_1, "a_1");
-       assert(!ret);
-       a_2 = bt_field_array_get_field(a, 2);
-       assert(a_2);
-       ret = bt_field_string_set_value(a_2, "a_2");
-       assert(!ret);
-       a_3 = bt_field_array_get_field(a, 3);
-       assert(a_3);
-       ret = bt_field_string_set_value(a_3, "a_3");
-       assert(!ret);
-       a_4 = bt_field_array_get_field(a, 4);
-       assert(a_4);
-       ret = bt_field_string_set_value(a_4, "a_4");
-       assert(!ret);
-
-       /* create copy of strct */
-       strct_copy = bt_field_copy(strct);
-       ok(strct_copy,
-               "bt_field_copy returns a valid pointer");
-
-       /* get all copied fields */
-       len_copy = bt_field_structure_get_field_by_name(strct_copy, "len");
-       assert(len_copy);
-       fp_copy = bt_field_structure_get_field_by_name(strct_copy, "fp");
-       assert(fp_copy);
-       s_copy = bt_field_structure_get_field_by_name(strct_copy, "s");
-       assert(s_copy);
-       e_copy = bt_field_structure_get_field_by_name(strct_copy, "e");
-       assert(e_copy);
-       e_int_copy = bt_field_enumeration_get_container(e_copy);
-       assert(e_int_copy);
-       v_copy = bt_field_structure_get_field_by_name(strct_copy, "v");
-       assert(v_copy);
-       v_selected_copy = bt_field_variant_get_field(v_copy, e_copy);
-       assert(v_selected_copy);
-       v_selected_0_copy = bt_field_sequence_get_field(v_selected_copy, 0);
-       assert(v_selected_0_copy);
-       v_selected_1_copy = bt_field_sequence_get_field(v_selected_copy, 1);
-       assert(v_selected_1_copy);
-       v_selected_2_copy = bt_field_sequence_get_field(v_selected_copy, 2);
-       assert(v_selected_2_copy);
-       v_selected_3_copy = bt_field_sequence_get_field(v_selected_copy, 3);
-       assert(v_selected_3_copy);
-       v_selected_4_copy = bt_field_sequence_get_field(v_selected_copy, 4);
-       assert(v_selected_4_copy);
-       v_selected_5_copy = bt_field_sequence_get_field(v_selected_copy, 5);
-       assert(v_selected_5_copy);
-       v_selected_6_copy = bt_field_sequence_get_field(v_selected_copy, 6);
-       assert(v_selected_6_copy);
-       a_copy = bt_field_structure_get_field_by_name(strct_copy, "a");
-       assert(a_copy);
-       a_0_copy = bt_field_array_get_field(a_copy, 0);
-       assert(a_0_copy);
-       a_1_copy = bt_field_array_get_field(a_copy, 1);
-       assert(a_1_copy);
-       a_2_copy = bt_field_array_get_field(a_copy, 2);
-       assert(a_2_copy);
-       a_3_copy = bt_field_array_get_field(a_copy, 3);
-       assert(a_3_copy);
-       a_4_copy = bt_field_array_get_field(a_copy, 4);
-       assert(a_4_copy);
-
-       /* make sure copied fields are different pointers */
-       field_copy_tests_validate_diff_ptrs(strct_copy, strct, "strct");
-       field_copy_tests_validate_diff_ptrs(len_copy, len, "len");
-       field_copy_tests_validate_diff_ptrs(fp_copy, fp, "fp");
-       field_copy_tests_validate_diff_ptrs(s_copy, s, "s");
-       field_copy_tests_validate_diff_ptrs(e_int_copy, e_int, "e_int");
-       field_copy_tests_validate_diff_ptrs(e_copy, e, "e");
-       field_copy_tests_validate_diff_ptrs(v_copy, v, "v");
-       field_copy_tests_validate_diff_ptrs(v_selected_copy, v_selected,
-               "v_selected");
-       field_copy_tests_validate_diff_ptrs(v_selected_0_copy, v_selected_0,
-               "v_selected_0");
-       field_copy_tests_validate_diff_ptrs(v_selected_1_copy, v_selected_1,
-               "v_selected_1");
-       field_copy_tests_validate_diff_ptrs(v_selected_2_copy, v_selected_2,
-               "v_selected_2");
-       field_copy_tests_validate_diff_ptrs(v_selected_3_copy, v_selected_3,
-               "v_selected_3");
-       field_copy_tests_validate_diff_ptrs(v_selected_4_copy, v_selected_4,
-               "v_selected_4");
-       field_copy_tests_validate_diff_ptrs(v_selected_5_copy, v_selected_5,
-               "v_selected_5");
-       field_copy_tests_validate_diff_ptrs(v_selected_6_copy, v_selected_6,
-               "v_selected_6");
-       field_copy_tests_validate_diff_ptrs(a_copy, a, "a");
-       field_copy_tests_validate_diff_ptrs(a_0_copy, a_0, "a_0");
-       field_copy_tests_validate_diff_ptrs(a_1_copy, a_1, "a_1");
-       field_copy_tests_validate_diff_ptrs(a_2_copy, a_2, "a_2");
-       field_copy_tests_validate_diff_ptrs(a_3_copy, a_3, "a_3");
-       field_copy_tests_validate_diff_ptrs(a_4_copy, a_4, "a_4");
-
-       /* make sure copied fields share the same types */
-       field_copy_tests_validate_same_type(strct_copy, strct_type, "strct");
-       field_copy_tests_validate_same_type(len_copy, len_type, "len");
-       field_copy_tests_validate_same_type(fp_copy, fp_type, "fp");
-       field_copy_tests_validate_same_type(e_int_copy, e_int_type, "e_int");
-       field_copy_tests_validate_same_type(e_copy, e_type, "e");
-       field_copy_tests_validate_same_type(v_copy, v_type, "v");
-       field_copy_tests_validate_same_type(v_selected_copy, v_label2_seq_type,
-               "v_selected");
-       field_copy_tests_validate_same_type(v_selected_0_copy, v_label2_type,
-               "v_selected_0");
-       field_copy_tests_validate_same_type(v_selected_1_copy, v_label2_type,
-               "v_selected_1");
-       field_copy_tests_validate_same_type(v_selected_2_copy, v_label2_type,
-               "v_selected_2");
-       field_copy_tests_validate_same_type(v_selected_3_copy, v_label2_type,
-               "v_selected_3");
-       field_copy_tests_validate_same_type(v_selected_4_copy, v_label2_type,
-               "v_selected_4");
-       field_copy_tests_validate_same_type(v_selected_5_copy, v_label2_type,
-               "v_selected_5");
-       field_copy_tests_validate_same_type(v_selected_6_copy, v_label2_type,
-               "v_selected_6");
-       field_copy_tests_validate_same_type(a_copy, v_label1_array_type, "a");
-       field_copy_tests_validate_same_type(a_0_copy, v_label1_type, "a_0");
-       field_copy_tests_validate_same_type(a_1_copy, v_label1_type, "a_1");
-       field_copy_tests_validate_same_type(a_2_copy, v_label1_type, "a_2");
-       field_copy_tests_validate_same_type(a_3_copy, v_label1_type, "a_3");
-       field_copy_tests_validate_same_type(a_4_copy, v_label1_type, "a_4");
-
-       /* validate len copy */
-       ret = bt_field_unsigned_integer_get_value(len_copy, &uint64_t_val);
-       assert(!ret);
-       ok(uint64_t_val == 7,
-               "bt_field_copy creates a valid integer field copy");
-
-       /* validate fp copy */
-       ret = bt_field_floating_point_get_value(fp_copy, &double_val);
-       assert(!ret);
-       ok(double_val == 3.14,
-               "bt_field_copy creates a valid floating point number field copy");
-
-       /* validate s copy */
-       str_val = bt_field_string_get_value(s_copy);
-       ok(str_val && !strcmp(str_val, "btbt"),
-               "bt_field_copy creates a valid string field copy");
-
-       /* validate e_int copy */
-       ret = bt_field_unsigned_integer_get_value(e_int_copy,
-               &uint64_t_val);
-       assert(!ret);
-       ok(uint64_t_val == 23,
-               "bt_field_copy creates a valid enum's integer field copy");
-
-       /* validate e copy */
-       e_iter = bt_field_enumeration_get_mappings(e_copy);
-       (void) bt_field_type_enumeration_mapping_iterator_next(e_iter);
-       (void) bt_field_type_enumeration_mapping_iterator_get_signed(e_iter,
-               &str_val, NULL, NULL);
-       ok(str_val && !strcmp(str_val, "LABEL2"),
-               "bt_field_copy creates a valid enum field copy");
-
-       /* validate v_selected copy */
-       v_selected_copy_len = bt_field_sequence_get_length(v_selected);
-       assert(v_selected_copy_len);
-       ret = bt_field_unsigned_integer_get_value(v_selected_copy_len,
-               &uint64_t_val);
-       assert(!ret);
-       ok(uint64_t_val == 7,
-               "bt_field_copy creates a sequence field copy with the proper length");
-       bt_put(v_selected_copy_len);
-       v_selected_copy_len = NULL;
-
-       /* validate v_selected copy fields */
-       ret = bt_field_unsigned_integer_get_value(v_selected_0_copy,
-               &uint64_t_val);
-       assert(!ret);
-       ok(uint64_t_val == 7,
-               "bt_field_copy creates a valid sequence field element copy (v_selected_0)");
-       ret = bt_field_unsigned_integer_get_value(v_selected_1_copy,
-               &uint64_t_val);
-       assert(!ret);
-       ok(uint64_t_val == 6,
-               "bt_field_copy creates a valid sequence field element copy (v_selected_1)");
-       ret = bt_field_unsigned_integer_get_value(v_selected_2_copy,
-               &uint64_t_val);
-       assert(!ret);
-       ok(uint64_t_val == 5,
-               "bt_field_copy creates a valid sequence field element copy (v_selected_2)");
-       ret = bt_field_unsigned_integer_get_value(v_selected_3_copy,
-               &uint64_t_val);
-       assert(!ret);
-       ok(uint64_t_val == 4,
-               "bt_field_copy creates a valid sequence field element copy (v_selected_3)");
-       ret = bt_field_unsigned_integer_get_value(v_selected_4_copy,
-               &uint64_t_val);
-       assert(!ret);
-       ok(uint64_t_val == 3,
-               "bt_field_copy creates a valid sequence field element copy (v_selected_4)");
-       ret = bt_field_unsigned_integer_get_value(v_selected_5_copy,
-               &uint64_t_val);
-       assert(!ret);
-       ok(uint64_t_val == 2,
-               "bt_field_copy creates a valid sequence field element copy (v_selected_5)");
-       ret = bt_field_unsigned_integer_get_value(v_selected_6_copy,
-               &uint64_t_val);
-       assert(!ret);
-       ok(uint64_t_val == 1,
-               "bt_field_copy creates a valid sequence field element copy (v_selected_6)");
-
-       /* validate a copy fields */
-       str_val = bt_field_string_get_value(a_0_copy);
-       ok(str_val && !strcmp(str_val, "a_0"),
-               "bt_field_copy creates a valid array field element copy (a_0)");
-       str_val = bt_field_string_get_value(a_1_copy);
-       ok(str_val && !strcmp(str_val, "a_1"),
-               "bt_field_copy creates a valid array field element copy (a_1)");
-       str_val = bt_field_string_get_value(a_2_copy);
-       ok(str_val && !strcmp(str_val, "a_2"),
-               "bt_field_copy creates a valid array field element copy (a_2)");
-       str_val = bt_field_string_get_value(a_3_copy);
-       ok(str_val && !strcmp(str_val, "a_3"),
-               "bt_field_copy creates a valid array field element copy (a_3)");
-       str_val = bt_field_string_get_value(a_4_copy);
-       ok(str_val && !strcmp(str_val, "a_4"),
-               "bt_field_copy creates a valid array field element copy (a_4)");
-
-       /* put everything */
-       bt_put(len_type);
-       bt_put(fp_type);
-       bt_put(s_type);
-       bt_put(e_int_type);
-       bt_put(e_type);
-       bt_put(v_type);
-       bt_put(v_label1_type);
-       bt_put(v_label1_array_type);
-       bt_put(v_label2_type);
-       bt_put(v_label2_seq_type);
-       bt_put(strct_type);
-       bt_put(len);
-       bt_put(fp);
-       bt_put(s);
-       bt_put(e_int);
-       bt_put(e);
-       bt_put(v);
-       bt_put(v_selected);
-       bt_put(v_selected_0);
-       bt_put(v_selected_1);
-       bt_put(v_selected_2);
-       bt_put(v_selected_3);
-       bt_put(v_selected_4);
-       bt_put(v_selected_5);
-       bt_put(v_selected_6);
-       bt_put(a);
-       bt_put(a_0);
-       bt_put(a_1);
-       bt_put(a_2);
-       bt_put(a_3);
-       bt_put(a_4);
-       bt_put(strct);
-       bt_put(len_copy);
-       bt_put(fp_copy);
-       bt_put(s_copy);
-       bt_put(e_int_copy);
-       bt_put(e_copy);
-       bt_put(v_copy);
-       bt_put(v_selected_copy);
-       bt_put(v_selected_0_copy);
-       bt_put(v_selected_1_copy);
-       bt_put(v_selected_2_copy);
-       bt_put(v_selected_3_copy);
-       bt_put(v_selected_4_copy);
-       bt_put(v_selected_5_copy);
-       bt_put(v_selected_6_copy);
-       bt_put(a_copy);
-       bt_put(a_0_copy);
-       bt_put(a_1_copy);
-       bt_put(a_2_copy);
-       bt_put(a_3_copy);
-       bt_put(a_4_copy);
-       bt_put(strct_copy);
-       bt_put(e_iter);
-}
-
 static
 void type_field_tests()
 {
-       struct bt_field *uint_12;
-       struct bt_field *int_16;
-       struct bt_field *string;
-       struct bt_field_type *composite_structure_type;
-       struct bt_field_type *structure_seq_type;
-       struct bt_field_type *string_type;
-       struct bt_field_type *sequence_type;
-       struct bt_field_type *uint_8_type;
-       struct bt_field_type *int_16_type;
-       struct bt_field_type *uint_12_type =
-               bt_field_type_integer_create(12);
-       struct bt_field_type *enumeration_type;
-       struct bt_field_type *returned_type;
+       struct bt_ctf_field *uint_12;
+       struct bt_ctf_field *int_16;
+       struct bt_ctf_field *string;
+       struct bt_ctf_field_type *composite_structure_type;
+       struct bt_ctf_field_type *structure_seq_type;
+       struct bt_ctf_field_type *string_type;
+       struct bt_ctf_field_type *sequence_type;
+       struct bt_ctf_field_type *uint_8_type;
+       struct bt_ctf_field_type *int_16_type;
+       struct bt_ctf_field_type *uint_12_type =
+               bt_ctf_field_type_integer_create(12);
+       struct bt_ctf_field_type *enumeration_type;
+       struct bt_ctf_field_type *returned_type;
        const char *ret_string;
 
        ok(uint_12_type, "Create an unsigned integer type");
-       ok(bt_field_type_integer_set_base(uint_12_type,
-               BT_INTEGER_BASE_BINARY) == 0,
+       ok(bt_ctf_field_type_integer_set_base(uint_12_type,
+               BT_CTF_INTEGER_BASE_BINARY) == 0,
                "Set integer type's base as binary");
-       ok(bt_field_type_integer_set_base(uint_12_type,
-               BT_INTEGER_BASE_DECIMAL) == 0,
+       ok(bt_ctf_field_type_integer_set_base(uint_12_type,
+               BT_CTF_INTEGER_BASE_DECIMAL) == 0,
                "Set integer type's base as decimal");
-       ok(bt_field_type_integer_set_base(uint_12_type,
-               BT_INTEGER_BASE_UNKNOWN),
+       ok(bt_ctf_field_type_integer_set_base(uint_12_type,
+               BT_CTF_INTEGER_BASE_UNKNOWN),
                "Reject integer type's base set as unknown");
-       ok(bt_field_type_integer_set_base(uint_12_type,
-               BT_INTEGER_BASE_OCTAL) == 0,
+       ok(bt_ctf_field_type_integer_set_base(uint_12_type,
+               BT_CTF_INTEGER_BASE_OCTAL) == 0,
                "Set integer type's base as octal");
-       ok(bt_field_type_integer_set_base(uint_12_type,
-               BT_INTEGER_BASE_HEXADECIMAL) == 0,
+       ok(bt_ctf_field_type_integer_set_base(uint_12_type,
+               BT_CTF_INTEGER_BASE_HEXADECIMAL) == 0,
                "Set integer type's base as hexadecimal");
-       ok(bt_field_type_integer_set_base(uint_12_type, 457417),
+       ok(bt_ctf_field_type_integer_set_base(uint_12_type, 457417),
                "Reject unknown integer base value");
        ok(bt_ctf_field_type_integer_set_signed(uint_12_type, 952835) == 0,
                "Set integer type signedness to signed");
        ok(bt_ctf_field_type_integer_set_signed(uint_12_type, 0) == 0,
                "Set integer type signedness to unsigned");
-       ok(bt_field_type_integer_get_size(uint_12_type) == 12,
-               "bt_field_type_integer_get_size returns a correct value");
+       ok(bt_ctf_field_type_integer_get_size(uint_12_type) == 12,
+               "bt_ctf_field_type_integer_get_size returns a correct value");
        ok(bt_ctf_field_type_integer_get_signed(uint_12_type) == 0,
-               "bt_field_type_integer_get_signed returns a correct value for unsigned types");
-
-       ok(bt_field_type_set_byte_order(NULL,
-               BT_BYTE_ORDER_LITTLE_ENDIAN) < 0,
-               "bt_field_type_set_byte_order handles NULL correctly");
-       ok(bt_field_type_set_byte_order(uint_12_type,
-               (enum bt_byte_order) 42) < 0,
-               "bt_field_type_set_byte_order rejects invalid values");
-       ok(bt_field_type_set_byte_order(uint_12_type,
-               BT_BYTE_ORDER_LITTLE_ENDIAN) == 0,
+               "bt_ctf_field_type_integer_get_signed returns a correct value for unsigned types");
+
+       ok(bt_ctf_field_type_set_byte_order(NULL,
+               BT_CTF_BYTE_ORDER_LITTLE_ENDIAN) < 0,
+               "bt_ctf_field_type_set_byte_order handles NULL correctly");
+       ok(bt_ctf_field_type_set_byte_order(uint_12_type,
+               (enum bt_ctf_byte_order) 42) < 0,
+               "bt_ctf_field_type_set_byte_order rejects invalid values");
+       ok(bt_ctf_field_type_set_byte_order(uint_12_type,
+               BT_CTF_BYTE_ORDER_LITTLE_ENDIAN) == 0,
                "Set an integer's byte order to little endian");
-       ok(bt_field_type_set_byte_order(uint_12_type,
-               BT_BYTE_ORDER_BIG_ENDIAN) == 0,
+       ok(bt_ctf_field_type_set_byte_order(uint_12_type,
+               BT_CTF_BYTE_ORDER_BIG_ENDIAN) == 0,
                "Set an integer's byte order to big endian");
-       ok(bt_field_type_get_byte_order(uint_12_type) ==
-               BT_BYTE_ORDER_BIG_ENDIAN,
-               "bt_field_type_get_byte_order returns a correct value");
-
-       ok(bt_field_type_get_type_id(uint_12_type) ==
-               BT_FIELD_TYPE_ID_INTEGER,
-               "bt_field_type_get_type_id returns a correct value with an integer type");
-
-       ok(bt_field_type_integer_get_base(uint_12_type) ==
-               BT_INTEGER_BASE_HEXADECIMAL,
-               "bt_field_type_integer_get_base returns a correct value");
-
-       ok(bt_field_type_integer_set_encoding(NULL,
-               BT_STRING_ENCODING_ASCII) < 0,
-               "bt_field_type_integer_set_encoding handles NULL correctly");
-       ok(bt_field_type_integer_set_encoding(uint_12_type,
-               (enum bt_string_encoding) 123) < 0,
-               "bt_field_type_integer_set_encoding handles invalid encodings correctly");
-       ok(bt_field_type_integer_set_encoding(uint_12_type,
-               BT_STRING_ENCODING_UTF8) == 0,
+       ok(bt_ctf_field_type_get_byte_order(uint_12_type) ==
+               BT_CTF_BYTE_ORDER_BIG_ENDIAN,
+               "bt_ctf_field_type_get_byte_order returns a correct value");
+
+       ok(bt_ctf_field_type_get_type_id(uint_12_type) ==
+               BT_CTF_FIELD_TYPE_ID_INTEGER,
+               "bt_ctf_field_type_get_type_id returns a correct value with an integer type");
+
+       ok(bt_ctf_field_type_integer_get_base(uint_12_type) ==
+               BT_CTF_INTEGER_BASE_HEXADECIMAL,
+               "bt_ctf_field_type_integer_get_base returns a correct value");
+
+       ok(bt_ctf_field_type_integer_set_encoding(NULL,
+               BT_CTF_STRING_ENCODING_ASCII) < 0,
+               "bt_ctf_field_type_integer_set_encoding handles NULL correctly");
+       ok(bt_ctf_field_type_integer_set_encoding(uint_12_type,
+               (enum bt_ctf_string_encoding) 123) < 0,
+               "bt_ctf_field_type_integer_set_encoding handles invalid encodings correctly");
+       ok(bt_ctf_field_type_integer_set_encoding(uint_12_type,
+               BT_CTF_STRING_ENCODING_UTF8) == 0,
                "Set integer type encoding to UTF8");
-       ok(bt_field_type_integer_get_encoding(uint_12_type) ==
-               BT_STRING_ENCODING_UTF8,
-               "bt_field_type_integer_get_encoding returns a correct value");
+       ok(bt_ctf_field_type_integer_get_encoding(uint_12_type) ==
+               BT_CTF_STRING_ENCODING_UTF8,
+               "bt_ctf_field_type_integer_get_encoding returns a correct value");
 
-       int_16_type = bt_field_type_integer_create(16);
+       int_16_type = bt_ctf_field_type_integer_create(16);
        assert(int_16_type);
        ok(!bt_ctf_field_type_integer_set_signed(int_16_type, 1),
                "Set signedness of 16 bit integer to true");
        ok(bt_ctf_field_type_integer_get_signed(int_16_type) == 1,
-               "bt_field_type_integer_get_signed returns a correct value for signed types");
-       uint_8_type = bt_field_type_integer_create(8);
+               "bt_ctf_field_type_integer_get_signed returns a correct value for signed types");
+       uint_8_type = bt_ctf_field_type_integer_create(8);
        sequence_type =
-               bt_field_type_sequence_create(int_16_type, "seq_len");
+               bt_ctf_field_type_sequence_create(int_16_type, "seq_len");
        ok(sequence_type, "Create a sequence of int16_t type");
-       ok(bt_field_type_get_type_id(sequence_type) ==
-               BT_FIELD_TYPE_ID_SEQUENCE,
-               "bt_field_type_get_type_id returns a correct value with a sequence type");
+       ok(bt_ctf_field_type_get_type_id(sequence_type) ==
+               BT_CTF_FIELD_TYPE_ID_SEQUENCE,
+               "bt_ctf_field_type_get_type_id returns a correct value with a sequence type");
 
-       ret_string = bt_field_type_sequence_get_length_field_name(
+       ret_string = bt_ctf_field_type_sequence_get_length_field_name(
                sequence_type);
        ok(!strcmp(ret_string, "seq_len"),
-               "bt_field_type_sequence_get_length_field_name returns the correct value");
-       returned_type = bt_field_type_sequence_get_element_type(
+               "bt_ctf_field_type_sequence_get_length_field_name returns the correct value");
+       returned_type = bt_ctf_field_type_sequence_get_element_field_type(
                sequence_type);
        ok(returned_type == int_16_type,
-               "bt_field_type_sequence_get_element_type returns the correct type");
+               "bt_ctf_field_type_sequence_get_element_field_type returns the correct type");
        bt_put(returned_type);
 
-       string_type = bt_field_type_string_create();
+       string_type = bt_ctf_field_type_string_create();
        ok(string_type, "Create a string type");
-       ok(bt_field_type_string_set_encoding(string_type,
-               BT_STRING_ENCODING_NONE),
+       ok(bt_ctf_field_type_string_set_encoding(string_type,
+               BT_CTF_STRING_ENCODING_NONE),
                "Reject invalid \"None\" string encoding");
-       ok(bt_field_type_string_set_encoding(string_type,
+       ok(bt_ctf_field_type_string_set_encoding(string_type,
                42),
                "Reject invalid string encoding");
-       ok(bt_field_type_string_set_encoding(string_type,
-               BT_STRING_ENCODING_ASCII) == 0,
+       ok(bt_ctf_field_type_string_set_encoding(string_type,
+               BT_CTF_STRING_ENCODING_ASCII) == 0,
                "Set string encoding to ASCII");
 
-       ok(bt_field_type_string_get_encoding(string_type) ==
-               BT_STRING_ENCODING_ASCII,
-               "bt_field_type_string_get_encoding returns the correct value");
+       ok(bt_ctf_field_type_string_get_encoding(string_type) ==
+               BT_CTF_STRING_ENCODING_ASCII,
+               "bt_ctf_field_type_string_get_encoding returns the correct value");
 
-       structure_seq_type = bt_field_type_structure_create();
-       ok(bt_field_type_get_type_id(structure_seq_type) ==
-               BT_FIELD_TYPE_ID_STRUCT,
-               "bt_field_type_get_type_id returns a correct value with a structure type");
+       structure_seq_type = bt_ctf_field_type_structure_create();
+       ok(bt_ctf_field_type_get_type_id(structure_seq_type) ==
+               BT_CTF_FIELD_TYPE_ID_STRUCT,
+               "bt_ctf_field_type_get_type_id returns a correct value with a structure type");
        ok(structure_seq_type, "Create a structure type");
-       ok(bt_field_type_structure_add_field(structure_seq_type,
+       ok(bt_ctf_field_type_structure_add_field(structure_seq_type,
                uint_8_type, "seq_len") == 0,
                "Add a uint8_t type to a structure");
-       ok(bt_field_type_structure_add_field(structure_seq_type,
+       ok(bt_ctf_field_type_structure_add_field(structure_seq_type,
                sequence_type, "a_sequence") == 0,
                "Add a sequence type to a structure");
 
-       ok(bt_field_type_structure_get_field_count(structure_seq_type) == 2,
-               "bt_field_type_structure_get_field_count returns a correct value");
+       ok(bt_ctf_field_type_structure_get_field_count(structure_seq_type) == 2,
+               "bt_ctf_field_type_structure_get_field_count returns a correct value");
 
        ok(bt_ctf_field_type_structure_get_field(structure_seq_type,
                NULL, &returned_type, 1) == 0,
-               "bt_field_type_structure_get_field handles a NULL name correctly");
+               "bt_ctf_field_type_structure_get_field handles a NULL name correctly");
        bt_put(returned_type);
        ok(bt_ctf_field_type_structure_get_field(structure_seq_type,
                &ret_string, NULL, 1) == 0,
-               "bt_field_type_structure_get_field handles a NULL return type correctly");
+               "bt_ctf_field_type_structure_get_field handles a NULL return type correctly");
        ok(bt_ctf_field_type_structure_get_field(structure_seq_type,
                &ret_string, &returned_type, 1) == 0,
-               "bt_field_type_structure_get_field returns a field");
+               "bt_ctf_field_type_structure_get_field returns a field");
        ok(!strcmp(ret_string, "a_sequence"),
-               "bt_field_type_structure_get_field returns a correct field name");
+               "bt_ctf_field_type_structure_get_field returns a correct field name");
        ok(returned_type == sequence_type,
-               "bt_field_type_structure_get_field returns a correct field type");
+               "bt_ctf_field_type_structure_get_field returns a correct field type");
        bt_put(returned_type);
 
-       returned_type = bt_field_type_structure_get_field_type_by_name(
+       returned_type = bt_ctf_field_type_structure_get_field_type_by_name(
                structure_seq_type, "a_sequence");
        ok(returned_type == sequence_type,
-               "bt_field_type_structure_get_field_type_by_name returns the correct field type");
+               "bt_ctf_field_type_structure_get_field_type_by_name returns the correct field type");
        bt_put(returned_type);
 
-       composite_structure_type = bt_field_type_structure_create();
-       ok(bt_field_type_structure_add_field(composite_structure_type,
+       composite_structure_type = bt_ctf_field_type_structure_create();
+       ok(bt_ctf_field_type_structure_add_field(composite_structure_type,
                string_type, "a_string") == 0,
                "Add a string type to a structure");
-       ok(bt_field_type_structure_add_field(composite_structure_type,
+       ok(bt_ctf_field_type_structure_add_field(composite_structure_type,
                structure_seq_type, "inner_structure") == 0,
                "Add a structure type to a structure");
 
-       returned_type = bt_field_type_structure_get_field_type_by_name(
+       returned_type = bt_ctf_field_type_structure_get_field_type_by_name(
                structure_seq_type, "a_sequence");
        ok(returned_type == sequence_type,
-               "bt_field_type_structure_get_field_type_by_name returns a correct type");
+               "bt_ctf_field_type_structure_get_field_type_by_name returns a correct type");
        bt_put(returned_type);
 
-       int_16 = bt_field_create(int_16_type);
+       int_16 = bt_ctf_field_create(int_16_type);
        ok(int_16, "Instanciate a signed 16-bit integer");
-       uint_12 = bt_field_create(uint_12_type);
+       uint_12 = bt_ctf_field_create(uint_12_type);
        ok(uint_12, "Instanciate an unsigned 12-bit integer");
-       returned_type = bt_field_get_type(int_16);
+       returned_type = bt_ctf_field_get_type(int_16);
        ok(returned_type == int_16_type,
-               "bt_field_get_type returns the correct type");
+               "bt_ctf_field_get_type returns the correct type");
 
        /* Can't modify types after instanciating them */
-       ok(bt_field_type_integer_set_base(uint_12_type,
-               BT_INTEGER_BASE_DECIMAL),
+       ok(bt_ctf_field_type_integer_set_base(uint_12_type,
+               BT_CTF_INTEGER_BASE_DECIMAL),
                "Check an integer type' base can't be modified after instanciation");
        ok(bt_ctf_field_type_integer_set_signed(uint_12_type, 0),
                "Check an integer type's signedness can't be modified after instanciation");
 
        /* Check overflows are properly tested for */
-       ok(bt_field_signed_integer_set_value(int_16, -32768) == 0,
+       ok(bt_ctf_field_integer_signed_set_value(int_16, -32768) == 0,
                "Check -32768 is allowed for a signed 16-bit integer");
-       ok(bt_field_signed_integer_set_value(int_16, 32767) == 0,
+       ok(bt_ctf_field_integer_signed_set_value(int_16, 32767) == 0,
                "Check 32767 is allowed for a signed 16-bit integer");
-       ok(bt_field_signed_integer_set_value(int_16, -42) == 0,
+       ok(bt_ctf_field_integer_signed_set_value(int_16, -42) == 0,
                "Check -42 is allowed for a signed 16-bit integer");
 
-       ok(bt_field_unsigned_integer_set_value(uint_12, 4095) == 0,
+       ok(bt_ctf_field_integer_unsigned_set_value(uint_12, 4095) == 0,
                "Check 4095 is allowed for an unsigned 12-bit integer");
-       ok(bt_field_unsigned_integer_set_value(uint_12, 0) == 0,
+       ok(bt_ctf_field_integer_unsigned_set_value(uint_12, 0) == 0,
                "Check 0 is allowed for an unsigned 12-bit integer");
 
-       string = bt_field_create(string_type);
+       string = bt_ctf_field_create(string_type);
        ok(string, "Instanciate a string field");
-       ok(bt_field_string_set_value(string, "A value") == 0,
+       ok(bt_ctf_field_string_set_value(string, "A value") == 0,
                "Set a string's value");
 
-       enumeration_type = bt_field_type_enumeration_create(uint_12_type);
+       enumeration_type = bt_ctf_field_type_enumeration_create(uint_12_type);
        ok(enumeration_type,
                "Create an enumeration type with an unsigned 12-bit integer as container");
 
@@ -1660,8 +1063,8 @@ void type_field_tests()
 }
 
 static
-void packet_resize_test(struct bt_stream_class *stream_class,
-               struct bt_stream *stream, struct bt_ctf_clock *clock)
+void packet_resize_test(struct bt_ctf_stream_class *stream_class,
+               struct bt_ctf_stream *stream, struct bt_ctf_clock *clock)
 {
        /*
         * Append enough events to force the underlying packet to be resized.
@@ -1670,84 +1073,82 @@ void packet_resize_test(struct bt_stream_class *stream_class,
         */
        int ret = 0;
        int i;
-       struct bt_event_class *event_class = bt_event_class_create(
+       struct bt_ctf_event_class *event_class = bt_ctf_event_class_create(
                "Spammy_Event");
-       struct bt_field_type *integer_type =
-               bt_field_type_integer_create(17);
-       struct bt_field_type *string_type =
-               bt_field_type_string_create();
-       struct bt_event *event = NULL;
-       struct bt_field *ret_field = NULL;
-       struct bt_field_type *ret_field_type = NULL;
+       struct bt_ctf_field_type *integer_type =
+               bt_ctf_field_type_integer_create(17);
+       struct bt_ctf_field_type *string_type =
+               bt_ctf_field_type_string_create();
+       struct bt_ctf_event *event = NULL;
+       struct bt_ctf_field *ret_field = NULL;
+       struct bt_ctf_field_type *ret_field_type = NULL;
        uint64_t ret_uint64;
        int events_appended = 0;
-       struct bt_field *packet_context = NULL,
+       struct bt_ctf_field *packet_context = NULL,
                *packet_context_field = NULL, *stream_event_context = NULL;
-       struct bt_field_type *ep_field_1_type = NULL;
-       struct bt_field_type *ep_a_string_type = NULL;
-       struct bt_field_type *ep_type = NULL;
+       struct bt_ctf_field_type *ep_field_1_type = NULL;
+       struct bt_ctf_field_type *ep_a_string_type = NULL;
+       struct bt_ctf_field_type *ep_type = NULL;
 
-       ret |= bt_event_class_add_field(event_class, integer_type,
+       ret |= bt_ctf_event_class_add_field(event_class, integer_type,
                "field_1");
-       ret |= bt_event_class_add_field(event_class, string_type,
+       ret |= bt_ctf_event_class_add_field(event_class, string_type,
                "a_string");
-       ret |= bt_stream_class_add_event_class(stream_class, event_class);
+       ret |= bt_ctf_stream_class_add_event_class(stream_class, event_class);
        ok(ret == 0, "Add a new event class to a stream class after writing an event");
        if (ret) {
                goto end;
        }
 
        /*
-        * bt_stream_class_add_event_class() copies the field types
+        * bt_ctf_stream_class_add_event_class() copies the field types
         * of event_class, so we retrieve the new ones to create the
         * appropriate fields.
         */
-       ep_type = bt_event_class_get_payload_type(event_class);
+       ep_type = bt_ctf_event_class_get_payload_field_type(event_class);
        assert(ep_type);
-       ep_field_1_type = bt_field_type_structure_get_field_type_by_name(
+       ep_field_1_type = bt_ctf_field_type_structure_get_field_type_by_name(
                ep_type, "field_1");
        assert(ep_field_1_type);
-       ep_a_string_type = bt_field_type_structure_get_field_type_by_name(
+       ep_a_string_type = bt_ctf_field_type_structure_get_field_type_by_name(
                ep_type, "a_string");
        assert(ep_a_string_type);
 
-       event = bt_event_create(event_class);
-       ret_field = bt_event_get_payload_by_index(event, 0);
-       ret_field_type = bt_field_get_type(ret_field);
-       ok(bt_field_type_compare(ret_field_type, integer_type) == 0,
-               "bt_event_get_payload_by_index returns a correct field");
+       event = bt_ctf_event_create(event_class);
+       ret_field = bt_ctf_event_get_payload(event, 0);
+       ret_field_type = bt_ctf_field_get_type(ret_field);
        bt_put(ret_field_type);
        bt_put(ret_field);
        bt_put(event);
 
        for (i = 0; i < packet_resize_test_length; i++) {
-               event = bt_event_create(event_class);
-               struct bt_field *integer =
-                       bt_field_create(ep_field_1_type);
-               struct bt_field *string =
-                       bt_field_create(ep_a_string_type);
+               event = bt_ctf_event_create(event_class);
+               struct bt_ctf_field *integer =
+                       bt_ctf_field_create(ep_field_1_type);
+               struct bt_ctf_field *string =
+                       bt_ctf_field_create(ep_a_string_type);
 
                ret |= bt_ctf_clock_set_time(clock, ++current_time);
-               ret |= bt_field_unsigned_integer_set_value(integer, i);
-               ret |= bt_event_set_payload(event, "field_1",
+               ret |= bt_ctf_field_integer_unsigned_set_value(integer, i);
+               ret |= bt_ctf_event_set_payload(event, "field_1",
                        integer);
                bt_put(integer);
-               ret |= bt_field_string_set_value(string, "This is a test");
-               ret |= bt_event_set_payload(event, "a_string",
+               ret |= bt_ctf_field_string_set_value(string, "This is a test");
+               ret |= bt_ctf_event_set_payload(event, "a_string",
                        string);
                bt_put(string);
 
                /* Populate stream event context */
                stream_event_context =
-                       bt_event_get_stream_event_context(event);
-               integer = bt_field_structure_get_field_by_name(stream_event_context,
+                       bt_ctf_event_get_stream_event_context(event);
+               integer = bt_ctf_field_structure_get_field_by_name(stream_event_context,
                        "common_event_context");
                BT_PUT(stream_event_context);
-               ret |= bt_field_unsigned_integer_set_value(integer,
+               ret |= bt_ctf_field_integer_unsigned_set_value(integer,
                        i % 42);
                bt_put(integer);
 
-               ret |= bt_stream_append_event(stream, event);
+               ret |= bt_ctf_stream_append_event(stream, event);
                bt_put(event);
 
                if (ret) {
@@ -1756,13 +1157,13 @@ void packet_resize_test(struct bt_stream_class *stream_class,
        }
 
        events_appended = !!(i == packet_resize_test_length);
-       ret = bt_stream_get_discarded_events_count(stream, &ret_uint64);
+       ret = bt_ctf_stream_get_discarded_events_count(stream, &ret_uint64);
        ok(ret == 0 && ret_uint64 == 0,
-               "bt_stream_get_discarded_events_count returns a correct number of discarded events when none were discarded");
-       bt_stream_append_discarded_events(stream, 1000);
-       ret = bt_stream_get_discarded_events_count(stream, &ret_uint64);
+               "bt_ctf_stream_get_discarded_events_count returns a correct number of discarded events when none were discarded");
+       bt_ctf_stream_append_discarded_events(stream, 1000);
+       ret = bt_ctf_stream_get_discarded_events_count(stream, &ret_uint64);
        ok(ret == 0 && ret_uint64 == 1000,
-               "bt_stream_get_discarded_events_count returns a correct number of discarded events when some were discarded");
+               "bt_ctf_stream_get_discarded_events_count returns a correct number of discarded events when some were discarded");
 
 end:
        ok(events_appended, "Append 100 000 events to a stream");
@@ -1771,16 +1172,16 @@ end:
         * Populate the custom packet context field with a dummy value
         * otherwise flush will fail.
         */
-       packet_context = bt_stream_get_packet_context(stream);
-       packet_context_field = bt_field_structure_get_field_by_name(packet_context,
+       packet_context = bt_ctf_stream_get_packet_context(stream);
+       packet_context_field = bt_ctf_field_structure_get_field_by_name(packet_context,
                "custom_packet_context_field");
-       bt_field_unsigned_integer_set_value(packet_context_field, 2);
+       bt_ctf_field_integer_unsigned_set_value(packet_context_field, 2);
 
-       ok(bt_stream_flush(stream) == 0,
+       ok(bt_ctf_stream_flush(stream) == 0,
                "Flush a stream that forces a packet resize");
-       ret = bt_stream_get_discarded_events_count(stream, &ret_uint64);
+       ret = bt_ctf_stream_get_discarded_events_count(stream, &ret_uint64);
        ok(ret == 0 && ret_uint64 == 1000,
-               "bt_stream_get_discarded_events_count returns a correct number of discarded events after a flush");
+               "bt_ctf_stream_get_discarded_events_count returns a correct number of discarded events after a flush");
        bt_put(integer_type);
        bt_put(string_type);
        bt_put(packet_context);
@@ -1796,9 +1197,9 @@ static
 void test_empty_stream(struct bt_ctf_writer *writer)
 {
        int ret = 0;
-       struct bt_trace *trace = NULL, *ret_trace = NULL;
-       struct bt_stream_class *stream_class = NULL;
-       struct bt_stream *stream = NULL;
+       struct bt_ctf_trace *trace = NULL, *ret_trace = NULL;
+       struct bt_ctf_stream_class *stream_class = NULL;
+       struct bt_ctf_stream *stream = NULL;
 
        trace = bt_ctf_writer_get_trace(writer);
        if (!trace) {
@@ -1807,20 +1208,20 @@ void test_empty_stream(struct bt_ctf_writer *writer)
                goto end;
        }
 
-       stream_class = bt_stream_class_create("empty_stream");
+       stream_class = bt_ctf_stream_class_create("empty_stream");
        if (!stream_class) {
                diag("Failed to create stream class");
                ret = -1;
                goto end;
        }
 
-       ret = bt_stream_class_set_packet_context_type(stream_class, NULL);
+       ret = bt_ctf_stream_class_set_packet_context_type(stream_class, NULL);
        assert(ret == 0);
-       ret = bt_stream_class_set_event_header_type(stream_class, NULL);
+       ret = bt_ctf_stream_class_set_event_header_type(stream_class, NULL);
        assert(ret == 0);
 
-       ok(bt_stream_class_get_trace(stream_class) == NULL,
-               "bt_stream_class_get_trace returns NULL when stream class is orphaned");
+       ok(bt_ctf_stream_class_get_trace(stream_class) == NULL,
+               "bt_ctf_stream_class_get_trace returns NULL when stream class is orphaned");
 
        stream = bt_ctf_writer_create_stream(writer, stream_class);
        if (!stream) {
@@ -1829,9 +1230,9 @@ void test_empty_stream(struct bt_ctf_writer *writer)
                goto end;
        }
 
-       ret_trace = bt_stream_class_get_trace(stream_class);
+       ret_trace = bt_ctf_stream_class_get_trace(stream_class);
        ok(ret_trace == trace,
-               "bt_stream_class_get_trace returns the correct trace after a stream has been created");
+               "bt_ctf_stream_class_get_trace returns the correct trace after a stream has been created");
 end:
        ok(ret == 0,
                "Created a stream class with default attributes and an empty stream");
@@ -1846,22 +1247,22 @@ void test_custom_event_header_stream(struct bt_ctf_writer *writer,
                        struct bt_ctf_clock *clock)
 {
        int i, ret;
-       struct bt_stream_class *stream_class = NULL;
-       struct bt_stream *stream = NULL;
-       struct bt_field_type *integer_type = NULL,
+       struct bt_ctf_stream_class *stream_class = NULL;
+       struct bt_ctf_stream *stream = NULL;
+       struct bt_ctf_field_type *integer_type = NULL,
                *sequence_type = NULL, *event_header_type = NULL;
-       struct bt_field *integer = NULL, *sequence = NULL,
+       struct bt_ctf_field *integer = NULL, *sequence = NULL,
                *event_header = NULL, *packet_header = NULL;
-       struct bt_event_class *event_class = NULL;
-       struct bt_event *event = NULL;
+       struct bt_ctf_event_class *event_class = NULL;
+       struct bt_ctf_event *event = NULL;
 
-       stream_class = bt_stream_class_create("custom_event_header_stream");
+       stream_class = bt_ctf_stream_class_create("custom_event_header_stream");
        if (!stream_class) {
                fail("Failed to create stream class");
                goto end;
        }
 
-       ret = bt_stream_class_set_clock(stream_class, clock);
+       ret = bt_ctf_stream_class_set_clock(stream_class, clock);
        if (ret) {
                fail("Failed to set stream class clock");
                goto end;
@@ -1872,27 +1273,27 @@ void test_custom_event_header_stream(struct bt_ctf_writer *writer,
         * which will be used as the length of a sequence in an event of this
         * stream.
         */
-       event_header_type = bt_stream_class_get_event_header_type(
+       event_header_type = bt_ctf_stream_class_get_event_header_type(
                stream_class);
        if (!event_header_type) {
                fail("Failed to get event header type");
                goto end;
        }
 
-       integer_type = bt_field_type_integer_create(13);
+       integer_type = bt_ctf_field_type_integer_create(13);
        if (!integer_type) {
                fail("Failed to create length integer type");
                goto end;
        }
 
-       ret = bt_field_type_structure_add_field(event_header_type,
+       ret = bt_ctf_field_type_structure_add_field(event_header_type,
                integer_type, "seq_len");
        if (ret) {
                fail("Failed to add a new field to stream event header");
                goto end;
        }
 
-       event_class = bt_event_class_create("sequence_event");
+       event_class = bt_ctf_event_class_create("sequence_event");
        if (!event_class) {
                fail("Failed to create event class");
                goto end;
@@ -1902,21 +1303,21 @@ void test_custom_event_header_stream(struct bt_ctf_writer *writer,
         * This event's payload will contain a sequence which references
         * stream.event.header.seq_len as its length field.
         */
-       sequence_type = bt_field_type_sequence_create(integer_type,
+       sequence_type = bt_ctf_field_type_sequence_create(integer_type,
                "stream.event.header.seq_len");
        if (!sequence_type) {
                fail("Failed to create a sequence");
                goto end;
        }
 
-       ret = bt_event_class_add_field(event_class, sequence_type,
+       ret = bt_ctf_event_class_add_field(event_class, sequence_type,
                "some_sequence");
        if (ret) {
                fail("Failed to add a sequence to an event class");
                goto end;
        }
 
-       ret = bt_stream_class_add_event_class(stream_class, event_class);
+       ret = bt_ctf_stream_class_add_event_class(stream_class, event_class);
        if (ret) {
                fail("Failed to add event class to stream class");
                goto end;
@@ -1932,59 +1333,59 @@ void test_custom_event_header_stream(struct bt_ctf_writer *writer,
         * We have defined a custom packet header field. We have to populate it
         * explicitly.
         */
-       packet_header = bt_stream_get_packet_header(stream);
+       packet_header = bt_ctf_stream_get_packet_header(stream);
        if (!packet_header) {
                fail("Failed to get stream packet header");
                goto end;
        }
 
-       integer = bt_field_structure_get_field_by_name(packet_header,
+       integer = bt_ctf_field_structure_get_field_by_name(packet_header,
                "custom_trace_packet_header_field");
        if (!integer) {
                fail("Failed to retrieve custom_trace_packet_header_field");
                goto end;
        }
 
-       ret = bt_field_unsigned_integer_set_value(integer, 3487);
+       ret = bt_ctf_field_integer_unsigned_set_value(integer, 3487);
        if (ret) {
                fail("Failed to set custom_trace_packet_header_field value");
                goto end;
        }
        bt_put(integer);
 
-       event = bt_event_create(event_class);
+       event = bt_ctf_event_create(event_class);
        if (!event) {
                fail("Failed to create event");
                goto end;
        }
 
-       event_header = bt_event_get_header(event);
+       event_header = bt_ctf_event_get_header(event);
        if (!event_header) {
                fail("Failed to get event header");
                goto end;
        }
 
-       integer = bt_field_structure_get_field_by_name(event_header,
+       integer = bt_ctf_field_structure_get_field_by_name(event_header,
                "seq_len");
        if (!integer) {
                fail("Failed to get seq_len field from event header");
                goto end;
        }
 
-       ret = bt_field_unsigned_integer_set_value(integer, 2);
+       ret = bt_ctf_field_integer_unsigned_set_value(integer, 2);
        if (ret) {
                fail("Failed to set seq_len value in event header");
                goto end;
        }
 
        /* Populate both sequence integer fields */
-       sequence = bt_event_get_payload(event, "some_sequence");
+       sequence = bt_ctf_event_get_payload(event, "some_sequence");
        if (!sequence) {
                fail("Failed to retrieve sequence from event");
                goto end;
        }
 
-       ret = bt_field_sequence_set_length(sequence, integer);
+       ret = bt_ctf_field_sequence_set_length(sequence, integer);
        if (ret) {
                fail("Failed to set sequence length");
                goto end;
@@ -1992,13 +1393,13 @@ void test_custom_event_header_stream(struct bt_ctf_writer *writer,
        bt_put(integer);
 
        for (i = 0; i < 2; i++) {
-               integer = bt_field_sequence_get_field(sequence, i);
+               integer = bt_ctf_field_sequence_get_field(sequence, i);
                if (ret) {
                        fail("Failed to retrieve sequence element");
                        goto end;
                }
 
-               ret = bt_field_unsigned_integer_set_value(integer, i);
+               ret = bt_ctf_field_integer_unsigned_set_value(integer, i);
                if (ret) {
                        fail("Failed to set sequence element value");
                        goto end;
@@ -2008,13 +1409,13 @@ void test_custom_event_header_stream(struct bt_ctf_writer *writer,
                integer = NULL;
        }
 
-       ret = bt_stream_append_event(stream, event);
+       ret = bt_ctf_stream_append_event(stream, event);
        if (ret) {
                fail("Failed to append event to stream");
                goto end;
        }
 
-       ret = bt_stream_flush(stream);
+       ret = bt_ctf_stream_flush(stream);
        if (ret) {
                fail("Failed to flush custom_event_header stream");
        }
@@ -2037,63 +1438,71 @@ void test_instanciate_event_before_stream(struct bt_ctf_writer *writer,
                struct bt_ctf_clock *clock)
 {
        int ret = 0;
-       struct bt_stream_class *stream_class = NULL;
-       struct bt_stream *stream = NULL,
+       struct bt_ctf_stream_class *stream_class = NULL;
+       struct bt_ctf_stream *stream = NULL,
                *ret_stream = NULL;
-       struct bt_event_class *event_class = NULL;
-       struct bt_event *event = NULL;
-       struct bt_field_type *integer_type = NULL;
-       struct bt_field *integer = NULL;
+       struct bt_ctf_event_class *event_class = NULL;
+       struct bt_ctf_event *event = NULL;
+       struct bt_ctf_field_type *integer_type = NULL;
+       struct bt_ctf_field *payload_field = NULL;
+       struct bt_ctf_field *integer = NULL;
 
-       stream_class = bt_stream_class_create("event_before_stream_test");
+       stream_class = bt_ctf_stream_class_create("event_before_stream_test");
        if (!stream_class) {
                diag("Failed to create stream class");
                ret = -1;
                goto end;
        }
 
-       ret = bt_stream_class_set_clock(stream_class, clock);
+       ret = bt_ctf_stream_class_set_clock(stream_class, clock);
        if (ret) {
                diag("Failed to set stream class clock");
                goto end;
        }
 
-       event_class = bt_event_class_create("some_event_class_name");
-       integer_type = bt_field_type_integer_create(32);
+       event_class = bt_ctf_event_class_create("some_event_class_name");
+       integer_type = bt_ctf_field_type_integer_create(32);
        if (!integer_type) {
                diag("Failed to create integer field type");
                ret = -1;
                goto end;
        }
 
-       ret = bt_event_class_add_field(event_class, integer_type,
+       ret = bt_ctf_event_class_add_field(event_class, integer_type,
                "integer_field");
        if (ret) {
                diag("Failed to add field to event class");
                goto end;
        }
 
-       ret = bt_stream_class_add_event_class(stream_class,
+       ret = bt_ctf_stream_class_add_event_class(stream_class,
                event_class);
        if (ret) {
                diag("Failed to add event class to stream class");
        }
 
-       event = bt_event_create(event_class);
+       event = bt_ctf_event_create(event_class);
        if (!event) {
                diag("Failed to create event");
                ret = -1;
                goto end;
        }
 
-       integer = bt_event_get_payload_by_index(event, 0);
+       payload_field = bt_ctf_event_get_payload_field(event);
+       if (!payload_field) {
+               diag("Failed to get event's payload field");
+               ret = -1;
+               goto end;
+       }
+
+       integer = bt_ctf_field_structure_get_field_by_index(payload_field, 0);
        if (!integer) {
                diag("Failed to get integer field payload from event");
                ret = -1;
                goto end;
        }
 
-       ret = bt_field_unsigned_integer_set_value(integer, 1234);
+       ret = bt_ctf_field_integer_unsigned_set_value(integer, 1234);
        if (ret) {
                diag("Failed to set integer field value");
                goto end;
@@ -2106,15 +1515,15 @@ void test_instanciate_event_before_stream(struct bt_ctf_writer *writer,
                goto end;
        }
 
-       ret = bt_stream_append_event(stream, event);
+       ret = bt_ctf_stream_append_event(stream, event);
        if (ret) {
                diag("Failed to append event to stream");
                goto end;
        }
 
-       ret_stream = bt_event_get_stream(event);
+       ret_stream = bt_ctf_event_get_stream(event);
        ok(ret_stream == stream,
-               "bt_event_get_stream returns an event's stream after it has been appended");
+               "bt_ctf_event_get_stream returns an event's stream after it has been appended");
 end:
        ok(ret == 0,
                "Create an event before instanciating its associated stream");
@@ -2125,229 +1534,28 @@ end:
        bt_put(event);
        bt_put(integer_type);
        bt_put(integer);
+       bt_put(payload_field);
 }
 
 static
-void append_existing_event_class(struct bt_stream_class *stream_class)
+void append_existing_event_class(struct bt_ctf_stream_class *stream_class)
 {
-       struct bt_event_class *event_class;
+       struct bt_ctf_event_class *event_class;
 
-       event_class = bt_event_class_create("Simple Event");
+       event_class = bt_ctf_event_class_create("Simple Event");
        assert(event_class);
-       ok(bt_stream_class_add_event_class(stream_class, event_class) == 0,
+       ok(bt_ctf_stream_class_add_event_class(stream_class, event_class) == 0,
                "two event classes with the same name may cohabit within the same stream class");
        bt_put(event_class);
 
-       event_class = bt_event_class_create("different name, ok");
+       event_class = bt_ctf_event_class_create("different name, ok");
        assert(event_class);
-       assert(!bt_event_class_set_id(event_class, 13));
-       ok(bt_stream_class_add_event_class(stream_class, event_class),
+       assert(!bt_ctf_event_class_set_id(event_class, 13));
+       ok(bt_ctf_stream_class_add_event_class(stream_class, event_class),
                "two event classes with the same ID cannot cohabit within the same stream class");
        bt_put(event_class);
 }
 
-static
-struct bt_event_class *create_minimal_event_class(void)
-{
-       struct bt_event_class *ec = NULL;
-       struct bt_field_type *int_ft = NULL;
-       int ret;
-
-       int_ft = bt_field_type_integer_create(23);
-       assert(int_ft);
-       ec = bt_event_class_create("minimal");
-       assert(ec);
-       ret = bt_event_class_add_field(ec, int_ft, "field");
-       assert(!ret);
-       BT_PUT(int_ft);
-
-       return ec;
-}
-
-static
-void test_create_writer_vs_non_writer_mode(void)
-{
-       int ret;
-       gchar *trace_path;
-       const char *writer_stream_name = "writer stream instance";
-       struct bt_ctf_writer *writer = NULL;
-       struct bt_trace *writer_trace = NULL;
-       struct bt_stream_class *writer_sc = NULL;
-       struct bt_stream *writer_stream = NULL;
-       struct bt_stream *writer_stream2 = NULL;
-       struct bt_stream *packet_stream = NULL;
-       struct bt_trace *non_writer_trace = NULL;
-       struct bt_stream_class *non_writer_sc = NULL;
-       struct bt_stream *non_writer_stream = NULL;
-       struct bt_stream *non_writer_stream2 = NULL;
-       struct bt_event_class *writer_ec = NULL;
-       struct bt_event_class *non_writer_ec = NULL;
-       struct bt_event *event = NULL;
-       struct bt_event *event2 = NULL;
-       struct bt_field_type *empty_struct_ft = NULL;
-       struct bt_field *int_field = NULL;
-       struct bt_ctf_clock *writer_clock = NULL;
-       struct bt_clock_class *non_writer_clock_class = NULL;
-       struct bt_packet *packet = NULL;
-       struct bt_packet *packet2 = NULL;
-
-       trace_path = g_build_filename(g_get_tmp_dir(), "ctfwriter_XXXXXX", NULL);
-       if (!bt_mkdtemp(trace_path)) {
-               perror("# perror");
-       }
-
-       /* Create empty structure field type (event header) */
-       empty_struct_ft = bt_field_type_structure_create();
-       assert(empty_struct_ft);
-
-       /* Create writer, writer stream class, stream, and clock */
-       writer = bt_ctf_writer_create(trace_path);
-       assert(writer);
-       writer_clock = bt_ctf_clock_create("writer_clock");
-       assert(writer_clock);
-       ret = bt_ctf_writer_add_clock(writer, writer_clock);
-       assert(!ret);
-       ret = bt_ctf_writer_set_byte_order(writer, BT_BYTE_ORDER_LITTLE_ENDIAN);
-       assert(!ret);
-       writer_trace = bt_ctf_writer_get_trace(writer);
-       ok(writer_trace, "bt_ctf_writer_get_trace() returns a trace");
-       writer_sc = bt_stream_class_create("writer_sc");
-       assert(writer_sc);
-       ret = bt_stream_class_set_event_header_type(writer_sc,
-               empty_struct_ft);
-       assert(!ret);
-       ret = bt_stream_class_set_clock(writer_sc, writer_clock);
-       assert(!ret);
-       ret = bt_trace_add_stream_class(writer_trace, writer_sc);
-       assert(!ret);
-       writer_stream = bt_stream_create(writer_sc, writer_stream_name);
-       assert(writer_stream);
-       ok(!strcmp(bt_stream_get_name(writer_stream), writer_stream_name),
-               "bt_stream_get_name() returns the stream's name");
-
-       /* Create non-writer trace, stream class, stream, and clock */
-       non_writer_trace = bt_trace_create();
-       assert(non_writer_trace);
-       non_writer_sc = bt_stream_class_create("nonwriter_sc");
-       assert(non_writer_sc);
-       ret = bt_stream_class_set_event_header_type(non_writer_sc,
-               empty_struct_ft);
-       assert(!ret);
-       ret = bt_stream_class_set_packet_context_type(non_writer_sc, NULL);
-       assert(!ret);
-       ret = bt_trace_add_stream_class(non_writer_trace, non_writer_sc);
-       assert(!ret);
-       non_writer_stream = bt_stream_create(non_writer_sc, NULL);
-       assert(non_writer_stream);
-       non_writer_clock_class =
-               bt_clock_class_create("non_writer_clock_class",
-                       1000000000);
-       assert(non_writer_clock_class);
-       ret = bt_trace_add_clock_class(non_writer_trace,
-               non_writer_clock_class);
-       assert(!ret);
-
-       /* Create event class and event */
-       writer_ec = create_minimal_event_class();
-       assert(writer_ec);
-       ret = bt_stream_class_add_event_class(writer_sc, writer_ec);
-       assert(!ret);
-       event = bt_event_create(writer_ec);
-       assert(event);
-       int_field = bt_event_get_payload_by_index(event, 0);
-       assert(int_field);
-       bt_field_unsigned_integer_set_value(int_field, 17);
-
-       /*
-        * Verify non-writer stream: it should be impossible to append
-        * an event to it.
-        */
-       ok(bt_stream_append_event(non_writer_stream, event),
-               "bt_stream_append_event() fails with a non-writer stream");
-
-       /*
-        * Verify writer stream: it should be possible to append an
-        * event to it.
-        */
-       ok(!bt_stream_append_event(writer_stream, event),
-               "bt_stream_append_event() succeeds with a writer stream");
-
-       /*
-        * It should be possible to create a packet from a non-writer
-        * stream, but not from a writer stream.
-        */
-       packet = bt_packet_create(non_writer_stream);
-       ok(packet, "bt_packet_create() succeeds with a non-writer stream");
-       packet_stream = bt_packet_get_stream(packet);
-       ok(packet_stream == non_writer_stream,
-               "bt_packet_get_stream() returns the correct stream");
-
-       /*
-        * It should not be possible to append an event associated to
-        * a stream to a different stream.
-        */
-       writer_stream2 = bt_stream_create(writer_sc, "zoo");
-       assert(writer_stream2);
-
-       /*
-        * It should be possible to set the packet of a fresh event, as
-        * long as the originating stream classes are the same.
-        */
-       event2 = bt_event_create(writer_ec);
-       assert(event2);
-       non_writer_ec = create_minimal_event_class();
-       assert(non_writer_ec);
-       ret = bt_stream_class_add_event_class(non_writer_sc, non_writer_ec);
-       assert(!ret);
-       BT_PUT(event2);
-       event2 = bt_event_create(non_writer_ec);
-       assert(event2);
-       ok(!bt_event_set_packet(event2, packet),
-               "bt_event_set_packet() succeeds when the event's and the packet's stream class are the same");
-
-       /*
-        * It should be possible to set a packet created from the same
-        * stream to an event with an existing packet.
-        */
-       packet2 = bt_packet_create(non_writer_stream);
-       assert(packet2);
-       ok(!bt_event_set_packet(event2, packet2),
-               "bt_event_set_packet() succeeds when the event's current packet has the same stream");
-       BT_PUT(packet2);
-
-       /*
-        * It should not be possible to set a packet created from a
-        * different stream to an event with an existing packet.
-        */
-       non_writer_stream2 = bt_stream_create(non_writer_sc, "rj45");
-       assert(non_writer_stream2);
-       packet2 = bt_packet_create(non_writer_stream);
-       assert(packet2);
-
-       bt_put(writer);
-       bt_put(writer_trace);
-       bt_put(writer_sc);
-       bt_put(writer_stream);
-       bt_put(writer_stream2);
-       bt_put(non_writer_trace);
-       bt_put(non_writer_sc);
-       bt_put(non_writer_stream);
-       bt_put(non_writer_stream2);
-       bt_put(packet_stream);
-       bt_put(writer_ec);
-       bt_put(non_writer_ec);
-       bt_put(event);
-       bt_put(event2);
-       bt_put(int_field);
-       bt_put(empty_struct_ft);
-       bt_put(writer_clock);
-       bt_put(non_writer_clock_class);
-       bt_put(packet);
-       bt_put(packet2);
-       recursive_rmdir(trace_path);
-       g_free(trace_path);
-}
-
 static
 void test_clock_utils(void)
 {
@@ -2368,187 +1576,6 @@ void test_clock_utils(void)
        BT_PUT(clock);
 }
 
-void test_set_clock_non_writer_stream_class(void)
-{
-       struct bt_ctf_clock *clock;
-       struct bt_trace *trace;
-       struct bt_stream_class *sc;
-       int ret;
-
-       clock = bt_ctf_clock_create("the_clock");
-       assert(clock);
-
-       trace = bt_trace_create();
-       assert(trace);
-
-       sc = bt_stream_class_create(NULL);
-       assert(sc);
-
-       ret = bt_stream_class_set_clock(sc, clock);
-       assert(ret == 0);
-
-       ret = bt_trace_add_stream_class(trace, sc);
-       ok(ret < 0,
-               "bt_trace_add_stream_class() fails with a stream class with a registered clock");
-
-       bt_put(clock);
-       bt_put(trace);
-       bt_put(sc);
-}
-
-static
-void test_static_trace(void)
-{
-       struct bt_trace *trace;
-       struct bt_stream_class *stream_class;
-       struct bt_stream_class *stream_class2;
-       struct bt_stream *stream;
-       struct bt_clock_class *clock_class;
-       int ret;
-
-       trace = bt_trace_create();
-       assert(trace);
-       stream_class = bt_stream_class_create(NULL);
-       assert(stream_class);
-       ret = bt_stream_class_set_packet_context_type(stream_class, NULL);
-       assert(ret == 0);
-       ret = bt_trace_add_stream_class(trace, stream_class);
-       assert(ret == 0);
-       stream = bt_stream_create(stream_class, "hello");
-       ok(stream, "bt_stream_create() succeeds with a non-static trace");
-       bt_put(stream);
-       ok(!bt_trace_is_static(trace),
-               "bt_trace_is_static() returns the expected value");
-       ok(bt_trace_set_is_static(trace) == 0,
-               "bt_trace_set_is_static() succeeds");
-       ok(bt_trace_is_static(trace),
-               "bt_trace_is_static() returns the expected value");
-       clock_class = bt_clock_class_create("yes", 1000000000);
-       assert(clock_class);
-       stream_class2 = bt_stream_class_create(NULL);
-       assert(stream_class2);
-       ok(bt_trace_add_stream_class(trace, stream_class2),
-               "bt_trace_add_stream_class() fails with a static trace");
-       ok(bt_trace_add_clock_class(trace, clock_class),
-               "bt_trace_add_clock_class() fails with a static trace");
-       ok(!bt_stream_create(stream_class, "hello2"),
-               "bt_stream_create() fails with a static trace");
-
-       bt_put(trace);
-       bt_put(stream_class);
-       bt_put(stream_class2);
-       bt_put(clock_class);
-}
-
-static
-void trace_is_static_listener(struct bt_trace *trace, void *data)
-{
-       *((int *) data) |= 1;
-}
-
-static
-void trace_listener_removed(struct bt_trace *trace, void *data)
-{
-       *((int *) data) |= 2;
-}
-
-static
-void test_trace_is_static_listener(void)
-{
-       struct bt_trace *trace;
-       int ret;
-       int called1 = 0;
-       int called2 = 0;
-       int called3 = 0;
-       int called4 = 0;
-       int listener1_id;
-       int listener2_id;
-       int listener3_id;
-       int listener4_id;
-
-       trace = bt_trace_create();
-       assert(trace);
-       ret = bt_trace_add_is_static_listener(NULL,
-               trace_is_static_listener, trace_listener_removed, &called1);
-       ok(ret < 0, "bt_trace_add_is_static_listener() handles NULL (trace)");
-       ret = bt_trace_add_is_static_listener(trace, NULL,
-               trace_listener_removed, &called1);
-       ok(ret < 0, "bt_trace_add_is_static_listener() handles NULL (listener)");
-       listener1_id = bt_trace_add_is_static_listener(trace,
-               trace_is_static_listener, trace_listener_removed, &called1);
-       ok(listener1_id >= 0, "bt_trace_add_is_static_listener() succeeds (1)");
-       listener2_id = bt_trace_add_is_static_listener(trace,
-               trace_is_static_listener, trace_listener_removed, &called2);
-       ok(listener2_id >= 0, "bt_trace_add_is_static_listener() succeeds (2)");
-       listener3_id = bt_trace_add_is_static_listener(trace,
-               trace_is_static_listener, trace_listener_removed, &called3);
-       ok(listener3_id >= 0, "bt_trace_add_is_static_listener() succeeds (3)");
-       ret = bt_trace_remove_is_static_listener(NULL, 0);
-       ok(ret < 0, "bt_trace_remove_is_static_listener() handles NULL (trace)");
-       ret = bt_trace_remove_is_static_listener(trace, -2);
-       ok(ret < 0, "bt_trace_remove_is_static_listener() handles invalid ID (negative)");
-       ret = bt_trace_remove_is_static_listener(trace, 77);
-       ok(ret < 0, "bt_trace_remove_is_static_listener() handles invalid ID (non existing)");
-       ret = bt_trace_remove_is_static_listener(trace, listener2_id);
-       ok(ret == 0, "bt_trace_remove_is_static_listener() succeeds");
-       ok(called2 == 2, "bt_trace_remove_is_static_listener() calls the remove listener");
-       listener4_id = bt_trace_add_is_static_listener(trace,
-               trace_is_static_listener, NULL, &called4);
-       ok(listener4_id >= 0, "bt_trace_add_is_static_listener() succeeds (4)");
-       ok(called1 == 0, "\"trace is static\" listener not called before the trace is made static (1)");
-       ok(called2 == 2, "\"trace is static\" listener not called before the trace is made static (2)");
-       ok(called3 == 0, "\"trace is static\" listener not called before the trace is made static (3)");
-       ok(called4 == 0, "\"trace is static\" listener not called before the trace is made static (4)");
-       ret = bt_trace_set_is_static(trace);
-       assert(ret == 0);
-       ret = bt_trace_add_is_static_listener(trace,
-               trace_is_static_listener, trace_listener_removed, &called1);
-       ok(ret < 0,
-               "bt_trace_add_is_static_listener() fails when the trace is static");
-       ok(called1 == 1, "\"trace is static\" listener called when the trace is made static (1)");
-       ok(called2 == 2, "\"trace is static\" listener not called when the trace is made static (2)");
-       ok(called3 == 1, "\"trace is static\" listener called when the trace is made static (3)");
-       ok(called4 == 1, "\"trace is static\" listener called when the trace is made static (4)");
-       called1 = 0;
-       called2 = 0;
-       called3 = 0;
-       called4 = 0;
-       bt_put(trace);
-       ok(called1 == 2, "\"trace is static\" listener not called after the trace is put (1)");
-       ok(called2 == 0, "\"trace is static\" listener not called after the trace is put (2)");
-       ok(called3 == 2, "\"trace is static\" listener not called after the trace is put (3)");
-       ok(called4 == 0, "\"trace is static\" listener not called after the trace is put (4)");
-}
-
-static
-void test_trace_uuid(void)
-{
-       struct bt_trace *trace;
-       const unsigned char uuid[] = {
-               0x35, 0x92, 0x63, 0xab, 0xb4, 0xbe, 0x40, 0xb4,
-               0xb2, 0x60, 0xd3, 0xf1, 0x3b, 0xb0, 0xd8, 0x59,
-       };
-       const unsigned char *ret_uuid;
-
-       trace = bt_trace_create();
-       assert(trace);
-       ok(!bt_trace_get_uuid(trace),
-               "bt_trace_get_uuid() returns NULL initially");
-       ok(bt_trace_set_uuid(NULL, uuid),
-               "bt_trace_set_uuid() handles NULL (trace)");
-       ok(bt_trace_set_uuid(trace, NULL),
-               "bt_trace_set_uuid() handles NULL (UUID)");
-       ok(bt_trace_set_uuid(trace, uuid) == 0,
-               "bt_trace_set_uuid() succeeds with a valid UUID");
-       ret_uuid = bt_trace_get_uuid(trace);
-       ok(ret_uuid, "bt_trace_get_uuid() returns a UUID");
-       assert(ret_uuid);
-       ok(memcmp(uuid, ret_uuid, 16) == 0,
-               "bt_trace_get_uuid() returns the expected UUID");
-
-       bt_put(trace);
-}
-
 int main(int argc, char **argv)
 {
        const char *env_resize_length;
@@ -2570,14 +1597,14 @@ int main(int argc, char **argv)
        struct bt_utsname name = {"GNU/Linux", "testhost", "4.4.0-87-generic",
                "#110-Ubuntu SMP Tue Jul 18 12:55:35 UTC 2017", "x86_64"};
        struct bt_ctf_clock *clock, *ret_clock;
-       struct bt_clock_class *ret_clock_class;
-       struct bt_stream_class *stream_class, *ret_stream_class;
-       struct bt_stream *stream1;
-       struct bt_stream *stream;
+       struct bt_ctf_clock_class *ret_clock_class;
+       struct bt_ctf_stream_class *stream_class, *ret_stream_class;
+       struct bt_ctf_stream *stream1;
+       struct bt_ctf_stream *stream;
        const char *ret_string;
        const unsigned char *ret_uuid;
        unsigned char tmp_uuid[16] = { 0 };
-       struct bt_field_type *packet_context_type,
+       struct bt_ctf_field_type *packet_context_type,
                *packet_context_field_type,
                *packet_header_type,
                *packet_header_field_type,
@@ -2585,8 +1612,8 @@ int main(int argc, char **argv)
                *stream_event_context_type,
                *ret_field_type,
                *event_header_field_type;
-       struct bt_field *packet_header, *packet_header_field;
-       struct bt_trace *trace;
+       struct bt_ctf_field *packet_header, *packet_header_field;
+       struct bt_ctf_trace *trace;
        int ret;
        int64_t ret_int64_t;
        struct bt_value *obj;
@@ -2612,21 +1639,21 @@ int main(int argc, char **argv)
        metadata_path = g_build_filename(trace_path, "metadata", NULL);
 
        writer = bt_ctf_writer_create(trace_path);
-       ok(writer, "bt_create succeeds in creating trace with path");
+       ok(writer, "bt_ctf_create succeeds in creating trace with path");
 
        ok(!bt_ctf_writer_get_trace(NULL),
                "bt_ctf_writer_get_trace correctly handles NULL");
        trace = bt_ctf_writer_get_trace(writer);
-       ok(bt_trace_set_native_byte_order(trace, BT_BYTE_ORDER_NATIVE),
-               "Cannot set a trace's byte order to BT_BYTE_ORDER_NATIVE");
-       ok(bt_trace_set_native_byte_order(trace, BT_BYTE_ORDER_UNSPECIFIED),
-               "Cannot set a trace's byte order to BT_BYTE_ORDER_UNSPECIFIED");
+       ok(bt_ctf_trace_set_native_byte_order(trace, BT_CTF_BYTE_ORDER_NATIVE),
+               "Cannot set a trace's byte order to BT_CTF_BYTE_ORDER_NATIVE");
+       ok(bt_ctf_trace_set_native_byte_order(trace, BT_CTF_BYTE_ORDER_UNSPECIFIED),
+               "Cannot set a trace's byte order to BT_CTF_BYTE_ORDER_UNSPECIFIED");
        ok(trace,
-               "bt_ctf_writer_get_trace returns a bt_trace object");
-       ok(bt_trace_set_native_byte_order(trace, BT_BYTE_ORDER_BIG_ENDIAN) == 0,
+               "bt_ctf_writer_get_trace returns a bt_ctf_trace object");
+       ok(bt_ctf_trace_set_native_byte_order(trace, BT_CTF_BYTE_ORDER_BIG_ENDIAN) == 0,
                "Set a trace's byte order to big endian");
-       ok(bt_trace_get_native_byte_order(trace) == BT_BYTE_ORDER_BIG_ENDIAN,
-               "bt_trace_get_native_byte_order returns a correct endianness");
+       ok(bt_ctf_trace_get_native_byte_order(trace) == BT_CTF_BYTE_ORDER_BIG_ENDIAN,
+               "bt_ctf_trace_get_native_byte_order returns a correct endianness");
 
        /* Add environment context to the trace */
        ok(bt_ctf_writer_add_environment_field(writer, "host", name.nodename) == 0,
@@ -2642,102 +1669,102 @@ int main(int argc, char **argv)
                NULL),
                "bt_ctf_writer_add_environment_field error with NULL field value");
 
-       /* Test bt_trace_set_environment_field with an integer object */
+       /* Test bt_ctf_trace_set_environment_field with an integer object */
        obj = bt_value_integer_create_init(23);
        assert(obj);
-       ok(bt_trace_set_environment_field(NULL, "test_env_int_obj", obj),
-               "bt_trace_set_environment_field handles a NULL trace correctly");
-       ok(bt_trace_set_environment_field(trace, NULL, obj),
-               "bt_trace_set_environment_field handles a NULL name correctly");
-       ok(bt_trace_set_environment_field(trace, "test_env_int_obj", NULL),
-               "bt_trace_set_environment_field handles a NULL value correctly");
-       ok(!bt_trace_set_environment_field(trace, "test_env_int_obj", obj),
-               "bt_trace_set_environment_field succeeds in adding an integer object");
+       ok(bt_ctf_trace_set_environment_field(NULL, "test_env_int_obj", obj),
+               "bt_ctf_trace_set_environment_field handles a NULL trace correctly");
+       ok(bt_ctf_trace_set_environment_field(trace, NULL, obj),
+               "bt_ctf_trace_set_environment_field handles a NULL name correctly");
+       ok(bt_ctf_trace_set_environment_field(trace, "test_env_int_obj", NULL),
+               "bt_ctf_trace_set_environment_field handles a NULL value correctly");
+       ok(!bt_ctf_trace_set_environment_field(trace, "test_env_int_obj", obj),
+               "bt_ctf_trace_set_environment_field succeeds in adding an integer object");
        BT_PUT(obj);
 
-       /* Test bt_trace_set_environment_field with a string object */
+       /* Test bt_ctf_trace_set_environment_field with a string object */
        obj = bt_value_string_create_init("the value");
        assert(obj);
-       ok(!bt_trace_set_environment_field(trace, "test_env_str_obj", obj),
-               "bt_trace_set_environment_field succeeds in adding a string object");
+       ok(!bt_ctf_trace_set_environment_field(trace, "test_env_str_obj", obj),
+               "bt_ctf_trace_set_environment_field succeeds in adding a string object");
        BT_PUT(obj);
 
-       /* Test bt_trace_set_environment_field_integer */
-       ok(bt_trace_set_environment_field_integer(NULL, "test_env_int",
+       /* Test bt_ctf_trace_set_environment_field_integer */
+       ok(bt_ctf_trace_set_environment_field_integer(NULL, "test_env_int",
                -194875),
-               "bt_trace_set_environment_field_integer handles a NULL trace correctly");
-       ok(bt_trace_set_environment_field_integer(trace, NULL, -194875),
-               "bt_trace_set_environment_field_integer handles a NULL name correctly");
-       ok(!bt_trace_set_environment_field_integer(trace, "test_env_int",
+               "bt_ctf_trace_set_environment_field_integer handles a NULL trace correctly");
+       ok(bt_ctf_trace_set_environment_field_integer(trace, NULL, -194875),
+               "bt_ctf_trace_set_environment_field_integer handles a NULL name correctly");
+       ok(!bt_ctf_trace_set_environment_field_integer(trace, "test_env_int",
                -164973),
-               "bt_trace_set_environment_field_integer succeeds");
+               "bt_ctf_trace_set_environment_field_integer succeeds");
 
-       /* Test bt_trace_set_environment_field_string */
-       ok(bt_trace_set_environment_field_string(NULL, "test_env_str",
+       /* Test bt_ctf_trace_set_environment_field_string */
+       ok(bt_ctf_trace_set_environment_field_string(NULL, "test_env_str",
                "yeah"),
-               "bt_trace_set_environment_field_string handles a NULL trace correctly");
-       ok(bt_trace_set_environment_field_string(trace, NULL, "yeah"),
-               "bt_trace_set_environment_field_string handles a NULL name correctly");
-       ok(bt_trace_set_environment_field_string(trace, "test_env_str",
+               "bt_ctf_trace_set_environment_field_string handles a NULL trace correctly");
+       ok(bt_ctf_trace_set_environment_field_string(trace, NULL, "yeah"),
+               "bt_ctf_trace_set_environment_field_string handles a NULL name correctly");
+       ok(bt_ctf_trace_set_environment_field_string(trace, "test_env_str",
                NULL),
-               "bt_trace_set_environment_field_string handles a NULL value correctly");
-       ok(!bt_trace_set_environment_field_string(trace, "test_env_str",
+               "bt_ctf_trace_set_environment_field_string handles a NULL value correctly");
+       ok(!bt_ctf_trace_set_environment_field_string(trace, "test_env_str",
                "oh yeah"),
-               "bt_trace_set_environment_field_string succeeds");
+               "bt_ctf_trace_set_environment_field_string succeeds");
 
-       /* Test bt_trace_get_environment_field_count */
-       ok(bt_trace_get_environment_field_count(trace) == 5,
-               "bt_trace_get_environment_field_count returns a correct number of environment fields");
+       /* Test bt_ctf_trace_get_environment_field_count */
+       ok(bt_ctf_trace_get_environment_field_count(trace) == 5,
+               "bt_ctf_trace_get_environment_field_count returns a correct number of environment fields");
 
-       /* Test bt_trace_get_environment_field_name */
-       ret_string = bt_trace_get_environment_field_name_by_index(trace, 0);
+       /* Test bt_ctf_trace_get_environment_field_name */
+       ret_string = bt_ctf_trace_get_environment_field_name_by_index(trace, 0);
        ok(ret_string && !strcmp(ret_string, "host"),
-               "bt_trace_get_environment_field_name returns a correct field name");
-       ret_string = bt_trace_get_environment_field_name_by_index(trace, 1);
+               "bt_ctf_trace_get_environment_field_name returns a correct field name");
+       ret_string = bt_ctf_trace_get_environment_field_name_by_index(trace, 1);
        ok(ret_string && !strcmp(ret_string, "test_env_int_obj"),
-               "bt_trace_get_environment_field_name returns a correct field name");
-       ret_string = bt_trace_get_environment_field_name_by_index(trace, 2);
+               "bt_ctf_trace_get_environment_field_name returns a correct field name");
+       ret_string = bt_ctf_trace_get_environment_field_name_by_index(trace, 2);
        ok(ret_string && !strcmp(ret_string, "test_env_str_obj"),
-               "bt_trace_get_environment_field_name returns a correct field name");
-       ret_string = bt_trace_get_environment_field_name_by_index(trace, 3);
+               "bt_ctf_trace_get_environment_field_name returns a correct field name");
+       ret_string = bt_ctf_trace_get_environment_field_name_by_index(trace, 3);
        ok(ret_string && !strcmp(ret_string, "test_env_int"),
-               "bt_trace_get_environment_field_name returns a correct field name");
-       ret_string = bt_trace_get_environment_field_name_by_index(trace, 4);
+               "bt_ctf_trace_get_environment_field_name returns a correct field name");
+       ret_string = bt_ctf_trace_get_environment_field_name_by_index(trace, 4);
        ok(ret_string && !strcmp(ret_string, "test_env_str"),
-               "bt_trace_get_environment_field_name returns a correct field name");
+               "bt_ctf_trace_get_environment_field_name returns a correct field name");
 
-       /* Test bt_trace_get_environment_field_value */
-       obj = bt_trace_get_environment_field_value_by_index(trace, 1);
+       /* Test bt_ctf_trace_get_environment_field_value */
+       obj = bt_ctf_trace_get_environment_field_value_by_index(trace, 1);
        ret = bt_value_integer_get(obj, &ret_int64_t);
        ok(!ret && ret_int64_t == 23,
-               "bt_trace_get_environment_field_value succeeds in getting an integer value");
+               "bt_ctf_trace_get_environment_field_value succeeds in getting an integer value");
        BT_PUT(obj);
-       obj = bt_trace_get_environment_field_value_by_index(trace, 2);
+       obj = bt_ctf_trace_get_environment_field_value_by_index(trace, 2);
        ret = bt_value_string_get(obj, &ret_string);
        ok(!ret && ret_string && !strcmp(ret_string, "the value"),
-               "bt_trace_get_environment_field_value succeeds in getting a string value");
+               "bt_ctf_trace_get_environment_field_value succeeds in getting a string value");
        BT_PUT(obj);
 
-       /* Test bt_trace_get_environment_field_value_by_name */
-       ok(!bt_trace_get_environment_field_value_by_name(trace, "oh oh"),
-               "bt_trace_get_environment_field_value_by_name returns NULL or an unknown field name");
-       obj = bt_trace_get_environment_field_value_by_name(trace,
+       /* Test bt_ctf_trace_get_environment_field_value_by_name */
+       ok(!bt_ctf_trace_get_environment_field_value_by_name(trace, "oh oh"),
+               "bt_ctf_trace_get_environment_field_value_by_name returns NULL or an unknown field name");
+       obj = bt_ctf_trace_get_environment_field_value_by_name(trace,
                "test_env_str");
        ret = bt_value_string_get(obj, &ret_string);
        ok(!ret && ret_string && !strcmp(ret_string, "oh yeah"),
-               "bt_trace_get_environment_field_value_by_name succeeds in getting an existing field");
+               "bt_ctf_trace_get_environment_field_value_by_name succeeds in getting an existing field");
        BT_PUT(obj);
 
        /* Test environment field replacement */
-       ok(!bt_trace_set_environment_field_integer(trace, "test_env_int",
+       ok(!bt_ctf_trace_set_environment_field_integer(trace, "test_env_int",
                654321),
-               "bt_trace_set_environment_field_integer succeeds with an existing name");
-       ok(bt_trace_get_environment_field_count(trace) == 5,
-               "bt_trace_set_environment_field_integer with an existing key does not increase the environment size");
-       obj = bt_trace_get_environment_field_value_by_index(trace, 3);
+               "bt_ctf_trace_set_environment_field_integer succeeds with an existing name");
+       ok(bt_ctf_trace_get_environment_field_count(trace) == 5,
+               "bt_ctf_trace_set_environment_field_integer with an existing key does not increase the environment size");
+       obj = bt_ctf_trace_get_environment_field_value_by_index(trace, 3);
        ret = bt_value_integer_get(obj, &ret_int64_t);
        ok(!ret && ret_int64_t == 654321,
-               "bt_trace_get_environment_field_value successfully replaces an existing field");
+               "bt_ctf_trace_get_environment_field_value successfully replaces an existing field");
        BT_PUT(obj);
 
        ok(bt_ctf_writer_add_environment_field(writer, "sysname", name.sysname)
@@ -2820,10 +1847,8 @@ int main(int argc, char **argv)
                "Set clock absolute property");
        ok(bt_ctf_clock_get_is_absolute(clock) == !!is_absolute,
                "bt_ctf_clock_get_precision returns the correct is_absolute attribute once it is set");
-
        ok(bt_ctf_clock_set_time(clock, current_time) == 0,
                "Set clock time");
-
        ret_uuid = bt_ctf_clock_get_uuid(clock);
        ok(ret_uuid,
                "bt_ctf_clock_get_uuid returns a UUID");
@@ -2842,150 +1867,151 @@ int main(int argc, char **argv)
                "bt_ctf_clock_get_uuid returns the correct UUID after setting a new one");
 
        /* Define a stream class */
-       stream_class = bt_stream_class_create("test_stream");
-
-       ret_string = bt_stream_class_get_name(stream_class);
+       stream_class = bt_ctf_stream_class_create("test_stream");
+       ret_string = bt_ctf_stream_class_get_name(stream_class);
        ok(ret_string && !strcmp(ret_string, "test_stream"),
-               "bt_stream_class_get_name returns a correct stream class name");
+               "bt_ctf_stream_class_get_name returns a correct stream class name");
 
-       ok(bt_stream_class_get_clock(stream_class) == NULL,
-               "bt_stream_class_get_clock returns NULL when a clock was not set");
-       ok(bt_stream_class_get_clock(NULL) == NULL,
-               "bt_stream_class_get_clock handles NULL correctly");
+       ok(bt_ctf_stream_class_get_clock(stream_class) == NULL,
+               "bt_ctf_stream_class_get_clock returns NULL when a clock was not set");
+       ok(bt_ctf_stream_class_get_clock(NULL) == NULL,
+               "bt_ctf_stream_class_get_clock handles NULL correctly");
 
        ok(stream_class, "Create stream class");
-       ok(bt_stream_class_set_clock(stream_class, clock) == 0,
+       ok(bt_ctf_stream_class_set_clock(stream_class, clock) == 0,
                "Set a stream class' clock");
-       ret_clock = bt_stream_class_get_clock(stream_class);
+       ret_clock = bt_ctf_stream_class_get_clock(stream_class);
        ok(ret_clock == clock,
-               "bt_stream_class_get_clock returns a correct clock");
+               "bt_ctf_stream_class_get_clock returns a correct clock");
        bt_put(ret_clock);
 
        /* Test the event fields and event types APIs */
        type_field_tests();
 
-       /* Test fields copying */
-       field_copy_tests();
-
-       ok(bt_stream_class_get_id(stream_class) < 0,
-               "bt_stream_class_get_id returns an error when no id is set");
-       ok(bt_stream_class_set_id(NULL, 123) < 0,
-               "bt_stream_class_set_id handles NULL correctly");
-       ok(bt_stream_class_set_id(stream_class, 123) == 0,
+       ok(bt_ctf_stream_class_get_id(stream_class) < 0,
+               "bt_ctf_stream_class_get_id returns an error when no id is set");
+       ok(bt_ctf_stream_class_set_id(NULL, 123) < 0,
+               "bt_ctf_stream_class_set_id handles NULL correctly");
+       ok(bt_ctf_stream_class_set_id(stream_class, 123) == 0,
                "Set an stream class' id");
-       ok(bt_stream_class_get_id(stream_class) == 123,
-               "bt_stream_class_get_id returns the correct value");
+       ok(bt_ctf_stream_class_get_id(stream_class) == 123,
+               "bt_ctf_stream_class_get_id returns the correct value");
 
        /* Validate default event header fields */
-       ret_field_type = bt_stream_class_get_event_header_type(
+       ret_field_type = bt_ctf_stream_class_get_event_header_type(
                stream_class);
        ok(ret_field_type,
-               "bt_stream_class_get_event_header_type returns an event header type");
-       ok(bt_field_type_get_type_id(ret_field_type) == BT_FIELD_TYPE_ID_STRUCT,
+               "bt_ctf_stream_class_get_event_header_type returns an event header type");
+       ok(bt_ctf_field_type_get_type_id(ret_field_type) == BT_CTF_FIELD_TYPE_ID_STRUCT,
                "Default event header type is a structure");
        event_header_field_type =
-               bt_field_type_structure_get_field_type_by_name(
+               bt_ctf_field_type_structure_get_field_type_by_name(
                ret_field_type, "id");
        ok(event_header_field_type,
                "Default event header type contains an \"id\" field");
-       ok(bt_field_type_get_type_id(
-               event_header_field_type) == BT_FIELD_TYPE_ID_INTEGER,
+       ok(bt_ctf_field_type_get_type_id(
+               event_header_field_type) == BT_CTF_FIELD_TYPE_ID_INTEGER,
                "Default event header \"id\" field is an integer");
        bt_put(event_header_field_type);
        event_header_field_type =
-               bt_field_type_structure_get_field_type_by_name(
+               bt_ctf_field_type_structure_get_field_type_by_name(
                ret_field_type, "timestamp");
        ok(event_header_field_type,
                "Default event header type contains a \"timestamp\" field");
-       ok(bt_field_type_get_type_id(
-               event_header_field_type) == BT_FIELD_TYPE_ID_INTEGER,
+       ok(bt_ctf_field_type_get_type_id(
+               event_header_field_type) == BT_CTF_FIELD_TYPE_ID_INTEGER,
                "Default event header \"timestamp\" field is an integer");
        bt_put(event_header_field_type);
        bt_put(ret_field_type);
 
        /* Add a custom trace packet header field */
-       packet_header_type = bt_trace_get_packet_header_type(trace);
+       packet_header_type = bt_ctf_trace_get_packet_header_field_type(trace);
        ok(packet_header_type,
-               "bt_trace_get_packet_header_type returns a packet header");
-       ok(bt_field_type_get_type_id(packet_header_type) == BT_FIELD_TYPE_ID_STRUCT,
-               "bt_trace_get_packet_header_type returns a packet header of type struct");
-       ret_field_type = bt_field_type_structure_get_field_type_by_name(
+               "bt_ctf_trace_get_packet_header_field_type returns a packet header");
+       ok(bt_ctf_field_type_get_type_id(packet_header_type) == BT_CTF_FIELD_TYPE_ID_STRUCT,
+               "bt_ctf_trace_get_packet_header_field_type returns a packet header of type struct");
+       ret_field_type = bt_ctf_field_type_structure_get_field_type_by_name(
                packet_header_type, "magic");
        ok(ret_field_type, "Default packet header type contains a \"magic\" field");
        bt_put(ret_field_type);
-       ret_field_type = bt_field_type_structure_get_field_type_by_name(
+       ret_field_type = bt_ctf_field_type_structure_get_field_type_by_name(
                packet_header_type, "uuid");
        ok(ret_field_type, "Default packet header type contains a \"uuid\" field");
        bt_put(ret_field_type);
-       ret_field_type = bt_field_type_structure_get_field_type_by_name(
+       ret_field_type = bt_ctf_field_type_structure_get_field_type_by_name(
                packet_header_type, "stream_id");
        ok(ret_field_type, "Default packet header type contains a \"stream_id\" field");
        bt_put(ret_field_type);
 
-       packet_header_field_type = bt_field_type_integer_create(22);
-       ok(!bt_field_type_structure_add_field(packet_header_type,
+       packet_header_field_type = bt_ctf_field_type_integer_create(22);
+       ok(!bt_ctf_field_type_structure_add_field(packet_header_type,
                packet_header_field_type, "custom_trace_packet_header_field"),
                "Added a custom trace packet header field successfully");
 
-       ok(bt_trace_set_packet_header_type(NULL, packet_header_type) < 0,
-               "bt_trace_set_packet_header_type handles a NULL trace correctly");
-       ok(!bt_trace_set_packet_header_type(trace, packet_header_type),
+       ok(bt_ctf_trace_set_packet_header_field_type(NULL, packet_header_type) < 0,
+               "bt_ctf_trace_set_packet_header_field_type handles a NULL trace correctly");
+       ok(!bt_ctf_trace_set_packet_header_field_type(trace, packet_header_type),
                "Set a trace packet_header_type successfully");
 
        /* Add a custom field to the stream class' packet context */
-       packet_context_type = bt_stream_class_get_packet_context_type(stream_class);
+       packet_context_type = bt_ctf_stream_class_get_packet_context_type(stream_class);
        ok(packet_context_type,
-               "bt_stream_class_get_packet_context_type returns a packet context type.");
-       ok(bt_field_type_get_type_id(packet_context_type) == BT_FIELD_TYPE_ID_STRUCT,
+               "bt_ctf_stream_class_get_packet_context_type returns a packet context type.");
+       ok(bt_ctf_field_type_get_type_id(packet_context_type) == BT_CTF_FIELD_TYPE_ID_STRUCT,
                "Packet context is a structure");
 
-       ok(bt_stream_class_set_packet_context_type(NULL, packet_context_type),
-               "bt_stream_class_set_packet_context_type handles a NULL stream class correctly");
+       ok(bt_ctf_stream_class_set_packet_context_type(NULL, packet_context_type),
+               "bt_ctf_stream_class_set_packet_context_type handles a NULL stream class correctly");
+
+       integer_type = bt_ctf_field_type_integer_create(32);
 
-       integer_type = bt_field_type_integer_create(32);
-       ok(bt_stream_class_set_packet_context_type(stream_class,
+       ok(bt_ctf_stream_class_set_packet_context_type(stream_class,
                integer_type) < 0,
-               "bt_stream_class_set_packet_context_type rejects a packet context that is not a structure");
+               "bt_ctf_stream_class_set_packet_context_type rejects a packet context that is not a structure");
+
        /* Create a "uint5_t" equivalent custom packet context field */
-       packet_context_field_type = bt_field_type_integer_create(5);
+       packet_context_field_type = bt_ctf_field_type_integer_create(5);
 
-       ret = bt_field_type_structure_add_field(packet_context_type,
+       ret = bt_ctf_field_type_structure_add_field(packet_context_type,
                packet_context_field_type, "custom_packet_context_field");
        ok(ret == 0, "Packet context field added successfully");
 
        /* Define a stream event context containing a my_integer field. */
-       stream_event_context_type = bt_field_type_structure_create();
-       bt_field_type_structure_add_field(stream_event_context_type,
+       stream_event_context_type = bt_ctf_field_type_structure_create();
+       bt_ctf_field_type_structure_add_field(stream_event_context_type,
                integer_type, "common_event_context");
 
-       ok(bt_stream_class_set_event_context_type(NULL,
+       ok(bt_ctf_stream_class_set_event_context_type(NULL,
                stream_event_context_type) < 0,
-               "bt_stream_class_set_event_context_type handles a NULL stream_class correctly");
-       ok(bt_stream_class_set_event_context_type(stream_class,
+               "bt_ctf_stream_class_set_event_context_type handles a NULL stream_class correctly");
+       ok(bt_ctf_stream_class_set_event_context_type(stream_class,
                integer_type) < 0,
-               "bt_stream_class_set_event_context_type validates that the event context os a structure");
+               "bt_ctf_stream_class_set_event_context_type validates that the event context os a structure");
 
-       ok(bt_stream_class_set_event_context_type(
+       ok(bt_ctf_stream_class_set_event_context_type(
                stream_class, stream_event_context_type) == 0,
                "Set a new stream event context type");
-       ret_field_type = bt_stream_class_get_event_context_type(
+
+       ret_field_type = bt_ctf_stream_class_get_event_context_type(
                stream_class);
        ok(ret_field_type == stream_event_context_type,
-               "bt_stream_class_get_event_context_type returns the correct field type.");
+               "bt_ctf_stream_class_get_event_context_type returns the correct field type.");
        bt_put(ret_field_type);
 
+
        /* Instantiate a stream and append events */
        ret = bt_ctf_writer_add_clock(writer, clock);
        assert(ret == 0);
-       ok(bt_trace_get_stream_count(trace) == 0,
-               "bt_trace_get_stream_count() succeeds and returns the correct value (0)");
+
+       ok(bt_ctf_trace_get_stream_count(trace) == 0,
+               "bt_ctf_trace_get_stream_count() succeeds and returns the correct value (0)");
        stream1 = bt_ctf_writer_create_stream(writer, stream_class);
        ok(stream1, "Instanciate a stream class from writer");
-       ok(bt_trace_get_stream_count(trace) == 1,
-               "bt_trace_get_stream_count() succeeds and returns the correct value (1)");
-       stream = bt_trace_get_stream_by_index(trace, 0);
+       ok(bt_ctf_trace_get_stream_count(trace) == 1,
+               "bt_ctf_trace_get_stream_count() succeeds and returns the correct value (1)");
+       stream = bt_ctf_trace_get_stream_by_index(trace, 0);
        ok(stream == stream1,
-               "bt_trace_get_stream_by_index() succeeds and returns the correct value");
+               "bt_ctf_trace_get_stream_by_index() succeeds and returns the correct value");
        BT_PUT(stream);
 
        /*
@@ -2993,24 +2019,24 @@ int main(int argc, char **argv)
         * class to the writer's trace, thus registering the stream
         * class's clock to the trace.
         */
-       ok(bt_trace_get_clock_class_count(trace) == 1,
-               "bt_trace_get_clock_class_count returns the correct number of clocks");
-       ret_clock_class = bt_trace_get_clock_class_by_index(trace, 0);
-       ok(strcmp(bt_clock_class_get_name(ret_clock_class),
+       ok(bt_ctf_trace_get_clock_class_count(trace) == 1,
+               "bt_ctf_trace_get_clock_class_count returns the correct number of clocks");
+       ret_clock_class = bt_ctf_trace_get_clock_class_by_index(trace, 0);
+       ok(strcmp(bt_ctf_clock_class_get_name(ret_clock_class),
                bt_ctf_clock_get_name(clock)) == 0,
-               "bt_trace_get_clock_class returns the right clock instance");
+               "bt_ctf_trace_get_clock_class returns the right clock instance");
        bt_put(ret_clock_class);
-       ret_clock_class = bt_trace_get_clock_class_by_name(trace, clock_name);
-       ok(strcmp(bt_clock_class_get_name(ret_clock_class),
+       ret_clock_class = bt_ctf_trace_get_clock_class_by_name(trace, clock_name);
+       ok(strcmp(bt_ctf_clock_class_get_name(ret_clock_class),
                bt_ctf_clock_get_name(clock)) == 0,
-               "bt_trace_get_clock_class returns the right clock instance");
+               "bt_ctf_trace_get_clock_class returns the right clock instance");
        bt_put(ret_clock_class);
-       ok(!bt_trace_get_clock_class_by_name(trace, "random"),
-               "bt_trace_get_clock_by_name fails when the requested clock doesn't exist");
+       ok(!bt_ctf_trace_get_clock_class_by_name(trace, "random"),
+               "bt_ctf_trace_get_clock_by_name fails when the requested clock doesn't exist");
 
-       ret_stream_class = bt_stream_get_class(stream1);
+       ret_stream_class = bt_ctf_stream_get_class(stream1);
        ok(ret_stream_class,
-               "bt_stream_get_class returns a stream class");
+               "bt_ctf_stream_get_class returns a stream class");
        ok(ret_stream_class == stream_class,
                "Returned stream class is of the correct type");
 
@@ -3022,20 +2048,20 @@ int main(int argc, char **argv)
        BT_PUT(packet_header_type);
        BT_PUT(packet_context_type);
        BT_PUT(stream_event_context_type);
-       packet_header_type = bt_trace_get_packet_header_type(trace);
+       packet_header_type = bt_ctf_trace_get_packet_header_field_type(trace);
        assert(packet_header_type);
        packet_context_type =
-               bt_stream_class_get_packet_context_type(stream_class);
+               bt_ctf_stream_class_get_packet_context_type(stream_class);
        assert(packet_context_type);
        stream_event_context_type =
-               bt_stream_class_get_event_context_type(stream_class);
+               bt_ctf_stream_class_get_event_context_type(stream_class);
        assert(stream_event_context_type);
 
        /*
         * Try to modify the packet context type after a stream has been
         * created.
         */
-       ret = bt_field_type_structure_add_field(packet_header_type,
+       ret = bt_ctf_field_type_structure_add_field(packet_header_type,
                packet_header_field_type, "should_fail");
        ok(ret < 0,
                "Trace packet header type can't be modified once a stream has been instanciated");
@@ -3044,7 +2070,7 @@ int main(int argc, char **argv)
         * Try to modify the packet context type after a stream has been
         * created.
         */
-       ret = bt_field_type_structure_add_field(packet_context_type,
+       ret = bt_ctf_field_type_structure_add_field(packet_context_type,
                packet_context_field_type, "should_fail");
        ok(ret < 0,
                "Packet context type can't be modified once a stream has been instanciated");
@@ -3053,41 +2079,39 @@ int main(int argc, char **argv)
         * Try to modify the stream event context type after a stream has been
         * created.
         */
-       ret = bt_field_type_structure_add_field(stream_event_context_type,
+       ret = bt_ctf_field_type_structure_add_field(stream_event_context_type,
                integer_type, "should_fail");
        ok(ret < 0,
                "Stream event context type can't be modified once a stream has been instanciated");
 
        /* Should fail after instanciating a stream (frozen) */
-       ok(bt_stream_class_set_clock(stream_class, clock),
+       ok(bt_ctf_stream_class_set_clock(stream_class, clock),
                "Changes to a stream class that was already instantiated fail");
 
        /* Populate the custom packet header field only once for all tests */
-       ok(bt_stream_get_packet_header(NULL) == NULL,
-               "bt_stream_get_packet_header handles NULL correctly");
-       packet_header = bt_stream_get_packet_header(stream1);
+       ok(bt_ctf_stream_get_packet_header(NULL) == NULL,
+               "bt_ctf_stream_get_packet_header handles NULL correctly");
+       packet_header = bt_ctf_stream_get_packet_header(stream1);
        ok(packet_header,
-               "bt_stream_get_packet_header returns a packet header");
-       ret_field_type = bt_field_get_type(packet_header);
+               "bt_ctf_stream_get_packet_header returns a packet header");
+       ret_field_type = bt_ctf_field_get_type(packet_header);
        ok(ret_field_type == packet_header_type,
                "Stream returns a packet header of the appropriate type");
        bt_put(ret_field_type);
-       packet_header_field = bt_field_structure_get_field_by_name(packet_header,
+       packet_header_field = bt_ctf_field_structure_get_field_by_name(packet_header,
                "custom_trace_packet_header_field");
        ok(packet_header_field,
                "Packet header structure contains a custom field with the appropriate name");
-       ret_field_type = bt_field_get_type(packet_header_field);
-       ok(bt_field_type_compare(ret_field_type, packet_header_field_type) == 0,
-               "Custom packet header field is of the expected type");
-       ok(!bt_field_unsigned_integer_set_value(packet_header_field,
+       ret_field_type = bt_ctf_field_get_type(packet_header_field);
+       ok(!bt_ctf_field_integer_unsigned_set_value(packet_header_field,
                54321), "Set custom packet header value successfully");
-       ok(bt_stream_set_packet_header(stream1, NULL) < 0,
-               "bt_stream_set_packet_header handles a NULL packet header correctly");
-       ok(bt_stream_set_packet_header(NULL, packet_header) < 0,
-               "bt_stream_set_packet_header handles a NULL stream correctly");
-       ok(bt_stream_set_packet_header(stream1, packet_header_field) < 0,
-               "bt_stream_set_packet_header rejects a packet header of the wrong type");
-       ok(!bt_stream_set_packet_header(stream1, packet_header),
+       ok(bt_ctf_stream_set_packet_header(stream1, NULL) < 0,
+               "bt_ctf_stream_set_packet_header handles a NULL packet header correctly");
+       ok(bt_ctf_stream_set_packet_header(NULL, packet_header) < 0,
+               "bt_ctf_stream_set_packet_header handles a NULL stream correctly");
+       ok(bt_ctf_stream_set_packet_header(stream1, packet_header_field) < 0,
+               "bt_ctf_stream_set_packet_header rejects a packet header of the wrong type");
+       ok(!bt_ctf_stream_set_packet_header(stream1, packet_header),
                "Successfully set a stream's packet header");
 
        ok(bt_ctf_writer_add_environment_field(writer, "new_field", "test") == 0,
@@ -3095,10 +2119,6 @@ int main(int argc, char **argv)
 
        test_clock_utils();
 
-       test_create_writer_vs_non_writer_mode();
-
-       test_set_clock_non_writer_stream_class();
-
        test_instanciate_event_before_stream(writer, clock);
 
        append_simple_event(stream_class, stream1, clock);
@@ -3113,12 +2133,6 @@ int main(int argc, char **argv)
 
        test_custom_event_header_stream(writer, clock);
 
-       test_static_trace();
-
-       test_trace_is_static_listener();
-
-       test_trace_uuid();
-
        metadata_string = bt_ctf_writer_get_metadata_string(writer);
        ok(metadata_string, "Get metadata string");
 
@@ -3143,7 +2157,7 @@ int main(int argc, char **argv)
 
        validate_trace(argv[1], trace_path);
 
-       //recursive_rmdir(trace_path);
+       recursive_rmdir(trace_path);
        g_free(trace_path);
        g_free(metadata_path);
 
index 7c1c8c261705bf49e3aacd79391dfa87fc07eec7..50498c2cf4d7a600c2b6aa2fa844d0f8a54e1e4f 100644 (file)
@@ -73,6 +73,7 @@ struct bt_event_class *init_event_class(const char *name)
 {
        int ret;
        struct bt_event_class *ec = bt_event_class_create(name);
+       struct bt_field_type *payload_ft = NULL;;
        struct bt_field_type *int_field =
                        bt_field_type_integer_create(8);
 
@@ -80,16 +81,20 @@ struct bt_event_class *init_event_class(const char *name)
                goto error;
        }
 
-       ret = bt_event_class_add_field(ec, int_field, "an_int_field");
+       payload_ft = bt_event_class_get_payload_field_type(ec);
+       ret = bt_field_type_structure_add_field(payload_ft,
+               int_field, "an_int_field");
        if (ret) {
                goto error;
        }
 
        BT_PUT(int_field);
+       BT_PUT(payload_ft);
        return ec;
 error:
        BT_PUT(ec);
        BT_PUT(int_field);
+       BT_PUT(payload_ft);
        return NULL;
 }
 
@@ -125,10 +130,10 @@ static void set_stream_class_field_types(
        assert(ret == 0);
        bt_put(ft);
 
-       ret = bt_stream_class_set_packet_context_type(stream_class,
+       ret = bt_stream_class_set_packet_context_field_type(stream_class,
                packet_context_type);
        assert(ret == 0);
-       ret = bt_stream_class_set_event_header_type(stream_class,
+       ret = bt_stream_class_set_event_header_field_type(stream_class,
                event_header_type);
        assert(ret == 0);
 
@@ -151,7 +156,7 @@ static void set_trace_packet_header(struct bt_trace *trace)
        assert(ret == 0);
        bt_put(ft);
 
-       ret = bt_trace_set_packet_header_type(trace,
+       ret = bt_trace_set_packet_header_field_type(trace,
                packet_header_type);
        assert(ret == 0);
 
index f652fa99d6ab79234579fa6b6de8f9d1f29011a9..aa7f29809e3e2d2bc695ccf002baa7f06e041a18 100644 (file)
@@ -315,7 +315,7 @@ void init_static_data(void)
        ret = bt_trace_set_native_byte_order(trace,
                BT_BYTE_ORDER_LITTLE_ENDIAN);
        assert(ret == 0);
-       ret = bt_trace_set_packet_header_type(trace, empty_struct_ft);
+       ret = bt_trace_set_packet_header_field_type(trace, empty_struct_ft);
        assert(ret == 0);
        src_clock_class = bt_clock_class_create("my-clock", 1000000000);
        assert(src_clock_class);
@@ -332,20 +332,20 @@ void init_static_data(void)
        assert(ret == 0);
        src_stream_class = bt_stream_class_create("my-stream-class");
        assert(src_stream_class);
-       ret = bt_stream_class_set_packet_context_type(src_stream_class,
+       ret = bt_stream_class_set_packet_context_field_type(src_stream_class,
                empty_struct_ft);
        assert(ret == 0);
-       ret = bt_stream_class_set_event_header_type(src_stream_class,
+       ret = bt_stream_class_set_event_header_field_type(src_stream_class,
                empty_struct_ft);
        assert(ret == 0);
-       ret = bt_stream_class_set_event_context_type(src_stream_class,
+       ret = bt_stream_class_set_event_context_field_type(src_stream_class,
                empty_struct_ft);
        assert(ret == 0);
        src_event_class = bt_event_class_create("my-event-class");
-       ret = bt_event_class_set_context_type(src_event_class,
+       ret = bt_event_class_set_context_field_type(src_event_class,
                empty_struct_ft);
        assert(ret == 0);
-       ret = bt_event_class_set_context_type(src_event_class,
+       ret = bt_event_class_set_context_field_type(src_event_class,
                empty_struct_ft);
        assert(ret == 0);
        ret = bt_stream_class_add_event_class(src_stream_class,
@@ -353,22 +353,22 @@ void init_static_data(void)
        assert(ret == 0);
        ret = bt_trace_add_stream_class(trace, src_stream_class);
        assert(ret == 0);
-       stream = bt_stream_create(src_stream_class, "stream0");
+       stream = bt_stream_create(src_stream_class, "stream0", 0);
        assert(stream);
        src_packet0 = bt_packet_create(stream);
        assert(src_packet0);
        bt_put(stream);
-       stream = bt_stream_create(src_stream_class, "stream1");
+       stream = bt_stream_create(src_stream_class, "stream1", 1);
        assert(stream);
        src_packet1 = bt_packet_create(stream);
        assert(src_packet0);
        bt_put(stream);
-       stream = bt_stream_create(src_stream_class, "stream2");
+       stream = bt_stream_create(src_stream_class, "stream2", 2);
        assert(stream);
        src_packet2 = bt_packet_create(stream);
        assert(src_packet0);
        bt_put(stream);
-       stream = bt_stream_create(src_stream_class, "stream3");
+       stream = bt_stream_create(src_stream_class, "stream3", 3);
        assert(stream);
        src_packet3 = bt_packet_create(stream);
        assert(src_packet0);
This page took 0.545724 seconds and 4 git commands to generate.