lib: fully detach CTF IR and CTF writer implementations
authorPhilippe Proulx <eeppeliteloop@gmail.com>
Wed, 15 Aug 2018 22:42:03 +0000 (18:42 -0400)
committerPhilippe Proulx <eeppeliteloop@gmail.com>
Thu, 2 May 2019 04:07:36 +0000 (00:07 -0400)
This patch makes the CTF IR and CTF writer implementations completely
independent. To achieve this, files were partly or fully copied from CTF
IR to CTF writer directories, and everything part of the copied "common"
part was prefixed with `bt_ctf_` or `BT_CTF_` instead of `bt_` or `BT_`.

For the moment, both CTF IR and CTF writer implementations have their
own common part, each of which is only common to its own implementation
now.

Having independent implementations makes it easier to modify one,
sometimes drastically, without caring about not changing the common part
too much.

The BT_LIB_LOG*() macros do not accept the `w` category anymore, making
the CTF writer objects not supported by them. The `_` category is still
accepted for the common part of the CTF IR objects.

The CTF writer clock class API is hidden instead of being public as of
this patch because this was faster to implement and it does not break
backward compatibility with Babeltrace 1.

For some reason, `plugins/text/pretty/print.c` used some `BT_CTF_*`
enumeration members, so this is fixed too.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
56 files changed:
include/Makefile.am
include/babeltrace/babeltrace.h
include/babeltrace/ctf-ir/utils.h
include/babeltrace/ctf-writer/attributes-internal.h [new file with mode: 0644]
include/babeltrace/ctf-writer/clock-class-internal.h [new file with mode: 0644]
include/babeltrace/ctf-writer/clock-class.h [deleted file]
include/babeltrace/ctf-writer/clock-internal.h
include/babeltrace/ctf-writer/event-class-internal.h [new file with mode: 0644]
include/babeltrace/ctf-writer/event-fields.h
include/babeltrace/ctf-writer/event-internal.h
include/babeltrace/ctf-writer/event-types.h
include/babeltrace/ctf-writer/event.h
include/babeltrace/ctf-writer/field-path-internal.h [new file with mode: 0644]
include/babeltrace/ctf-writer/field-types-internal.h
include/babeltrace/ctf-writer/field-types.h
include/babeltrace/ctf-writer/field-wrapper-internal.h [new file with mode: 0644]
include/babeltrace/ctf-writer/fields-internal.h
include/babeltrace/ctf-writer/fields.h
include/babeltrace/ctf-writer/resolve-internal.h [new file with mode: 0644]
include/babeltrace/ctf-writer/serialize-internal.h
include/babeltrace/ctf-writer/stream-class-internal.h
include/babeltrace/ctf-writer/stream-class.h
include/babeltrace/ctf-writer/stream-internal.h
include/babeltrace/ctf-writer/trace-internal.h
include/babeltrace/ctf-writer/trace.h
include/babeltrace/ctf-writer/utils-internal.h [new file with mode: 0644]
include/babeltrace/ctf-writer/utils.h [new file with mode: 0644]
include/babeltrace/ctf-writer/validation-internal.h [new file with mode: 0644]
include/babeltrace/ctf-writer/visitor-internal.h [new file with mode: 0644]
include/babeltrace/ctf-writer/visitor.h [new file with mode: 0644]
include/babeltrace/ctf-writer/writer-internal.h
include/babeltrace/lib-logging-internal.h
lib/ctf-writer/Makefile.am
lib/ctf-writer/attributes.c [new file with mode: 0644]
lib/ctf-writer/clock-class.c [new file with mode: 0644]
lib/ctf-writer/clock.c
lib/ctf-writer/event-class.c
lib/ctf-writer/event.c
lib/ctf-writer/field-path.c [new file with mode: 0644]
lib/ctf-writer/field-types.c
lib/ctf-writer/field-wrapper.c [new file with mode: 0644]
lib/ctf-writer/fields.c
lib/ctf-writer/functor.c
lib/ctf-writer/resolve.c [new file with mode: 0644]
lib/ctf-writer/serialize.c
lib/ctf-writer/stream-class.c
lib/ctf-writer/stream.c
lib/ctf-writer/trace.c
lib/ctf-writer/utils.c [new file with mode: 0644]
lib/ctf-writer/validation.c [new file with mode: 0644]
lib/ctf-writer/visitor.c [new file with mode: 0644]
lib/ctf-writer/writer.c
lib/lib-logging.c
plugins/text/pretty/print.c
plugins/utils/trimmer/iterator.c
tests/lib/test_ctf_writer.c

index 5bb35abe219af030e507b81c609744b7edabe423..004a337cfa3194587ea7259bbda22adb213f3d8a 100644 (file)
@@ -86,7 +86,6 @@ 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.h \
@@ -96,6 +95,8 @@ babeltracectfwriterinclude_HEADERS = \
        babeltrace/ctf-writer/stream-class.h \
        babeltrace/ctf-writer/stream.h \
        babeltrace/ctf-writer/trace.h \
+       babeltrace/ctf-writer/utils.h \
+       babeltrace/ctf-writer/visitor.h \
        babeltrace/ctf-writer/writer.h
 
 # CTF IR API
@@ -180,16 +181,25 @@ noinst_HEADERS = \
        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/attributes-internal.h \
+       babeltrace/ctf-writer/clock-class-internal.h \
+       babeltrace/ctf-writer/clock-internal.h \
+       babeltrace/ctf-writer/event-class-internal.h \
        babeltrace/ctf-writer/event-internal.h \
-       babeltrace/ctf-writer/trace-internal.h \
+       babeltrace/ctf-writer/field-path-internal.h \
+       babeltrace/ctf-writer/fields-internal.h \
        babeltrace/ctf-writer/field-types-internal.h \
+       babeltrace/ctf-writer/field-wrapper-internal.h \
+       babeltrace/ctf-writer/functor-internal.h \
+       babeltrace/ctf-writer/resolve-internal.h \
        babeltrace/ctf-writer/serialize-internal.h \
-       babeltrace/ctf-writer/writer-internal.h \
+       babeltrace/ctf-writer/stream-class-internal.h \
        babeltrace/ctf-writer/stream-internal.h \
-       babeltrace/ctf-writer/clock-internal.h \
-       babeltrace/ctf-writer/functor-internal.h \
+       babeltrace/ctf-writer/trace-internal.h \
+       babeltrace/ctf-writer/utils-internal.h \
+       babeltrace/ctf-writer/validation-internal.h \
+       babeltrace/ctf-writer/visitor-internal.h \
+       babeltrace/ctf-writer/writer-internal.h \
        babeltrace/mmap-align-internal.h \
        babeltrace/align-internal.h \
        babeltrace/logging-internal.h \
index b208b8b02b30181f8069d6f1d23ab5d4cff4cd7e..ec07b88fa87d9443e8ed5fff988483ca14293bda 100644 (file)
@@ -36,7 +36,6 @@
 #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>
@@ -46,6 +45,8 @@
 #include <babeltrace/ctf-writer/stream-class.h>
 #include <babeltrace/ctf-writer/stream.h>
 #include <babeltrace/ctf-writer/trace.h>
+#include <babeltrace/ctf-writer/utils.h>
+#include <babeltrace/ctf-writer/visitor.h>
 #include <babeltrace/ctf-writer/writer.h>
 
 /* CTF IR API */
index 483e69463f0df2b7f39100adcf98a04dfc42466e..c93b0d8442c8b2fdef4a799a5facc516e389f3d5 100644 (file)
@@ -71,13 +71,6 @@ extern bt_bool bt_identifier_is_valid(const char *identifier);
 
 /** @} */
 
-/* Pre-2.0 CTF writer compatibility */
-static inline
-int bt_ctf_validate_identifier(const char *identifier)
-{
-       return bt_identifier_is_valid(identifier) ? 1 : 0;
-}
-
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/babeltrace/ctf-writer/attributes-internal.h b/include/babeltrace/ctf-writer/attributes-internal.h
new file mode 100644 (file)
index 0000000..2fc6c59
--- /dev/null
@@ -0,0 +1,71 @@
+#ifndef BABELTRACE_CTF_WRITER_ATTRIBUTES_H
+#define BABELTRACE_CTF_WRITER_ATTRIBUTES_H
+
+/*
+ * attributes.c
+ *
+ * Babeltrace - CTF writer: Attributes internal
+ *
+ * Copyright (c) 2015 EfficiOS Inc. and Linux Foundation
+ * Copyright (c) 2015 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.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include <babeltrace/babeltrace-internal.h>
+#include <babeltrace/values.h>
+
+BT_HIDDEN
+struct bt_value *bt_ctf_attributes_create(void);
+
+BT_HIDDEN
+void bt_ctf_attributes_destroy(struct bt_value *attr_obj);
+
+BT_HIDDEN
+int64_t bt_ctf_attributes_get_count(struct bt_value *attr_obj);
+
+BT_HIDDEN
+const char *bt_ctf_attributes_get_field_name(struct bt_value *attr_obj,
+               uint64_t index);
+
+BT_HIDDEN
+struct bt_value *bt_ctf_attributes_borrow_field_value(struct bt_value *attr_obj,
+               uint64_t index);
+
+BT_HIDDEN
+int bt_ctf_attributes_set_field_value(struct bt_value *attr_obj,
+               const char *name, struct bt_value *value_obj);
+
+BT_HIDDEN
+struct bt_value *bt_ctf_attributes_borrow_field_value_by_name(
+               struct bt_value *attr_obj, const char *name);
+
+BT_HIDDEN
+int bt_ctf_attributes_freeze(struct bt_value *attr_obj);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BABELTRACE_CTF_WRITER_ATTRIBUTES_H */
diff --git a/include/babeltrace/ctf-writer/clock-class-internal.h b/include/babeltrace/ctf-writer/clock-class-internal.h
new file mode 100644 (file)
index 0000000..b50eaae
--- /dev/null
@@ -0,0 +1,121 @@
+#ifndef BABELTRACE_CTF_WRITER_CLOCK_CLASS_INTERNAL_H
+#define BABELTRACE_CTF_WRITER_CLOCK_CLASS_INTERNAL_H
+
+/*
+ * BabelTrace - CTF writer: Clock class internal
+ *
+ * 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.
+ */
+
+#include <babeltrace/object-internal.h>
+#include <babeltrace/babeltrace-internal.h>
+#include <babeltrace/object-pool-internal.h>
+#include <babeltrace/compat/uuid-internal.h>
+#include <babeltrace/types.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <glib.h>
+
+struct bt_ctf_clock_class {
+       struct bt_object base;
+       GString *name;
+       GString *description;
+       uint64_t frequency;
+       uint64_t precision;
+       int64_t offset_s;       /* Offset in seconds */
+       int64_t offset;         /* Offset in ticks */
+       unsigned char uuid[BABELTRACE_UUID_LEN];
+       int uuid_set;
+       int absolute;
+
+       /*
+        * A clock's properties can't be modified once it is added to a stream
+        * class.
+        */
+       int frozen;
+};
+
+BT_HIDDEN
+void bt_ctf_clock_class_freeze(struct bt_ctf_clock_class *clock_class);
+
+BT_HIDDEN
+bt_bool bt_ctf_clock_class_is_valid(struct bt_ctf_clock_class *clock_class);
+
+BT_HIDDEN
+int bt_ctf_clock_class_compare(struct bt_ctf_clock_class *clock_class_a,
+               struct bt_ctf_clock_class *clock_class_b);
+
+BT_HIDDEN
+struct bt_ctf_clock_class *bt_ctf_clock_class_create(const char *name,
+               uint64_t freq);
+BT_HIDDEN
+const char *bt_ctf_clock_class_get_name(
+               struct bt_ctf_clock_class *clock_class);
+BT_HIDDEN
+int bt_ctf_clock_class_set_name(struct bt_ctf_clock_class *clock_class,
+               const char *name);
+BT_HIDDEN
+const char *bt_ctf_clock_class_get_description(
+               struct bt_ctf_clock_class *clock_class);
+BT_HIDDEN
+int bt_ctf_clock_class_set_description(
+               struct bt_ctf_clock_class *clock_class,
+               const char *desc);
+BT_HIDDEN
+uint64_t bt_ctf_clock_class_get_frequency(
+               struct bt_ctf_clock_class *clock_class);
+BT_HIDDEN
+int bt_ctf_clock_class_set_frequency(
+               struct bt_ctf_clock_class *clock_class, uint64_t freq);
+BT_HIDDEN
+uint64_t bt_ctf_clock_class_get_precision(
+               struct bt_ctf_clock_class *clock_class);
+BT_HIDDEN
+int bt_ctf_clock_class_set_precision(
+               struct bt_ctf_clock_class *clock_class, uint64_t precision);
+BT_HIDDEN
+int bt_ctf_clock_class_get_offset_s(
+               struct bt_ctf_clock_class *clock_class, int64_t *seconds);
+BT_HIDDEN
+int bt_ctf_clock_class_set_offset_s(
+               struct bt_ctf_clock_class *clock_class, int64_t seconds);
+BT_HIDDEN
+int bt_ctf_clock_class_get_offset_cycles(
+               struct bt_ctf_clock_class *clock_class, int64_t *cycles);
+BT_HIDDEN
+int bt_ctf_clock_class_set_offset_cycles(
+               struct bt_ctf_clock_class *clock_class, int64_t cycles);
+BT_HIDDEN
+bt_bool bt_ctf_clock_class_is_absolute(
+               struct bt_ctf_clock_class *clock_class);
+BT_HIDDEN
+int bt_ctf_clock_class_set_is_absolute(
+               struct bt_ctf_clock_class *clock_class, bt_bool is_absolute);
+BT_HIDDEN
+const unsigned char *bt_ctf_clock_class_get_uuid(
+               struct bt_ctf_clock_class *clock_class);
+BT_HIDDEN
+int bt_ctf_clock_class_set_uuid(struct bt_ctf_clock_class *clock_class,
+               const unsigned char *uuid);
+
+#endif /* BABELTRACE_CTF_WRITER_CLOCK_CLASS_INTERNAL_H */
diff --git a/include/babeltrace/ctf-writer/clock-class.h b/include/babeltrace/ctf-writer/clock-class.h
deleted file mode 100644 (file)
index 2ba1d8e..0000000
+++ /dev/null
@@ -1,288 +0,0 @@
-#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 5c59e29a5bda3ed1b4f4cde723fa9d3581cb2c62..0a3811d6c4d6ffdd026a94c71da93ed39a384dce 100644 (file)
  */
 
 #include <babeltrace/ctf-writer/clock.h>
-#include <babeltrace/ctf-ir/clock-class.h>
-#include <babeltrace/ctf-ir/trace-internal.h>
+#include <babeltrace/ctf-writer/clock-class-internal.h>
+#include <babeltrace/ctf-writer/trace-internal.h>
 #include <babeltrace/object-internal.h>
 #include <babeltrace/babeltrace-internal.h>
 #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_ctf_clock_class *clock_class;
diff --git a/include/babeltrace/ctf-writer/event-class-internal.h b/include/babeltrace/ctf-writer/event-class-internal.h
new file mode 100644 (file)
index 0000000..cef39ae
--- /dev/null
@@ -0,0 +1,395 @@
+#ifndef BABELTRACE_CTF_WRITER_EVENT_CLASS_INTERNAL_H
+#define BABELTRACE_CTF_WRITER_EVENT_CLASS_INTERNAL_H
+
+/*
+ * Babeltrace - CTF writer: Event class internal
+ *
+ * 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.
+ */
+
+#include <babeltrace/assert-internal.h>
+#include <babeltrace/babeltrace-internal.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-internal.h>
+#include <babeltrace/object-internal.h>
+#include <babeltrace/values.h>
+#include <glib.h>
+
+struct bt_ctf_event_class_common {
+       struct bt_object base;
+       struct bt_ctf_field_type_common *context_field_type;
+       struct bt_ctf_field_type_common *payload_field_type;
+       int frozen;
+
+       /*
+        * This flag indicates if the event class is valid. A valid
+        * event class is _always_ frozen. However, an event class
+        * may be frozen, but not valid yet. This is okay, as long as
+        * no events are created out of this event class.
+        */
+       int valid;
+
+       /* Attributes */
+       GString *name;
+       int64_t id;
+       int log_level;
+       GString *emf_uri;
+};
+
+BT_HIDDEN
+void bt_ctf_event_class_common_freeze(struct bt_ctf_event_class_common *event_class);
+
+BT_HIDDEN
+void bt_ctf_event_class_common_set_native_byte_order(
+               struct bt_ctf_event_class_common *event_class, int byte_order);
+
+static inline
+struct bt_ctf_stream_class_common *bt_ctf_event_class_common_borrow_stream_class(
+               struct bt_ctf_event_class_common *event_class)
+{
+       BT_ASSERT(event_class);
+       return (void *) bt_object_borrow_parent(&event_class->base);
+}
+
+typedef struct bt_ctf_field_type_common *(*bt_ctf_field_type_structure_create_func)();
+
+BT_HIDDEN
+int bt_ctf_event_class_common_initialize(struct bt_ctf_event_class_common *event_class,
+               const char *name, bt_object_release_func release_func,
+               bt_ctf_field_type_structure_create_func ft_struct_create_func);
+
+BT_HIDDEN
+void bt_ctf_event_class_common_finalize(struct bt_object *obj);
+
+BT_HIDDEN
+int bt_ctf_event_class_common_validate_single_clock_class(
+               struct bt_ctf_event_class_common *event_class,
+               struct bt_ctf_clock_class **expected_clock_class);
+
+static inline
+const char *bt_ctf_event_class_common_get_name(
+               struct bt_ctf_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_ctf_event_class_common_get_id(
+               struct bt_ctf_event_class_common *event_class)
+{
+       BT_ASSERT_PRE_NON_NULL(event_class, "Event class");
+       return event_class->id;
+}
+
+static inline
+int bt_ctf_event_class_common_set_id(
+               struct bt_ctf_event_class_common *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_ctf_event_class_common_get_name(event_class),
+                       bt_ctf_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_ctf_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_ctf_event_class_common_get_name(event_class), id);
+
+end:
+       return ret;
+}
+
+static inline
+int bt_ctf_event_class_common_get_log_level(
+               struct bt_ctf_event_class_common *event_class)
+{
+       BT_ASSERT_PRE_NON_NULL(event_class, "Event class");
+       return event_class->log_level;
+}
+
+static inline
+int bt_ctf_event_class_common_set_log_level(
+               struct bt_ctf_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_ctf_event_class_common_get_name(event_class),
+                       bt_ctf_event_class_common_get_id(event_class));
+               ret = -1;
+               goto end;
+       }
+
+       switch (log_level) {
+       case BT_CTF_EVENT_CLASS_LOG_LEVEL_UNSPECIFIED:
+       case BT_CTF_EVENT_CLASS_LOG_LEVEL_EMERGENCY:
+       case BT_CTF_EVENT_CLASS_LOG_LEVEL_ALERT:
+       case BT_CTF_EVENT_CLASS_LOG_LEVEL_CRITICAL:
+       case BT_CTF_EVENT_CLASS_LOG_LEVEL_ERROR:
+       case BT_CTF_EVENT_CLASS_LOG_LEVEL_WARNING:
+       case BT_CTF_EVENT_CLASS_LOG_LEVEL_NOTICE:
+       case BT_CTF_EVENT_CLASS_LOG_LEVEL_INFO:
+       case BT_CTF_EVENT_CLASS_LOG_LEVEL_DEBUG_SYSTEM:
+       case BT_CTF_EVENT_CLASS_LOG_LEVEL_DEBUG_PROGRAM:
+       case BT_CTF_EVENT_CLASS_LOG_LEVEL_DEBUG_PROCESS:
+       case BT_CTF_EVENT_CLASS_LOG_LEVEL_DEBUG_MODULE:
+       case BT_CTF_EVENT_CLASS_LOG_LEVEL_DEBUG_UNIT:
+       case BT_CTF_EVENT_CLASS_LOG_LEVEL_DEBUG_FUNCTION:
+       case BT_CTF_EVENT_CLASS_LOG_LEVEL_DEBUG_LINE:
+       case BT_CTF_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_ctf_event_class_common_get_name(event_class),
+                       bt_ctf_event_class_common_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_ctf_event_class_common_get_name(event_class),
+               bt_ctf_event_class_common_get_id(event_class),
+               bt_ctf_event_class_log_level_string(log_level));
+
+end:
+       return ret;
+}
+
+static inline
+const char *bt_ctf_event_class_common_get_emf_uri(
+               struct bt_ctf_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_ctf_event_class_common_set_emf_uri(
+               struct bt_ctf_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_ctf_event_class_common_get_name(event_class),
+                       bt_ctf_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_ctf_event_class_common_get_name(event_class),
+                       bt_ctf_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_ctf_event_class_common_get_name(event_class),
+                       bt_ctf_event_class_common_get_id(event_class));
+       }
+
+end:
+       return ret;
+}
+
+static inline
+struct bt_ctf_field_type_common *bt_ctf_event_class_common_borrow_context_field_type(
+               struct bt_ctf_event_class_common *event_class)
+{
+       struct bt_ctf_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_ctf_event_class_common_get_name(event_class),
+                       bt_ctf_event_class_common_get_id(event_class));
+               goto end;
+       }
+
+       context_ft = event_class->context_field_type;
+
+end:
+       return context_ft;
+}
+
+static inline
+int bt_ctf_event_class_common_set_context_field_type(
+               struct bt_ctf_event_class_common *event_class,
+               struct bt_ctf_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_ctf_event_class_common_get_name(event_class),
+                       bt_ctf_event_class_common_get_id(event_class));
+               ret = -1;
+               goto end;
+       }
+
+       if (context_ft && bt_ctf_field_type_common_get_type_id(context_ft) !=
+                       BT_CTF_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_ctf_event_class_common_get_name(event_class),
+                       bt_ctf_event_class_common_get_id(event_class),
+                       bt_ctf_field_type_id_string(
+                               bt_ctf_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_ctf_event_class_common_get_name(event_class),
+               bt_ctf_event_class_common_get_id(event_class), context_ft);
+
+end:
+       return ret;
+}
+
+static inline
+struct bt_ctf_field_type_common *bt_ctf_event_class_common_borrow_payload_field_type(
+               struct bt_ctf_event_class_common *event_class)
+{
+       BT_ASSERT_PRE_NON_NULL(event_class, "Event class");
+       return event_class->payload_field_type;
+}
+
+static inline
+int bt_ctf_event_class_common_set_payload_field_type(
+               struct bt_ctf_event_class_common *event_class,
+               struct bt_ctf_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_ctf_field_type_common_get_type_id(payload_ft) !=
+                       BT_CTF_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_ctf_event_class_common_get_name(event_class),
+                       bt_ctf_event_class_common_get_id(event_class), payload_ft,
+                       bt_ctf_field_type_id_string(
+                               bt_ctf_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_ctf_event_class_common_get_name(event_class),
+               bt_ctf_event_class_common_get_id(event_class), payload_ft);
+end:
+       return ret;
+}
+
+#endif /* BABELTRACE_CTF_WRITER_EVENT_CLASS_INTERNAL_H */
index e06c354c50659a6f07be4161b194ba668c7e5c43..089b1c5f07cc6b73ea8d104c0051b8f8f69cc3c5 100644 (file)
@@ -57,14 +57,14 @@ extern "C" {
 
 /* Pre-2.0 CTF writer compatibility */
 static inline
-void bt_ctf_field_get(struct bt_field *field)
+void bt_ctf_field_get(struct bt_ctf_field *field)
 {
        bt_get(field);
 }
 
 /* Pre-2.0 CTF writer compatibility */
 static inline
-void bt_ctf_field_put(struct bt_field *field)
+void bt_ctf_field_put(struct bt_ctf_field *field)
 {
        bt_put(field);
 }
index 6c987a6b1ae0784287081e6d15f9349d816382d9..3a06131b26066635a9f69c5fc4ea53a7b374de3e 100644 (file)
  * http://www.efficios.com/ctf
  */
 
+#include <babeltrace/assert-internal.h>
+#include <babeltrace/assert-pre-internal.h>
 #include <babeltrace/babeltrace-internal.h>
-#include <babeltrace/ctf-ir/event-class-internal.h>
-#include <babeltrace/ctf-ir/event-internal.h>
+#include <babeltrace/ctf-writer/event-class-internal.h>
+#include <babeltrace/ctf-writer/event-internal.h>
 #include <babeltrace/ctf-writer/field-types.h>
+#include <babeltrace/ctf-writer/field-wrapper-internal.h>
+#include <babeltrace/ctf-writer/fields-internal.h>
+#include <babeltrace/ctf-writer/fields.h>
+#include <babeltrace/ctf-writer/stream-class.h>
+#include <babeltrace/ctf-writer/stream-internal.h>
+#include <babeltrace/ctf-writer/stream.h>
+#include <babeltrace/ctf-writer/validation-internal.h>
+#include <babeltrace/object-internal.h>
+#include <babeltrace/values.h>
 
 struct bt_ctf_stream_class;
 struct bt_ctf_stream_pos;
 struct metadata_context;
 
+struct bt_ctf_event_common {
+       struct bt_object base;
+       struct bt_ctf_event_class_common *class;
+       struct bt_ctf_field_wrapper *header_field;
+       struct bt_ctf_field_common *stream_event_context_field;
+       struct bt_ctf_field_common *context_field;
+       struct bt_ctf_field_common *payload_field;
+       int frozen;
+};
+
+BT_HIDDEN
+int _bt_ctf_event_common_validate(struct bt_ctf_event_common *event);
+
+BT_HIDDEN
+void _bt_ctf_event_common_set_is_frozen(struct bt_ctf_event_common *event,
+               bool is_frozen);
+
+#ifdef BT_DEV_MODE
+# define bt_ctf_event_common_validate  _bt_ctf_event_common_validate
+# define bt_ctf_event_common_set_is_frozen     _bt_ctf_event_common_set_is_frozen
+#else
+# define bt_ctf_event_common_validate(_event)                  0
+# define bt_ctf_event_common_set_is_frozen(_event, _is_frozen)
+#endif
+
+#define BT_ASSERT_PRE_EVENT_COMMON_HOT(_event, _name)                  \
+       BT_ASSERT_PRE_HOT((_event), (_name), ": event-addr=%p", (_event))
+
+static inline
+struct bt_ctf_event_class_common *bt_ctf_event_common_borrow_class(
+               struct bt_ctf_event_common *event)
+{
+       BT_ASSERT(event);
+       return event->class;
+}
+
+typedef void *(*create_field_func)(void *);
+typedef void (*release_field_func)(void *);
+typedef void *(*create_header_field_func)(void *, void *);
+typedef void (*release_header_field_func)(void *, void *);
+
+BT_HIDDEN
+int bt_ctf_event_common_initialize(struct bt_ctf_event_common *event,
+               struct bt_ctf_event_class_common *event_class,
+               struct bt_ctf_clock_class *init_expected_clock_class,
+               bool is_shared_with_parent, bt_object_release_func release_func,
+               bt_ctf_validation_flag_copy_field_type_func field_type_copy_func,
+               bool must_be_in_trace,
+               int (*map_clock_classes_func)(struct bt_ctf_stream_class_common *stream_class,
+                       struct bt_ctf_field_type_common *packet_context_field_type,
+                       struct bt_ctf_field_type_common *event_header_field_type),
+               create_field_func create_field_func,
+               release_field_func release_field_func,
+               create_header_field_func create_header_field_func,
+               release_header_field_func release_header_field_func);
+
+static inline
+struct bt_ctf_field_common *bt_ctf_event_common_borrow_payload(
+               struct bt_ctf_event_common *event)
+{
+       struct bt_ctf_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_ctf_event_class_common_get_name(event->class),
+                       bt_ctf_event_class_common_get_id(event->class));
+               goto end;
+       }
+
+       payload = event->payload_field;
+
+end:
+       return payload;
+}
+
+static inline
+struct bt_ctf_field_common *bt_ctf_event_common_borrow_header(
+               struct bt_ctf_event_common *event)
+{
+       struct bt_ctf_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_ctf_event_class_common_get_name(event->class),
+                       bt_ctf_event_class_common_get_id(event->class));
+               goto end;
+       }
+
+       header = event->header_field->field;
+
+end:
+       return header;
+}
+
+static inline
+struct bt_ctf_field_common *bt_ctf_event_common_borrow_context(
+               struct bt_ctf_event_common *event)
+{
+       struct bt_ctf_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_ctf_event_class_common_get_name(event->class),
+                       bt_ctf_event_class_common_get_id(event->class));
+               goto end;
+       }
+
+       context = event->context_field;
+
+end:
+       return context;
+}
+
+static inline
+struct bt_ctf_field_common *bt_ctf_event_common_borrow_stream_event_context(
+               struct bt_ctf_event_common *event)
+{
+       struct bt_ctf_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_ctf_event_class_common_get_name(event->class),
+                       bt_ctf_event_class_common_get_id(event->class));
+               goto end;
+       }
+
+       stream_event_context = event->stream_event_context_field;
+
+end:
+       return stream_event_context;
+}
+
+static inline
+void bt_ctf_event_common_finalize(struct bt_object *obj,
+               void (*field_release_func)(void *),
+               void (*header_field_release_func)(void *, struct bt_ctf_event_common *))
+{
+       struct bt_ctf_event_common *event = (void *) obj;
+
+       BT_LOGD("Destroying event: addr=%p, "
+               "event-class-name=\"%s\", event-class-id=%" PRId64,
+               event,
+               event->class ? bt_ctf_event_class_common_get_name(event->class) : NULL,
+               event->class ? bt_ctf_event_class_common_get_id(event->class) : INT64_C(-1));
+
+       if (event->header_field) {
+               BT_LOGD_STR("Releasing event's header field.");
+               header_field_release_func(event->header_field, event);
+       }
+
+       if (event->stream_event_context_field) {
+               BT_LOGD_STR("Releasing event's stream event context field.");
+               field_release_func(event->stream_event_context_field);
+       }
+
+       if (event->context_field) {
+               BT_LOGD_STR("Releasing event's context field.");
+               field_release_func(event->context_field);
+       }
+
+       if (event->payload_field) {
+               BT_LOGD_STR("Releasing event's payload field.");
+               field_release_func(event->payload_field);
+       }
+
+       /*
+        * Leave this after calling header_field_release_func() because
+        * this function receives the event object and could need its
+        * class to perform some cleanup.
+        */
+       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);
+       }
+}
+
 struct bt_ctf_event {
-       struct bt_event_common common;
+       struct bt_ctf_event_common common;
 };
 
 struct bt_ctf_event_class {
-       struct bt_event_class_common common;
+       struct bt_ctf_event_class_common common;
 };
 
 BT_HIDDEN
@@ -60,8 +263,8 @@ 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)));
+       return BT_CTF_FROM_COMMON(bt_ctf_event_class_common_borrow_stream_class(
+               BT_CTF_TO_COMMON(event_class)));
 }
 
 #endif /* BABELTRACE_CTF_WRITER_EVENT_INTERNAL_H */
index 9b41bf09b04f0416e54cd9f8a5ca03aa33b7701b..7b1748ba21073f71ff2f21e246571f8dac67f2f7 100644 (file)
@@ -31,7 +31,7 @@
  */
 
 #include <babeltrace/ref.h>
-#include <babeltrace/ctf-ir/field-types.h>
+#include <babeltrace/ctf-writer/field-types.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -56,14 +56,14 @@ extern "C" {
 
 /* Pre-2.0 CTF writer compatibility */
 static inline
-void bt_ctf_field_type_get(struct bt_field_type *type)
+void bt_ctf_field_type_get(struct bt_ctf_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)
+void bt_ctf_field_type_put(struct bt_ctf_field_type *type)
 {
        bt_put(type);
 }
index 1a827a3f3a42f51a9b4d59035811f3616859581a..4c7ec2952de33d173ca8ec59e8a40e2419fe83de 100644 (file)
@@ -31,8 +31,6 @@
  */
 
 #include <babeltrace/ref.h>
-#include <babeltrace/ctf-ir/event-class.h>
-#include <babeltrace/ctf-ir/event.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -46,55 +44,55 @@ struct bt_ctf_field_type;
 
 enum bt_ctf_event_class_log_level {
        /// Unknown, used for errors.
-       BT_CTF_EVENT_CLASS_LOG_LEVEL_UNKNOWN            = BT_EVENT_CLASS_LOG_LEVEL_UNKNOWN,
+       BT_CTF_EVENT_CLASS_LOG_LEVEL_UNKNOWN            = -1,
 
        /// Unspecified log level.
-       BT_CTF_EVENT_CLASS_LOG_LEVEL_UNSPECIFIED        = BT_EVENT_CLASS_LOG_LEVEL_UNSPECIFIED,
+       BT_CTF_EVENT_CLASS_LOG_LEVEL_UNSPECIFIED        = 255,
 
        /// System is unusable.
-       BT_CTF_EVENT_CLASS_LOG_LEVEL_EMERGENCY          = BT_EVENT_CLASS_LOG_LEVEL_EMERGENCY,
+       BT_CTF_EVENT_CLASS_LOG_LEVEL_EMERGENCY          = 0,
 
        /// Action must be taken immediately.
-       BT_CTF_EVENT_CLASS_LOG_LEVEL_ALERT              = BT_EVENT_CLASS_LOG_LEVEL_ALERT,
+       BT_CTF_EVENT_CLASS_LOG_LEVEL_ALERT              = 1,
 
        /// Critical conditions.
-       BT_CTF_EVENT_CLASS_LOG_LEVEL_CRITICAL           = BT_EVENT_CLASS_LOG_LEVEL_CRITICAL,
+       BT_CTF_EVENT_CLASS_LOG_LEVEL_CRITICAL           = 2,
 
        /// Error conditions.
-       BT_CTF_EVENT_CLASS_LOG_LEVEL_ERROR              = BT_EVENT_CLASS_LOG_LEVEL_ERROR,
+       BT_CTF_EVENT_CLASS_LOG_LEVEL_ERROR              = 3,
 
        /// Warning conditions.
-       BT_CTF_EVENT_CLASS_LOG_LEVEL_WARNING            = BT_EVENT_CLASS_LOG_LEVEL_WARNING,
+       BT_CTF_EVENT_CLASS_LOG_LEVEL_WARNING            = 4,
 
        /// Normal, but significant, condition.
-       BT_CTF_EVENT_CLASS_LOG_LEVEL_NOTICE             = BT_EVENT_CLASS_LOG_LEVEL_NOTICE,
+       BT_CTF_EVENT_CLASS_LOG_LEVEL_NOTICE             = 5,
 
        /// Informational message.
-       BT_CTF_EVENT_CLASS_LOG_LEVEL_INFO               = BT_EVENT_CLASS_LOG_LEVEL_INFO,
+       BT_CTF_EVENT_CLASS_LOG_LEVEL_INFO               = 6,
 
        /// Debug information with system-level scope (set of programs).
-       BT_CTF_EVENT_CLASS_LOG_LEVEL_DEBUG_SYSTEM       = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_SYSTEM,
+       BT_CTF_EVENT_CLASS_LOG_LEVEL_DEBUG_SYSTEM       = 7,
 
        /// Debug information with program-level scope (set of processes).
-       BT_CTF_EVENT_CLASS_LOG_LEVEL_DEBUG_PROGRAM      = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROGRAM,
+       BT_CTF_EVENT_CLASS_LOG_LEVEL_DEBUG_PROGRAM      = 8,
 
        /// Debug information with process-level scope (set of modules).
-       BT_CTF_EVENT_CLASS_LOG_LEVEL_DEBUG_PROCESS      = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROCESS,
+       BT_CTF_EVENT_CLASS_LOG_LEVEL_DEBUG_PROCESS      = 9,
 
        /// 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,
+       BT_CTF_EVENT_CLASS_LOG_LEVEL_DEBUG_MODULE       = 10,
 
        /// Debug information with compilation unit scope (set of functions).
-       BT_CTF_EVENT_CLASS_LOG_LEVEL_DEBUG_UNIT         = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_UNIT,
+       BT_CTF_EVENT_CLASS_LOG_LEVEL_DEBUG_UNIT         = 11,
 
        /// Debug information with function-level scope.
-       BT_CTF_EVENT_CLASS_LOG_LEVEL_DEBUG_FUNCTION     = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_FUNCTION,
+       BT_CTF_EVENT_CLASS_LOG_LEVEL_DEBUG_FUNCTION     = 12,
 
        /// Debug information with line-level scope (default log level).
-       BT_CTF_EVENT_CLASS_LOG_LEVEL_DEBUG_LINE         = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_LINE,
+       BT_CTF_EVENT_CLASS_LOG_LEVEL_DEBUG_LINE         = 13,
 
        /// Debug-level message.
-       BT_CTF_EVENT_CLASS_LOG_LEVEL_DEBUG              = BT_EVENT_CLASS_LOG_LEVEL_DEBUG,
+       BT_CTF_EVENT_CLASS_LOG_LEVEL_DEBUG              = 14,
 };
 
 extern struct bt_ctf_event *bt_ctf_event_create(
diff --git a/include/babeltrace/ctf-writer/field-path-internal.h b/include/babeltrace/ctf-writer/field-path-internal.h
new file mode 100644 (file)
index 0000000..329ca6d
--- /dev/null
@@ -0,0 +1,69 @@
+#ifndef BABELTRACE_CTF_WRITER_FIELD_PATH_INTERNAL
+#define BABELTRACE_CTF_WRITER_FIELD_PATH_INTERNAL
+
+/*
+ * BabelTrace - CTF writer: Field path
+ *
+ * Copyright 2016 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.
+ *
+ * The Common Trace Format (CTF) Specification is available at
+ * http://www.efficios.com/ctf
+ */
+
+#include <babeltrace/common-internal.h>
+#include <babeltrace/object-internal.h>
+#include <babeltrace/assert-internal.h>
+#include <babeltrace/ctf-writer/field-types.h>
+#include <glib.h>
+
+struct bt_ctf_field_path {
+       struct bt_object base;
+       enum bt_ctf_scope root;
+
+       /*
+        * Array of integers (int) indicating the index in either
+        * structures, variants, arrays, or sequences that make up
+        * the path to a field type. -1 means the "current element
+        * of an array or sequence type".
+        */
+       GArray *indexes;
+};
+
+BT_HIDDEN
+struct bt_ctf_field_path *bt_ctf_field_path_create(void);
+
+BT_HIDDEN
+void bt_ctf_field_path_clear(struct bt_ctf_field_path *field_path);
+
+BT_HIDDEN
+struct bt_ctf_field_path *bt_ctf_field_path_copy(
+               struct bt_ctf_field_path *path);
+
+BT_HIDDEN enum bt_ctf_scope bt_ctf_field_path_get_root_scope(
+               const struct bt_ctf_field_path *field_path);
+
+BT_HIDDEN int64_t bt_ctf_field_path_get_index_count(
+               const struct bt_ctf_field_path *field_path);
+
+BT_HIDDEN int bt_ctf_field_path_get_index(
+               const struct bt_ctf_field_path *field_path, uint64_t index);
+
+#endif /* BABELTRACE_CTF_WRITER_FIELD_PATH_INTERNAL */
index 48ab3c3616aff53612b819185d5b54c94a9ddbfd..597bbefda20b720d95256ae98890ee7c4d09b210 100644 (file)
 #include <stdint.h>
 #include <stddef.h>
 
-/* For bt_bool */
+#include <babeltrace/assert-pre-internal.h>
+#include <babeltrace/babeltrace-internal.h>
+#include <babeltrace/ctf-writer/clock-class-internal.h>
 #include <babeltrace/ctf-writer/field-types.h>
 #include <babeltrace/ctf-writer/writer-internal.h>
+#include <babeltrace/object-internal.h>
+#include <babeltrace/types.h>
+
+#define BT_ASSERT_PRE_CTF_FT_COMMON_HAS_ID(_ft, _type_id, _name)       \
+       BT_ASSERT_PRE(((struct bt_ctf_field_type_common *) (_ft))->id == (_type_id), \
+               _name " has the wrong type ID: expected-type-id=%s, "   \
+               "ft-addr=%p", bt_ctf_field_type_id_string(_type_id), (_ft))
+
+#define BT_ASSERT_PRE_CTF_FT_HOT(_ft, _name)                           \
+       BT_ASSERT_PRE_HOT((_ft), (_name), ": ft-addr=%p", (_ft))
+
+#define BT_CTF_FIELD_TYPE_COMMON_STRUCTURE_FIELD_AT_INDEX(_ft, _index) \
+       (&g_array_index(((struct bt_ctf_field_type_common_structure *) (_ft))->fields, \
+               struct bt_ctf_field_type_common_structure_field, (_index)))
+
+#define BT_CTF_FIELD_TYPE_COMMON_VARIANT_CHOICE_AT_INDEX(_ft, _index)  \
+       (&g_array_index(((struct bt_ctf_field_type_common_variant *) (_ft))->choices, \
+               struct bt_ctf_field_type_common_variant_choice, (_index)))
+
+struct bt_ctf_field_common;
+struct bt_ctf_field_type_common;
+
+typedef void (*bt_ctf_field_type_common_method_freeze)(
+               struct bt_ctf_field_type_common *);
+typedef int (*bt_ctf_field_type_common_method_validate)(
+               struct bt_ctf_field_type_common *);
+typedef void (*bt_ctf_field_type_common_method_set_byte_order)(
+               struct bt_ctf_field_type_common *, enum bt_ctf_byte_order);
+typedef struct bt_ctf_field_type_common *(*bt_ctf_field_type_common_method_copy)(
+               struct bt_ctf_field_type_common *);
+typedef int (*bt_ctf_field_type_common_method_compare)(
+               struct bt_ctf_field_type_common *,
+               struct bt_ctf_field_type_common *);
+
+struct bt_ctf_field_type_common_methods {
+       bt_ctf_field_type_common_method_freeze freeze;
+       bt_ctf_field_type_common_method_validate validate;
+       bt_ctf_field_type_common_method_set_byte_order set_byte_order;
+       bt_ctf_field_type_common_method_copy copy;
+       bt_ctf_field_type_common_method_compare compare;
+};
+
+struct bt_ctf_field_type_common {
+       struct bt_object base;
+       enum bt_ctf_field_type_id id;
+       unsigned int alignment;
+
+       /* Virtual table */
+       struct bt_ctf_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.
+        */
+       int frozen;
+
+       /*
+        * This flag indicates if the field type is valid. A valid
+        * field type is _always_ frozen. All the nested field types of
+        * 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_ctf_field_type_common *` so that you can cast it to `struct
+        *   bt_ctf_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_ctf_field_type_common_integer {
+       struct bt_ctf_field_type_common common;
+
+       /* Owned by this */
+       struct bt_ctf_clock_class *mapped_clock_class;
+
+       enum bt_ctf_byte_order user_byte_order;
+       bt_bool is_signed;
+       unsigned int size;
+       enum bt_ctf_integer_base base;
+       enum bt_ctf_string_encoding encoding;
+};
+
+struct bt_ctf_enumeration_mapping {
+       union {
+               uint64_t _unsigned;
+               int64_t _signed;
+       } range_start;
+       union {
+               uint64_t _unsigned;
+               int64_t _signed;
+       } range_end;
+       GQuark string;
+};
+
+struct bt_ctf_field_type_common_enumeration {
+       struct bt_ctf_field_type_common common;
+
+       /* Owned by this */
+       struct bt_ctf_field_type_common_integer *container_ft;
+
+       /* Array of `struct bt_ctf_enumeration_mapping *`, owned by this */
+       GPtrArray *entries;
+
+       /* Only set during validation */
+       bt_bool has_overlapping_ranges;
+};
+
+enum bt_ctf_field_type_enumeration_mapping_iterator_type {
+       CTF_ITERATOR_BY_NAME,
+       CTF_ITERATOR_BY_SIGNED_VALUE,
+       CTF_ITERATOR_BY_UNSIGNED_VALUE,
+};
+
+struct bt_ctf_field_type_enumeration_mapping_iterator {
+       struct bt_object base;
+
+       /* Owned by this */
+       struct bt_ctf_field_type_common_enumeration *enumeration_ft;
+
+       enum bt_ctf_field_type_enumeration_mapping_iterator_type type;
+       int index;
+       union {
+               GQuark name_quark;
+               int64_t signed_value;
+               uint64_t unsigned_value;
+       } u;
+};
+
+struct bt_ctf_field_type_common_floating_point {
+       struct bt_ctf_field_type_common common;
+       enum bt_ctf_byte_order user_byte_order;
+       unsigned int exp_dig;
+       unsigned int mant_dig;
+};
+
+struct bt_ctf_field_type_common_structure_field {
+       GQuark name;
+
+       /* Owned by this */
+       struct bt_ctf_field_type_common *type;
+};
+
+struct bt_ctf_field_type_common_structure {
+       struct bt_ctf_field_type_common common;
+       GHashTable *field_name_to_index;
+
+       /*
+        * Array of `struct bt_ctf_field_type_common_structure_field`,
+        * owned by this
+        */
+       GArray *fields;
+};
+
+struct bt_ctf_field_type_common_variant_choice_range {
+       union {
+               int64_t i;
+               uint64_t u;
+       } lower;
+       union {
+               int64_t i;
+               uint64_t u;
+       } upper;
+};
+
+struct bt_ctf_field_type_common_variant_choice {
+       GQuark name;
+
+       /* Owned by this */
+       struct bt_ctf_field_type_common *type;
+
+       /* Array of `struct bt_ctf_field_type_common_variant_choice_range` */
+       GArray *ranges;
+};
+
+struct bt_ctf_field_type_common_variant {
+       struct bt_ctf_field_type_common common;
+       GString *tag_name;
+       bool choices_up_to_date;
+
+       /* Owned by this */
+       struct bt_ctf_field_type_common_enumeration *tag_ft;
+
+       /* Owned by this */
+       struct bt_ctf_field_path *tag_field_path;
+
+       GHashTable *choice_name_to_index;
+
+       /*
+        * Array of `struct bt_ctf_field_type_common_variant_choice`,
+        * owned by this */
+       GArray *choices;
+};
+
+struct bt_ctf_field_type_common_array {
+       struct bt_ctf_field_type_common common;
+
+       /* Owned by this */
+       struct bt_ctf_field_type_common *element_ft;
+
+       unsigned int length;
+};
+
+struct bt_ctf_field_type_common_sequence {
+       struct bt_ctf_field_type_common common;
+
+       /* Owned by this */
+       struct bt_ctf_field_type_common *element_ft;
+
+       GString *length_field_name;
+
+       /* Owned by this */
+       struct bt_ctf_field_path *length_field_path;
+};
+
+struct bt_ctf_field_type_common_string {
+       struct bt_ctf_field_type_common common;
+       enum bt_ctf_string_encoding encoding;
+};
+
+typedef struct bt_ctf_field_common *(* bt_ctf_field_common_create_func)(
+               struct bt_ctf_field_type_common *);
+
+BT_HIDDEN
+void bt_ctf_field_type_common_initialize(struct bt_ctf_field_type_common *ft,
+               bool init_bo, bt_object_release_func release_func,
+               struct bt_ctf_field_type_common_methods *methods);
+
+BT_HIDDEN
+void bt_ctf_field_type_common_integer_initialize(
+               struct bt_ctf_field_type_common *ft,
+               unsigned int size, bt_object_release_func release_func,
+               struct bt_ctf_field_type_common_methods *methods);
+
+BT_HIDDEN
+void bt_ctf_field_type_common_floating_point_initialize(
+               struct bt_ctf_field_type_common *ft,
+               bt_object_release_func release_func,
+               struct bt_ctf_field_type_common_methods *methods);
+
+BT_HIDDEN
+void bt_ctf_field_type_common_enumeration_initialize(
+               struct bt_ctf_field_type_common *ft,
+               struct bt_ctf_field_type_common *container_ft,
+               bt_object_release_func release_func,
+               struct bt_ctf_field_type_common_methods *methods);
+
+BT_HIDDEN
+void bt_ctf_field_type_common_string_initialize(
+               struct bt_ctf_field_type_common *ft,
+               bt_object_release_func release_func,
+               struct bt_ctf_field_type_common_methods *methods);
+
+BT_HIDDEN
+void bt_ctf_field_type_common_structure_initialize(
+               struct bt_ctf_field_type_common *ft,
+               bt_object_release_func release_func,
+               struct bt_ctf_field_type_common_methods *methods);
+
+BT_HIDDEN
+void bt_ctf_field_type_common_array_initialize(
+               struct bt_ctf_field_type_common *ft,
+               struct bt_ctf_field_type_common *element_ft,
+               unsigned int length, bt_object_release_func release_func,
+               struct bt_ctf_field_type_common_methods *methods);
+
+BT_HIDDEN
+void bt_ctf_field_type_common_sequence_initialize(
+               struct bt_ctf_field_type_common *ft,
+               struct bt_ctf_field_type_common *element_ft,
+               const char *length_field_name,
+               bt_object_release_func release_func,
+               struct bt_ctf_field_type_common_methods *methods);
+
+BT_HIDDEN
+void bt_ctf_field_type_common_variant_initialize(
+               struct bt_ctf_field_type_common *ft,
+               struct bt_ctf_field_type_common *tag_ft,
+               const char *tag_name,
+               bt_object_release_func release_func,
+               struct bt_ctf_field_type_common_methods *methods);
+
+BT_HIDDEN
+void bt_ctf_field_type_common_integer_destroy(struct bt_object *obj);
+
+BT_HIDDEN
+void bt_ctf_field_type_common_floating_point_destroy(struct bt_object *obj);
+
+BT_HIDDEN
+void bt_ctf_field_type_common_enumeration_destroy_recursive(struct bt_object *obj);
+
+BT_HIDDEN
+void bt_ctf_field_type_common_string_destroy(struct bt_object *obj);
+
+BT_HIDDEN
+void bt_ctf_field_type_common_structure_destroy_recursive(struct bt_object *obj);
+
+BT_HIDDEN
+void bt_ctf_field_type_common_array_destroy_recursive(struct bt_object *obj);
+
+BT_HIDDEN
+void bt_ctf_field_type_common_sequence_destroy_recursive(struct bt_object *obj);
+
+BT_HIDDEN
+void bt_ctf_field_type_common_variant_destroy_recursive(struct bt_object *obj);
+
+BT_HIDDEN
+int bt_ctf_field_type_common_integer_validate(struct bt_ctf_field_type_common *ft);
+
+BT_HIDDEN
+int bt_ctf_field_type_common_enumeration_validate_recursive(
+               struct bt_ctf_field_type_common *ft);
+
+BT_HIDDEN
+int bt_ctf_field_type_common_sequence_validate_recursive(
+               struct bt_ctf_field_type_common *ft);
+
+BT_HIDDEN
+int bt_ctf_field_type_common_array_validate_recursive(
+               struct bt_ctf_field_type_common *ft);
+
+BT_HIDDEN
+int bt_ctf_field_type_common_structure_validate_recursive(
+               struct bt_ctf_field_type_common *ft);
+
+BT_HIDDEN
+int bt_ctf_field_type_common_variant_validate_recursive(
+               struct bt_ctf_field_type_common *type);
+
+BT_HIDDEN
+int bt_ctf_field_type_common_validate(struct bt_ctf_field_type_common *ft);
+
+BT_HIDDEN
+int bt_ctf_field_type_common_integer_get_size(struct bt_ctf_field_type_common *ft);
+
+BT_HIDDEN
+bt_bool bt_ctf_field_type_common_integer_is_signed(struct bt_ctf_field_type_common *ft);
+
+BT_HIDDEN
+int bt_ctf_field_type_common_integer_set_is_signed(struct bt_ctf_field_type_common *ft,
+               bt_bool is_signed);
+
+BT_HIDDEN
+int bt_ctf_field_type_common_integer_set_size(struct bt_ctf_field_type_common *ft,
+               unsigned int size);
+
+BT_HIDDEN
+enum bt_ctf_integer_base bt_ctf_field_type_common_integer_get_base(
+               struct bt_ctf_field_type_common *ft);
+
+BT_HIDDEN
+int bt_ctf_field_type_common_integer_set_base(struct bt_ctf_field_type_common *ft,
+               enum bt_ctf_integer_base base);
+
+BT_HIDDEN
+enum bt_ctf_string_encoding bt_ctf_field_type_common_integer_get_encoding(
+               struct bt_ctf_field_type_common *ft);
+
+BT_HIDDEN
+int bt_ctf_field_type_common_integer_set_encoding(struct bt_ctf_field_type_common *ft,
+               enum bt_ctf_string_encoding encoding);
+
+BT_HIDDEN
+struct bt_ctf_clock_class *bt_ctf_field_type_common_integer_borrow_mapped_clock_class(
+               struct bt_ctf_field_type_common *ft);
+
+BT_HIDDEN
+int bt_ctf_field_type_common_integer_set_mapped_clock_class_no_check_frozen(
+               struct bt_ctf_field_type_common *ft,
+               struct bt_ctf_clock_class *clock_class);
+
+BT_HIDDEN
+int bt_ctf_field_type_common_integer_set_mapped_clock_class(
+               struct bt_ctf_field_type_common *ft,
+               struct bt_ctf_clock_class *clock_class);
+
+BT_HIDDEN
+struct bt_ctf_field_type_enumeration_mapping_iterator *
+bt_ctf_field_type_common_enumeration_find_mappings_by_name(
+               struct bt_ctf_field_type_common *ft, const char *name);
+
+BT_HIDDEN
+struct bt_ctf_field_type_enumeration_mapping_iterator *
+bt_ctf_field_type_common_enumeration_signed_find_mappings_by_value(
+               struct bt_ctf_field_type_common *ft, int64_t value);
+
+BT_HIDDEN
+struct bt_ctf_field_type_enumeration_mapping_iterator *
+bt_ctf_field_type_common_enumeration_unsigned_find_mappings_by_value(
+               struct bt_ctf_field_type_common *ft, uint64_t value);
+
+BT_HIDDEN
+int bt_ctf_field_type_common_enumeration_signed_get_mapping_by_index(
+               struct bt_ctf_field_type_common *ft, uint64_t index,
+               const char **mapping_name, int64_t *range_begin,
+               int64_t *range_end);
+
+BT_HIDDEN
+int bt_ctf_field_type_common_enumeration_unsigned_get_mapping_by_index(
+               struct bt_ctf_field_type_common *ft, uint64_t index,
+               const char **mapping_name, uint64_t *range_begin,
+               uint64_t *range_end);
+
+BT_HIDDEN
+struct bt_ctf_field_type_common *
+bt_ctf_field_type_common_enumeration_borrow_container_field_type(
+               struct bt_ctf_field_type_common *ft);
+
+BT_HIDDEN
+int bt_ctf_field_type_common_enumeration_signed_add_mapping(
+               struct bt_ctf_field_type_common *ft, const char *string,
+               int64_t range_start, int64_t range_end);
+
+BT_HIDDEN
+int bt_ctf_field_type_common_enumeration_unsigned_add_mapping(
+               struct bt_ctf_field_type_common *ft, const char *string,
+               uint64_t range_start, uint64_t range_end);
+
+BT_HIDDEN
+int64_t bt_ctf_field_type_common_enumeration_get_mapping_count(
+               struct bt_ctf_field_type_common *ft);
+
+BT_HIDDEN
+int bt_ctf_field_type_common_floating_point_get_exponent_digits(
+               struct bt_ctf_field_type_common *ft);
+
+BT_HIDDEN
+int bt_ctf_field_type_common_floating_point_set_exponent_digits(
+               struct bt_ctf_field_type_common *ft,
+               unsigned int exponent_digits);
+
+BT_HIDDEN
+int bt_ctf_field_type_common_floating_point_get_mantissa_digits(
+               struct bt_ctf_field_type_common *type);
+
+BT_HIDDEN
+int bt_ctf_field_type_common_floating_point_set_mantissa_digits(
+               struct bt_ctf_field_type_common *ft, unsigned int mantissa_digits);
+
+BT_HIDDEN
+int bt_ctf_field_type_common_structure_replace_field(
+               struct bt_ctf_field_type_common *ft,
+               const char *field_name,
+               struct bt_ctf_field_type_common *field_type);
+
+BT_HIDDEN
+int bt_ctf_field_type_common_structure_add_field(struct bt_ctf_field_type_common *ft,
+               struct bt_ctf_field_type_common *field_type,
+               const char *field_name);
+
+BT_HIDDEN
+int64_t bt_ctf_field_type_common_structure_get_field_count(
+               struct bt_ctf_field_type_common *ft);
+
+BT_HIDDEN
+int bt_ctf_field_type_common_structure_borrow_field_by_index(
+               struct bt_ctf_field_type_common *ft,
+               const char **field_name,
+               struct bt_ctf_field_type_common **field_type, uint64_t index);
+
+BT_HIDDEN
+struct bt_ctf_field_type_common *
+bt_ctf_field_type_common_structure_borrow_field_type_by_name(
+               struct bt_ctf_field_type_common *ft, const char *name);
+
+BT_HIDDEN
+struct bt_ctf_field_type_common *
+bt_ctf_field_type_common_variant_borrow_tag_field_type(
+               struct bt_ctf_field_type_common *ft);
+
+BT_HIDDEN
+const char *bt_ctf_field_type_common_variant_get_tag_name(
+               struct bt_ctf_field_type_common *ft);
+
+BT_HIDDEN
+int bt_ctf_field_type_common_variant_set_tag_name(
+               struct bt_ctf_field_type_common *ft, const char *name);
+
+BT_HIDDEN
+int bt_ctf_field_type_common_variant_add_field(struct bt_ctf_field_type_common *ft,
+               struct bt_ctf_field_type_common *field_type,
+               const char *field_name);
+
+BT_HIDDEN
+int bt_ctf_field_type_common_variant_update_choices(
+               struct bt_ctf_field_type_common *ft);
+
+BT_HIDDEN
+struct bt_ctf_field_type_common *
+bt_ctf_field_type_common_variant_borrow_field_type_by_name(
+               struct bt_ctf_field_type_common *ft,
+               const char *field_name);
+
+BT_HIDDEN
+int64_t bt_ctf_field_type_common_variant_get_field_count(
+               struct bt_ctf_field_type_common *ft);
+
+BT_HIDDEN
+int bt_ctf_field_type_common_variant_borrow_field_by_index(
+               struct bt_ctf_field_type_common *ft,
+               const char **field_name,
+               struct bt_ctf_field_type_common **field_type, uint64_t index);
+
+BT_HIDDEN
+struct bt_ctf_field_type_common *
+bt_ctf_field_type_common_array_borrow_element_field_type(
+               struct bt_ctf_field_type_common *ft);
+
+BT_HIDDEN
+int bt_ctf_field_type_common_array_set_element_field_type(
+               struct bt_ctf_field_type_common *ft,
+               struct bt_ctf_field_type_common *element_ft);
+
+BT_HIDDEN
+int64_t bt_ctf_field_type_common_array_get_length(struct bt_ctf_field_type_common *ft);
+
+BT_HIDDEN
+struct bt_ctf_field_type_common *
+bt_ctf_field_type_common_sequence_borrow_element_field_type(
+               struct bt_ctf_field_type_common *ft);
+
+BT_HIDDEN
+int bt_ctf_field_type_common_sequence_set_element_field_type(
+               struct bt_ctf_field_type_common *ft,
+               struct bt_ctf_field_type_common *element_ft);
+
+BT_HIDDEN
+const char *bt_ctf_field_type_common_sequence_get_length_field_name(
+               struct bt_ctf_field_type_common *ft);
+
+BT_HIDDEN
+enum bt_ctf_string_encoding bt_ctf_field_type_common_string_get_encoding(
+               struct bt_ctf_field_type_common *ft);
+
+BT_HIDDEN
+int bt_ctf_field_type_common_string_set_encoding(struct bt_ctf_field_type_common *ft,
+               enum bt_ctf_string_encoding encoding);
+
+BT_HIDDEN
+int bt_ctf_field_type_common_get_alignment(struct bt_ctf_field_type_common *type);
+
+BT_HIDDEN
+int bt_ctf_field_type_common_set_alignment(struct bt_ctf_field_type_common *ft,
+               unsigned int alignment);
+
+BT_HIDDEN
+enum bt_ctf_byte_order bt_ctf_field_type_common_get_byte_order(
+               struct bt_ctf_field_type_common *ft);
+
+BT_HIDDEN
+int bt_ctf_field_type_common_set_byte_order(struct bt_ctf_field_type_common *ft,
+               enum bt_ctf_byte_order byte_order);
+
+BT_HIDDEN
+enum bt_ctf_field_type_id bt_ctf_field_type_common_get_type_id(
+               struct bt_ctf_field_type_common *ft);
+
+BT_HIDDEN
+void bt_ctf_field_type_common_freeze(struct bt_ctf_field_type_common *ft);
+
+BT_HIDDEN
+struct bt_ctf_field_type_common *
+bt_ctf_field_type_common_variant_borrow_field_type_signed(
+               struct bt_ctf_field_type_common_variant *var_ft,
+               int64_t tag_value);
+
+BT_HIDDEN
+struct bt_ctf_field_type_common *
+bt_ctf_field_type_common_variant_borrow_field_type_unsigned(
+               struct bt_ctf_field_type_common_variant *var_ft,
+               uint64_t tag_value);
+
+BT_HIDDEN
+struct bt_ctf_field_type_common *bt_ctf_field_type_common_copy(
+               struct bt_ctf_field_type_common *ft);
+
+BT_HIDDEN
+int bt_ctf_field_type_common_structure_get_field_name_index(
+               struct bt_ctf_field_type_common *ft, const char *name);
+
+BT_HIDDEN
+int bt_ctf_field_type_common_variant_get_field_name_index(
+               struct bt_ctf_field_type_common *ft, const char *name);
+
+BT_HIDDEN
+int bt_ctf_field_type_common_sequence_set_length_field_path(
+               struct bt_ctf_field_type_common *ft, struct bt_ctf_field_path *path);
+
+BT_HIDDEN
+int bt_ctf_field_type_common_variant_set_tag_field_path(
+               struct bt_ctf_field_type_common *ft,
+               struct bt_ctf_field_path *path);
+
+BT_HIDDEN
+int bt_ctf_field_type_common_variant_set_tag_field_type(
+               struct bt_ctf_field_type_common *ft,
+               struct bt_ctf_field_type_common *tag_ft);
+
+BT_HIDDEN
+void bt_ctf_field_type_common_generic_freeze(struct bt_ctf_field_type_common *ft);
+
+BT_HIDDEN
+void bt_ctf_field_type_common_enumeration_freeze_recursive(
+               struct bt_ctf_field_type_common *ft);
+
+BT_HIDDEN
+void bt_ctf_field_type_common_structure_freeze_recursive(
+               struct bt_ctf_field_type_common *ft);
+
+BT_HIDDEN
+void bt_ctf_field_type_common_variant_freeze_recursive(
+               struct bt_ctf_field_type_common *ft);
+
+BT_HIDDEN
+void bt_ctf_field_type_common_array_freeze_recursive(
+               struct bt_ctf_field_type_common *ft);
+
+BT_HIDDEN
+void bt_ctf_field_type_common_sequence_freeze_recursive(
+               struct bt_ctf_field_type_common *type);
+
+BT_HIDDEN
+void bt_ctf_field_type_common_integer_set_byte_order(
+               struct bt_ctf_field_type_common *ft, enum bt_ctf_byte_order byte_order);
+
+BT_HIDDEN
+void bt_ctf_field_type_common_enumeration_set_byte_order_recursive(
+               struct bt_ctf_field_type_common *ft, enum bt_ctf_byte_order byte_order);
+
+BT_HIDDEN
+void bt_ctf_field_type_common_floating_point_set_byte_order(
+               struct bt_ctf_field_type_common *ft, enum bt_ctf_byte_order byte_order);
+
+BT_HIDDEN
+void bt_ctf_field_type_common_structure_set_byte_order_recursive(
+               struct bt_ctf_field_type_common *ft,
+               enum bt_ctf_byte_order byte_order);
+
+BT_HIDDEN
+void bt_ctf_field_type_common_variant_set_byte_order_recursive(
+               struct bt_ctf_field_type_common *ft,
+               enum bt_ctf_byte_order byte_order);
+
+BT_HIDDEN
+void bt_ctf_field_type_common_array_set_byte_order_recursive(
+               struct bt_ctf_field_type_common *ft,
+               enum bt_ctf_byte_order byte_order);
+
+BT_HIDDEN
+void bt_ctf_field_type_common_sequence_set_byte_order_recursive(
+               struct bt_ctf_field_type_common *ft,
+               enum bt_ctf_byte_order byte_order);
+
+BT_HIDDEN
+int bt_ctf_field_type_common_integer_compare(struct bt_ctf_field_type_common *ft_a,
+               struct bt_ctf_field_type_common *ft_b);
+
+BT_HIDDEN
+int bt_ctf_field_type_common_floating_point_compare(
+               struct bt_ctf_field_type_common *ft_a,
+               struct bt_ctf_field_type_common *ft_b);
+
+BT_HIDDEN
+int bt_ctf_field_type_common_enumeration_compare_recursive(
+               struct bt_ctf_field_type_common *ft_a,
+               struct bt_ctf_field_type_common *ft_b);
+
+BT_HIDDEN
+int bt_ctf_field_type_common_string_compare(struct bt_ctf_field_type_common *ft_a,
+               struct bt_ctf_field_type_common *ft_b);
+
+BT_HIDDEN
+int bt_ctf_field_type_common_structure_compare_recursive(
+               struct bt_ctf_field_type_common *ft_a,
+               struct bt_ctf_field_type_common *ft_b);
+
+BT_HIDDEN
+int bt_ctf_field_type_common_variant_compare_recursive(
+               struct bt_ctf_field_type_common *ft_a,
+               struct bt_ctf_field_type_common *ft_b);
+
+BT_HIDDEN
+int bt_ctf_field_type_common_array_compare_recursive(
+               struct bt_ctf_field_type_common *ft_a,
+               struct bt_ctf_field_type_common *ft_b);
+
+BT_HIDDEN
+int bt_ctf_field_type_common_sequence_compare_recursive(
+               struct bt_ctf_field_type_common *ft_a,
+               struct bt_ctf_field_type_common *ft_b);
+
+BT_HIDDEN
+int bt_ctf_field_type_common_compare(struct bt_ctf_field_type_common *ft_a,
+               struct bt_ctf_field_type_common *ft_b);
+
+BT_HIDDEN
+int64_t bt_ctf_field_type_common_get_field_count(struct bt_ctf_field_type_common *ft);
+
+BT_HIDDEN
+struct bt_ctf_field_type_common *bt_ctf_field_type_common_borrow_field_at_index(
+               struct bt_ctf_field_type_common *ft, int index);
+
+BT_HIDDEN
+int bt_ctf_field_type_common_get_field_index(struct bt_ctf_field_type_common *ft,
+               const char *name);
+
+BT_HIDDEN
+struct bt_ctf_field_path *bt_ctf_field_type_common_variant_borrow_tag_field_path(
+               struct bt_ctf_field_type_common *ft);
+
+BT_HIDDEN
+struct bt_ctf_field_path *bt_ctf_field_type_common_sequence_borrow_length_field_path(
+               struct bt_ctf_field_type_common *ft);
+
+BT_HIDDEN
+int bt_ctf_field_type_common_validate_single_clock_class(
+               struct bt_ctf_field_type_common *ft,
+               struct bt_ctf_clock_class **expected_clock_class);
+
+BT_HIDDEN
+int64_t bt_ctf_field_type_common_variant_find_choice_index(
+               struct bt_ctf_field_type_common *ft, uint64_t uval,
+               bool is_signed);
 
 BT_HIDDEN
 int bt_ctf_field_type_serialize_recursive(struct bt_ctf_field_type *type,
index 36bfbfe0551d8a58ac45499dca974a0af4c9f9f6..5584a2936a24894d90ae614c5fd2dd39f00aeb09 100644 (file)
@@ -34,7 +34,6 @@
 #include <stddef.h>
 
 #include <babeltrace/types.h>
-#include <babeltrace/ctf-ir/field-types.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -43,36 +42,64 @@ extern "C" {
 struct bt_ctf_field;
 struct bt_ctf_field_type;
 
+enum bt_ctf_scope {
+       /// Unknown, used for errors.
+       BT_CTF_SCOPE_UNKNOWN                    = -1,
+
+       /// Trace packet header.
+       BT_CTF_SCOPE_TRACE_PACKET_HEADER        = 1,
+
+       /// Stream packet context.
+       BT_CTF_SCOPE_STREAM_PACKET_CONTEXT      = 2,
+
+       /// Stream event header.
+       BT_CTF_SCOPE_STREAM_EVENT_HEADER        = 3,
+
+       /// Stream event context.
+       BT_CTF_SCOPE_STREAM_EVENT_CONTEXT       = 4,
+
+       /// Event context.
+       BT_CTF_SCOPE_EVENT_CONTEXT              = 5,
+
+       /// Event payload.
+       BT_CTF_SCOPE_EVENT_PAYLOAD              = 6,
+
+       /// @cond DOCUMENT
+       BT_CTF_SCOPE_ENV                        = 0,
+       BT_CTF_SCOPE_EVENT_FIELDS               = 6,
+       /// @endcond
+};
+
 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,
+       BT_CTF_FIELD_TYPE_ID_UNKNOWN    = -1,
+       BT_CTF_FIELD_TYPE_ID_INTEGER    = 0,
+       BT_CTF_FIELD_TYPE_ID_FLOAT      = 1,
+       BT_CTF_FIELD_TYPE_ID_ENUM       = 2,
+       BT_CTF_FIELD_TYPE_ID_STRING     = 3,
+       BT_CTF_FIELD_TYPE_ID_STRUCT     = 4,
+       BT_CTF_FIELD_TYPE_ID_ARRAY      = 5,
+       BT_CTF_FIELD_TYPE_ID_SEQUENCE   = 6,
+       BT_CTF_FIELD_TYPE_ID_VARIANT    = 7,
+       BT_CTF_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,
+       BT_CTF_BYTE_ORDER_UNKNOWN               = -1,
+       BT_CTF_BYTE_ORDER_NATIVE                = 0,
+       BT_CTF_BYTE_ORDER_UNSPECIFIED,
+       BT_CTF_BYTE_ORDER_LITTLE_ENDIAN,
+       BT_CTF_BYTE_ORDER_BIG_ENDIAN,
+       BT_CTF_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,
+       BT_CTF_STRING_ENCODING_UNKNOWN  = -1,
+       BT_CTF_STRING_ENCODING_NONE,
+       BT_CTF_STRING_ENCODING_UTF8,
+       BT_CTF_STRING_ENCODING_ASCII,
 };
 
 /* Pre-2.0 CTF writer compatibility */
diff --git a/include/babeltrace/ctf-writer/field-wrapper-internal.h b/include/babeltrace/ctf-writer/field-wrapper-internal.h
new file mode 100644 (file)
index 0000000..f75f43b
--- /dev/null
@@ -0,0 +1,47 @@
+#ifndef BABELTRACE_CTF_WRITER_FIELD_WRAPPER_INTERNAL_H
+#define BABELTRACE_CTF_WRITER_FIELD_WRAPPER_INTERNAL_H
+
+/*
+ * Copyright 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.
+ */
+
+#include <babeltrace/ctf-writer/fields-internal.h>
+#include <babeltrace/object-pool-internal.h>
+#include <babeltrace/object-internal.h>
+
+struct bt_ctf_field_wrapper {
+       struct bt_object base;
+
+       /* Owned by this */
+       struct bt_ctf_field_common *field;
+};
+
+BT_HIDDEN
+struct bt_ctf_field_wrapper *bt_ctf_field_wrapper_new(void *data);
+
+BT_HIDDEN
+void bt_ctf_field_wrapper_destroy(struct bt_ctf_field_wrapper *field);
+
+BT_HIDDEN
+struct bt_ctf_field_wrapper *bt_ctf_field_wrapper_create(
+               struct bt_object_pool *pool, struct bt_ctf_field_type *ft);
+
+#endif /* BABELTRACE_CTF_WRITER_FIELD_WRAPPER_INTERNAL_H */
index d0e97471da456368ff59c773b2e0d43f41dab434..64d33a9a60734021116d6bc87d63085d1bf7a101 100644 (file)
 #include <stdint.h>
 #include <stddef.h>
 
+#include <babeltrace/assert-pre-internal.h>
+#include <babeltrace/babeltrace-internal.h>
 #include <babeltrace/babeltrace.h>
-#include <babeltrace/ctf-ir/fields-internal.h>
+#include <babeltrace/common-internal.h>
+#include <babeltrace/ctf-writer/field-types-internal.h>
 #include <babeltrace/ctf-writer/fields.h>
 #include <babeltrace/ctf-writer/serialize-internal.h>
+#include <babeltrace/ctf-writer/utils-internal.h>
+#include <babeltrace/object-internal.h>
+#include <babeltrace/types.h>
+#include <glib.h>
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+
+#define BT_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(_field, _type_id, _name) \
+       BT_ASSERT_PRE((_field)->type->id == ((int) (_type_id)),         \
+               _name " has the wrong type ID: expected-type-id=%s, "   \
+               "field-addr=%p",                                        \
+               bt_ctf_field_type_id_string((int) (_type_id)), (_field))
+
+#define BT_ASSERT_PRE_CTF_FIELD_COMMON_IS_SET(_field, _name)           \
+       BT_ASSERT_PRE(bt_ctf_field_common_is_set_recursive(_field),     \
+               _name " is not set: field-addr=%p", (_field))
+
+#define BT_ASSERT_PRE_CTF_FIELD_COMMON_HOT(_field, _name)              \
+       BT_ASSERT_PRE_HOT((_field), (_name), ": field-addr=%p", (_field))
+
+struct bt_ctf_field_common;
+
+typedef void (*bt_ctf_field_common_method_set_is_frozen)(struct bt_ctf_field_common *,
+               bool);
+typedef int (*bt_ctf_field_common_method_validate)(struct bt_ctf_field_common *);
+typedef struct bt_ctf_field_common *(*bt_ctf_field_common_method_copy)(
+               struct bt_ctf_field_common *);
+typedef bt_bool (*bt_ctf_field_common_method_is_set)(struct bt_ctf_field_common *);
+typedef void (*bt_ctf_field_common_method_reset)(struct bt_ctf_field_common *);
+
+struct bt_ctf_field_common_methods {
+       bt_ctf_field_common_method_set_is_frozen set_is_frozen;
+       bt_ctf_field_common_method_validate validate;
+       bt_ctf_field_common_method_copy copy;
+       bt_ctf_field_common_method_is_set is_set;
+       bt_ctf_field_common_method_reset reset;
+};
+
+struct bt_ctf_field_common {
+       struct bt_object base;
+       struct bt_ctf_field_type_common *type;
+       struct bt_ctf_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_ctf_field_common_integer {
+       struct bt_ctf_field_common common;
+       union {
+               int64_t signd;
+               uint64_t unsignd;
+       } payload;
+};
+
+struct bt_ctf_field_common_floating_point {
+       struct bt_ctf_field_common common;
+       double payload;
+};
+
+struct bt_ctf_field_common_structure {
+       struct bt_ctf_field_common common;
+
+       /* Array of `struct bt_ctf_field_common *`, owned by this */
+       GPtrArray *fields;
+};
+
+struct bt_ctf_field_common_variant {
+       struct bt_ctf_field_common common;
+
+       union {
+               uint64_t u;
+               int64_t i;
+       } tag_value;
+
+       /* Weak: belongs to `choices` below */
+       struct bt_ctf_field_common *current_field;
+
+       /* Array of `struct bt_ctf_field_common *`, owned by this */
+       GPtrArray *fields;
+};
+
+struct bt_ctf_field_common_array {
+       struct bt_ctf_field_common common;
+
+       /* Array of `struct bt_ctf_field_common *`, owned by this */
+       GPtrArray *elements;
+};
+
+struct bt_ctf_field_common_sequence {
+       struct bt_ctf_field_common common;
+
+       /*
+        * This is the true sequence field's length: its value can be
+        * less than `elements->len` below because we never shrink the
+        * array of elements to avoid reallocation.
+        */
+       uint64_t length;
+
+       /* Array of `struct bt_ctf_field_common *`, owned by this */
+       GPtrArray *elements;
+};
+
+struct bt_ctf_field_common_string {
+       struct bt_ctf_field_common common;
+       GArray *buf;
+       size_t size;
+};
+
+BT_HIDDEN
+struct bt_ctf_field_common *bt_ctf_field_common_copy(struct bt_ctf_field_common *field);
+
+BT_HIDDEN
+int bt_ctf_field_common_structure_initialize(struct bt_ctf_field_common *field,
+               struct bt_ctf_field_type_common *type,
+               bool is_shared, bt_object_release_func release_func,
+               struct bt_ctf_field_common_methods *methods,
+               bt_ctf_field_common_create_func field_create_func,
+               GDestroyNotify field_release_func);
+
+BT_HIDDEN
+int bt_ctf_field_common_array_initialize(struct bt_ctf_field_common *field,
+               struct bt_ctf_field_type_common *type,
+               bool is_shared, bt_object_release_func release_func,
+               struct bt_ctf_field_common_methods *methods,
+               bt_ctf_field_common_create_func field_create_func,
+               GDestroyNotify field_destroy_func);
+
+BT_HIDDEN
+int bt_ctf_field_common_sequence_initialize(struct bt_ctf_field_common *field,
+               struct bt_ctf_field_type_common *type,
+               bool is_shared, bt_object_release_func release_func,
+               struct bt_ctf_field_common_methods *methods,
+               GDestroyNotify field_destroy_func);
+
+BT_HIDDEN
+int bt_ctf_field_common_variant_initialize(struct bt_ctf_field_common *field,
+               struct bt_ctf_field_type_common *type,
+               bool is_shared, bt_object_release_func release_func,
+               struct bt_ctf_field_common_methods *methods,
+               bt_ctf_field_common_create_func field_create_func,
+               GDestroyNotify field_release_func);
+
+BT_HIDDEN
+int bt_ctf_field_common_string_initialize(struct bt_ctf_field_common *field,
+               struct bt_ctf_field_type_common *type,
+               bool is_shared, bt_object_release_func release_func,
+               struct bt_ctf_field_common_methods *methods);
+
+BT_HIDDEN
+int bt_ctf_field_common_generic_validate(struct bt_ctf_field_common *field);
+
+BT_HIDDEN
+int bt_ctf_field_common_structure_validate_recursive(struct bt_ctf_field_common *field);
+
+BT_HIDDEN
+int bt_ctf_field_common_variant_validate_recursive(struct bt_ctf_field_common *field);
+
+BT_HIDDEN
+int bt_ctf_field_common_array_validate_recursive(struct bt_ctf_field_common *field);
+
+BT_HIDDEN
+int bt_ctf_field_common_sequence_validate_recursive(struct bt_ctf_field_common *field);
+
+BT_HIDDEN
+void bt_ctf_field_common_generic_reset(struct bt_ctf_field_common *field);
+
+BT_HIDDEN
+void bt_ctf_field_common_structure_reset_recursive(struct bt_ctf_field_common *field);
+
+BT_HIDDEN
+void bt_ctf_field_common_variant_reset_recursive(struct bt_ctf_field_common *field);
+
+BT_HIDDEN
+void bt_ctf_field_common_array_reset_recursive(struct bt_ctf_field_common *field);
+
+BT_HIDDEN
+void bt_ctf_field_common_sequence_reset_recursive(struct bt_ctf_field_common *field);
+
+BT_HIDDEN
+void bt_ctf_field_common_generic_set_is_frozen(struct bt_ctf_field_common *field,
+               bool is_frozen);
+
+BT_HIDDEN
+void bt_ctf_field_common_structure_set_is_frozen_recursive(
+               struct bt_ctf_field_common *field, bool is_frozen);
+
+BT_HIDDEN
+void bt_ctf_field_common_variant_set_is_frozen_recursive(
+               struct bt_ctf_field_common *field, bool is_frozen);
+
+BT_HIDDEN
+void bt_ctf_field_common_array_set_is_frozen_recursive(
+               struct bt_ctf_field_common *field, bool is_frozen);
+
+BT_HIDDEN
+void bt_ctf_field_common_sequence_set_is_frozen_recursive(
+               struct bt_ctf_field_common *field, bool is_frozen);
+
+BT_HIDDEN
+void _bt_ctf_field_common_set_is_frozen_recursive(struct bt_ctf_field_common *field,
+               bool is_frozen);
+
+BT_HIDDEN
+bt_bool bt_ctf_field_common_generic_is_set(struct bt_ctf_field_common *field);
+
+BT_HIDDEN
+bt_bool bt_ctf_field_common_structure_is_set_recursive(
+               struct bt_ctf_field_common *field);
+
+BT_HIDDEN
+bt_bool bt_ctf_field_common_variant_is_set_recursive(struct bt_ctf_field_common *field);
+
+BT_HIDDEN
+bt_bool bt_ctf_field_common_array_is_set_recursive(struct bt_ctf_field_common *field);
+
+BT_HIDDEN
+bt_bool bt_ctf_field_common_sequence_is_set_recursive(struct bt_ctf_field_common *field);
+
+#ifdef BT_DEV_MODE
+# define bt_ctf_field_common_validate_recursive                _bt_ctf_field_common_validate_recursive
+# define bt_ctf_field_common_set_is_frozen_recursive   _bt_ctf_field_common_set_is_frozen_recursive
+# define bt_ctf_field_common_is_set_recursive          _bt_ctf_field_common_is_set_recursive
+# define bt_ctf_field_common_reset_recursive           _bt_ctf_field_common_reset_recursive
+# define bt_ctf_field_common_set                               _bt_ctf_field_common_set
+#else
+# define bt_ctf_field_common_validate_recursive(_field)        (-1)
+# define bt_ctf_field_common_set_is_frozen_recursive(_field, _is_frozen)
+# define bt_ctf_field_common_is_set_recursive(_field)  (BT_FALSE)
+# define bt_ctf_field_common_reset_recursive(_field)
+# define bt_ctf_field_common_set(_field, _val)
+#endif
+
+BT_ASSERT_FUNC
+static inline bool field_type_common_has_known_id(
+               struct bt_ctf_field_type_common *ft)
+{
+       return (int) ft->id > BT_CTF_FIELD_TYPE_ID_UNKNOWN ||
+               (int) ft->id < BT_CTF_FIELD_TYPE_ID_NR;
+}
+
+static inline
+int _bt_ctf_field_common_validate_recursive(struct bt_ctf_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_ctf_field_common_reset_recursive(struct bt_ctf_field_common *field)
+{
+       BT_ASSERT(field);
+       BT_ASSERT(field->methods->reset);
+       field->methods->reset(field);
+}
+
+static inline
+void _bt_ctf_field_common_set(struct bt_ctf_field_common *field, bool value)
+{
+       BT_ASSERT(field);
+       field->payload_set = value;
+}
+
+static inline
+bt_bool _bt_ctf_field_common_is_set_recursive(struct bt_ctf_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_ctf_field_common_initialize(struct bt_ctf_field_common *field,
+               struct bt_ctf_field_type_common *ft, bool is_shared,
+               bt_object_release_func release_func,
+               struct bt_ctf_field_common_methods *methods)
+{
+       BT_ASSERT(field);
+       BT_ASSERT(ft);
+       bt_object_init(&field->base, is_shared, release_func);
+       field->methods = methods;
+       field->type = bt_get(ft);
+}
+
+static inline
+struct bt_ctf_field_type_common *bt_ctf_field_common_borrow_type(
+               struct bt_ctf_field_common *field)
+{
+       struct bt_ctf_field_type_common *ret = NULL;
+
+       BT_ASSERT_PRE_NON_NULL(field, "Field");
+       ret = field->type;
+       return ret;
+}
+
+static inline
+int64_t bt_ctf_field_common_sequence_get_length(struct bt_ctf_field_common *field)
+{
+       struct bt_ctf_field_common_sequence *sequence = BT_CTF_FROM_COMMON(field);
+
+       BT_ASSERT_PRE_NON_NULL(field, "Sequence field");
+       BT_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(field, BT_CTF_FIELD_TYPE_ID_SEQUENCE,
+               "Field");
+       return (int64_t) sequence->length;
+}
+
+static inline
+int bt_ctf_field_common_sequence_set_length(struct bt_ctf_field_common *field,
+               uint64_t length, bt_ctf_field_common_create_func field_create_func)
+{
+       int ret = 0;
+       struct bt_ctf_field_common_sequence *sequence = BT_CTF_FROM_COMMON(field);
+
+       BT_ASSERT_PRE_NON_NULL(field, "Sequence field");
+       BT_ASSERT_PRE(((int64_t) length) >= 0,
+               "Invalid sequence length (too large): length=%" PRId64,
+               length);
+       BT_ASSERT_PRE_CTF_FIELD_COMMON_HOT(field, "Sequence field");
+
+       if (unlikely(length > sequence->elements->len)) {
+               /* Make more room */
+               struct bt_ctf_field_type_common_sequence *sequence_ft;
+               uint64_t cur_len = sequence->elements->len;
+               uint64_t i;
+
+               g_ptr_array_set_size(sequence->elements, length);
+               sequence_ft = BT_CTF_FROM_COMMON(sequence->common.type);
+
+               for (i = cur_len; i < sequence->elements->len; i++) {
+                       struct bt_ctf_field_common *elem_field =
+                               field_create_func(sequence_ft->element_ft);
+
+                       if (!elem_field) {
+                               ret = -1;
+                               goto end;
+                       }
+
+                       BT_ASSERT(!sequence->elements->pdata[i]);
+                       sequence->elements->pdata[i] = elem_field;
+               }
+       }
+
+       sequence->length = length;
+
+end:
+       return ret;
+}
+
+static inline
+struct bt_ctf_field_common *bt_ctf_field_common_structure_borrow_field_by_name(
+               struct bt_ctf_field_common *field, const char *name)
+{
+       struct bt_ctf_field_common *ret = NULL;
+       GQuark field_quark;
+       struct bt_ctf_field_type_common_structure *structure_ft;
+       struct bt_ctf_field_common_structure *structure = BT_CTF_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_CTF_FIELD_COMMON_HAS_TYPE_ID(field,
+               BT_CTF_FIELD_TYPE_ID_STRUCT, "Field");
+       structure_ft = BT_CTF_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 = structure->fields->pdata[index];
+       BT_ASSERT(ret);
+
+error:
+       return ret;
+}
+
+static inline
+struct bt_ctf_field_common *bt_ctf_field_common_structure_borrow_field_by_index(
+               struct bt_ctf_field_common *field, uint64_t index)
+{
+       struct bt_ctf_field_common_structure *structure = BT_CTF_FROM_COMMON(field);
+
+       BT_ASSERT_PRE_NON_NULL(field, "Structure field");
+       BT_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(field,
+               BT_CTF_FIELD_TYPE_ID_STRUCT, "Field");
+       BT_ASSERT_PRE(index < structure->fields->len,
+               "Index is out of bound: struct-field-addr=%p, "
+               "index=%" PRIu64 ", count=%u", field, index,
+               structure->fields->len);
+       return structure->fields->pdata[index];
+}
+
+static inline
+struct bt_ctf_field_common *bt_ctf_field_common_array_borrow_field(
+               struct bt_ctf_field_common *field, uint64_t index)
+{
+       struct bt_ctf_field_common_array *array = BT_CTF_FROM_COMMON(field);
+
+       BT_ASSERT_PRE_NON_NULL(field, "Array field");
+       BT_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(field, BT_CTF_FIELD_TYPE_ID_ARRAY,
+               "Field");
+       BT_ASSERT_PRE(index < array->elements->len,
+               "Index is out of bound: array-field-addr=%p, "
+               "index=%" PRIu64 ", count=%u", field,
+               index, array->elements->len);
+       return array->elements->pdata[(size_t) index];
+}
+
+static inline
+struct bt_ctf_field_common *bt_ctf_field_common_sequence_borrow_field(
+               struct bt_ctf_field_common *field, uint64_t index)
+{
+       struct bt_ctf_field_common_sequence *sequence = BT_CTF_FROM_COMMON(field);
+
+       BT_ASSERT_PRE_NON_NULL(field, "Sequence field");
+       BT_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(field, BT_CTF_FIELD_TYPE_ID_SEQUENCE,
+               "Field");
+       BT_ASSERT_PRE(index < sequence->length,
+               "Index is out of bound: seq-field-addr=%p, "
+               "index=%" PRIu64 ", count=%u", field, index,
+               sequence->elements->len);
+       return sequence->elements->pdata[(size_t) index];
+}
+
+static inline
+int bt_ctf_field_common_variant_set_tag(struct bt_ctf_field_common *variant_field,
+               uint64_t tag_uval, bool is_signed)
+{
+       int ret = 0;
+       int64_t choice_index;
+       struct bt_ctf_field_common_variant *variant = BT_CTF_FROM_COMMON(variant_field);
+
+       BT_ASSERT_PRE_NON_NULL(variant_field, "Variant field");
+       BT_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(variant_field,
+               BT_CTF_FIELD_TYPE_ID_VARIANT, "Field");
+
+       /* Find matching index in variant field's type */
+       choice_index = bt_ctf_field_type_common_variant_find_choice_index(
+               variant_field->type, tag_uval, is_signed);
+       if (choice_index < 0) {
+               ret = -1;
+               goto end;
+       }
+
+       /* Select corresponding field */
+       BT_ASSERT(choice_index < variant->fields->len);
+       variant->current_field = variant->fields->pdata[choice_index];
+       variant->tag_value.u = tag_uval;
+
+end:
+       return ret;
+}
+
+static inline
+struct bt_ctf_field_common *bt_ctf_field_common_variant_borrow_current_field(
+               struct bt_ctf_field_common *variant_field)
+{
+       struct bt_ctf_field_common_variant *variant = BT_CTF_FROM_COMMON(variant_field);
+
+       BT_ASSERT_PRE_NON_NULL(variant_field, "Variant field");
+       BT_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(variant_field,
+               BT_CTF_FIELD_TYPE_ID_VARIANT, "Field");
+       BT_ASSERT_PRE(variant->current_field,
+               "Variant field has no current field: field-addr=%p", variant_field);
+       return variant->current_field;
+}
+
+static inline
+int bt_ctf_field_common_variant_get_tag_signed(struct bt_ctf_field_common *variant_field,
+       int64_t *tag)
+{
+       struct bt_ctf_field_common_variant *variant = BT_CTF_FROM_COMMON(variant_field);
+
+       BT_ASSERT_PRE_NON_NULL(variant_field, "Variant field");
+       BT_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(variant_field,
+               BT_CTF_FIELD_TYPE_ID_VARIANT, "Field");
+       BT_ASSERT_PRE(variant->current_field,
+               "Variant field has no current field: field-addr=%p", variant_field);
+       *tag = variant->tag_value.i;
+       return 0;
+}
+
+static inline
+int bt_ctf_field_common_variant_get_tag_unsigned(struct bt_ctf_field_common *variant_field,
+       uint64_t *tag)
+{
+       struct bt_ctf_field_common_variant *variant = BT_CTF_FROM_COMMON(variant_field);
+
+       BT_ASSERT_PRE_NON_NULL(variant_field, "Variant field");
+       BT_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(variant_field,
+               BT_CTF_FIELD_TYPE_ID_VARIANT, "Field");
+       BT_ASSERT_PRE(variant->current_field,
+               "Variant field has no current field: field-addr=%p", variant_field);
+       *tag = variant->tag_value.u;
+       return 0;
+}
+
+static inline
+int bt_ctf_field_common_floating_point_get_value(struct bt_ctf_field_common *field,
+               double *value)
+{
+       struct bt_ctf_field_common_floating_point *floating_point =
+               BT_CTF_FROM_COMMON(field);
+
+       BT_ASSERT_PRE_NON_NULL(field, "Floating point number field");
+       BT_ASSERT_PRE_NON_NULL(value, "Value");
+       BT_ASSERT_PRE_CTF_FIELD_COMMON_IS_SET(field, "Floating point number field");
+       BT_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(field,
+               BT_CTF_FIELD_TYPE_ID_FLOAT, "Field");
+       *value = floating_point->payload;
+       return 0;
+}
+
+static inline
+int bt_ctf_field_common_floating_point_set_value(struct bt_ctf_field_common *field,
+               double value)
+{
+       struct bt_ctf_field_common_floating_point *floating_point =
+               BT_CTF_FROM_COMMON(field);
+
+       BT_ASSERT_PRE_NON_NULL(field, "Floating point number field");
+       BT_ASSERT_PRE_CTF_FIELD_COMMON_HOT(field, "Floating point number field");
+       BT_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(field,
+               BT_CTF_FIELD_TYPE_ID_FLOAT, "Field");
+       floating_point->payload = value;
+       bt_ctf_field_common_set(field, true);
+       return 0;
+}
+
+static inline
+const char *bt_ctf_field_common_string_get_value(struct bt_ctf_field_common *field)
+{
+       struct bt_ctf_field_common_string *string = BT_CTF_FROM_COMMON(field);
+
+       BT_ASSERT_PRE_NON_NULL(field, "String field");
+       BT_ASSERT_PRE_CTF_FIELD_COMMON_IS_SET(field, "String field");
+       BT_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(field,
+               BT_CTF_FIELD_TYPE_ID_STRING, "Field");
+       return (const char *) string->buf->data;
+}
+
+static inline
+int bt_ctf_field_common_string_clear(struct bt_ctf_field_common *field)
+{
+       struct bt_ctf_field_common_string *string_field = BT_CTF_FROM_COMMON(field);
+
+       BT_ASSERT_PRE_NON_NULL(field, "String field");
+       BT_ASSERT_PRE_CTF_FIELD_COMMON_HOT(field, "String field");
+       BT_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(field,
+               BT_CTF_FIELD_TYPE_ID_STRING, "Field");
+       string_field->size = 0;
+       bt_ctf_field_common_set(field, true);
+       return 0;
+}
+
+static inline
+int bt_ctf_field_common_string_append_len(struct bt_ctf_field_common *field,
+               const char *value, unsigned int length)
+{
+       struct bt_ctf_field_common_string *string_field = BT_CTF_FROM_COMMON(field);
+       char *data;
+       size_t new_size;
+
+       BT_ASSERT_PRE_NON_NULL(field, "String field");
+       BT_ASSERT_PRE_NON_NULL(value, "Value");
+       BT_ASSERT_PRE_CTF_FIELD_COMMON_HOT(field, "String field");
+       BT_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(field,
+               BT_CTF_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);
+
+       new_size = string_field->size + length;
+
+       if (unlikely(new_size + 1 > string_field->buf->len)) {
+               g_array_set_size(string_field->buf, new_size + 1);
+       }
+
+       data = string_field->buf->data;
+       memcpy(data + string_field->size, value, length);
+       ((char *) string_field->buf->data)[new_size] = '\0';
+       string_field->size = new_size;
+       bt_ctf_field_common_set(field, true);
+       return 0;
+}
+
+static inline
+int bt_ctf_field_common_string_append(struct bt_ctf_field_common *field,
+               const char *value)
+{
+       BT_ASSERT_PRE_NON_NULL(value, "Value");
+       return bt_ctf_field_common_string_append_len(field, value,
+               strlen(value));
+}
+
+static inline
+int bt_ctf_field_common_string_set_value(struct bt_ctf_field_common *field,
+               const char *value)
+{
+       BT_ASSERT_PRE_NON_NULL(field, "String field");
+       BT_ASSERT_PRE_NON_NULL(value, "Value");
+       BT_ASSERT_PRE_CTF_FIELD_COMMON_HOT(field, "String field");
+       BT_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(field,
+               BT_CTF_FIELD_TYPE_ID_STRING, "Field");
+       bt_ctf_field_common_string_clear(field);
+       return bt_ctf_field_common_string_append_len(field,
+               value, strlen(value));
+}
+
+static inline
+void bt_ctf_field_common_finalize(struct bt_ctf_field_common *field)
+{
+       BT_ASSERT(field);
+       BT_LOGD_STR("Putting field's type.");
+       bt_put(field->type);
+}
+
+static inline
+void bt_ctf_field_common_integer_finalize(struct bt_ctf_field_common *field)
+{
+       BT_ASSERT(field);
+       BT_LOGD("Finalizing common integer field object: addr=%p", field);
+       bt_ctf_field_common_finalize(field);
+}
+
+static inline
+void bt_ctf_field_common_floating_point_finalize(struct bt_ctf_field_common *field)
+{
+       BT_ASSERT(field);
+       BT_LOGD("Finalizing common floating point number field object: addr=%p", field);
+       bt_ctf_field_common_finalize(field);
+}
+
+static inline
+void bt_ctf_field_common_structure_finalize_recursive(struct bt_ctf_field_common *field)
+{
+       struct bt_ctf_field_common_structure *structure = BT_CTF_FROM_COMMON(field);
+
+       BT_ASSERT(field);
+       BT_LOGD("Finalizing common structure field object: addr=%p", field);
+       bt_ctf_field_common_finalize(field);
+
+       if (structure->fields) {
+               g_ptr_array_free(structure->fields, TRUE);
+       }
+}
+
+static inline
+void bt_ctf_field_common_variant_finalize_recursive(struct bt_ctf_field_common *field)
+{
+       struct bt_ctf_field_common_variant *variant = BT_CTF_FROM_COMMON(field);
+
+       BT_ASSERT(field);
+       BT_LOGD("Finalizing common variant field object: addr=%p", field);
+       bt_ctf_field_common_finalize(field);
+
+       if (variant->fields) {
+               g_ptr_array_free(variant->fields, TRUE);
+       }
+}
+
+static inline
+void bt_ctf_field_common_array_finalize_recursive(struct bt_ctf_field_common *field)
+{
+       struct bt_ctf_field_common_array *array = BT_CTF_FROM_COMMON(field);
+
+       BT_ASSERT(field);
+       BT_LOGD("Finalizing common array field object: addr=%p", field);
+       bt_ctf_field_common_finalize(field);
+
+       if (array->elements) {
+               g_ptr_array_free(array->elements, TRUE);
+       }
+}
+
+static inline
+void bt_ctf_field_common_sequence_finalize_recursive(struct bt_ctf_field_common *field)
+{
+       struct bt_ctf_field_common_sequence *sequence = BT_CTF_FROM_COMMON(field);
+
+       BT_ASSERT(field);
+       BT_LOGD("Finalizing common sequence field object: addr=%p", field);
+       bt_ctf_field_common_finalize(field);
+
+       if (sequence->elements) {
+               g_ptr_array_free(sequence->elements, TRUE);
+       }
+}
+
+static inline
+void bt_ctf_field_common_string_finalize(struct bt_ctf_field_common *field)
+{
+       struct bt_ctf_field_common_string *string = BT_CTF_FROM_COMMON(field);
+
+       BT_ASSERT(field);
+       BT_LOGD("Finalizing common string field object: addr=%p", field);
+       bt_ctf_field_common_finalize(field);
+
+       if (string->buf) {
+               g_array_free(string->buf, TRUE);
+       }
+}
+
+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;
+}
+
+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;
+}
 
 struct bt_ctf_field_enumeration {
-       struct bt_field_common common;
-       struct bt_field_common_integer *container;
+       struct bt_ctf_field_common common;
+       struct bt_ctf_field_common_integer *container;
 };
 
 struct bt_ctf_field_variant {
-       struct bt_field_common_variant common;
+       struct bt_ctf_field_common_variant common;
        struct bt_ctf_field_enumeration *tag;
 };
 
@@ -64,7 +848,7 @@ struct bt_ctf_field *bt_ctf_field_enumeration_borrow_container(
 static inline
 bt_bool bt_ctf_field_is_set_recursive(struct bt_ctf_field *field)
 {
-       return bt_field_common_is_set_recursive((void *) field);
+       return bt_ctf_field_common_is_set_recursive((void *) field);
 }
 
 #endif /* BABELTRACE_CTF_WRITER_FIELDS_INTERNAL_H */
index ceee0e3838426c235ccde3df09ceae04cc4e5fb4..eba9abd2dcee3e89b5ec2f7e696dc187d5731c02 100644 (file)
@@ -33,9 +33,6 @@
 #include <stdint.h>
 #include <stddef.h>
 
-/* For bt_bool */
-#include <babeltrace/ctf-writer/fields.h>
-
 #ifdef __cplusplus
 extern "C" {
 #endif
diff --git a/include/babeltrace/ctf-writer/resolve-internal.h b/include/babeltrace/ctf-writer/resolve-internal.h
new file mode 100644 (file)
index 0000000..cd2b01f
--- /dev/null
@@ -0,0 +1,72 @@
+#ifndef BABELTRACE_CTF_WRITER_RESOLVE_INTERNAL_H
+#define BABELTRACE_CTF_WRITER_RESOLVE_INTERNAL_H
+
+/*
+ * Babeltrace - CTF writer: Type resolving internal
+ *
+ * Copyright 2015 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ * Copyright 2016 Philippe Proulx <pproulx@efficios.com>
+ *
+ * Authors: Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *          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.
+ */
+
+#include <babeltrace/ctf-writer/field-types.h>
+#include <babeltrace/ctf-writer/field-types-internal.h>
+#include <babeltrace/values.h>
+#include <babeltrace/babeltrace-internal.h>
+#include <glib.h>
+
+enum bt_ctf_resolve_flag {
+       BT_CTF_RESOLVE_FLAG_PACKET_HEADER       = 0x01,
+       BT_CTF_RESOLVE_FLAG_PACKET_CONTEXT      = 0x02,
+       BT_CTF_RESOLVE_FLAG_EVENT_HEADER        = 0x04,
+       BT_CTF_RESOLVE_FLAG_STREAM_EVENT_CTX    = 0x08,
+       BT_CTF_RESOLVE_FLAG_EVENT_CONTEXT       = 0x10,
+       BT_CTF_RESOLVE_FLAG_EVENT_PAYLOAD       = 0x20,
+};
+
+/*
+ * Resolves CTF IR field types: recursively locates the tag and length
+ * field types of resp. variant and sequence field types.
+ *
+ * All `*_type` parameters may be resolved, and may as well serve as
+ * resolving targets.
+ *
+ * Resolving is performed based on the flags in `flags`.
+ *
+ * It is expected that, amongst all the provided types, no common
+ * references to sequence variant field types exist. In other words,
+ * this function does not copy field types.
+ *
+ * All parameters are owned by the caller.
+ */
+BT_HIDDEN
+int bt_ctf_resolve_types(struct bt_value *environment,
+               struct bt_ctf_field_type_common *packet_header_type,
+               struct bt_ctf_field_type_common *packet_context_type,
+               struct bt_ctf_field_type_common *event_header_type,
+               struct bt_ctf_field_type_common *stream_event_ctx_type,
+               struct bt_ctf_field_type_common *event_context_type,
+               struct bt_ctf_field_type_common *event_payload_type,
+               enum bt_ctf_resolve_flag flags);
+
+#endif /* BABELTRACE_CTF_WRITER_RESOLVE_INTERNAL_H */
index 5728841e2405e43d28355b43fd1c9fc306d94cf4..7e6073a04a39ee34a2f3dec6cff4f533176c2358 100644 (file)
@@ -37,9 +37,9 @@
 #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/ctf-writer/fields-internal.h>
+#include <babeltrace/ctf-writer/fields.h>
 #include <babeltrace/assert-internal.h>
 
 #define PACKET_LEN_INCREMENT   (bt_common_get_page_size() * 8 * CHAR_BIT)
@@ -58,12 +58,12 @@ struct bt_ctf_stream_pos {
 };
 
 BT_HIDDEN
-int bt_ctf_field_integer_write(struct bt_field_common *field,
+int bt_ctf_field_integer_write(struct bt_ctf_field_common *field,
                struct bt_ctf_stream_pos *pos,
                enum bt_ctf_byte_order native_byte_order);
 
 BT_HIDDEN
-int bt_ctf_field_floating_point_write(struct bt_field_common *field,
+int bt_ctf_field_floating_point_write(struct bt_ctf_field_common *field,
                struct bt_ctf_stream_pos *pos,
                enum bt_ctf_byte_order native_byte_order);
 
index 30215590c76c0206355507bb385872093a967ea5..91a60b4e822281a96cf9efb022f3171c72d4a1f3 100644 (file)
  * http://www.efficios.com/ctf
  */
 
-#include <babeltrace/ctf-ir/stream-class-internal.h>
-#include <babeltrace/ctf-writer/field-types.h>
+#include <babeltrace/assert-internal.h>
+#include <babeltrace/babeltrace-internal.h>
+#include <babeltrace/common-internal.h>
 #include <babeltrace/ctf-writer/clock-internal.h>
+#include <babeltrace/ctf-writer/field-types-internal.h>
+#include <babeltrace/ctf-writer/field-types.h>
+#include <babeltrace/ctf-writer/stream-class-internal.h>
+#include <babeltrace/ctf-writer/utils-internal.h>
+#include <babeltrace/ctf-writer/validation-internal.h>
+#include <babeltrace/ctf-writer/visitor.h>
+#include <babeltrace/object-internal.h>
+#include <inttypes.h>
+
+struct bt_ctf_stream_class_common {
+       struct bt_object base;
+       GString *name;
+
+       /* 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;
+       struct bt_ctf_field_type_common *packet_context_field_type;
+       struct bt_ctf_field_type_common *event_header_field_type;
+       struct bt_ctf_field_type_common *event_context_field_type;
+       int frozen;
+       int byte_order;
+
+       /*
+        * This flag indicates if the stream class is valid. A valid
+        * stream class is _always_ frozen.
+        */
+       int valid;
+
+       /*
+        * Unique clock class mapped to any field type within this
+        * stream class, including all the stream class's event class
+        * field types. This is only set if the stream class is frozen.
+        *
+        * If the stream class is frozen and this is still NULL, it is
+        * still possible that it becomes non-NULL because
+        * bt_ctf_stream_class_add_event_class() can add an event class
+        * containing a field type mapped to some clock class. In this
+        * case, this is the mapped clock class, and at this point, both
+        * the new event class and the stream class are frozen, so the
+        * next added event classes are expected to contain field types
+        * which only map to this specific clock class.
+        *
+        * If this is a CTF writer stream class, then this is the
+        * backing clock class of the `clock` member above.
+        */
+       struct bt_ctf_clock_class *clock_class;
+};
+
+struct bt_ctf_event_class_common;
+
+BT_HIDDEN
+int bt_ctf_stream_class_common_initialize(struct bt_ctf_stream_class_common *stream_class,
+               const char *name, bt_object_release_func release_func);
+
+BT_HIDDEN
+void bt_ctf_stream_class_common_finalize(struct bt_ctf_stream_class_common *stream_class);
+
+BT_HIDDEN
+void bt_ctf_stream_class_common_freeze(struct bt_ctf_stream_class_common *stream_class);
+
+static inline
+const char *bt_ctf_stream_class_common_get_name(
+               struct bt_ctf_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_ctf_stream_class_common_get_id(
+               struct bt_ctf_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_ctf_stream_class_common_get_name(stream_class));
+               ret = (int64_t) -1;
+               goto end;
+       }
+
+       ret = stream_class->id;
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+void bt_ctf_stream_class_common_set_byte_order(
+               struct bt_ctf_stream_class_common *stream_class, int byte_order);
+
+BT_HIDDEN
+int bt_ctf_stream_class_common_validate_single_clock_class(
+               struct bt_ctf_stream_class_common *stream_class,
+               struct bt_ctf_clock_class **expected_clock_class);
+
+BT_HIDDEN
+int bt_ctf_stream_class_common_add_event_class(
+               struct bt_ctf_stream_class_common *stream_class,
+               struct bt_ctf_event_class_common *event_class,
+               bt_ctf_validation_flag_copy_field_type_func copy_field_type_func);
+
+BT_HIDDEN
+int bt_ctf_stream_class_common_visit(struct bt_ctf_stream_class_common *stream_class,
+               bt_ctf_visitor visitor, void *data);
+
+BT_HIDDEN
+int bt_ctf_stream_class_visit(struct bt_ctf_stream_class *stream_class,
+               bt_ctf_visitor visitor, void *data);
+
+static inline
+struct bt_ctf_trace_common *bt_ctf_stream_class_common_borrow_trace(
+               struct bt_ctf_stream_class_common *stream_class)
+{
+       BT_ASSERT(stream_class);
+       return (void *) bt_object_borrow_parent(&stream_class->base);
+}
+
+static inline
+int bt_ctf_stream_class_common_set_name(struct bt_ctf_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_ctf_stream_class_common_get_name(stream_class),
+                       bt_ctf_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_ctf_stream_class_common_get_name(stream_class),
+               bt_ctf_stream_class_common_get_id(stream_class));
+end:
+       return ret;
+}
+
+static inline
+void _bt_ctf_stream_class_common_set_id(
+               struct bt_ctf_stream_class_common *stream_class, int64_t id)
+{
+       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_ctf_stream_class_common_get_name(stream_class),
+               bt_ctf_stream_class_common_get_id(stream_class));
+}
+
+static inline
+int bt_ctf_stream_class_common_set_id_no_check(
+               struct bt_ctf_stream_class_common *stream_class, int64_t id)
+{
+       _bt_ctf_stream_class_common_set_id(stream_class, id);
+       return 0;
+}
+
+static inline
+int bt_ctf_stream_class_common_set_id(struct bt_ctf_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_ctf_stream_class_common_get_name(stream_class),
+                       bt_ctf_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_ctf_stream_class_common_get_name(stream_class),
+                       bt_ctf_stream_class_common_get_id(stream_class),
+                       id_param);
+               ret = -1;
+               goto end;
+       }
+
+       ret = bt_ctf_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_ctf_stream_class_common_get_name(stream_class),
+                       bt_ctf_stream_class_common_get_id(stream_class));
+       }
+end:
+       return ret;
+}
+
+static inline
+int64_t bt_ctf_stream_class_common_get_event_class_count(
+               struct bt_ctf_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_ctf_event_class_common *bt_ctf_stream_class_common_borrow_event_class_by_index(
+               struct bt_ctf_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 g_ptr_array_index(stream_class->event_classes, index);
+}
+
+static inline
+struct bt_ctf_event_class_common *bt_ctf_stream_class_common_borrow_event_class_by_id(
+               struct bt_ctf_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 g_hash_table_lookup(stream_class->event_classes_ht,
+                       &id_key);
+}
+
+static inline
+struct bt_ctf_field_type_common *
+bt_ctf_stream_class_common_borrow_packet_context_field_type(
+               struct bt_ctf_stream_class_common *stream_class)
+{
+       BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
+       return stream_class->packet_context_field_type;
+}
+
+static inline
+int bt_ctf_stream_class_common_set_packet_context_field_type(
+               struct bt_ctf_stream_class_common *stream_class,
+               struct bt_ctf_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_ctf_stream_class_common_get_name(stream_class),
+                       bt_ctf_stream_class_common_get_id(stream_class));
+               ret = -1;
+               goto end;
+       }
+
+       if (packet_context_type &&
+                       bt_ctf_field_type_common_get_type_id(packet_context_type) !=
+                               BT_CTF_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_ctf_stream_class_common_get_name(stream_class),
+                       bt_ctf_stream_class_common_get_id(stream_class),
+                       packet_context_type,
+                       bt_ctf_field_type_id_string(
+                               bt_ctf_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_ctf_stream_class_common_get_name(stream_class),
+               bt_ctf_stream_class_common_get_id(stream_class),
+               packet_context_type);
+
+end:
+       return ret;
+}
+
+static inline
+struct bt_ctf_field_type_common *
+bt_ctf_stream_class_common_borrow_event_header_field_type(
+               struct bt_ctf_stream_class_common *stream_class)
+{
+       struct bt_ctf_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_ctf_stream_class_common_get_name(stream_class),
+                       bt_ctf_stream_class_common_get_id(stream_class));
+               goto end;
+       }
+
+       ret = stream_class->event_header_field_type;
+
+end:
+       return ret;
+}
+
+static inline
+int bt_ctf_stream_class_common_set_event_header_field_type(
+               struct bt_ctf_stream_class_common *stream_class,
+               struct bt_ctf_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_ctf_stream_class_common_get_name(stream_class),
+                       bt_ctf_stream_class_common_get_id(stream_class));
+               ret = -1;
+               goto end;
+       }
+
+       if (event_header_type &&
+                       bt_ctf_field_type_common_get_type_id(event_header_type) !=
+                               BT_CTF_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_ctf_stream_class_common_get_name(stream_class),
+                       bt_ctf_stream_class_common_get_id(stream_class),
+                       event_header_type,
+                       bt_ctf_field_type_id_string(
+                               bt_ctf_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_ctf_stream_class_common_get_name(stream_class),
+               bt_ctf_stream_class_common_get_id(stream_class),
+               event_header_type);
+end:
+       return ret;
+}
+
+static inline
+struct bt_ctf_field_type_common *
+bt_ctf_stream_class_common_borrow_event_context_field_type(
+               struct bt_ctf_stream_class_common *stream_class)
+{
+       struct bt_ctf_field_type_common *ret = NULL;
+
+       BT_ASSERT_PRE_NON_NULL(stream_class, "Stream class");
+
+       if (!stream_class->event_context_field_type) {
+               goto end;
+       }
+
+       ret = stream_class->event_context_field_type;
+
+end:
+       return ret;
+}
+
+static inline
+int bt_ctf_stream_class_common_set_event_context_field_type(
+               struct bt_ctf_stream_class_common *stream_class,
+               struct bt_ctf_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_ctf_stream_class_common_get_name(stream_class),
+                       bt_ctf_stream_class_common_get_id(stream_class));
+               ret = -1;
+               goto end;
+       }
+
+       if (event_context_type &&
+                       bt_ctf_field_type_common_get_type_id(event_context_type) !=
+                               BT_CTF_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_ctf_stream_class_common_get_name(stream_class),
+                       bt_ctf_stream_class_common_get_id(stream_class),
+                       event_context_type,
+                       bt_ctf_field_type_id_string(
+                               bt_ctf_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_ctf_stream_class_common_get_name(stream_class),
+               bt_ctf_stream_class_common_get_id(stream_class),
+               event_context_type);
+end:
+       return ret;
+}
 
 struct bt_ctf_stream_class {
-       struct bt_stream_class_common common;
+       struct bt_ctf_stream_class_common common;
        struct bt_ctf_clock *clock;
        int64_t next_stream_id;
 };
index 1cc00689a1d4fd613ba94aa4ad9b32119f66ed5f..33f653dd013e5e8f24aa283dc07048568f42590e 100644 (file)
@@ -31,7 +31,6 @@
  */
 
 #include <babeltrace/ref.h>
-#include <babeltrace/ctf-ir/stream-class.h>
 
 #ifdef __cplusplus
 extern "C" {
index 1d6e8fcf06cd5ebf0168266bbbbb5081109b4d45..3da0966433a669b0130722d0f00d855d156078eb 100644 (file)
  * http://www.efficios.com/ctf
  */
 
+#include <babeltrace/assert-internal.h>
 #include <babeltrace/assert-pre-internal.h>
-#include <babeltrace/ctf-ir/stream-internal.h>
-#include <babeltrace/ctf-writer/serialize-internal.h>
+#include <babeltrace/babeltrace-internal.h>
 #include <babeltrace/babeltrace.h>
+#include <babeltrace/ctf-writer/serialize-internal.h>
+#include <babeltrace/ctf-writer/stream-internal.h>
+#include <babeltrace/ctf-writer/stream.h>
+#include <babeltrace/ctf-writer/utils-internal.h>
+#include <babeltrace/object-internal.h>
 #include <stdint.h>
 
+struct bt_ctf_stream_common;
+
+struct bt_ctf_stream_common {
+       struct bt_object base;
+       int64_t id;
+       struct bt_ctf_stream_class_common *stream_class;
+       GString *name;
+};
+
+BT_HIDDEN
+int bt_ctf_stream_common_initialize(
+               struct bt_ctf_stream_common *stream,
+               struct bt_ctf_stream_class_common *stream_class, const char *name,
+               uint64_t id, bt_object_release_func release_func);
+
+BT_HIDDEN
+void bt_ctf_stream_common_finalize(struct bt_ctf_stream_common *stream);
+
+static inline
+struct bt_ctf_stream_class_common *bt_ctf_stream_common_borrow_class(
+               struct bt_ctf_stream_common *stream)
+{
+       BT_ASSERT(stream);
+       return stream->stream_class;
+}
+
+static inline
+const char *bt_ctf_stream_common_get_name(struct bt_ctf_stream_common *stream)
+{
+       BT_ASSERT_PRE_NON_NULL(stream, "Stream");
+       return stream->name ? stream->name->str : NULL;
+}
+
+static inline
+int64_t bt_ctf_stream_common_get_id(struct bt_ctf_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_ctf_stream_common_get_name(stream));
+       }
+
+       return ret;
+}
+
 struct bt_ctf_stream {
-       struct bt_stream_common common;
+       struct bt_ctf_stream_common common;
        struct bt_ctf_field *packet_header;
        struct bt_ctf_field *packet_context;
 
@@ -51,7 +104,7 @@ struct bt_ctf_stream {
 };
 
 BT_HIDDEN
-int bt_stream_set_fd(struct bt_stream *stream, int fd);
+int bt_ctf_stream_set_fd(struct bt_ctf_stream *stream, int fd);
 
 BT_HIDDEN
 struct bt_ctf_stream *bt_ctf_stream_create_with_id(
index 47d746eec2d0561a1ee297bb847ab880b62ab2fa..e3d73c18012df44e54bdbe5c1b72cedc14a09946 100644 (file)
  * http://www.efficios.com/ctf
  */
 
-#include <babeltrace/ctf-ir/trace-internal.h>
+#include <babeltrace/assert-pre-internal.h>
+#include <babeltrace/babeltrace-internal.h>
+#include <babeltrace/compat/uuid-internal.h>
+#include <babeltrace/ctf-writer/attributes-internal.h>
+#include <babeltrace/ctf-writer/clock-class-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/trace.h>
+#include <babeltrace/ctf-writer/validation-internal.h>
+#include <babeltrace/object-internal.h>
+#include <babeltrace/types.h>
+#include <babeltrace/values.h>
+#include <glib.h>
+#include <sys/types.h>
+
+struct bt_ctf_trace_common {
+       struct bt_object base;
+       GString *name;
+       int frozen;
+       unsigned char uuid[BABELTRACE_UUID_LEN];
+       bt_bool uuid_set;
+       enum bt_ctf_byte_order native_byte_order;
+       struct bt_value *environment;
+       GPtrArray *clock_classes; /* Array of pointers to bt_ctf_clock_class */
+       GPtrArray *stream_classes; /* Array of ptrs to bt_ctf_stream_class_common */
+       GPtrArray *streams; /* Array of ptrs to bt_ctf_stream_common */
+       struct bt_ctf_field_type_common *packet_header_field_type;
+       int64_t next_stream_id;
+
+       /*
+        * This flag indicates if the trace is valid. A valid
+        * trace is _always_ frozen.
+        */
+       int valid;
+};
+
+BT_HIDDEN
+bt_bool bt_ctf_trace_common_has_clock_class(struct bt_ctf_trace_common *trace,
+               struct bt_ctf_clock_class *clock_class);
+
+BT_HIDDEN
+int bt_ctf_trace_common_initialize(struct bt_ctf_trace_common *trace,
+               bt_object_release_func release_func);
+
+BT_HIDDEN
+void bt_ctf_trace_common_finalize(struct bt_ctf_trace_common *trace);
+
+static inline
+const char *bt_ctf_trace_common_get_name(struct bt_ctf_trace_common *trace)
+{
+       BT_ASSERT_PRE_NON_NULL(trace, "Trace");
+       return trace->name ? trace->name->str : NULL;
+}
+
+BT_HIDDEN
+int bt_ctf_trace_common_set_name(struct bt_ctf_trace_common *trace, const char *name);
+
+static inline
+const unsigned char *bt_ctf_trace_common_get_uuid(struct bt_ctf_trace_common *trace)
+{
+       BT_ASSERT_PRE_NON_NULL(trace, "Trace");
+       return trace->uuid_set ? trace->uuid : NULL;
+}
+
+BT_HIDDEN
+int bt_ctf_trace_common_set_uuid(struct bt_ctf_trace_common *trace, const unsigned char *uuid);
+
+BT_HIDDEN
+int bt_ctf_trace_common_set_environment_field(struct bt_ctf_trace_common *trace,
+               const char *name, struct bt_value *value);
+
+BT_HIDDEN
+int bt_ctf_trace_common_set_environment_field_string(struct bt_ctf_trace_common *trace,
+               const char *name, const char *value);
+
+BT_HIDDEN
+int bt_ctf_trace_common_set_environment_field_integer(struct bt_ctf_trace_common *trace,
+               const char *name, int64_t value);
+
+static inline
+int64_t bt_ctf_trace_common_get_environment_field_count(
+               struct bt_ctf_trace_common *trace)
+{
+       int64_t ret;
+
+       BT_ASSERT_PRE_NON_NULL(trace, "Trace");
+       ret = bt_ctf_attributes_get_count(trace->environment);
+       BT_ASSERT(ret >= 0);
+       return ret;
+}
+
+static inline
+const char *
+bt_ctf_trace_common_get_environment_field_name_by_index(
+               struct bt_ctf_trace_common *trace, uint64_t index)
+{
+       BT_ASSERT_PRE_NON_NULL(trace, "Trace");
+       return bt_ctf_attributes_get_field_name(trace->environment, index);
+}
+
+static inline
+struct bt_value *bt_ctf_trace_common_borrow_environment_field_value_by_index(
+               struct bt_ctf_trace_common *trace, uint64_t index)
+{
+       BT_ASSERT_PRE_NON_NULL(trace, "Trace");
+       return bt_ctf_attributes_borrow_field_value(trace->environment, index);
+}
+
+static inline
+struct bt_value *bt_ctf_trace_common_borrow_environment_field_value_by_name(
+               struct bt_ctf_trace_common *trace, const char *name)
+{
+       BT_ASSERT_PRE_NON_NULL(trace, "Trace");
+       BT_ASSERT_PRE_NON_NULL(name, "Name");
+       return bt_ctf_attributes_borrow_field_value_by_name(trace->environment,
+               name);
+}
+
+BT_HIDDEN
+int bt_ctf_trace_common_add_clock_class(struct bt_ctf_trace_common *trace,
+               struct bt_ctf_clock_class *clock_class);
+
+static inline
+int64_t bt_ctf_trace_common_get_clock_class_count(struct bt_ctf_trace_common *trace)
+{
+       BT_ASSERT_PRE_NON_NULL(trace, "Trace");
+       return trace->clock_classes->len;
+}
+
+static inline
+struct bt_ctf_clock_class *bt_ctf_trace_common_borrow_clock_class_by_index(
+               struct bt_ctf_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 g_ptr_array_index(trace->clock_classes, index);
+}
+
+static inline
+int64_t bt_ctf_trace_common_get_stream_count(struct bt_ctf_trace_common *trace)
+{
+       BT_ASSERT_PRE_NON_NULL(trace, "Trace");
+       return (int64_t) trace->streams->len;
+}
+
+static inline
+struct bt_ctf_stream_common *bt_ctf_trace_common_borrow_stream_by_index(
+               struct bt_ctf_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 g_ptr_array_index(trace->streams, index);
+}
+
+static inline
+int64_t bt_ctf_trace_common_get_stream_class_count(struct bt_ctf_trace_common *trace)
+{
+       BT_ASSERT_PRE_NON_NULL(trace, "Trace");
+       return (int64_t) trace->stream_classes->len;
+}
+
+static inline
+struct bt_ctf_stream_class_common *bt_ctf_trace_common_borrow_stream_class_by_index(
+               struct bt_ctf_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 g_ptr_array_index(trace->stream_classes, index);
+}
+
+static inline
+struct bt_ctf_stream_class_common *bt_ctf_trace_common_borrow_stream_class_by_id(
+               struct bt_ctf_trace_common *trace, uint64_t id_param)
+{
+       int i;
+       struct bt_ctf_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_ctf_stream_class_common *stream_class_candidate;
+
+               stream_class_candidate =
+                       g_ptr_array_index(trace->stream_classes, i);
+
+               if (bt_ctf_stream_class_common_get_id(stream_class_candidate) ==
+                               (int64_t) id) {
+                       stream_class = stream_class_candidate;
+                       goto end;
+               }
+       }
+
+end:
+       return stream_class;
+}
+
+static inline
+struct bt_ctf_clock_class *bt_ctf_trace_common_borrow_clock_class_by_name(
+               struct bt_ctf_trace_common *trace, const char *name)
+{
+       size_t i;
+       struct bt_ctf_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_ctf_clock_class *cur_clk =
+                       g_ptr_array_index(trace->clock_classes, i);
+               const char *cur_clk_name = bt_ctf_clock_class_get_name(cur_clk);
+
+               if (!cur_clk_name) {
+                       goto end;
+               }
+
+               if (!strcmp(cur_clk_name, name)) {
+                       clock_class = cur_clk;
+                       goto end;
+               }
+       }
+
+end:
+       return clock_class;
+}
+
+static inline
+enum bt_ctf_byte_order bt_ctf_trace_common_get_native_byte_order(
+               struct bt_ctf_trace_common *trace)
+{
+       BT_ASSERT_PRE_NON_NULL(trace, "Trace");
+       return trace->native_byte_order;
+}
+
+BT_HIDDEN
+int bt_ctf_trace_common_set_native_byte_order(struct bt_ctf_trace_common *trace,
+               enum bt_ctf_byte_order byte_order, bool allow_unspecified);
+
+static inline
+struct bt_ctf_field_type_common *bt_ctf_trace_common_borrow_packet_header_field_type(
+               struct bt_ctf_trace_common *trace)
+{
+       BT_ASSERT_PRE_NON_NULL(trace, "Trace");
+       return trace->packet_header_field_type;
+}
+
+BT_HIDDEN
+int bt_ctf_trace_common_set_packet_header_field_type(struct bt_ctf_trace_common *trace,
+               struct bt_ctf_field_type_common *packet_header_field_type);
+
+static inline
+void bt_ctf_trace_common_freeze(struct bt_ctf_trace_common *trace)
+{
+       int i;
+
+       if (trace->frozen) {
+               return;
+       }
+
+       BT_LOGD("Freezing trace: addr=%p, name=\"%s\"",
+               trace, bt_ctf_trace_common_get_name(trace));
+       BT_LOGD_STR("Freezing packet header field type.");
+       bt_ctf_field_type_common_freeze(trace->packet_header_field_type);
+       BT_LOGD_STR("Freezing environment attributes.");
+       bt_ctf_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_ctf_clock_class *clock_class =
+                       g_ptr_array_index(trace->clock_classes, i);
+
+               bt_ctf_clock_class_freeze(clock_class);
+       }
+
+       trace->frozen = 1;
+}
+
+BT_HIDDEN
+int bt_ctf_trace_common_add_stream_class(struct bt_ctf_trace_common *trace,
+               struct bt_ctf_stream_class_common *stream_class,
+               bt_ctf_validation_flag_copy_field_type_func copy_field_type_func,
+               struct bt_ctf_clock_class *init_expected_clock_class,
+               int (*map_clock_classes_func)(struct bt_ctf_stream_class_common *stream_class,
+                       struct bt_ctf_field_type_common *packet_context_field_type,
+                       struct bt_ctf_field_type_common *event_header_field_type),
+               bool check_ts_begin_end_mapped);
 
 struct bt_ctf_trace {
-       struct bt_trace_common common;
+       struct bt_ctf_trace_common common;
 };
 
 /*
@@ -52,4 +353,20 @@ char *bt_ctf_trace_get_metadata_string(struct bt_ctf_trace *trace);
 BT_HIDDEN
 struct bt_ctf_trace *bt_ctf_trace_create(void);
 
+BT_HIDDEN
+int64_t bt_ctf_trace_get_clock_class_count(
+               struct bt_ctf_trace *trace);
+
+BT_HIDDEN
+struct bt_ctf_clock_class *bt_ctf_trace_get_clock_class_by_index(
+               struct bt_ctf_trace *trace, uint64_t index);
+
+BT_HIDDEN
+struct bt_ctf_clock_class *bt_ctf_trace_get_clock_class_by_name(
+               struct bt_ctf_trace *trace, const char *name);
+
+BT_HIDDEN
+int bt_ctf_trace_add_clock_class(struct bt_ctf_trace *trace,
+               struct bt_ctf_clock_class *clock_class);
+
 #endif /* BABELTRACE_CTF_WRITER_TRACE_INTERNAL_H */
index e8947cb8bcb5b46e12536c6665008e9d1ad6b9fe..68af9a8b48d0203711f0c971f7a03c77d40ee6ab 100644 (file)
@@ -37,7 +37,6 @@ extern "C" {
 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);
@@ -84,18 +83,6 @@ extern struct bt_ctf_field_type *bt_ctf_trace_get_packet_header_field_type(
 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);
 
diff --git a/include/babeltrace/ctf-writer/utils-internal.h b/include/babeltrace/ctf-writer/utils-internal.h
new file mode 100644 (file)
index 0000000..264bf33
--- /dev/null
@@ -0,0 +1,225 @@
+#ifndef BABELTRACE_CTF_WRITER_UTILS_INTERNAL_H
+#define BABELTRACE_CTF_WRITER_UTILS_INTERNAL_H
+
+/*
+ * Babeltrace - Internal CTF writer utilities
+ *
+ * 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.
+ */
+
+#include <babeltrace/babeltrace-internal.h>
+#include <babeltrace/ctf-writer/field-types.h>
+#include <babeltrace/ctf-writer/field-path-internal.h>
+#include <babeltrace/ctf-writer/event.h>
+#include <stdint.h>
+
+#define BT_CTF_TO_COMMON(_obj)         (&(_obj)->common)
+#define BT_CTF_FROM_COMMON(_obj)       ((void *) _obj)
+
+struct bt_ctf_search_query {
+       gpointer value;
+       int found;
+};
+
+BT_HIDDEN
+const char *bt_ctf_get_byte_order_string(enum bt_ctf_byte_order byte_order);
+
+static inline
+const char *bt_ctf_field_type_id_string(enum bt_ctf_field_type_id type_id)
+{
+       switch (type_id) {
+       case BT_CTF_FIELD_TYPE_ID_UNKNOWN:
+               return "BT_CTF_FIELD_TYPE_ID_UNKNOWN";
+       case BT_CTF_FIELD_TYPE_ID_INTEGER:
+               return "BT_CTF_FIELD_TYPE_ID_INTEGER";
+       case BT_CTF_FIELD_TYPE_ID_FLOAT:
+               return "BT_CTF_FIELD_TYPE_ID_FLOAT";
+       case BT_CTF_FIELD_TYPE_ID_ENUM:
+               return "BT_CTF_FIELD_TYPE_ID_ENUM";
+       case BT_CTF_FIELD_TYPE_ID_STRING:
+               return "BT_CTF_FIELD_TYPE_ID_STRING";
+       case BT_CTF_FIELD_TYPE_ID_STRUCT:
+               return "BT_CTF_FIELD_TYPE_ID_STRUCT";
+       case BT_CTF_FIELD_TYPE_ID_ARRAY:
+               return "BT_CTF_FIELD_TYPE_ID_ARRAY";
+       case BT_CTF_FIELD_TYPE_ID_SEQUENCE:
+               return "BT_CTF_FIELD_TYPE_ID_SEQUENCE";
+       case BT_CTF_FIELD_TYPE_ID_VARIANT:
+               return "BT_CTF_FIELD_TYPE_ID_VARIANT";
+       default:
+               return "(unknown)";
+       }
+};
+
+static inline
+const char *bt_ctf_byte_order_string(enum bt_ctf_byte_order bo)
+{
+       switch (bo) {
+       case BT_CTF_BYTE_ORDER_UNKNOWN:
+               return "BT_CTF_BYTE_ORDER_UNKNOWN";
+       case BT_CTF_BYTE_ORDER_UNSPECIFIED:
+               return "BT_CTF_BYTE_ORDER_UNSPECIFIED";
+       case BT_CTF_BYTE_ORDER_NATIVE:
+               return "BT_CTF_BYTE_ORDER_NATIVE";
+       case BT_CTF_BYTE_ORDER_LITTLE_ENDIAN:
+               return "BT_CTF_BYTE_ORDER_LITTLE_ENDIAN";
+       case BT_CTF_BYTE_ORDER_BIG_ENDIAN:
+               return "BT_CTF_BYTE_ORDER_BIG_ENDIAN";
+       case BT_CTF_BYTE_ORDER_NETWORK:
+               return "BT_CTF_BYTE_ORDER_NETWORK";
+       default:
+               return "(unknown)";
+       }
+};
+
+static inline
+const char *bt_ctf_string_encoding_string(enum bt_ctf_string_encoding encoding)
+{
+       switch (encoding) {
+       case BT_CTF_STRING_ENCODING_UNKNOWN:
+               return "BT_CTF_STRING_ENCODING_UNKNOWN";
+       case BT_CTF_STRING_ENCODING_NONE:
+               return "BT_CTF_STRING_ENCODING_NONE";
+       case BT_CTF_STRING_ENCODING_UTF8:
+               return "BT_CTF_STRING_ENCODING_UTF8";
+       case BT_CTF_STRING_ENCODING_ASCII:
+               return "BT_CTF_STRING_ENCODING_ASCII";
+       default:
+               return "(unknown)";
+       }
+};
+
+static inline
+const char *bt_ctf_integer_base_string(enum bt_ctf_integer_base base)
+{
+       switch (base) {
+       case BT_CTF_INTEGER_BASE_UNKNOWN:
+               return "BT_CTF_INTEGER_BASE_UNKNOWN";
+       case BT_CTF_INTEGER_BASE_UNSPECIFIED:
+               return "BT_CTF_INTEGER_BASE_UNSPECIFIED";
+       case BT_CTF_INTEGER_BASE_BINARY:
+               return "BT_CTF_INTEGER_BASE_BINARY";
+       case BT_CTF_INTEGER_BASE_OCTAL:
+               return "BT_CTF_INTEGER_BASE_OCTAL";
+       case BT_CTF_INTEGER_BASE_DECIMAL:
+               return "BT_CTF_INTEGER_BASE_DECIMAL";
+       case BT_CTF_INTEGER_BASE_HEXADECIMAL:
+               return "BT_CTF_INTEGER_BASE_HEXADECIMAL";
+       default:
+               return "(unknown)";
+       }
+}
+
+static inline
+const char *bt_ctf_scope_string(enum bt_ctf_scope scope)
+{
+       switch (scope) {
+       case BT_CTF_SCOPE_UNKNOWN:
+               return "BT_CTF_SCOPE_UNKNOWN";
+       case BT_CTF_SCOPE_TRACE_PACKET_HEADER:
+               return "BT_CTF_SCOPE_TRACE_PACKET_HEADER";
+       case BT_CTF_SCOPE_STREAM_PACKET_CONTEXT:
+               return "BT_CTF_SCOPE_STREAM_PACKET_CONTEXT";
+       case BT_CTF_SCOPE_STREAM_EVENT_HEADER:
+               return "BT_CTF_SCOPE_STREAM_EVENT_HEADER";
+       case BT_CTF_SCOPE_STREAM_EVENT_CONTEXT:
+               return "BT_CTF_SCOPE_STREAM_EVENT_CONTEXT";
+       case BT_CTF_SCOPE_EVENT_CONTEXT:
+               return "BT_CTF_SCOPE_EVENT_CONTEXT";
+       case BT_CTF_SCOPE_EVENT_PAYLOAD:
+               return "BT_CTF_SCOPE_EVENT_PAYLOAD";
+       case BT_CTF_SCOPE_ENV:
+               return "BT_CTF_SCOPE_ENV";
+       default:
+               return "(unknown)";
+       }
+}
+
+static inline
+const char *bt_ctf_event_class_log_level_string(
+               enum bt_ctf_event_class_log_level level)
+{
+       switch (level) {
+       case BT_CTF_EVENT_CLASS_LOG_LEVEL_UNKNOWN:
+               return "BT_CTF_EVENT_CLASS_LOG_LEVEL_UNKNOWN";
+       case BT_CTF_EVENT_CLASS_LOG_LEVEL_UNSPECIFIED:
+               return "BT_CTF_EVENT_CLASS_LOG_LEVEL_UNSPECIFIED";
+       case BT_CTF_EVENT_CLASS_LOG_LEVEL_EMERGENCY:
+               return "BT_CTF_EVENT_CLASS_LOG_LEVEL_EMERGENCY";
+       case BT_CTF_EVENT_CLASS_LOG_LEVEL_ALERT:
+               return "BT_CTF_EVENT_CLASS_LOG_LEVEL_ALERT";
+       case BT_CTF_EVENT_CLASS_LOG_LEVEL_CRITICAL:
+               return "BT_CTF_EVENT_CLASS_LOG_LEVEL_CRITICAL";
+       case BT_CTF_EVENT_CLASS_LOG_LEVEL_ERROR:
+               return "BT_CTF_EVENT_CLASS_LOG_LEVEL_ERROR";
+       case BT_CTF_EVENT_CLASS_LOG_LEVEL_WARNING:
+               return "BT_CTF_EVENT_CLASS_LOG_LEVEL_WARNING";
+       case BT_CTF_EVENT_CLASS_LOG_LEVEL_NOTICE:
+               return "BT_CTF_EVENT_CLASS_LOG_LEVEL_NOTICE";
+       case BT_CTF_EVENT_CLASS_LOG_LEVEL_INFO:
+               return "BT_CTF_EVENT_CLASS_LOG_LEVEL_INFO";
+       case BT_CTF_EVENT_CLASS_LOG_LEVEL_DEBUG_SYSTEM:
+               return "BT_CTF_EVENT_CLASS_LOG_LEVEL_DEBUG_SYSTEM";
+       case BT_CTF_EVENT_CLASS_LOG_LEVEL_DEBUG_PROGRAM:
+               return "BT_CTF_EVENT_CLASS_LOG_LEVEL_DEBUG_PROGRAM";
+       case BT_CTF_EVENT_CLASS_LOG_LEVEL_DEBUG_PROCESS:
+               return "BT_CTF_EVENT_CLASS_LOG_LEVEL_DEBUG_PROCESS";
+       case BT_CTF_EVENT_CLASS_LOG_LEVEL_DEBUG_MODULE:
+               return "BT_CTF_EVENT_CLASS_LOG_LEVEL_DEBUG_MODULE";
+       case BT_CTF_EVENT_CLASS_LOG_LEVEL_DEBUG_UNIT:
+               return "BT_CTF_EVENT_CLASS_LOG_LEVEL_DEBUG_UNIT";
+       case BT_CTF_EVENT_CLASS_LOG_LEVEL_DEBUG_FUNCTION:
+               return "BT_CTF_EVENT_CLASS_LOG_LEVEL_DEBUG_FUNCTION";
+       case BT_CTF_EVENT_CLASS_LOG_LEVEL_DEBUG_LINE:
+               return "BT_CTF_EVENT_CLASS_LOG_LEVEL_DEBUG_LINE";
+       case BT_CTF_EVENT_CLASS_LOG_LEVEL_DEBUG:
+               return "BT_CTF_EVENT_CLASS_LOG_LEVEL_DEBUG";
+       default:
+               return "(unknown)";
+       }
+};
+
+static inline
+GString *bt_ctf_field_path_string(struct bt_ctf_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_ctf_field_path_get_root_scope(path)));
+
+       for (i = 0; i < bt_ctf_field_path_get_index_count(path); i++) {
+               int index = bt_ctf_field_path_get_index(path, i);
+
+               g_string_append_printf(str, ", %d", index);
+       }
+
+       g_string_append(str, "]");
+
+end:
+       return str;
+}
+
+#endif /* BABELTRACE_CTF_WRITER_UTILS_INTERNAL_H */
diff --git a/include/babeltrace/ctf-writer/utils.h b/include/babeltrace/ctf-writer/utils.h
new file mode 100644 (file)
index 0000000..34cf476
--- /dev/null
@@ -0,0 +1,48 @@
+#ifndef BABELTRACE_CTF_WRITER_UTILS_H
+#define BABELTRACE_CTF_WRITER_UTILS_H
+
+/*
+ * BabelTrace - CTF writer: Utilities
+ *
+ * Copyright 2015 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
+ */
+
+/* For bt_bool */
+#include <babeltrace/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern bt_bool bt_ctf_identifier_is_valid(const char *identifier);
+
+static inline
+int bt_ctf_validate_identifier(const char *identifier)
+{
+       return bt_ctf_identifier_is_valid(identifier) ? 1 : 0;
+}
+
+#endif /* BABELTRACE_CTF_WRITER_UTILS_H */
diff --git a/include/babeltrace/ctf-writer/validation-internal.h b/include/babeltrace/ctf-writer/validation-internal.h
new file mode 100644 (file)
index 0000000..887b5a7
--- /dev/null
@@ -0,0 +1,129 @@
+#ifndef BABELTRACE_CTF_WRITER_VALIDATION_INTERNAL_H
+#define BABELTRACE_CTF_WRITER_VALIDATION_INTERNAL_H
+
+/*
+ * Babeltrace - CTF writer: Validation of trace, stream class, and event class
+ *
+ * Copyright 2016 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.
+ */
+
+#include <babeltrace/values.h>
+#include <babeltrace/babeltrace-internal.h>
+
+struct bt_ctf_trace_common;
+struct bt_ctf_stream_class_common;
+struct bt_ctf_event_class_common;
+struct bt_ctf_field_type_common;
+
+typedef struct bt_ctf_field_type_common *(*bt_ctf_validation_flag_copy_field_type_func)(
+               struct bt_ctf_field_type_common *);
+
+enum bt_ctf_validation_flag {
+       BT_CTF_VALIDATION_FLAG_TRACE    = 1,
+       BT_CTF_VALIDATION_FLAG_STREAM   = 2,
+       BT_CTF_VALIDATION_FLAG_EVENT    = 4,
+};
+
+/*
+ * Validation output structure.
+ *
+ * This is where the results of the validation function go. The field
+ * types are the validated ones which should replace the original field
+ * types of a trace, a stream class, and an event class.
+ *
+ * `valid_flags` contains the results of the validation.
+ */
+struct bt_ctf_validation_output {
+       struct bt_ctf_field_type_common *packet_header_type;
+       struct bt_ctf_field_type_common *packet_context_type;
+       struct bt_ctf_field_type_common *event_header_type;
+       struct bt_ctf_field_type_common *stream_event_ctx_type;
+       struct bt_ctf_field_type_common *event_context_type;
+       struct bt_ctf_field_type_common *event_payload_type;
+       enum bt_ctf_validation_flag valid_flags;
+};
+
+/*
+ * This function resolves and validates the field types of an event
+ * class, a stream class, and a trace. Copies are created if needed
+ * and the resulting field types to use are placed in the `output`
+ * validation structure, which also contains the results of the
+ * validation. Copies can replace the original field types of a trace,
+ * a stream class, and an event class using
+ * bt_ctf_validation_replace_types().
+ *
+ * The current known validity of the field types of the trace,
+ * stream class, and event class must be indicated with the
+ * `trace_valid`, `stream_class_valid`, and `event_class_valid`
+ * parameters. If a class is valid, its field types are not copied,
+ * validated, or resolved during this call.
+ *
+ * The validation flags `validate_flags` indicate which classes should
+ * have their field types validated.
+ *
+ * All parameters are owned by the caller.
+ */
+BT_HIDDEN
+int bt_ctf_validate_class_types(struct bt_value *environment,
+               struct bt_ctf_field_type_common *packet_header_type,
+               struct bt_ctf_field_type_common *packet_context_type,
+               struct bt_ctf_field_type_common *event_header_type,
+               struct bt_ctf_field_type_common *stream_event_ctx_type,
+               struct bt_ctf_field_type_common *event_context_type,
+               struct bt_ctf_field_type_common *event_payload_type,
+               int trace_valid, int stream_class_valid, int event_class_valid,
+               struct bt_ctf_validation_output *output,
+               enum bt_ctf_validation_flag validate_flags,
+               bt_ctf_validation_flag_copy_field_type_func copy_field_type_func);
+
+/*
+ * This function replaces the actual field types of a trace, a stream
+ * class, and an event class with the appropriate field types contained
+ * in a validation output structure.
+ *
+ * The replace flags `replace_flags` indicate which classes should have
+ * their field types replaced.
+ *
+ * Note that the field types that are not used in the validation output
+ * structure are still owned by it at the end of this call.
+ * bt_ctf_validation_output_put_types() should be called to clean the
+ * structure.
+ *
+ * All parameters are owned by the caller.
+ */
+BT_HIDDEN
+void bt_ctf_validation_replace_types(struct bt_ctf_trace_common *trace,
+               struct bt_ctf_stream_class_common *stream_class,
+               struct bt_ctf_event_class_common *event_class,
+               struct bt_ctf_validation_output *output,
+               enum bt_ctf_validation_flag replace_flags);
+
+/*
+ * This function puts all the field types contained in a given
+ * validation output structure.
+ *
+ * `output` is owned by the caller and is not freed here.
+ */
+BT_HIDDEN
+void bt_ctf_validation_output_put_types(
+               struct bt_ctf_validation_output *output);
+
+#endif /* BABELTRACE_CTF_WRITER_VALIDATION_INTERNAL_H */
diff --git a/include/babeltrace/ctf-writer/visitor-internal.h b/include/babeltrace/ctf-writer/visitor-internal.h
new file mode 100644 (file)
index 0000000..a52abaf
--- /dev/null
@@ -0,0 +1,51 @@
+#ifndef BABELTRACE_CTF_WRITER_VISITOR_INTERNAL_H
+#define BABELTRACE_CTF_WRITER_VISITOR_INTERNAL_H
+
+/*
+ * BabelTrace - CTF writer: Visitor internal
+ *
+ * Copyright 2016 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.
+ */
+
+#include <babeltrace/ctf-writer/visitor.h>
+#include <babeltrace/babeltrace-internal.h>
+
+typedef void *(*bt_ctf_child_accessor)(void *object, int index);
+typedef int64_t (*bt_ctf_child_count_accessor)(void *object);
+typedef int (*bt_ctf_child_visitor)(void *object, bt_ctf_visitor visitor,
+               void *data);
+
+struct bt_ctf_visitor_object {
+       enum bt_ctf_visitor_object_type type;
+       void *object;
+};
+
+BT_HIDDEN
+int visitor_helper(struct bt_ctf_visitor_object *root,
+               bt_ctf_child_count_accessor child_counter,
+               bt_ctf_child_accessor child_accessor,
+               bt_ctf_child_visitor child_visitor,
+               bt_ctf_visitor visitor,
+               void *data);
+
+#endif /* BABELTRACE_CTF_WRITER_VISITOR_INTERNAL_H */
diff --git a/include/babeltrace/ctf-writer/visitor.h b/include/babeltrace/ctf-writer/visitor.h
new file mode 100644 (file)
index 0000000..b6583a9
--- /dev/null
@@ -0,0 +1,175 @@
+#ifndef BABELTRACE_CTF_WRITER_VISITOR_H
+#define BABELTRACE_CTF_WRITER_VISITOR_H
+
+/*
+ * BabelTrace - CTF writer: Visitor
+ *
+ * Copyright 2016 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
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+@defgroup ctfirvisitor CTF IR visitor
+@ingroup ctfir
+@brief CTF IR visitor.
+
+@code
+#include <babeltrace/ctf-ir/visitor.h>
+@endcode
+
+A CTF IR <strong><em>visitor</em></strong> is a function that you
+can use to visit the hierarchy of a
+\link ctfirtraceclass CTF IR trace class\endlink with
+bt_ctf_trace_visit() or of a
+\link ctfirstreamclass CTF IR stream class\endlink with
+bt_ctf_stream_class_visit().
+
+The traversal of the object's hierarchy is always done in a
+pre-order fashion.
+
+@sa ctfirstreamclass
+@sa ctfirtraceclass
+
+@file
+@brief CTF IR visitor types and functions.
+@sa ctfirvisitor
+
+@addtogroup ctfirvisitor
+@{
+*/
+
+/**
+@struct bt_object
+@brief A CTF IR object wrapper.
+
+This structure wraps both a CTF IR object and its type
+(see #bt_object_type). It is used in the visiting function.
+
+You can use the bt_object_get_type() and
+bt_object_get_object() accessors to get the type and wrapped
+CTF IR object of a CTF IR object wrapper.
+
+A CTF IR object wrapper has <strong>no reference count</strong>: do \em
+not use bt_put() or bt_get() on it.
+
+@sa ctfirvisitor
+*/
+struct bt_ctf_visitor_object;
+
+/**
+@brief CTF IR object wrapper type.
+*/
+enum bt_ctf_visitor_object_type {
+       /// Unknown (used for errors).
+       BT_CTF_VISITOR_OBJECT_TYPE_UNKNOWN = -1,
+
+       /// \ref ctfirtraceclass.
+       BT_CTF_VISITOR_OBJECT_TYPE_TRACE = 0,
+
+       /// \ref ctfirstreamclass.
+       BT_CTF_VISITOR_OBJECT_TYPE_STREAM_CLASS = 1,
+
+       /// \ref ctfirstream.
+       BT_CTF_VISITOR_OBJECT_TYPE_STREAM = 2,
+
+       /// \ref ctfireventclass.
+       BT_CTF_VISITOR_OBJECT_TYPE_EVENT_CLASS = 3,
+
+       /// \ref ctfirevent.
+       BT_CTF_VISITOR_OBJECT_TYPE_EVENT = 4,
+
+       /// Number of entries in this enumeration.
+       BT_CTF_VISITOR_OBJECT_TYPE_NR,
+};
+
+/**
+@brief Visting function type.
+
+A function of this type is called by bt_ctf_trace_visit() or
+bt_ctf_stream_class_visit() when visiting the CTF IR object wrapper
+\p object.
+
+\p object has <strong>no reference count</strong>: do \em not use
+bt_put() or bt_get() on it.
+
+@param[in] object      Currently visited CTF IR object wrapper.
+@param[in] data                User data.
+@returns               0 on success, or a negative value on error.
+
+@prenotnull{object}
+
+@sa bt_ctf_trace_visit(): Accepts a visitor to visit a trace class.
+@sa bt_ctf_stream_class_visit(): Accepts a visitor to visit a stream
+       class.
+*/
+typedef int (*bt_ctf_visitor)(struct bt_ctf_visitor_object *object,
+               void *data);
+
+/**
+@brief Returns the type of the CTF IR object wrapped by the CTF IR
+       object wrapper \p object.
+
+@param[in] object      Object wrapper of which to get the type.
+@returns               Type of \p object.
+
+@prenotnull{object}
+
+@sa bt_ctf_visitor_object_get_object(): Returns the object wrapped by a given
+       CTF IR object wrapper.
+*/
+enum bt_ctf_visitor_object_type bt_ctf_visitor_object_get_type(
+               struct bt_ctf_visitor_object *object);
+
+/**
+@brief Returns the CTF IR object wrapped by the CTF IR object
+       wrapper \p object.
+
+The reference count of \p object is \em not incremented by this
+function. On success, you must call bt_get() on the return value to
+have your own reference.
+
+@param[in] object      Object wrapper of which to get the wrapped
+                       CTF IR object.
+@returns               CTF IR object wrapped by \p object.
+
+@prenotnull{object}
+@post The reference count of the returned object is not modified.
+
+@sa bt_ctf_visitor_object_get_type(): Returns the type of a given
+       CTF IR object wrapper.
+*/
+void *bt_ctf_visitor_object_get_object(struct bt_ctf_visitor_object *object);
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BABELTRACE_CTF_WRITER_VISITOR_H */
index 55ad145d8b88b22419472f73c6fade795196218b..07fed4656253373d6954398330dc42a3babb8156 100644 (file)
@@ -32,7 +32,7 @@
 #include <glib.h>
 #include <dirent.h>
 #include <sys/types.h>
-#include <babeltrace/ctf-ir/trace.h>
+#include <babeltrace/ctf-writer/trace.h>
 #include <babeltrace/object-internal.h>
 
 struct metadata_context {
@@ -63,7 +63,7 @@ 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);
+const char *bt_ctf_get_byte_order_string(enum bt_ctf_byte_order byte_order);
 
 BT_HIDDEN
 void bt_ctf_writer_freeze(struct bt_ctf_writer *writer);
index ca893d8ee2661eca16869242aba13aa0dac73610..9fcbec8ef41e5514a41c119b4205bc873f33429d 100644 (file)
@@ -70,8 +70,8 @@ int bt_lib_log_level;
  * 3. Optional: `+` to print extended fields. This depends on the
  *    provided format specifier.
  *
- * 4. Objet category: `w` for CTF writer objects, `_` for common
- *    objects, or nothing for default objects (includes CTF IR).
+ * 4. Objet category: `_` for common objects, or nothing for default
+ *    objects (includes CTF IR).
  *
  * 5. Format specifier (see below).
  *
@@ -146,33 +146,6 @@ int bt_lib_log_level;
  *   `o`:
  *       Object pool. The parameter type is `struct bt_object_pool *`.
  *
- * CTF writer category:
- *   `F`:
- *       CTF writer field type. The parameter type is `struct bt_field_type *`.
- *
- *   `f`:
- *       CTF writer field. The parameter type is `struct bt_field *`.
- *
- *   `E`:
- *       CTF writer event class. The parameter type is
- *       `struct bt_event_class *`.
- *
- *   `e`:
- *       CTF writer event. The parameter type is `struct bt_event *`.
- *
- *   `S`:
- *       CTF writer stream class. The parameter type is
- *       `struct bt_stream_class *`.
- *
- *   `s`:
- *       CTF writer stream. The parameter type is `struct bt_stream *`.
- *
- *   `t`:
- *       CTF writer trace. The parameter type is `struct bt_trace *`.
- *
- *   `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 *`.
@@ -202,7 +175,6 @@ int bt_lib_log_level;
  *     %!f
  *     %![my-event-]+e
  *     %!_t
- *     %![ctf-writer-ec-]wE
  *     %!+_F
  *
  * The string `, ` is printed between individual fields, but not after
index 1557f2e1c19bdd846edea9e8a9dbcad8ad86d8c3..b387f2531eb19bf4ae095d648ecf8609af444fa4 100644 (file)
@@ -1,16 +1,24 @@
 noinst_LTLIBRARIES = libctf-writer.la
 
 libctf_writer_la_SOURCES = \
+       attributes.c \
        clock.c \
-       event-class.c \
+       clock-class.c \
        event.c \
-       field-types.c \
+       event-class.c \
+       field-path.c \
        fields.c \
+       field-types.c \
+       field-wrapper.c \
        functor.c \
+       resolve.c \
        serialize.c \
-       stream-class.c \
        stream.c \
+       stream-class.c \
        trace.c \
+       utils.c \
+       validation.c \
+       visitor.c \
        writer.c
 
 libctf_writer_la_LIBADD = $(UUID_LIBS)
diff --git a/lib/ctf-writer/attributes.c b/lib/ctf-writer/attributes.c
new file mode 100644 (file)
index 0000000..af5bbea
--- /dev/null
@@ -0,0 +1,350 @@
+/*
+ * attributes.c
+ *
+ * Babeltrace CTF writer - Attributes
+ *
+ * Copyright (c) 2015 EfficiOS Inc. and Linux Foundation
+ * Copyright (c) 2015 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-ATTRS"
+#include <babeltrace/lib-logging-internal.h>
+
+#include <babeltrace/assert-internal.h>
+#include <babeltrace/babeltrace-internal.h>
+#include <babeltrace/compat/string-internal.h>
+#include <babeltrace/ref.h>
+#include <babeltrace/values-internal.h>
+#include <babeltrace/values.h>
+#include <inttypes.h>
+
+#define BT_CTF_ATTR_NAME_INDEX         0
+#define BT_CTF_ATTR_VALUE_INDEX                1
+
+BT_HIDDEN
+struct bt_value *bt_ctf_attributes_create(void)
+{
+       struct bt_value *attr_obj;
+
+       /*
+        * Attributes: array value object of array value objects, each one
+        * containing two entries: a string value object (attributes
+        * field name), and a value object (attributes field value).
+        *
+        * Example (JSON representation):
+        *
+        *     [
+        *         ["hostname", "eeppdesk"],
+        *         ["sysname", "Linux"],
+        *         ["tracer_major", 2],
+        *         ["tracer_minor", 5]
+        *     ]
+        */
+       BT_LOGD_STR("Creating attributes object.");
+       attr_obj = bt_value_array_create();
+       if (!attr_obj) {
+               BT_LOGE_STR("Failed to create array value.");
+       } else {
+               BT_LOGD("Created attributes object: addr=%p",
+                       attr_obj);
+       }
+
+       return attr_obj;
+}
+
+BT_HIDDEN
+void bt_ctf_attributes_destroy(struct bt_value *attr_obj)
+{
+       BT_LOGD("Destroying attributes object: addr=%p", attr_obj);
+       bt_put(attr_obj);
+}
+
+BT_HIDDEN
+int64_t bt_ctf_attributes_get_count(struct bt_value *attr_obj)
+{
+       return bt_value_array_size(attr_obj);
+}
+
+BT_HIDDEN
+const char *bt_ctf_attributes_get_field_name(struct bt_value *attr_obj,
+               uint64_t index)
+{
+       int rc;
+       const char *ret = NULL;
+       struct bt_value *attr_field_obj = NULL;
+       struct bt_value *attr_field_name_obj = NULL;
+
+       if (!attr_obj) {
+               BT_LOGW_STR("Invalid parameter: attributes object is NULL.");
+               goto end;
+       }
+
+       if (index >= bt_value_array_size(attr_obj)) {
+               BT_LOGW("Invalid parameter: index is out of bounds: "
+                       "index=%" PRIu64 ", count=%" PRId64,
+                       index, bt_value_array_size(attr_obj));
+               goto end;
+       }
+
+       attr_field_obj = bt_value_array_borrow(attr_obj, index);
+       if (!attr_field_obj) {
+               BT_LOGE("Cannot get attributes object's array value's element by index: "
+                       "value-addr=%p, index=%" PRIu64, attr_obj, index);
+               goto end;
+       }
+
+       attr_field_name_obj = bt_value_array_borrow(attr_field_obj,
+               BT_CTF_ATTR_NAME_INDEX);
+       if (!attr_field_name_obj) {
+               BT_LOGE("Cannot get attribute array value's element by index: "
+                       "value-addr=%p, index=%" PRIu64, attr_field_obj,
+                       (uint64_t) BT_CTF_ATTR_NAME_INDEX);
+               goto end;
+       }
+
+       rc = bt_value_string_get(attr_field_name_obj, &ret);
+       if (rc) {
+               BT_LOGE("Cannot get raw value from string value: value-addr=%p",
+                       attr_field_name_obj);
+               ret = NULL;
+       }
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+struct bt_value *bt_ctf_attributes_borrow_field_value(struct bt_value *attr_obj,
+               uint64_t index)
+{
+       struct bt_value *value_obj = NULL;
+       struct bt_value *attr_field_obj = NULL;
+
+       if (!attr_obj) {
+               BT_LOGW_STR("Invalid parameter: attributes object is NULL.");
+               goto end;
+       }
+
+       if (index >= bt_value_array_size(attr_obj)) {
+               BT_LOGW("Invalid parameter: index is out of bounds: "
+                       "index=%" PRIu64 ", count=%" PRId64,
+                       index, bt_value_array_size(attr_obj));
+               goto end;
+       }
+
+       attr_field_obj = bt_value_array_borrow(attr_obj, index);
+       if (!attr_field_obj) {
+               BT_LOGE("Cannot get attributes object's array value's element by index: "
+                       "value-addr=%p, index=%" PRIu64, attr_obj, index);
+               goto end;
+       }
+
+       value_obj = bt_value_array_borrow(attr_field_obj,
+               BT_CTF_ATTR_VALUE_INDEX);
+       if (!value_obj) {
+               BT_LOGE("Cannot get attribute array value's element by index: "
+                       "value-addr=%p, index=%" PRIu64, attr_field_obj,
+                       (uint64_t) BT_CTF_ATTR_VALUE_INDEX);
+       }
+
+end:
+       return value_obj;
+}
+
+static
+struct bt_value *bt_ctf_attributes_borrow_field_by_name(
+               struct bt_value *attr_obj, const char *name)
+{
+       uint64_t i;
+       int64_t attr_size;
+       struct bt_value *value_obj = NULL;
+       struct bt_value *attr_field_name_obj = NULL;
+
+       attr_size = bt_value_array_size(attr_obj);
+       if (attr_size < 0) {
+               BT_LOGE("Cannot get array value's size: value-addr=%p",
+                       attr_obj);
+               goto error;
+       }
+
+       for (i = 0; i < attr_size; ++i) {
+               int ret;
+               const char *field_name;
+
+               value_obj = bt_value_array_borrow(attr_obj, i);
+               if (!value_obj) {
+                       BT_LOGE("Cannot get attributes object's array value's element by index: "
+                               "value-addr=%p, index=%" PRIu64, attr_obj, i);
+                       goto error;
+               }
+
+               attr_field_name_obj = bt_value_array_borrow(value_obj,
+                       BT_CTF_ATTR_NAME_INDEX);
+               if (!attr_field_name_obj) {
+                       BT_LOGE("Cannot get attribute array value's element by index: "
+                               "value-addr=%p, index=%" PRIu64,
+                               value_obj, (int64_t) BT_CTF_ATTR_NAME_INDEX);
+                       goto error;
+               }
+
+               ret = bt_value_string_get(attr_field_name_obj, &field_name);
+               if (ret) {
+                       BT_LOGE("Cannot get raw value from string value: value-addr=%p",
+                               attr_field_name_obj);
+                       goto error;
+               }
+
+               if (!strcmp(field_name, name)) {
+                       break;
+               }
+
+               value_obj = NULL;
+       }
+
+       return value_obj;
+
+error:
+       value_obj = NULL;
+       return value_obj;
+}
+
+BT_HIDDEN
+int bt_ctf_attributes_set_field_value(struct bt_value *attr_obj,
+               const char *name, struct bt_value *value_obj)
+{
+       int ret = 0;
+       struct bt_value *attr_field_obj = NULL;
+
+       if (!attr_obj || !name || !value_obj) {
+               BT_LOGW("Invalid parameter: attributes object, name, or value object is NULL: "
+                       "attr-value-addr=%p, name-addr=%p, value-addr=%p",
+                       attr_obj, name, value_obj);
+               ret = -1;
+               goto end;
+       }
+
+       attr_field_obj = bt_ctf_attributes_borrow_field_by_name(attr_obj, name);
+       if (attr_field_obj) {
+               ret = bt_value_array_set(attr_field_obj,
+                       BT_CTF_ATTR_VALUE_INDEX, value_obj);
+               attr_field_obj = NULL;
+               goto end;
+       }
+
+       attr_field_obj = bt_value_array_create();
+       if (!attr_field_obj) {
+               BT_LOGE_STR("Failed to create empty array value.");
+               ret = -1;
+               goto end;
+       }
+
+       ret = bt_value_array_append_string(attr_field_obj, name);
+       ret |= bt_value_array_append(attr_field_obj, value_obj);
+       if (ret) {
+               BT_LOGE("Cannot append elements to array value: addr=%p",
+                       attr_field_obj);
+               goto end;
+       }
+
+       ret = bt_value_array_append(attr_obj, attr_field_obj);
+       if (ret) {
+               BT_LOGE("Cannot append element to array value: "
+                       "array-value-addr=%p, element-value-addr=%p",
+                       attr_obj, attr_field_obj);
+       }
+
+end:
+       bt_put(attr_field_obj);
+       return ret;
+}
+
+BT_HIDDEN
+struct bt_value *bt_ctf_attributes_borrow_field_value_by_name(
+               struct bt_value *attr_obj, const char *name)
+{
+       struct bt_value *value_obj = NULL;
+       struct bt_value *attr_field_obj = NULL;
+
+       if (!attr_obj || !name) {
+               BT_LOGW("Invalid parameter: attributes object or name is NULL: "
+                       "value-addr=%p, name-addr=%p", attr_obj, name);
+               goto end;
+       }
+
+       attr_field_obj = bt_ctf_attributes_borrow_field_by_name(attr_obj, name);
+       if (!attr_field_obj) {
+               BT_LOGD("Cannot find attributes object's field by name: "
+                       "value-addr=%p, name=\"%s\"", attr_obj, name);
+               goto end;
+       }
+
+       value_obj = bt_value_array_borrow(attr_field_obj,
+               BT_CTF_ATTR_VALUE_INDEX);
+       if (!value_obj) {
+               BT_LOGE("Cannot get attribute array value's element by index: "
+                       "value-addr=%p, index=%" PRIu64, attr_field_obj,
+                       (uint64_t) BT_CTF_ATTR_VALUE_INDEX);
+       }
+
+end:
+       return value_obj;
+}
+
+BT_HIDDEN
+int bt_ctf_attributes_freeze(struct bt_value *attr_obj)
+{
+       uint64_t i;
+       int64_t count;
+       int ret = 0;
+
+       if (!attr_obj) {
+               BT_LOGW_STR("Invalid parameter: attributes object is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       BT_LOGD("Freezing attributes object: value-addr=%p", attr_obj);
+       count = bt_value_array_size(attr_obj);
+       BT_ASSERT(count >= 0);
+
+       /*
+        * We do not freeze the array value object itself here, since
+        * internal stuff could need to modify/add attributes. Each
+        * attribute is frozen one by one.
+        */
+       for (i = 0; i < count; ++i) {
+               struct bt_value *obj = NULL;
+
+               obj = bt_ctf_attributes_borrow_field_value(attr_obj, i);
+               if (!obj) {
+                       BT_LOGE("Cannot get attributes object's field value by index: "
+                               "value-addr=%p, index=%" PRIu64,
+                               attr_obj, i);
+                       ret = -1;
+                       goto end;
+               }
+
+               bt_value_freeze(obj);
+       }
+
+end:
+       return ret;
+}
diff --git a/lib/ctf-writer/clock-class.c b/lib/ctf-writer/clock-class.c
new file mode 100644 (file)
index 0000000..fa468f3
--- /dev/null
@@ -0,0 +1,704 @@
+/*
+ * clock-class.c
+ *
+ * Babeltrace CTF writer - Clock class
+ *
+ * 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-CLOCK-CLASS"
+#include <babeltrace/lib-logging-internal.h>
+
+#include <babeltrace/assert-pre-internal.h>
+#include <babeltrace/compat/uuid-internal.h>
+#include <babeltrace/ctf-writer/clock-class-internal.h>
+#include <babeltrace/ctf-writer/utils.h>
+#include <babeltrace/ref.h>
+#include <babeltrace/compiler-internal.h>
+#include <babeltrace/types.h>
+#include <babeltrace/compat/string-internal.h>
+#include <inttypes.h>
+#include <babeltrace/object-internal.h>
+#include <babeltrace/assert-internal.h>
+
+static
+void bt_ctf_clock_class_destroy(struct bt_object *obj);
+
+BT_HIDDEN
+bt_bool bt_ctf_clock_class_is_valid(struct bt_ctf_clock_class *clock_class)
+{
+       return clock_class && clock_class->name;
+}
+
+BT_HIDDEN
+int bt_ctf_clock_class_set_name(struct bt_ctf_clock_class *clock_class,
+               const char *name)
+{
+       int ret = 0;
+
+       if (!clock_class) {
+               BT_LOGW_STR("Invalid parameter: clock class is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       if (clock_class->frozen) {
+               BT_LOGW("Invalid parameter: clock class is frozen: addr=%p, name=\"%s\"",
+                       clock_class, bt_ctf_clock_class_get_name(clock_class));
+               ret = -1;
+               goto end;
+       }
+
+       if (!bt_ctf_identifier_is_valid(name)) {
+               BT_LOGW("Clock class's name is not a valid CTF identifier: "
+                       "addr=%p, name=\"%s\"",
+                       clock_class, name);
+               ret = -1;
+               goto end;
+       }
+
+       if (clock_class->name) {
+               g_string_assign(clock_class->name, name);
+       } else {
+               clock_class->name = g_string_new(name);
+               if (!clock_class->name) {
+                       BT_LOGE_STR("Failed to allocate a GString.");
+                       ret = -1;
+                       goto end;
+               }
+       }
+
+       BT_LOGV("Set clock class's name: addr=%p, name=\"%s\"",
+               clock_class, name);
+
+end:
+       return ret;
+}
+
+static
+bool validate_freq(struct bt_ctf_clock_class *clock_class,
+               const char *name, uint64_t freq)
+{
+       bool is_valid = true;
+
+       if (freq == -1ULL || freq == 0) {
+               BT_LOGW("Invalid parameter: frequency is invalid: "
+                       "addr=%p, name=\"%s\", freq=%" PRIu64,
+                       clock_class, name, freq);
+               is_valid = false;
+               goto end;
+       }
+
+end:
+       return is_valid;
+}
+
+BT_HIDDEN
+struct bt_ctf_clock_class *bt_ctf_clock_class_create(const char *name,
+               uint64_t freq)
+{
+       int ret;
+       struct bt_ctf_clock_class *clock_class = NULL;
+
+       BT_LOGD("Creating default clock class object: name=\"%s\"",
+               name);
+
+       if (!validate_freq(NULL, name, freq)) {
+               /* validate_freq() logs errors */
+               goto error;
+       }
+
+       clock_class = g_new0(struct bt_ctf_clock_class, 1);
+       if (!clock_class) {
+               BT_LOGE_STR("Failed to allocate one clock class.");
+               goto error;
+       }
+
+       clock_class->precision = 1;
+       clock_class->frequency = freq;
+       bt_object_init_shared(&clock_class->base, bt_ctf_clock_class_destroy);
+
+       if (name) {
+               ret = bt_ctf_clock_class_set_name(clock_class, name);
+               if (ret) {
+                       /* bt_ctf_clock_class_set_name() logs errors */
+                       goto error;
+               }
+       }
+
+       BT_LOGD("Created clock class object: addr=%p, name=\"%s\"",
+               clock_class, name);
+       return clock_class;
+error:
+       BT_PUT(clock_class);
+       return clock_class;
+}
+
+BT_HIDDEN
+const char *bt_ctf_clock_class_get_name(struct bt_ctf_clock_class *clock_class)
+{
+       const char *ret = NULL;
+
+       if (!clock_class) {
+               BT_LOGW_STR("Invalid parameter: clock class is NULL.");
+               goto end;
+       }
+
+       if (clock_class->name) {
+               ret = clock_class->name->str;
+       }
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+const char *bt_ctf_clock_class_get_description(
+               struct bt_ctf_clock_class *clock_class)
+{
+       const char *ret = NULL;
+
+       if (!clock_class) {
+               BT_LOGW_STR("Invalid parameter: clock class is NULL.");
+               goto end;
+       }
+
+       if (clock_class->description) {
+               ret = clock_class->description->str;
+       }
+end:
+       return ret;
+}
+
+BT_HIDDEN
+int bt_ctf_clock_class_set_description(struct bt_ctf_clock_class *clock_class,
+               const char *desc)
+{
+       int ret = 0;
+
+       if (!clock_class || !desc) {
+               BT_LOGW("Invalid parameter: clock class or description is NULL: "
+                       "clock-class-addr=%p, name=\"%s\", desc-addr=%p",
+                       clock_class, bt_ctf_clock_class_get_name(clock_class),
+                       desc);
+               ret = -1;
+               goto end;
+       }
+
+       if (clock_class->frozen) {
+               BT_LOGW("Invalid parameter: clock class is frozen: addr=%p, name=\"%s\"",
+                       clock_class, bt_ctf_clock_class_get_name(clock_class));
+               ret = -1;
+               goto end;
+       }
+
+       clock_class->description = g_string_new(desc);
+       ret = clock_class->description ? 0 : -1;
+       BT_LOGV("Set clock class's description: addr=%p, "
+               "name=\"%s\", desc=\"%s\"",
+               clock_class, bt_ctf_clock_class_get_name(clock_class), desc);
+end:
+       return ret;
+}
+
+BT_HIDDEN
+uint64_t bt_ctf_clock_class_get_frequency(
+               struct bt_ctf_clock_class *clock_class)
+{
+       uint64_t ret = -1ULL;
+
+       if (!clock_class) {
+               BT_LOGW_STR("Invalid parameter: clock class is NULL.");
+               goto end;
+       }
+
+       ret = clock_class->frequency;
+end:
+       return ret;
+}
+
+BT_HIDDEN
+int bt_ctf_clock_class_set_frequency(struct bt_ctf_clock_class *clock_class,
+               uint64_t freq)
+{
+       int ret = 0;
+
+       if (!clock_class) {
+               BT_LOGW("Invalid parameter: clock class is NULL or frequency is invalid: "
+                       "addr=%p, name=\"%s\"",
+                       clock_class, bt_ctf_clock_class_get_name(clock_class));
+               ret = -1;
+               goto end;
+       }
+
+       if (!validate_freq(clock_class, bt_ctf_clock_class_get_name(clock_class),
+                       freq)) {
+               /* validate_freq() logs errors */
+               goto end;
+       }
+
+       if (clock_class->frozen) {
+               BT_LOGW("Invalid parameter: clock class is frozen: addr=%p, name=\"%s\"",
+                       clock_class, bt_ctf_clock_class_get_name(clock_class));
+               ret = -1;
+               goto end;
+       }
+
+       clock_class->frequency = freq;
+       BT_LOGV("Set clock class's frequency: addr=%p, name=\"%s\", freq=%" PRIu64,
+               clock_class, bt_ctf_clock_class_get_name(clock_class), freq);
+end:
+       return ret;
+}
+
+BT_HIDDEN
+uint64_t bt_ctf_clock_class_get_precision(struct bt_ctf_clock_class *clock_class)
+{
+       uint64_t ret = -1ULL;
+
+       if (!clock_class) {
+               BT_LOGW_STR("Invalid parameter: clock class is NULL.");
+               goto end;
+       }
+
+       ret = clock_class->precision;
+end:
+       return ret;
+}
+
+BT_HIDDEN
+int bt_ctf_clock_class_set_precision(struct bt_ctf_clock_class *clock_class,
+               uint64_t precision)
+{
+       int ret = 0;
+
+       if (!clock_class || precision == -1ULL) {
+               BT_LOGW("Invalid parameter: clock class is NULL or precision is invalid: "
+                       "addr=%p, name=\"%s\", precision=%" PRIu64,
+                       clock_class, bt_ctf_clock_class_get_name(clock_class),
+                       precision);
+               ret = -1;
+               goto end;
+       }
+
+       if (clock_class->frozen) {
+               BT_LOGW("Invalid parameter: clock class is frozen: addr=%p, name=\"%s\"",
+                       clock_class, bt_ctf_clock_class_get_name(clock_class));
+               ret = -1;
+               goto end;
+       }
+
+       clock_class->precision = precision;
+       BT_LOGV("Set clock class's precision: addr=%p, name=\"%s\", precision=%" PRIu64,
+               clock_class, bt_ctf_clock_class_get_name(clock_class),
+               precision);
+end:
+       return ret;
+}
+
+BT_HIDDEN
+int bt_ctf_clock_class_get_offset_s(struct bt_ctf_clock_class *clock_class,
+               int64_t *offset_s)
+{
+       int ret = 0;
+
+       if (!clock_class || !offset_s) {
+               BT_LOGW("Invalid parameter: clock class or offset pointer is NULL: "
+                       "clock-class-addr=%p, name=\"%s\", offset-addr=%p",
+                       clock_class, bt_ctf_clock_class_get_name(clock_class),
+                       offset_s);
+               ret = -1;
+               goto end;
+       }
+
+       *offset_s = clock_class->offset_s;
+end:
+       return ret;
+}
+
+BT_HIDDEN
+int bt_ctf_clock_class_set_offset_s(struct bt_ctf_clock_class *clock_class,
+               int64_t offset_s)
+{
+       int ret = 0;
+
+       if (!clock_class) {
+               BT_LOGW_STR("Invalid parameter: clock class is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       if (clock_class->frozen) {
+               BT_LOGW("Invalid parameter: clock class is frozen: addr=%p, name=\"%s\"",
+                       clock_class, bt_ctf_clock_class_get_name(clock_class));
+               ret = -1;
+               goto end;
+       }
+
+       clock_class->offset_s = offset_s;
+       BT_LOGV("Set clock class's offset (seconds): "
+               "addr=%p, name=\"%s\", offset-s=%" PRId64,
+               clock_class, bt_ctf_clock_class_get_name(clock_class),
+               offset_s);
+end:
+       return ret;
+}
+
+BT_HIDDEN
+int bt_ctf_clock_class_get_offset_cycles(struct bt_ctf_clock_class *clock_class,
+               int64_t *offset)
+{
+       int ret = 0;
+
+       if (!clock_class || !offset) {
+               BT_LOGW("Invalid parameter: clock class or offset pointer is NULL: "
+                       "clock-class-addr=%p, name=\"%s\", offset-addr=%p",
+                       clock_class, bt_ctf_clock_class_get_name(clock_class),
+                       offset);
+               ret = -1;
+               goto end;
+       }
+
+       *offset = clock_class->offset;
+end:
+       return ret;
+}
+
+BT_HIDDEN
+int bt_ctf_clock_class_set_offset_cycles(struct bt_ctf_clock_class *clock_class,
+               int64_t offset)
+{
+       int ret = 0;
+
+       if (!clock_class) {
+               BT_LOGW_STR("Invalid parameter: clock class is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       if (clock_class->frozen) {
+               BT_LOGW("Invalid parameter: clock class is frozen: addr=%p, name=\"%s\"",
+                       clock_class, bt_ctf_clock_class_get_name(clock_class));
+               ret = -1;
+               goto end;
+       }
+
+       clock_class->offset = offset;
+       BT_LOGV("Set clock class's offset (cycles): addr=%p, name=\"%s\", offset-cycles=%" PRId64,
+               clock_class, bt_ctf_clock_class_get_name(clock_class), offset);
+end:
+       return ret;
+}
+
+BT_HIDDEN
+bt_bool bt_ctf_clock_class_is_absolute(struct bt_ctf_clock_class *clock_class)
+{
+       int ret = -1;
+
+       if (!clock_class) {
+               BT_LOGW_STR("Invalid parameter: clock class is NULL.");
+               goto end;
+       }
+
+       ret = clock_class->absolute;
+end:
+       return ret;
+}
+
+BT_HIDDEN
+int bt_ctf_clock_class_set_is_absolute(struct bt_ctf_clock_class *clock_class,
+               bt_bool is_absolute)
+{
+       int ret = 0;
+
+       if (!clock_class) {
+               BT_LOGW_STR("Invalid parameter: clock class is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       if (clock_class->frozen) {
+               BT_LOGW("Invalid parameter: clock class is frozen: addr=%p, name=\"%s\"",
+                       clock_class, bt_ctf_clock_class_get_name(clock_class));
+               ret = -1;
+               goto end;
+       }
+
+       clock_class->absolute = !!is_absolute;
+       BT_LOGV("Set clock class's absolute flag: addr=%p, name=\"%s\", is-absolute=%d",
+               clock_class, bt_ctf_clock_class_get_name(clock_class),
+               is_absolute);
+end:
+       return ret;
+}
+
+BT_HIDDEN
+const unsigned char *bt_ctf_clock_class_get_uuid(
+               struct bt_ctf_clock_class *clock_class)
+{
+       const unsigned char *ret;
+
+       if (!clock_class) {
+               BT_LOGW_STR("Invalid parameter: clock class is NULL.");
+               ret = NULL;
+               goto end;
+       }
+
+       if (!clock_class->uuid_set) {
+               BT_LOGV("Clock class's UUID is not set: addr=%p, name=\"%s\"",
+                       clock_class, bt_ctf_clock_class_get_name(clock_class));
+               ret = NULL;
+               goto end;
+       }
+
+       ret = clock_class->uuid;
+end:
+       return ret;
+}
+
+BT_HIDDEN
+int bt_ctf_clock_class_set_uuid(struct bt_ctf_clock_class *clock_class,
+               const unsigned char *uuid)
+{
+       int ret = 0;
+
+       if (!clock_class || !uuid) {
+               BT_LOGW("Invalid parameter: clock class or UUID is NULL: "
+                       "clock-class-addr=%p, name=\"%s\", uuid-addr=%p",
+                       clock_class, bt_ctf_clock_class_get_name(clock_class),
+                       uuid);
+               ret = -1;
+               goto end;
+       }
+
+       if (clock_class->frozen) {
+               BT_LOGW("Invalid parameter: clock class is frozen: addr=%p, name=\"%s\"",
+                       clock_class, bt_ctf_clock_class_get_name(clock_class));
+               ret = -1;
+               goto end;
+       }
+
+       memcpy(clock_class->uuid, uuid, BABELTRACE_UUID_LEN);
+       clock_class->uuid_set = 1;
+       BT_LOGV("Set clock class's UUID: addr=%p, name=\"%s\", "
+               "uuid=\"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\"",
+               clock_class, bt_ctf_clock_class_get_name(clock_class),
+               (unsigned int) uuid[0],
+               (unsigned int) uuid[1],
+               (unsigned int) uuid[2],
+               (unsigned int) uuid[3],
+               (unsigned int) uuid[4],
+               (unsigned int) uuid[5],
+               (unsigned int) uuid[6],
+               (unsigned int) uuid[7],
+               (unsigned int) uuid[8],
+               (unsigned int) uuid[9],
+               (unsigned int) uuid[10],
+               (unsigned int) uuid[11],
+               (unsigned int) uuid[12],
+               (unsigned int) uuid[13],
+               (unsigned int) uuid[14],
+               (unsigned int) uuid[15]);
+end:
+       return ret;
+}
+
+BT_HIDDEN
+void bt_ctf_clock_class_freeze(struct bt_ctf_clock_class *clock_class)
+{
+       if (!clock_class || clock_class->frozen) {
+               return;
+       }
+
+       BT_LOGD("Freezing clock class: addr=%p, name=\"%s\"",
+               clock_class, bt_ctf_clock_class_get_name(clock_class));
+       clock_class->frozen = 1;
+}
+
+static
+void bt_ctf_clock_class_destroy(struct bt_object *obj)
+{
+       struct bt_ctf_clock_class *clock_class;
+
+       clock_class = container_of(obj, struct bt_ctf_clock_class, base);
+       BT_LOGD("Destroying clock class: addr=%p, name=\"%s\"",
+               obj, bt_ctf_clock_class_get_name(clock_class));
+
+       if (clock_class->name) {
+               g_string_free(clock_class->name, TRUE);
+       }
+
+       if (clock_class->description) {
+               g_string_free(clock_class->description, TRUE);
+       }
+
+       g_free(clock_class);
+}
+
+BT_HIDDEN
+int bt_ctf_clock_class_compare(struct bt_ctf_clock_class *clock_class_a,
+               struct bt_ctf_clock_class *clock_class_b)
+{
+       int ret = 1;
+       BT_ASSERT(clock_class_a);
+       BT_ASSERT(clock_class_b);
+
+       /* Name */
+       if (strcmp(clock_class_a->name->str, clock_class_b->name->str) != 0) {
+               BT_LOGV("Clock classes differ: different names: "
+                       "cc-a-name=\"%s\", cc-b-name=\"%s\"",
+                       clock_class_a->name->str,
+                       clock_class_b->name->str);
+               goto end;
+       }
+
+       /* Description */
+       if (clock_class_a->description) {
+               if (!clock_class_b->description) {
+                       BT_LOGV_STR("Clock classes differ: clock class A has a "
+                               "description, but clock class B does not.");
+                       goto end;
+               }
+
+               if (strcmp(clock_class_a->name->str, clock_class_b->name->str)
+                               != 0) {
+                       BT_LOGV("Clock classes differ: different descriptions: "
+                               "cc-a-descr=\"%s\", cc-b-descr=\"%s\"",
+                               clock_class_a->description->str,
+                               clock_class_b->description->str);
+                       goto end;
+               }
+       } else {
+               if (clock_class_b->description) {
+                       BT_LOGV_STR("Clock classes differ: clock class A has "
+                               "no description, but clock class B has one.");
+                       goto end;
+               }
+       }
+
+       /* Frequency */
+       if (clock_class_a->frequency != clock_class_b->frequency) {
+               BT_LOGV("Clock classes differ: different frequencies: "
+                       "cc-a-freq=%" PRIu64 ", cc-b-freq=%" PRIu64,
+                       clock_class_a->frequency,
+                       clock_class_b->frequency);
+               goto end;
+       }
+
+       /* Precision */
+       if (clock_class_a->precision != clock_class_b->precision) {
+               BT_LOGV("Clock classes differ: different precisions: "
+                       "cc-a-freq=%" PRIu64 ", cc-b-freq=%" PRIu64,
+                       clock_class_a->precision,
+                       clock_class_b->precision);
+               goto end;
+       }
+
+       /* Offset (seconds) */
+       if (clock_class_a->offset_s != clock_class_b->offset_s) {
+               BT_LOGV("Clock classes differ: different offsets (seconds): "
+                       "cc-a-offset-s=%" PRId64 ", cc-b-offset-s=%" PRId64,
+                       clock_class_a->offset_s,
+                       clock_class_b->offset_s);
+               goto end;
+       }
+
+       /* Offset (cycles) */
+       if (clock_class_a->offset != clock_class_b->offset) {
+               BT_LOGV("Clock classes differ: different offsets (cycles): "
+                       "cc-a-offset-s=%" PRId64 ", cc-b-offset-s=%" PRId64,
+                       clock_class_a->offset,
+                       clock_class_b->offset);
+               goto end;
+       }
+
+       /* UUIDs */
+       if (clock_class_a->uuid_set) {
+               if (!clock_class_b->uuid_set) {
+                       BT_LOGV_STR("Clock classes differ: clock class A has a "
+                               "UUID, but clock class B does not.");
+                       goto end;
+               }
+
+               if (memcmp(clock_class_a->uuid, clock_class_b->uuid,
+                               BABELTRACE_UUID_LEN) != 0) {
+                       BT_LOGV("Clock classes differ: different UUIDs: "
+                               "cc-a-uuid=\"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\", "
+                               "cc-b-uuid=\"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\"",
+                               (unsigned int) clock_class_a->uuid[0],
+                               (unsigned int) clock_class_a->uuid[1],
+                               (unsigned int) clock_class_a->uuid[2],
+                               (unsigned int) clock_class_a->uuid[3],
+                               (unsigned int) clock_class_a->uuid[4],
+                               (unsigned int) clock_class_a->uuid[5],
+                               (unsigned int) clock_class_a->uuid[6],
+                               (unsigned int) clock_class_a->uuid[7],
+                               (unsigned int) clock_class_a->uuid[8],
+                               (unsigned int) clock_class_a->uuid[9],
+                               (unsigned int) clock_class_a->uuid[10],
+                               (unsigned int) clock_class_a->uuid[11],
+                               (unsigned int) clock_class_a->uuid[12],
+                               (unsigned int) clock_class_a->uuid[13],
+                               (unsigned int) clock_class_a->uuid[14],
+                               (unsigned int) clock_class_a->uuid[15],
+                               (unsigned int) clock_class_b->uuid[0],
+                               (unsigned int) clock_class_b->uuid[1],
+                               (unsigned int) clock_class_b->uuid[2],
+                               (unsigned int) clock_class_b->uuid[3],
+                               (unsigned int) clock_class_b->uuid[4],
+                               (unsigned int) clock_class_b->uuid[5],
+                               (unsigned int) clock_class_b->uuid[6],
+                               (unsigned int) clock_class_b->uuid[7],
+                               (unsigned int) clock_class_b->uuid[8],
+                               (unsigned int) clock_class_b->uuid[9],
+                               (unsigned int) clock_class_b->uuid[10],
+                               (unsigned int) clock_class_b->uuid[11],
+                               (unsigned int) clock_class_b->uuid[12],
+                               (unsigned int) clock_class_b->uuid[13],
+                               (unsigned int) clock_class_b->uuid[14],
+                               (unsigned int) clock_class_b->uuid[15]);
+                       goto end;
+               }
+       } else {
+               if (clock_class_b->uuid_set) {
+                       BT_LOGV_STR("Clock classes differ: clock class A has "
+                               "no UUID, but clock class B has one.");
+                       goto end;
+               }
+       }
+
+       /* Absolute */
+       if (!!clock_class_a->absolute != !!clock_class_b->absolute) {
+               BT_LOGV("Clock classes differ: one is absolute, the other "
+                       "is not: cc-a-is-absolute=%d, cc-b-is-absolute=%d",
+                       !!clock_class_a->absolute,
+                       !!clock_class_b->absolute);
+               goto end;
+       }
+
+       /* Equal */
+       ret = 0;
+
+end:
+       return ret;
+}
index 0437207b1fa3c56eec05811aa16a27435db80b65..f838adbfbceb5c1f5a9f0b408563cde85ac007e8 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * clock.c
  *
- * Babeltrace CTF IR - Clock
+ * Babeltrace CTF writer - Clock
  *
  * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
  * Copyright 2017 Philippe Proulx <pproulx@efficios.com>
 #define BT_LOG_TAG "CTF-WRITER-CLOCK"
 #include <babeltrace/lib-logging-internal.h>
 
+#include <babeltrace/assert-internal.h>
+#include <babeltrace/compat/uuid-internal.h>
+#include <babeltrace/compiler-internal.h>
+#include <babeltrace/ctf-writer/clock-class-internal.h>
 #include <babeltrace/ctf-writer/clock-internal.h>
+#include <babeltrace/ctf-writer/utils.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>
-#include <babeltrace/compat/uuid-internal.h>
-#include <babeltrace/ref.h>
 #include <babeltrace/object-internal.h>
-#include <babeltrace/compiler-internal.h>
-#include <babeltrace/assert-internal.h>
+#include <babeltrace/ref.h>
 #include <inttypes.h>
 
 static
@@ -61,7 +60,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 = (void *) bt_clock_class_create(name, 1000000000);
+       clock->clock_class = (void *) bt_ctf_clock_class_create(name, 1000000000);
        if (!clock->clock_class) {
                goto error;
        }
@@ -72,8 +71,7 @@ struct bt_ctf_clock *bt_ctf_clock_create(const char *name)
                goto error;
        }
 
-       ret = bt_clock_class_set_uuid(BT_TO_COMMON(clock->clock_class),
-               cc_uuid);
+       ret = bt_ctf_clock_class_set_uuid(clock->clock_class, cc_uuid);
        BT_ASSERT(ret == 0);
        return clock;
 
@@ -85,108 +83,108 @@ 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(BT_TO_COMMON(clock->clock_class));
+       return bt_ctf_clock_class_get_name(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(BT_TO_COMMON(clock->clock_class));
+       return bt_ctf_clock_class_get_description(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(BT_TO_COMMON(clock->clock_class),
+       return bt_ctf_clock_class_set_description(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(BT_TO_COMMON(clock->clock_class));
+       return bt_ctf_clock_class_get_frequency(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(BT_TO_COMMON(clock->clock_class),
+       return bt_ctf_clock_class_set_frequency(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(BT_TO_COMMON(clock->clock_class));
+       return bt_ctf_clock_class_get_precision(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(BT_TO_COMMON(clock->clock_class),
+       return bt_ctf_clock_class_set_precision(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(BT_TO_COMMON(clock->clock_class),
+       return bt_ctf_clock_class_get_offset_s(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(BT_TO_COMMON(clock->clock_class),
+       return bt_ctf_clock_class_set_offset_s(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(BT_TO_COMMON(clock->clock_class),
+       return bt_ctf_clock_class_get_offset_cycles(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(BT_TO_COMMON(clock->clock_class),
+       return bt_ctf_clock_class_set_offset_cycles(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(BT_TO_COMMON(clock->clock_class));
+       return bt_ctf_clock_class_is_absolute(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(BT_TO_COMMON(clock->clock_class),
+       return bt_ctf_clock_class_set_is_absolute(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(BT_TO_COMMON(clock->clock_class));
+       return bt_ctf_clock_class_get_uuid(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(BT_TO_COMMON(clock->clock_class), uuid);
+       return bt_ctf_clock_class_set_uuid(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;
+       struct bt_ctf_clock_class *cc;
 
        BT_ASSERT_PRE_NON_NULL(clock, "CTF writer clock");
-       cc = BT_TO_COMMON(clock->clock_class);
+       cc = clock->clock_class;
 
        /* Common case where cycles are actually nanoseconds */
        if (cc->frequency == 1000000000) {
@@ -219,7 +217,7 @@ 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(BT_TO_COMMON(clock->clock_class));
+       bt_put(clock->clock_class);
        g_free(clock);
 }
 
@@ -231,24 +229,24 @@ void bt_ctf_clock_class_serialize(struct bt_ctf_clock_class *clock_class,
 
        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)),
+               bt_ctf_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(BT_TO_COMMON(clock_class)),
+                       bt_ctf_clock_class_get_name(clock_class),
                        context);
                return;
        }
 
-       uuid = clock_class->common.uuid;
+       uuid = clock_class->uuid;
        g_string_append(context->string, "clock {\n");
        g_string_append_printf(context->string, "\tname = %s;\n",
-               clock_class->common.name->str);
+               clock_class->name->str);
 
-       if (clock_class->common.uuid_set) {
+       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],
@@ -257,127 +255,20 @@ void bt_ctf_clock_class_serialize(struct bt_ctf_clock_class *clock_class,
                        uuid[12], uuid[13], uuid[14], uuid[15]);
        }
 
-       if (clock_class->common.description) {
+       if (clock_class->description) {
                g_string_append_printf(context->string, "\tdescription = \"%s\";\n",
-                       clock_class->common.description->str);
+                       clock_class->description->str);
        }
 
        g_string_append_printf(context->string, "\tfreq = %" PRIu64 ";\n",
-               clock_class->common.frequency);
+               clock_class->frequency);
        g_string_append_printf(context->string, "\tprecision = %" PRIu64 ";\n",
-               clock_class->common.precision);
+               clock_class->precision);
        g_string_append_printf(context->string, "\toffset_s = %" PRIu64 ";\n",
-               clock_class->common.offset_s);
+               clock_class->offset_s);
        g_string_append_printf(context->string, "\toffset = %" PRIu64 ";\n",
-               clock_class->common.offset);
+               clock_class->offset);
        g_string_append_printf(context->string, "\tabsolute = %s;\n",
-               clock_class->common.absolute ? "true" : "false");
+               clock_class->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);
-}
index 057fc12a44616213d7dcd5de894a53948517e5f4..713a465353f324598742469884dbbe0e13ce8094 100644 (file)
 #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/assert-pre-internal.h>
+#include <babeltrace/assert-internal.h>
+#include <babeltrace/compiler-internal.h>
+#include <babeltrace/ctf-writer/attributes-internal.h>
+#include <babeltrace/ctf-writer/event-class-internal.h>
 #include <babeltrace/ctf-writer/event-internal.h>
-#include <babeltrace/ctf-writer/field-types.h>
+#include <babeltrace/ctf-writer/event.h>
 #include <babeltrace/ctf-writer/field-types-internal.h>
+#include <babeltrace/ctf-writer/field-types.h>
+#include <babeltrace/ctf-writer/fields-internal.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/utils-internal.h>
+#include <babeltrace/ctf-writer/utils.h>
+#include <babeltrace/ctf-writer/validation-internal.h>
 #include <babeltrace/ctf-writer/writer-internal.h>
+#include <babeltrace/endian-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 <babeltrace/types.h>
+#include <babeltrace/values-internal.h>
 #include <glib.h>
+#include <inttypes.h>
+#include <inttypes.h>
+#include <stdlib.h>
+
+BT_HIDDEN
+void bt_ctf_event_class_common_finalize(struct bt_object *obj)
+{
+       struct bt_ctf_event_class_common *event_class;
+
+       event_class = container_of(obj, struct bt_ctf_event_class_common, base);
+       BT_LOGD("Finalizing common event class: addr=%p, name=\"%s\", id=%" PRId64,
+               event_class, bt_ctf_event_class_common_get_name(event_class),
+               bt_ctf_event_class_common_get_id(event_class));
+
+       if (event_class->name) {
+               g_string_free(event_class->name, TRUE);
+       }
+
+       if (event_class->emf_uri) {
+               g_string_free(event_class->emf_uri, TRUE);
+       }
+
+       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_ctf_event_class_common_initialize(struct bt_ctf_event_class_common *event_class,
+               const char *name, bt_object_release_func release_func,
+               bt_ctf_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_shared_with_parent(&event_class->base, 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;
+       }
+
+       event_class->id = -1;
+       event_class->name = g_string_new(name);
+       if (!event_class->name) {
+               BT_LOGE_STR("Failed to allocate a GString.");
+               goto error;
+       }
+
+       event_class->emf_uri = g_string_new(NULL);
+       if (!event_class->emf_uri) {
+               BT_LOGE_STR("Failed to allocate a GString.");
+               goto error;
+       }
+
+       event_class->log_level = BT_CTF_EVENT_CLASS_LOG_LEVEL_UNSPECIFIED;
+       BT_LOGD("Initialized common event class object: addr=%p, name=\"%s\"",
+               event_class, bt_ctf_event_class_common_get_name(event_class));
+       return ret;
+
+error:
+       ret = -1;
+       return ret;
+}
+
+BT_HIDDEN
+void bt_ctf_event_class_common_freeze(struct bt_ctf_event_class_common *event_class)
+{
+       BT_ASSERT(event_class);
+
+       if (event_class->frozen) {
+               return;
+       }
+
+       BT_LOGD("Freezing event class: addr=%p, name=\"%s\", id=%" PRId64,
+               event_class, bt_ctf_event_class_common_get_name(event_class),
+               bt_ctf_event_class_common_get_id(event_class));
+       event_class->frozen = 1;
+       BT_LOGD_STR("Freezing event class's context field type.");
+       bt_ctf_field_type_common_freeze(event_class->context_field_type);
+       BT_LOGD_STR("Freezing event class's payload field type.");
+       bt_ctf_field_type_common_freeze(event_class->payload_field_type);
+}
+
+BT_HIDDEN
+int bt_ctf_event_class_common_validate_single_clock_class(
+               struct bt_ctf_event_class_common *event_class,
+               struct bt_ctf_clock_class **expected_clock_class)
+{
+       int ret = 0;
+
+       BT_ASSERT(event_class);
+       BT_ASSERT(expected_clock_class);
+       ret = bt_ctf_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 "
+                       "is not recursively mapped to the "
+                       "expected clock class: "
+                       "event-class-addr=%p, "
+                       "event-class-name=\"%s\", "
+                       "event-class-id=%" PRId64 ", "
+                       "ft-addr=%p",
+                       event_class,
+                       bt_ctf_event_class_common_get_name(event_class),
+                       event_class->id,
+                       event_class->context_field_type);
+               goto end;
+       }
+
+       ret = bt_ctf_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 "
+                       "is not recursively mapped to the "
+                       "expected clock class: "
+                       "event-class-addr=%p, "
+                       "event-class-name=\"%s\", "
+                       "event-class-id=%" PRId64 ", "
+                       "ft-addr=%p",
+                       event_class,
+                       bt_ctf_event_class_common_get_name(event_class),
+                       event_class->id,
+                       event_class->payload_field_type);
+               goto end;
+       }
+
+end:
+       return ret;
+}
 
 static
 void bt_ctf_event_class_destroy(struct bt_object *obj)
 {
-       bt_event_class_common_finalize(obj);
+       bt_ctf_event_class_common_finalize(obj);
        g_free(obj);
 }
 
@@ -63,9 +206,9 @@ struct bt_ctf_event_class *bt_ctf_event_class_create(const char *name)
                goto error;
        }
 
-       ret = bt_event_class_common_initialize(BT_TO_COMMON(ctf_event_class),
+       ret = bt_ctf_event_class_common_initialize(BT_CTF_TO_COMMON(ctf_event_class),
                name, bt_ctf_event_class_destroy,
-               (bt_field_type_structure_create_func)
+               (bt_ctf_field_type_structure_create_func)
                        bt_ctf_field_type_structure_create);
        if (ret) {
                goto error;
@@ -82,43 +225,43 @@ end:
 
 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));
+       return bt_ctf_event_class_common_get_name(BT_CTF_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));
+       return bt_ctf_event_class_common_get_id(BT_CTF_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);
+       return bt_ctf_event_class_common_set_id(BT_CTF_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));
+       return bt_ctf_event_class_common_get_log_level(BT_CTF_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),
+       return bt_ctf_event_class_common_set_log_level(BT_CTF_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));
+       return bt_ctf_event_class_common_get_emf_uri(BT_CTF_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),
+       return bt_ctf_event_class_common_set_emf_uri(BT_CTF_TO_COMMON(event_class),
                emf_uri);
 }
 
@@ -126,38 +269,38 @@ 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)));
+       return bt_get(bt_ctf_event_class_common_borrow_stream_class(
+               BT_CTF_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_get(bt_event_class_common_borrow_payload_field_type(
-               BT_TO_COMMON(event_class)));
+       return bt_get(bt_ctf_event_class_common_borrow_payload_field_type(
+               BT_CTF_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);
+       return bt_ctf_event_class_common_set_payload_field_type(
+               BT_CTF_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_get(bt_event_class_common_borrow_context_field_type(
-               BT_TO_COMMON(event_class)));
+       return bt_get(bt_ctf_event_class_common_borrow_context_field_type(
+               BT_CTF_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);
+       return bt_ctf_event_class_common_set_context_field_type(
+               BT_CTF_TO_COMMON(event_class), (void *) field_type);
 }
 
 int bt_ctf_event_class_add_field(struct bt_ctf_event_class *event_class,
@@ -174,7 +317,7 @@ int bt_ctf_event_class_add_field(struct bt_ctf_event_class *event_class,
                goto end;
        }
 
-       if (!bt_identifier_is_valid(name)) {
+       if (!bt_ctf_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),
@@ -202,9 +345,9 @@ int bt_ctf_event_class_add_field(struct bt_ctf_event_class *event_class,
                goto end;
        }
 
-       BT_ASSERT(bt_field_type_common_get_type_id(
+       BT_ASSERT(bt_ctf_field_type_common_get_type_id(
                event_class->common.payload_field_type) ==
-               BT_FIELD_TYPE_ID_STRUCT);
+               BT_CTF_FIELD_TYPE_ID_STRUCT);
        ret = bt_ctf_field_type_structure_add_field(
                (void *) event_class->common.payload_field_type,
                (void *) type, name);
@@ -237,10 +380,10 @@ int64_t bt_ctf_event_class_get_payload_type_field_count(
                goto end;
        }
 
-       BT_ASSERT(bt_field_type_common_get_type_id(
+       BT_ASSERT(bt_ctf_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(
+                       BT_CTF_FIELD_TYPE_ID_STRUCT);
+       ret = bt_ctf_field_type_common_structure_get_field_count(
                event_class->common.payload_field_type);
 end:
        return ret;
@@ -268,9 +411,9 @@ int bt_ctf_event_class_get_payload_type_field_by_index(
                goto end;
        }
 
-       BT_ASSERT(bt_field_type_common_get_type_id(
+       BT_ASSERT(bt_ctf_field_type_common_get_type_id(
                event_class->common.payload_field_type) ==
-                       BT_FIELD_TYPE_ID_STRUCT);
+                       BT_CTF_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);
@@ -279,12 +422,12 @@ end:
        return ret;
 }
 
-struct bt_field_type *
+struct bt_ctf_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;
+       struct bt_ctf_field_type *field_type = NULL;
 
        if (!event_class || !name) {
                BT_LOGW("Invalid parameter: event class or name is NULL: "
@@ -301,9 +444,9 @@ bt_ctf_event_class_get_payload_type_field_type_by_name(
                goto end;
        }
 
-       BT_ASSERT(bt_field_type_common_get_type_id(
+       BT_ASSERT(bt_ctf_field_type_common_get_type_id(
                event_class->common.payload_field_type) ==
-                       BT_FIELD_TYPE_ID_STRUCT);
+                       BT_CTF_FIELD_TYPE_ID_STRUCT);
        name_quark = g_quark_try_string(name);
        if (!name_quark) {
                BT_LOGE("Cannot get GQuark: string=\"%s\"", name);
@@ -347,12 +490,12 @@ int bt_ctf_event_class_serialize(struct bt_ctf_event_class *event_class,
        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))));
+               bt_ctf_stream_class_common_get_id(
+                       bt_ctf_event_class_common_borrow_stream_class(
+                               BT_CTF_TO_COMMON(event_class))));
 
        if (event_class->common.log_level !=
-                       BT_EVENT_CLASS_LOG_LEVEL_UNSPECIFIED) {
+                       BT_CTF_EVENT_CLASS_LOG_LEVEL_UNSPECIFIED) {
                g_string_append_printf(context->string, "\tloglevel = %d;\n",
                        (int) event_class->common.log_level);
        }
@@ -423,7 +566,7 @@ struct bt_ctf_field_type *bt_ctf_event_class_get_field_by_name(
        }
 
        BT_ASSERT(event_class->common.payload_field_type->id ==
-               BT_FIELD_TYPE_ID_STRUCT);
+               BT_CTF_FIELD_TYPE_ID_STRUCT);
        name_quark = g_quark_try_string(name);
        if (!name_quark) {
                BT_LOGE("Cannot get GQuark: string=\"%s\"", name);
@@ -435,7 +578,7 @@ struct bt_ctf_field_type *bt_ctf_event_class_get_field_by_name(
         * from the structure already does.
         */
        field_type = bt_get(
-               bt_field_type_common_structure_borrow_field_type_by_name(
+               bt_ctf_field_type_common_structure_borrow_field_type_by_name(
                        event_class->common.payload_field_type, name));
 
 end:
index b2a7f23206622dc3a591a15528e2118c147bf558..603b3cf0339de442dd86242ab6c87ab785fb84b1 100644 (file)
 #define BT_LOG_TAG "CTF-WRITER-EVENT"
 #include <babeltrace/lib-logging-internal.h>
 
-#include <babeltrace/ctf-ir/event-internal.h>
+#include <babeltrace/assert-pre-internal.h>
+#include <babeltrace/assert-internal.h>
+#include <babeltrace/compiler-internal.h>
+#include <babeltrace/ctf-writer/attributes-internal.h>
+#include <babeltrace/ctf-writer/clock-class-internal.h>
 #include <babeltrace/ctf-writer/clock-internal.h>
+#include <babeltrace/ctf-writer/event-class-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-internal.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/stream-internal.h>
 #include <babeltrace/ctf-writer/trace-internal.h>
 #include <babeltrace/ctf-writer/trace.h>
+#include <babeltrace/ctf-writer/utils.h>
+#include <babeltrace/ctf-writer/validation-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>
 
 static
-void bt_ctf_event_destroy(struct bt_object *obj);
+int bt_ctf_event_common_validate_types_for_create(
+               struct bt_ctf_event_class_common *event_class,
+               struct bt_ctf_validation_output *validation_output,
+               bt_ctf_validation_flag_copy_field_type_func copy_field_type_func)
+{
+       int ret;
+       enum bt_ctf_validation_flag validation_flags =
+               BT_CTF_VALIDATION_FLAG_STREAM |
+               BT_CTF_VALIDATION_FLAG_EVENT;
+       struct bt_ctf_trace_common *trace = NULL;
+       struct bt_ctf_stream_class_common *stream_class = NULL;
+       struct bt_ctf_field_type_common *packet_header_type = NULL;
+       struct bt_ctf_field_type_common *packet_context_type = NULL;
+       struct bt_ctf_field_type_common *event_header_type = NULL;
+       struct bt_ctf_field_type_common *stream_event_ctx_type = NULL;
+       struct bt_ctf_field_type_common *event_context_type = NULL;
+       struct bt_ctf_field_type_common *event_payload_type = NULL;
+       int trace_valid = 0;
+       struct bt_value *environment = NULL;
+
+       stream_class = bt_ctf_event_class_common_borrow_stream_class(event_class);
+       BT_ASSERT(stream_class);
+       trace = bt_ctf_stream_class_common_borrow_trace(stream_class);
+       if (trace) {
+               BT_LOGD_STR("Event class is part of a trace.");
+               packet_header_type =
+                       bt_ctf_trace_common_borrow_packet_header_field_type(trace);
+               trace_valid = trace->valid;
+               BT_ASSERT(trace_valid);
+               environment = trace->environment;
+       }
+
+       packet_context_type =
+               bt_ctf_stream_class_common_borrow_packet_context_field_type(
+                       stream_class);
+       event_header_type =
+               bt_ctf_stream_class_common_borrow_event_header_field_type(
+                       stream_class);
+       stream_event_ctx_type =
+               bt_ctf_stream_class_common_borrow_event_context_field_type(
+                       stream_class);
+       event_context_type =
+               bt_ctf_event_class_common_borrow_context_field_type(event_class);
+       event_payload_type =
+               bt_ctf_event_class_common_borrow_payload_field_type(event_class);
+       ret = bt_ctf_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, copy_field_type_func);
+       if (ret) {
+               /*
+                * This means something went wrong during the validation
+                * process, not that the objects are invalid.
+                */
+               BT_LOGE("Failed to validate event and parents: ret=%d", ret);
+               goto error;
+       }
+
+       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);
+               goto error;
+       }
+
+       goto end;
+
+error:
+       bt_ctf_validation_output_put_types(validation_output);
+       ret = -1;
+
+end:
+       return ret;
+}
 
 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 bt_ctf_event_common_create_fields(
+               struct bt_ctf_stream_class_common *stream_class,
+               struct bt_ctf_validation_output *validation_output,
+               create_field_func create_field_func,
+               release_field_func release_field_func,
+               create_header_field_func create_header_field_func,
+               release_header_field_func release_header_field_func,
+               struct bt_ctf_field_wrapper **header_field,
+               struct bt_ctf_field_common **stream_event_context_field,
+               struct bt_ctf_field_common **context_field,
+               struct bt_ctf_field_common **payload_field)
+{
+       int ret = 0;
+
+       if (validation_output->event_header_type) {
+               BT_LOGD("Creating initial event header field: ft-addr=%p",
+                       validation_output->event_header_type);
+               *header_field =
+                       create_header_field_func(stream_class,
+                               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) {
+               BT_LOGD("Creating initial stream event context field: ft-addr=%p",
+                       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) {
+               BT_LOGD("Creating initial event context field: ft-addr=%p",
+                       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) {
+               BT_LOGD("Creating initial event payload field: ft-addr=%p",
+                       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:
+       if (*header_field) {
+               release_header_field_func(*header_field, stream_class);
+       }
+
+       if (*stream_event_context_field) {
+               release_field_func(*stream_event_context_field);
+       }
+
+       if (*context_field) {
+               release_field_func(*context_field);
+       }
+
+       if (*payload_field) {
+               release_field_func(*payload_field);
+       }
+
+       ret = -1;
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+int _bt_ctf_event_common_validate(struct bt_ctf_event_common *event)
+{
+       int ret = 0;
+       struct bt_ctf_stream_class_common *stream_class;
+
+       BT_ASSERT(event);
+       if (event->header_field) {
+               ret = bt_ctf_field_common_validate_recursive(
+                       event->header_field->field);
+               if (ret) {
+                       BT_ASSERT_PRE_MSG("Invalid event's header field: "
+                               "event-addr=%p, field-addr=%p",
+                               event, event->header_field->field);
+                       goto end;
+               }
+       }
+
+       stream_class = bt_ctf_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_ctf_field_common_validate_recursive(
+                       event->stream_event_context_field);
+               if (ret) {
+                       BT_ASSERT_PRE_MSG("Invalid event's stream event context field: "
+                               "event-addr=%p, field-addr=%p",
+                               event, event->stream_event_context_field);
+                       goto end;
+               }
+       }
+
+       if (event->class->context_field_type) {
+               ret = bt_ctf_field_common_validate_recursive(event->context_field);
+               if (ret) {
+                       BT_ASSERT_PRE_MSG("Invalid event's payload field: "
+                               "event-addr=%p, field-addr=%p",
+                               event, event->context_field);
+                       goto end;
+               }
+       }
+
+       ret = bt_ctf_field_common_validate_recursive(event->payload_field);
+       if (ret) {
+               BT_ASSERT_PRE_MSG("Invalid event's payload field: "
+                       "event-addr=%p, field-addr=%p",
+                       event, event->payload_field);
+               goto end;
+       }
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+void _bt_ctf_event_common_set_is_frozen(struct bt_ctf_event_common *event,
+               bool is_frozen)
+{
+       BT_ASSERT(event);
+       BT_LOGD("Freezing event: addr=%p, "
+               "event-class-name=\"%s\", event-class-id=%" PRId64,
+               event, bt_ctf_event_class_common_get_name(event->class),
+               bt_ctf_event_class_common_get_id(event->class));
+
+       if (event->header_field) {
+               BT_LOGD_STR("Freezing event's header field.");
+               bt_ctf_field_common_set_is_frozen_recursive(
+                       event->header_field->field, is_frozen);
+       }
+
+       if (event->stream_event_context_field) {
+               BT_LOGD_STR("Freezing event's stream event context field.");
+               bt_ctf_field_common_set_is_frozen_recursive(
+                       event->stream_event_context_field, is_frozen);
+       }
+
+       if (event->context_field) {
+               BT_LOGD_STR("Freezing event's context field.");
+               bt_ctf_field_common_set_is_frozen_recursive(event->context_field,
+                       is_frozen);
+       }
+
+       if (event->payload_field) {
+               BT_LOGD_STR("Freezing event's payload field.");
+               bt_ctf_field_common_set_is_frozen_recursive(event->payload_field,
+                       is_frozen);
+       }
+
+       event->frozen = is_frozen;
+}
+
+BT_HIDDEN
+int bt_ctf_event_common_initialize(struct bt_ctf_event_common *event,
+               struct bt_ctf_event_class_common *event_class,
+               struct bt_ctf_clock_class *init_expected_clock_class,
+               bool is_shared_with_parent, bt_object_release_func release_func,
+               bt_ctf_validation_flag_copy_field_type_func field_type_copy_func,
+               bool must_be_in_trace,
+               int (*map_clock_classes_func)(struct bt_ctf_stream_class_common *stream_class,
+                       struct bt_ctf_field_type_common *packet_context_field_type,
+                       struct bt_ctf_field_type_common *event_header_field_type),
+               create_field_func create_field_func,
+               release_field_func release_field_func,
+               create_header_field_func create_header_field_func,
+               release_header_field_func release_header_field_func)
+{
+       int ret;
+       struct bt_ctf_trace_common *trace = NULL;
+       struct bt_ctf_stream_class_common *stream_class = NULL;
+       struct bt_ctf_field_wrapper *event_header = NULL;
+       struct bt_ctf_field_common *stream_event_context = NULL;
+       struct bt_ctf_field_common *event_context = NULL;
+       struct bt_ctf_field_common *event_payload = NULL;
+       struct bt_ctf_validation_output validation_output = { 0 };
+       struct bt_ctf_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_ctf_event_class_common_get_name(event_class),
+               bt_ctf_event_class_common_get_id(event_class));
+
+       stream_class = bt_ctf_event_class_common_borrow_stream_class(event_class);
+       BT_ASSERT_PRE(stream_class,
+               "Event class is not part of a stream class: event-class-addr=%p",
+               event_class);
+
+       /* The event class was frozen when added to its stream class */
+       BT_ASSERT(event_class->frozen);
+       trace = bt_ctf_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-addr=%p, sc-addr=%p", 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.
+        */
+       if (is_shared_with_parent) {
+               bt_object_init_shared_with_parent(&event->base, release_func);
+       } else {
+               bt_object_init_unique(&event->base);
+       }
+
+       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_ctf_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_ctf_stream_class_common_get_id(stream_class),
+                               bt_ctf_stream_class_common_get_name(stream_class),
+                               expected_clock_class,
+                               expected_clock_class ?
+                                       bt_ctf_clock_class_get_name(expected_clock_class) :
+                                       NULL);
+                       goto error;
+               }
+       }
+
+       /* Validate the trace, the stream class, and the event class */
+       ret = bt_ctf_event_common_validate_types_for_create(
+               event_class, &validation_output, field_type_copy_func);
+       if (ret) {
+               /* bt_ctf_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_ctf_event_common_create_fields(stream_class,
+               &validation_output,
+               create_field_func, release_field_func,
+               create_header_field_func, release_header_field_func,
+               &event_header, &stream_event_context, &event_context,
+               &event_payload);
+       if (ret) {
+               /* bt_ctf_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_ctf_validation_replace_types(trace, stream_class, event_class,
+               &validation_output,
+               BT_CTF_VALIDATION_FLAG_STREAM | BT_CTF_VALIDATION_FLAG_EVENT);
+       event->header_field = event_header;
+       event_header = NULL;
+       event->stream_event_context_field = stream_event_context;
+       stream_event_context = NULL;
+       event->context_field = event_context;
+       event_context = NULL;
+       event->payload_field = event_payload;
+       event_payload = NULL;
+
+       /*
+        * Put what was not moved in bt_ctf_validation_replace_types().
+        */
+       bt_ctf_validation_output_put_types(&validation_output);
+
+       /*
+        * Freeze the stream class since the event header must not be changed
+        * anymore.
+        */
+       bt_ctf_stream_class_common_freeze(stream_class);
+
+       /*
+        * It is safe to set the stream class's unique clock class
+        * now because the stream class is frozen.
+        */
+       if (expected_clock_class) {
+               BT_MOVE(stream_class->clock_class, expected_clock_class);
+       }
+
+       /*
+        * Mark stream class, and event class as valid since
+        * they're all frozen now.
+        */
+       stream_class->valid = 1;
+       event_class->valid = 1;
+
+       /* Put stuff we borrowed from the event class */
+       BT_LOGD("Initialized event object: addr=%p, event-class-name=\"%s\", "
+               "event-class-id=%" PRId64,
+               event, bt_ctf_event_class_common_get_name(event->class),
+               bt_ctf_event_class_common_get_id(event->class));
+       goto end;
+
+error:
+       bt_ctf_validation_output_put_types(&validation_output);
+       bt_put(expected_clock_class);
+
+       if (event_header) {
+               release_header_field_func(event_header, stream_class);
+       }
+
+       if (stream_event_context) {
+               release_field_func(stream_event_context);
+       }
+
+       if (event_context) {
+               release_field_func(event_context);
+       }
+
+       if (event_payload) {
+               release_field_func(event_payload);
+       }
+
+       ret = -1;
+
+end:
+       return ret;
+}
+
+int map_clock_classes_func(struct bt_ctf_stream_class_common *stream_class,
+               struct bt_ctf_field_type_common *packet_context_type,
+               struct bt_ctf_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));
+               BT_CTF_FROM_COMMON(stream_class),
+               BT_CTF_FROM_COMMON(packet_context_type),
+               BT_CTF_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.");
@@ -63,26 +532,26 @@ int map_clock_classes_func(struct bt_stream_class_common *stream_class,
 }
 
 static
-void destroy_event_header_field(struct bt_field_wrapper *field_wrapper)
+void destroy_event_header_field(struct bt_ctf_field_wrapper *field_wrapper)
 {
        BT_ASSERT(field_wrapper);
        bt_put(field_wrapper->field);
-       bt_field_wrapper_destroy(field_wrapper);
+       bt_ctf_field_wrapper_destroy(field_wrapper);
 }
 
 static
-struct bt_field_wrapper *create_event_header_field(
-               struct bt_stream_class *stream_class,
-               struct bt_field_type_common *ft)
+struct bt_ctf_field_wrapper *create_event_header_field(
+               struct bt_ctf_stream_class *stream_class,
+               struct bt_ctf_field_type_common *ft)
 {
-       struct bt_field_wrapper *field_wrapper = NULL;
+       struct bt_ctf_field_wrapper *field_wrapper = NULL;
        struct bt_ctf_field *field = bt_ctf_field_create((void *) ft);
 
        if (!field) {
                goto error;
        }
 
-       field_wrapper = bt_field_wrapper_new(NULL);
+       field_wrapper = bt_ctf_field_wrapper_new(NULL);
        if (!field_wrapper) {
                goto error;
        }
@@ -103,11 +572,28 @@ end:
        return field_wrapper;
 }
 
+static
+void release_event_header_field(struct bt_ctf_field_wrapper *field_wrapper,
+               struct bt_ctf_event_common *event_common)
+{
+       BT_ASSERT(field_wrapper);
+       BT_PUT(field_wrapper->field);
+       bt_ctf_field_wrapper_destroy(field_wrapper);
+}
+
+static
+void bt_ctf_event_destroy(struct bt_object *obj)
+{
+       bt_ctf_event_common_finalize(obj, (void *) bt_put,
+               (void *) release_event_header_field);
+       g_free(obj);
+}
+
 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;
+       struct bt_ctf_clock_class *expected_clock_class = NULL;
 
        event = g_new0(struct bt_ctf_event, 1);
        if (!event) {
@@ -117,19 +603,18 @@ struct bt_ctf_event *bt_ctf_event_create(struct bt_ctf_event_class *event_class)
 
        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)));
+                       BT_CTF_FROM_COMMON(bt_ctf_event_class_common_borrow_stream_class(
+                               BT_CTF_TO_COMMON(event_class)));
 
                if (stream_class && stream_class->clock) {
-                       expected_clock_class = BT_TO_COMMON(
-                               stream_class->clock->clock_class);
+                       expected_clock_class = stream_class->clock->clock_class;
                }
        }
 
-       ret = bt_event_common_initialize(BT_TO_COMMON(event),
-               BT_TO_COMMON(event_class), expected_clock_class,
+       ret = bt_ctf_event_common_initialize(BT_CTF_TO_COMMON(event),
+               BT_CTF_TO_COMMON(event_class), expected_clock_class,
                true, bt_ctf_event_destroy,
-               (bt_validation_flag_copy_field_type_func)
+               (bt_ctf_validation_flag_copy_field_type_func)
                        bt_ctf_field_type_copy,
                false, map_clock_classes_func,
                (create_field_func) bt_ctf_field_create,
@@ -137,7 +622,7 @@ struct bt_ctf_event *bt_ctf_event_create(struct bt_ctf_event_class *event_class)
                (create_header_field_func) create_event_header_field,
                (release_header_field_func) destroy_event_header_field);
        if (ret) {
-               /* bt_event_common_initialize() logs errors */
+               /* bt_ctf_event_common_initialize() logs errors */
                goto error;
        }
 
@@ -153,7 +638,7 @@ end:
 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)));
+       return bt_get(bt_ctf_event_common_borrow_class(BT_CTF_TO_COMMON(event)));
 }
 
 BT_HIDDEN
@@ -161,7 +646,7 @@ 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)->base);
+               bt_object_borrow_parent(&BT_CTF_TO_COMMON(event)->base);
 }
 
 struct bt_ctf_stream *bt_ctf_event_get_stream(struct bt_ctf_event *event)
@@ -175,7 +660,7 @@ int bt_ctf_event_set_payload(struct bt_ctf_event *event, const char *name,
 {
        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");
+       BT_ASSERT_PRE_EVENT_COMMON_HOT(BT_CTF_TO_COMMON(event), "Event");
        return bt_ctf_field_structure_set_field_by_name(
                (void *) event->common.payload_field, name, field);
 }
@@ -189,9 +674,9 @@ struct bt_ctf_field *bt_ctf_event_get_payload(struct bt_ctf_event *event,
 
        if (name) {
                field = bt_ctf_field_structure_get_field_by_name(
-                       BT_FROM_COMMON(event->common.payload_field), name);
+                       BT_CTF_FROM_COMMON(event->common.payload_field), name);
        } else {
-               field = BT_FROM_COMMON(event->common.payload_field);
+               field = BT_CTF_FROM_COMMON(event->common.payload_field);
                bt_get(field);
        }
 
@@ -201,41 +686,24 @@ struct bt_ctf_field *bt_ctf_event_get_payload(struct bt_ctf_event *event,
 struct bt_ctf_field *bt_ctf_event_get_payload_field(
                struct bt_ctf_event *event)
 {
-       return bt_get(bt_event_common_borrow_payload(BT_TO_COMMON(event)));
+       return bt_get(bt_ctf_event_common_borrow_payload(BT_CTF_TO_COMMON(event)));
 }
 
 struct bt_ctf_field *bt_ctf_event_get_header(struct bt_ctf_event *event)
 {
-       return bt_get(bt_event_common_borrow_header(BT_TO_COMMON(event)));
+       return bt_get(bt_ctf_event_common_borrow_header(BT_CTF_TO_COMMON(event)));
 }
 
 struct bt_ctf_field *bt_ctf_event_get_context(struct bt_ctf_event *event)
 {
-       return bt_get(bt_event_common_borrow_context(BT_TO_COMMON(event)));
+       return bt_get(bt_ctf_event_common_borrow_context(BT_CTF_TO_COMMON(event)));
 }
 
 struct bt_ctf_field *bt_ctf_event_get_stream_event_context(
                struct bt_ctf_event *event)
 {
-       return bt_get(bt_event_common_borrow_stream_event_context(
-               BT_TO_COMMON(event)));
-}
-
-static
-void release_event_header_field(struct bt_field_wrapper *field_wrapper,
-               struct bt_event_common *event_common)
-{
-       BT_ASSERT(field_wrapper);
-       BT_PUT(field_wrapper->field);
-       bt_field_wrapper_destroy(field_wrapper);
-}
-
-static
-void bt_ctf_event_destroy(struct bt_object *obj)
-{
-       bt_event_common_finalize(obj, (void *) bt_put,
-               (void *) release_event_header_field);
-       g_free(obj);
+       return bt_get(bt_ctf_event_common_borrow_stream_event_context(
+               BT_CTF_TO_COMMON(event)));
 }
 
 BT_HIDDEN
@@ -258,8 +726,8 @@ int bt_ctf_event_serialize(struct bt_ctf_event *event,
                                "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));
+                               bt_ctf_event_class_common_get_name(event->common.class),
+                               bt_ctf_event_class_common_get_id(event->common.class));
                        goto end;
                }
        }
@@ -274,8 +742,8 @@ int bt_ctf_event_serialize(struct bt_ctf_event *event,
                                "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));
+                               bt_ctf_event_class_common_get_name(event->common.class),
+                               bt_ctf_event_class_common_get_id(event->common.class));
                        goto end;
                }
        }
@@ -287,35 +755,35 @@ end:
 BT_HIDDEN
 void _bt_ctf_event_freeze(struct bt_ctf_event *event)
 {
-       _bt_event_common_set_is_frozen(BT_TO_COMMON(event), true);
+       _bt_ctf_event_common_set_is_frozen(BT_CTF_TO_COMMON(event), true);
 }
 
 int bt_ctf_event_set_header(struct bt_ctf_event *event,
                struct bt_ctf_field *header)
 {
        BT_ASSERT_PRE_NON_NULL(event, "Event");
-       BT_ASSERT_PRE_EVENT_COMMON_HOT(BT_TO_COMMON(event), "Event");
+       BT_ASSERT_PRE_EVENT_COMMON_HOT(BT_CTF_TO_COMMON(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(
-                       ((struct bt_field_common *) header)->type,
-                       bt_event_class_common_borrow_stream_class(event->common.class)->event_header_field_type) == 0,
+               BT_ASSERT_PRE(bt_ctf_field_type_common_compare(
+                       ((struct bt_ctf_field_common *) header)->type,
+                       bt_ctf_event_class_common_borrow_stream_class(event->common.class)->event_header_field_type) == 0,
                        "Header field's type is different from the "
-                       "expected field type: %![event-]+we, %![ft-]+wF, "
-                       "%![expected-ft-]+wF",
-                       event, ((struct bt_field_common *) header)->type,
-                       bt_event_class_common_borrow_stream_class(event->common.class)->event_header_field_type);
+                       "expected field type: event-addr=%p, ft-addr=%p, "
+                       "expected-ft-addr=%p",
+                       event, ((struct bt_ctf_field_common *) header)->type,
+                       bt_ctf_event_class_common_borrow_stream_class(event->common.class)->event_header_field_type);
        } else {
-               BT_ASSERT_PRE(!bt_event_class_common_borrow_stream_class(event->common.class)->event_header_field_type,
+               BT_ASSERT_PRE(!bt_ctf_event_class_common_borrow_stream_class(event->common.class)->event_header_field_type,
                        "Setting no event header field, "
                        "but event header field type is not NULL: ",
-                       "%![event-]+we, %![header-ft-]+wF",
+                       "event-addr=%p, header-ft-addr=%p",
                        event,
-                       bt_event_class_common_borrow_stream_class(event->common.class)->event_header_field_type);
+                       bt_ctf_event_class_common_borrow_stream_class(event->common.class)->event_header_field_type);
        }
 
        bt_put(event->common.header_field->field);
@@ -323,8 +791,8 @@ int bt_ctf_event_set_header(struct bt_ctf_event *event,
        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->common.class),
-               bt_event_class_common_get_id(event->common.class), header);
+               event, bt_ctf_event_class_common_get_name(event->common.class),
+               bt_ctf_event_class_common_get_id(event->common.class), header);
        return 0;
 }
 
@@ -332,23 +800,23 @@ int bt_ctf_event_common_set_payload(struct bt_ctf_event *event,
                struct bt_ctf_field *payload)
 {
        BT_ASSERT_PRE_NON_NULL(event, "Event");
-       BT_ASSERT_PRE_EVENT_COMMON_HOT(BT_TO_COMMON(event), "Event");
+       BT_ASSERT_PRE_EVENT_COMMON_HOT(BT_CTF_TO_COMMON(event), "Event");
 
        if (payload) {
-               BT_ASSERT_PRE(bt_field_type_common_compare(
-                       ((struct bt_field_common *) payload)->type,
+               BT_ASSERT_PRE(bt_ctf_field_type_common_compare(
+                       ((struct bt_ctf_field_common *) payload)->type,
                        event->common.class->payload_field_type) == 0,
                        "Payload field's type is different from the "
-                       "expected field type: %![event-]+we, %![ft-]+wF, "
-                       "%![expected-ft-]+wF",
+                       "expected field type: event-addr=%p, ft-addr=%p, "
+                       "expected-ft-addr=%p",
                        event,
-                       ((struct bt_field_common *) payload)->type,
+                       ((struct bt_ctf_field_common *) payload)->type,
                        event->common.class->payload_field_type);
        } else {
                BT_ASSERT_PRE(!event->common.class->payload_field_type,
                        "Setting no event payload field, "
                        "but event payload field type is not NULL: ",
-                       "%![event-]+we, %![payload-ft-]+wF",
+                       "event-addr=%p, payload-ft-addr=%p",
                        event, event->common.class->payload_field_type);
        }
 
@@ -357,8 +825,8 @@ int bt_ctf_event_common_set_payload(struct bt_ctf_event *event,
        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->common.class),
-               bt_event_class_common_get_id(event->common.class), payload);
+               event, bt_ctf_event_class_common_get_name(event->common.class),
+               bt_ctf_event_class_common_get_id(event->common.class), payload);
        return 0;
 }
 
@@ -366,22 +834,22 @@ int bt_ctf_event_set_context(struct bt_ctf_event *event,
                struct bt_ctf_field *context)
 {
        BT_ASSERT_PRE_NON_NULL(event, "Event");
-       BT_ASSERT_PRE_EVENT_COMMON_HOT(BT_TO_COMMON(event), "Event");
+       BT_ASSERT_PRE_EVENT_COMMON_HOT(BT_CTF_TO_COMMON(event), "Event");
 
        if (context) {
-               BT_ASSERT_PRE(bt_field_type_common_compare(
-                       ((struct bt_field_common *) context)->type,
+               BT_ASSERT_PRE(bt_ctf_field_type_common_compare(
+                       ((struct bt_ctf_field_common *) context)->type,
                        event->common.class->context_field_type) == 0,
                        "Context field's type is different from the "
-                       "expected field type: %![event-]+we, %![ft-]+wF, "
-                       "%![expected-ft-]+wF",
-                       event, ((struct bt_field_common *) context)->type,
+                       "expected field type: event-addr=%p, ft-addr=%p, "
+                       "expected-ft-addr=%p",
+                       event, ((struct bt_ctf_field_common *) context)->type,
                        event->common.class->context_field_type);
        } else {
                BT_ASSERT_PRE(!event->common.class->context_field_type,
                        "Setting no event context field, "
                        "but event context field type is not NULL: ",
-                       "%![event-]+we, %![context-ft-]+wF",
+                       "event-addr=%p, context-ft-addr=%p",
                        event, event->common.class->context_field_type);
        }
 
@@ -390,8 +858,8 @@ int bt_ctf_event_set_context(struct bt_ctf_event *event,
        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->common.class),
-               bt_event_class_common_get_id(event->common.class), context);
+               event, bt_ctf_event_class_common_get_name(event->common.class),
+               bt_ctf_event_class_common_get_id(event->common.class), context);
        return 0;
 }
 
@@ -399,25 +867,25 @@ int bt_ctf_event_set_stream_event_context(struct bt_ctf_event *event,
                struct bt_ctf_field *stream_event_context)
 {
        BT_ASSERT_PRE_NON_NULL(event, "Event");
-       BT_ASSERT_PRE_EVENT_COMMON_HOT(BT_TO_COMMON(event), "Event");
+       BT_ASSERT_PRE_EVENT_COMMON_HOT(BT_CTF_TO_COMMON(event), "Event");
 
        if (stream_event_context) {
-               BT_ASSERT_PRE(bt_field_type_common_compare(
-                       ((struct bt_field_common *) stream_event_context)->type,
-                       bt_event_class_common_borrow_stream_class(event->common.class)->event_context_field_type) == 0,
+               BT_ASSERT_PRE(bt_ctf_field_type_common_compare(
+                       ((struct bt_ctf_field_common *) stream_event_context)->type,
+                       bt_ctf_event_class_common_borrow_stream_class(event->common.class)->event_context_field_type) == 0,
                        "Stream event context field's type is different from the "
-                       "expected field type: %![event-]+we, %![ft-]+wF, "
-                       "%![expected-ft-]+wF",
+                       "expected field type: event-addr=%p, ft-addr=%p, "
+                       "expected-ft-addr=%p",
                        event,
-                       ((struct bt_field_common *) stream_event_context)->type,
-                       bt_event_class_common_borrow_stream_class(event->common.class)->event_context_field_type);
+                       ((struct bt_ctf_field_common *) stream_event_context)->type,
+                       bt_ctf_event_class_common_borrow_stream_class(event->common.class)->event_context_field_type);
        } else {
-               BT_ASSERT_PRE(!bt_event_class_common_borrow_stream_class(event->common.class)->event_context_field_type,
+               BT_ASSERT_PRE(!bt_ctf_event_class_common_borrow_stream_class(event->common.class)->event_context_field_type,
                        "Setting no stream event context field, "
                        "but stream event context field type is not NULL: ",
-                       "%![event-]+we, %![context-ft-]+wF",
+                       "event-addr=%p, context-ft-addr=%p",
                        event,
-                       bt_event_class_common_borrow_stream_class(event->common.class)->event_context_field_type);
+                       bt_ctf_event_class_common_borrow_stream_class(event->common.class)->event_context_field_type);
        }
 
        bt_put(event->common.stream_event_context_field);
@@ -425,8 +893,8 @@ int bt_ctf_event_set_stream_event_context(struct bt_ctf_event *event,
        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->common.class),
-               bt_event_class_common_get_id(event->common.class),
+               event, bt_ctf_event_class_common_get_name(event->common.class),
+               bt_ctf_event_class_common_get_id(event->common.class),
                stream_event_context);
        return 0;
 }
diff --git a/lib/ctf-writer/field-path.c b/lib/ctf-writer/field-path.c
new file mode 100644 (file)
index 0000000..24ef9ef
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+ * field-path.c
+ *
+ * Babeltrace CTF writer - Field path
+ *
+ * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ * Copyright 2016 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-FIELD-PATH"
+#include <babeltrace/lib-logging-internal.h>
+
+#include <babeltrace/assert-internal.h>
+#include <babeltrace/ctf-writer/field-path-internal.h>
+#include <babeltrace/ctf-writer/field-types-internal.h>
+#include <babeltrace/ctf-writer/field-types.h>
+#include <glib.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <stdint.h>
+
+static
+void field_path_destroy(struct bt_object *obj)
+{
+       struct bt_ctf_field_path *field_path = (struct bt_ctf_field_path *) obj;
+
+       BT_LOGD("Destroying field path: addr=%p", obj);
+
+       if (!field_path) {
+               return;
+       }
+
+       if (field_path->indexes) {
+               g_array_free(field_path->indexes, TRUE);
+       }
+       g_free(field_path);
+}
+
+BT_HIDDEN
+struct bt_ctf_field_path *bt_ctf_field_path_create(void)
+{
+       struct bt_ctf_field_path *field_path = NULL;
+
+       BT_LOGD_STR("Creating empty field path object.");
+
+       field_path = g_new0(struct bt_ctf_field_path, 1);
+       if (!field_path) {
+               BT_LOGE_STR("Failed to allocate one field path.");
+               goto error;
+       }
+
+       bt_object_init_shared(&field_path->base, field_path_destroy);
+       field_path->root = BT_CTF_SCOPE_UNKNOWN;
+       field_path->indexes = g_array_new(TRUE, FALSE, sizeof(int));
+       if (!field_path->indexes) {
+               BT_LOGE_STR("Failed to allocate a GArray.");
+               goto error;
+       }
+
+       BT_LOGD("Created empty field path object: addr=%p", field_path);
+       return field_path;
+
+error:
+       BT_PUT(field_path);
+       return NULL;
+}
+
+BT_HIDDEN
+void bt_ctf_field_path_clear(struct bt_ctf_field_path *field_path)
+{
+       if (field_path->indexes->len > 0) {
+               g_array_remove_range(field_path->indexes, 0,
+                       field_path->indexes->len);
+       }
+}
+
+BT_HIDDEN
+struct bt_ctf_field_path *bt_ctf_field_path_copy(
+               struct bt_ctf_field_path *path)
+{
+       struct bt_ctf_field_path *new_path;
+
+       BT_ASSERT(path);
+       BT_LOGD("Copying field path: addr=%p, index-count=%u",
+               path, path->indexes->len);
+       new_path = bt_ctf_field_path_create();
+       if (!new_path) {
+               BT_LOGE_STR("Cannot create empty field path.");
+               goto end;
+       }
+
+       new_path->root = path->root;
+       g_array_insert_vals(new_path->indexes, 0,
+               path->indexes->data, path->indexes->len);
+       BT_LOGD("Copied field path: original-addr=%p, copy-addr=%p",
+               path, new_path);
+end:
+       return new_path;
+}
+
+enum bt_ctf_scope bt_ctf_field_path_get_root_scope(
+               const struct bt_ctf_field_path *field_path)
+{
+       enum bt_ctf_scope scope = BT_CTF_SCOPE_UNKNOWN;
+
+       if (!field_path) {
+               BT_LOGW_STR("Invalid parameter: field path is NULL.");
+               goto end;
+       }
+
+       scope = field_path->root;
+
+end:
+       return scope;
+}
+
+int64_t bt_ctf_field_path_get_index_count(
+               const struct bt_ctf_field_path *field_path)
+{
+       int64_t count = (int64_t) -1;
+
+       if (!field_path) {
+               BT_LOGW_STR("Invalid parameter: field path is NULL.");
+               goto end;
+       }
+
+       count = (int64_t) field_path->indexes->len;
+
+end:
+       return count;
+}
+
+int bt_ctf_field_path_get_index(const struct bt_ctf_field_path *field_path,
+               uint64_t index)
+{
+       int ret = INT_MIN;
+
+       if (!field_path) {
+               BT_LOGW_STR("Invalid parameter: field path is NULL.");
+               goto end;
+       }
+
+       if (index >= field_path->indexes->len) {
+               BT_LOGW("Invalid parameter: index is out of bounds: "
+                       "addr=%p, index=%" PRIu64 ", count=%u",
+                       field_path, index, field_path->indexes->len);
+               goto end;
+       }
+
+       ret = g_array_index(field_path->indexes, int, index);
+
+end:
+       return ret;
+}
index 7fbb0bf88ef92cb71a83c3d234c971676b85b9fc..c7938af101e2c086274d93126752c027253cbead 100644 (file)
 #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/assert-internal.h>
+#include <babeltrace/compiler-internal.h>
+#include <babeltrace/ctf-writer/clock-class-internal.h>
+#include <babeltrace/ctf-writer/clock-internal.h>
+#include <babeltrace/ctf-writer/field-path-internal.h>
 #include <babeltrace/ctf-writer/field-types-internal.h>
-#include <babeltrace/ctf-writer/fields.h>
+#include <babeltrace/ctf-writer/field-types.h>
 #include <babeltrace/ctf-writer/fields-internal.h>
-#include <babeltrace/ctf-writer/clock-internal.h>
+#include <babeltrace/ctf-writer/fields.h>
+#include <babeltrace/ctf-writer/utils-internal.h>
+#include <babeltrace/ctf-writer/utils.h>
+#include <babeltrace/endian-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
+void destroy_enumeration_mapping(struct bt_ctf_enumeration_mapping *mapping)
+{
+       g_free(mapping);
+}
+
+BT_HIDDEN
+void bt_ctf_field_type_common_initialize(struct bt_ctf_field_type_common *ft,
+               bool init_bo, bt_object_release_func release_func,
+               struct bt_ctf_field_type_common_methods *methods)
+{
+       BT_ASSERT(ft && (ft->id > BT_CTF_FIELD_TYPE_ID_UNKNOWN) &&
+               (ft->id < BT_CTF_FIELD_TYPE_ID_NR));
+
+       bt_object_init_shared(&ft->base, release_func);
+       ft->methods = methods;
+
+       if (init_bo) {
+               int ret;
+               const enum bt_ctf_byte_order bo = BT_CTF_BYTE_ORDER_NATIVE;
+
+               BT_LOGD("Setting initial field type's byte order: bo=%s",
+                       bt_ctf_byte_order_string(bo));
+               ret = bt_ctf_field_type_common_set_byte_order(ft, bo);
+               BT_ASSERT(ret == 0);
+       }
+
+       ft->alignment = 1;
+}
+
+BT_HIDDEN
+void bt_ctf_field_type_common_integer_initialize(
+               struct bt_ctf_field_type_common *ft,
+               unsigned int size, bt_object_release_func release_func,
+               struct bt_ctf_field_type_common_methods *methods)
+{
+       struct bt_ctf_field_type_common_integer *int_ft = BT_CTF_FROM_COMMON(ft);
+
+       BT_ASSERT(size > 0);
+       BT_LOGD("Initializing common integer field type object: size=%u",
+               size);
+       ft->id = BT_CTF_FIELD_TYPE_ID_INTEGER;
+       int_ft->size = size;
+       int_ft->base = BT_CTF_INTEGER_BASE_DECIMAL;
+       int_ft->encoding = BT_CTF_STRING_ENCODING_NONE;
+       bt_ctf_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_ctf_field_type_common_floating_point_initialize(
+               struct bt_ctf_field_type_common *ft,
+               bt_object_release_func release_func,
+               struct bt_ctf_field_type_common_methods *methods)
+{
+       struct bt_ctf_field_type_common_floating_point *flt_ft = BT_CTF_FROM_COMMON(ft);
+
+       BT_LOGD_STR("Initializing common floating point number field type object.");
+       ft->id = BT_CTF_FIELD_TYPE_ID_FLOAT;
+       flt_ft->exp_dig = sizeof(float) * CHAR_BIT - FLT_MANT_DIG;
+       flt_ft->mant_dig = FLT_MANT_DIG;
+       bt_ctf_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_ctf_field_type_common_enumeration_initialize(
+               struct bt_ctf_field_type_common *ft,
+               struct bt_ctf_field_type_common *container_ft,
+               bt_object_release_func release_func,
+               struct bt_ctf_field_type_common_methods *methods)
+{
+       struct bt_ctf_field_type_common_enumeration *enum_ft = BT_CTF_FROM_COMMON(ft);
+
+       BT_ASSERT(container_ft);
+       BT_LOGD("Initializing common enumeration field type object: int-ft-addr=%p",
+               container_ft);
+       ft->id = BT_CTF_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_ctf_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_ctf_field_type_common_integer_get_size(container_ft));
+}
+
+BT_HIDDEN
+void bt_ctf_field_type_common_string_initialize(
+               struct bt_ctf_field_type_common *ft,
+               bt_object_release_func release_func,
+               struct bt_ctf_field_type_common_methods *methods)
+{
+       struct bt_ctf_field_type_common_string *string_ft = BT_CTF_FROM_COMMON(ft);
+
+       BT_LOGD_STR("Initializing common string field type object.");
+       ft->id = BT_CTF_FIELD_TYPE_ID_STRING;
+       bt_ctf_field_type_common_initialize(ft, true, release_func, methods);
+       string_ft->encoding = BT_CTF_STRING_ENCODING_UTF8;
+       ft->alignment = CHAR_BIT;
+       BT_LOGD("Initialized common string field type object: addr=%p", ft);
+}
+
+BT_HIDDEN
+void bt_ctf_field_type_common_structure_initialize(
+               struct bt_ctf_field_type_common *ft,
+               bt_object_release_func release_func,
+               struct bt_ctf_field_type_common_methods *methods)
+{
+       struct bt_ctf_field_type_common_structure *struct_ft = BT_CTF_FROM_COMMON(ft);
+
+       BT_LOGD_STR("Initializing common structure field type object.");
+       ft->id = BT_CTF_FIELD_TYPE_ID_STRUCT;
+       struct_ft->fields = g_array_new(FALSE, TRUE,
+               sizeof(struct bt_ctf_field_type_common_structure_field));
+       struct_ft->field_name_to_index = g_hash_table_new(NULL, NULL);
+       bt_ctf_field_type_common_initialize(ft, true, release_func, methods);
+       BT_LOGD("Initialized common structure field type object: addr=%p", ft);
+}
+
+BT_HIDDEN
+void bt_ctf_field_type_common_array_initialize(
+               struct bt_ctf_field_type_common *ft,
+               struct bt_ctf_field_type_common *element_ft,
+               unsigned int length, bt_object_release_func release_func,
+               struct bt_ctf_field_type_common_methods *methods)
+{
+       struct bt_ctf_field_type_common_array *array_ft = BT_CTF_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_CTF_FIELD_TYPE_ID_ARRAY;
+       array_ft->element_ft = bt_get(element_ft);
+       array_ft->length = length;
+       bt_ctf_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_ctf_field_type_common_sequence_initialize(
+               struct bt_ctf_field_type_common *ft,
+               struct bt_ctf_field_type_common *element_ft,
+               const char *length_field_name,
+               bt_object_release_func release_func,
+               struct bt_ctf_field_type_common_methods *methods)
+{
+       struct bt_ctf_field_type_common_sequence *seq_ft = BT_CTF_FROM_COMMON(ft);
+
+       BT_ASSERT(element_ft);
+       BT_ASSERT(length_field_name);
+       BT_ASSERT(bt_ctf_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_CTF_FIELD_TYPE_ID_SEQUENCE;
+       seq_ft->element_ft = bt_get(element_ft);
+       seq_ft->length_field_name = g_string_new(length_field_name);
+       bt_ctf_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_ctf_field_type_common_variant_initialize(
+               struct bt_ctf_field_type_common *ft,
+               struct bt_ctf_field_type_common *tag_ft,
+               const char *tag_name,
+               bt_object_release_func release_func,
+               struct bt_ctf_field_type_common_methods *methods)
+{
+       struct bt_ctf_field_type_common_variant *var_ft = BT_CTF_FROM_COMMON(ft);
+
+       BT_ASSERT(!tag_name || bt_ctf_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_CTF_FIELD_TYPE_ID_VARIANT;
+       var_ft->tag_name = g_string_new(tag_name);
+       var_ft->choice_name_to_index = g_hash_table_new(NULL, NULL);
+       var_ft->choices = g_array_new(FALSE, TRUE,
+               sizeof(struct bt_ctf_field_type_common_variant_choice));
+
+       if (tag_ft) {
+               var_ft->tag_ft = bt_get(tag_ft);
+       }
+
+       bt_ctf_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_ctf_field_type_common_integer_destroy(struct bt_object *obj)
+{
+       struct bt_ctf_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_ctf_field_type_common_floating_point_destroy(struct bt_object *obj)
+{
+       struct bt_ctf_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_ctf_field_type_common_enumeration_destroy_recursive(struct bt_object *obj)
+{
+       struct bt_ctf_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_ctf_field_type_common_string_destroy(struct bt_object *obj)
+{
+       struct bt_ctf_field_type_common_string *ft = (void *) obj;
+
+       if (!ft) {
+               return;
+       }
+
+       BT_LOGD("Destroying string field type object: addr=%p", ft);
+       g_free(ft);
+}
+
+static
+void bt_ctf_field_type_common_structure_field_finalize(
+               struct bt_ctf_field_type_common_structure_field *field)
+{
+       if (!field) {
+               return;
+       }
+
+       BT_LOGD("Finalizing structure field type's field: "
+               "addr=%p, field-ft-addr=%p, field-name=\"%s\"",
+               field, field->type, g_quark_to_string(field->name));
+       BT_LOGD_STR("Putting field type.");
+       bt_put(field->type);
+}
+
+BT_HIDDEN
+void bt_ctf_field_type_common_structure_destroy_recursive(struct bt_object *obj)
+{
+       struct bt_ctf_field_type_common_structure *ft = (void *) obj;
+       uint64_t i;
+
+       if (!ft) {
+               return;
+       }
+
+       BT_LOGD("Destroying structure field type object: addr=%p", ft);
+
+       if (ft->fields) {
+               for (i = 0; i < ft->fields->len; i++) {
+                       bt_ctf_field_type_common_structure_field_finalize(
+                               BT_CTF_FIELD_TYPE_COMMON_STRUCTURE_FIELD_AT_INDEX(
+                                       ft, i));
+               }
+
+               g_array_free(ft->fields, TRUE);
+       }
+
+       if (ft->field_name_to_index) {
+               g_hash_table_destroy(ft->field_name_to_index);
+       }
+
+       g_free(ft);
+}
+
+BT_HIDDEN
+void bt_ctf_field_type_common_array_destroy_recursive(struct bt_object *obj)
+{
+       struct bt_ctf_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_ctf_field_type_common_sequence_destroy_recursive(struct bt_object *obj)
+{
+       struct bt_ctf_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);
+}
+
+static
+void bt_ctf_field_type_common_variant_choice_finalize(
+               struct bt_ctf_field_type_common_variant_choice *choice)
+{
+       if (!choice) {
+               return;
+       }
+
+       BT_LOGD("Finalizing variant field type's choice: "
+               "addr=%p, field-ft-addr=%p, field-name=\"%s\"",
+               choice, choice->type, g_quark_to_string(choice->name));
+       BT_LOGD_STR("Putting field type.");
+       bt_put(choice->type);
+
+       if (choice->ranges) {
+               g_array_free(choice->ranges, TRUE);
+       }
+}
+
+BT_HIDDEN
+void bt_ctf_field_type_common_variant_destroy_recursive(struct bt_object *obj)
+{
+       struct bt_ctf_field_type_common_variant *ft = (void *) obj;
+       uint64_t i;
+
+       if (!ft) {
+               return;
+       }
+
+       BT_LOGD("Destroying variant field type object: addr=%p", ft);
+
+       if (ft->choices) {
+               for (i = 0; i < ft->choices->len; i++) {
+                       bt_ctf_field_type_common_variant_choice_finalize(
+                               BT_CTF_FIELD_TYPE_COMMON_VARIANT_CHOICE_AT_INDEX(
+                                       ft, i));
+               }
+
+               g_array_free(ft->choices, TRUE);
+       }
+
+       if (ft->choice_name_to_index) {
+               g_hash_table_destroy(ft->choice_name_to_index);
+       }
+
+       if (ft->tag_name) {
+               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)
+{
+       struct bt_ctf_enumeration_mapping *mapping = element;
+       struct range_overlap_query *overlap_query = query;
+
+       if (mapping->range_start._signed <= overlap_query->range_end._signed
+                       && overlap_query->range_start._signed <=
+                       mapping->range_end._signed) {
+               overlap_query->overlaps = 1;
+               overlap_query->mapping_name = mapping->string;
+       }
+
+       overlap_query->overlaps |=
+               mapping->string == overlap_query->mapping_name;
+
+       if (overlap_query->overlaps) {
+               BT_LOGV("Overlapping enumeration field type mappings: "
+                       "mapping-name=\"%s\", "
+                       "mapping-a-range-start=%" PRId64 ", "
+                       "mapping-a-range-end=%" PRId64 ", "
+                       "mapping-b-range-start=%" PRId64 ", "
+                       "mapping-b-range-end=%" PRId64,
+                       g_quark_to_string(mapping->string),
+                       mapping->range_start._signed,
+                       mapping->range_end._signed,
+                       overlap_query->range_start._signed,
+                       overlap_query->range_end._signed);
+       }
+}
+
+static
+void check_ranges_overlap_unsigned(gpointer element, gpointer query)
+{
+       struct bt_ctf_enumeration_mapping *mapping = element;
+       struct range_overlap_query *overlap_query = query;
+
+       if (mapping->range_start._unsigned <= overlap_query->range_end._unsigned
+                       && overlap_query->range_start._unsigned <=
+                       mapping->range_end._unsigned) {
+               overlap_query->overlaps = 1;
+               overlap_query->mapping_name = mapping->string;
+       }
+
+       overlap_query->overlaps |=
+               mapping->string == overlap_query->mapping_name;
+
+       if (overlap_query->overlaps) {
+               BT_LOGW("Overlapping enumeration field type mappings: "
+                       "mapping-name=\"%s\", "
+                       "mapping-a-range-start=%" PRIu64 ", "
+                       "mapping-a-range-end=%" PRIu64 ", "
+                       "mapping-b-range-start=%" PRIu64 ", "
+                       "mapping-b-range-end=%" PRIu64,
+                       g_quark_to_string(mapping->string),
+                       mapping->range_start._unsigned,
+                       mapping->range_end._unsigned,
+                       overlap_query->range_start._unsigned,
+                       overlap_query->range_end._unsigned);
+       }
+}
+
+static
+gint compare_enumeration_mappings_signed(struct bt_ctf_enumeration_mapping **a,
+               struct bt_ctf_enumeration_mapping **b)
+{
+       return ((*a)->range_start._signed < (*b)->range_start._signed) ? -1 : 1;
+}
+
+static
+gint compare_enumeration_mappings_unsigned(struct bt_ctf_enumeration_mapping **a,
+               struct bt_ctf_enumeration_mapping **b)
+{
+       return ((*a)->range_start._unsigned < (*b)->range_start._unsigned) ? -1 : 1;
+}
+
+static
+int add_structure_variant_member(GArray *members,
+               GHashTable *field_name_to_index,
+               struct bt_ctf_field_type_common *field_type, const char *field_name,
+               bool is_variant)
+{
+       int ret = 0;
+       GQuark name_quark = g_quark_from_string(field_name);
+       struct bt_ctf_field_type_common **member_ft;
+       GQuark *member_name;
+
+       /* Make sure structure does not contain a field of the same name */
+       if (g_hash_table_lookup_extended(field_name_to_index,
+                       GUINT_TO_POINTER(name_quark), NULL, NULL)) {
+               BT_LOGW("Structure or variant field type already contains a field type with this name: "
+                       "field-name=\"%s\"", field_name);
+               ret = -1;
+               goto end;
+       }
+
+       g_array_set_size(members, members->len + 1);
+
+       if (is_variant) {
+               struct bt_ctf_field_type_common_variant_choice *choice =
+                       &g_array_index(members,
+                               struct bt_ctf_field_type_common_variant_choice,
+                               members->len - 1);
+
+               member_ft = &choice->type;
+               member_name = &choice->name;
+               BT_ASSERT(!choice->ranges);
+               choice->ranges = g_array_new(FALSE, TRUE,
+                       sizeof(struct bt_ctf_field_type_common_variant_choice_range));
+               BT_ASSERT(choice->ranges);
+       } else {
+               struct bt_ctf_field_type_common_structure_field *field =
+                       &g_array_index(members,
+                               struct bt_ctf_field_type_common_structure_field,
+                               members->len - 1);
+
+               member_ft = &field->type;
+               member_name = &field->name;
+       }
+
+       *member_name = name_quark;
+       *member_ft = bt_get(field_type);
+       g_hash_table_insert(field_name_to_index,
+               GUINT_TO_POINTER(name_quark),
+               GUINT_TO_POINTER(members->len - 1));
+       BT_LOGV("Added structure/variant field type member: member-ft-addr=%p, "
+               "member-name=\"%s\"", field_type, field_name);
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+int bt_ctf_field_type_common_integer_validate(struct bt_ctf_field_type_common *ft)
+{
+       int ret = 0;
+       struct bt_ctf_field_type_common_integer *int_ft = BT_CTF_FROM_COMMON(ft);
+
+       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\"",
+                       ft, int_ft->mapped_clock_class,
+                       bt_ctf_clock_class_get_name(int_ft->mapped_clock_class));
+               ret = -1;
+               goto end;
+       }
+
+end:
+       return ret;
+}
+
+static
+void bt_ctf_field_type_enum_iter_destroy(struct bt_object *obj)
+{
+       struct bt_ctf_field_type_enumeration_mapping_iterator *iter =
+               container_of(obj,
+                       struct bt_ctf_field_type_enumeration_mapping_iterator,
+                       base);
+
+       BT_LOGD("Destroying enumeration field type mapping iterator: addr=%p",
+               obj);
+       BT_LOGD_STR("Putting parent enumeration field type.");
+       bt_put(iter->enumeration_ft);
+       g_free(iter);
+}
+
+static
+struct bt_ctf_field_type_enumeration_mapping_iterator *
+bt_ctf_field_type_common_enumeration_find_mappings_type(
+               struct bt_ctf_field_type_common *ft,
+               enum bt_ctf_field_type_enumeration_mapping_iterator_type iterator_type)
+{
+       struct bt_ctf_field_type_enumeration_mapping_iterator *iter = NULL;
+
+       BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+       BT_ASSERT_PRE_CTF_FT_COMMON_HAS_ID(ft, BT_CTF_FIELD_TYPE_ID_ENUM,
+               "Field type");
+       iter = g_new0(struct bt_ctf_field_type_enumeration_mapping_iterator, 1);
+       if (!iter) {
+               BT_LOGE_STR("Failed to allocate one enumeration field type mapping.");
+               goto end;
+       }
+
+       bt_object_init_shared(&iter->base, bt_ctf_field_type_enum_iter_destroy);
+       iter->enumeration_ft = bt_get(ft);
+       iter->index = -1;
+       iter->type = iterator_type;
+
+end:
+       return iter;
+}
+
+BT_HIDDEN
+struct bt_ctf_field_type_enumeration_mapping_iterator *
+bt_ctf_field_type_common_enumeration_find_mappings_by_name(
+               struct bt_ctf_field_type_common *ft, const char *name)
+{
+       struct bt_ctf_field_type_enumeration_mapping_iterator *iter;
+
+       iter = bt_ctf_field_type_common_enumeration_find_mappings_type(
+                       ft, CTF_ITERATOR_BY_NAME);
+       if (!iter) {
+               BT_LOGW("Cannot create enumeration field type mapping iterator: "
+                       "ft-addr=%p, mapping-name=\"%s\"", ft, name);
+               goto error;
+       }
+
+       iter->u.name_quark = g_quark_try_string(name);
+       if (!iter->u.name_quark) {
+               /*
+                * No results are possible, set the iterator's position at the
+                * end.
+                */
+               iter->index = iter->enumeration_ft->entries->len;
+       }
+
+       return iter;
+
+error:
+       bt_put(iter);
+       return NULL;
+}
+
+static
+struct bt_ctf_enumeration_mapping *bt_ctf_field_type_common_enumeration_get_mapping_by_index(
+               struct bt_ctf_field_type_common *ft, uint64_t index)
+{
+       struct bt_ctf_field_type_common_enumeration *enum_ft = BT_CTF_FROM_COMMON(ft);
+       struct bt_ctf_enumeration_mapping *mapping = NULL;
+
+       if (index >= enum_ft->entries->len) {
+               BT_LOGW("Invalid parameter: index is out of bounds: "
+                       "addr=%p, index=%" PRIu64 ", count=%u",
+                       ft, index, enum_ft->entries->len);
+               goto end;
+       }
+
+       mapping = g_ptr_array_index(enum_ft->entries, index);
+
+end:
+       return mapping;
+}
+
+BT_HIDDEN
+int bt_ctf_field_type_enumeration_mapping_iterator_next(
+               struct bt_ctf_field_type_enumeration_mapping_iterator *iter)
+{
+       struct bt_ctf_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");
+       len = enum_ft->entries->len;
+       for (i = iter->index + 1; i < len; i++) {
+               struct bt_ctf_enumeration_mapping *mapping =
+                       bt_ctf_field_type_common_enumeration_get_mapping_by_index(
+                               BT_CTF_TO_COMMON(enum_ft), i);
+
+               switch (iter->type) {
+               case CTF_ITERATOR_BY_NAME:
+                       if (mapping->string == iter->u.name_quark) {
+                               iter->index = i;
+                               goto end;
+                       }
+                       break;
+               case CTF_ITERATOR_BY_SIGNED_VALUE:
+               {
+                       int64_t value = iter->u.signed_value;
+
+                       if (value >= mapping->range_start._signed &&
+                                       value <= mapping->range_end._signed) {
+                               iter->index = i;
+                               goto end;
+                       }
+                       break;
+               }
+               case CTF_ITERATOR_BY_UNSIGNED_VALUE:
+               {
+                       uint64_t value = iter->u.unsigned_value;
+
+                       if (value >= mapping->range_start._unsigned &&
+                                       value <= mapping->range_end._unsigned) {
+                               iter->index = i;
+                               goto end;
+                       }
+                       break;
+               }
+               default:
+                       BT_LOGF("Invalid enumeration field type mapping iterator type: "
+                               "type=%d", iter->type);
+                       abort();
+               }
+       }
+
+       ret = -1;
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+struct bt_ctf_field_type_enumeration_mapping_iterator *
+bt_ctf_field_type_common_enumeration_signed_find_mappings_by_value(
+               struct bt_ctf_field_type_common *ft, int64_t value)
+{
+       struct bt_ctf_field_type_enumeration_mapping_iterator *iter;
+
+       iter = bt_ctf_field_type_common_enumeration_find_mappings_type(
+                       ft, CTF_ITERATOR_BY_SIGNED_VALUE);
+       if (!iter) {
+               BT_LOGW("Cannot create enumeration field type mapping iterator: "
+                       "ft-addr=%p, value=%" PRId64, ft, value);
+               goto error;
+       }
+
+       if (bt_ctf_field_type_common_integer_is_signed(
+                       BT_CTF_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",
+                       ft, iter->enumeration_ft->container_ft);
+               goto error;
+       }
+
+       iter->u.signed_value = value;
+       return iter;
+
+error:
+       bt_put(iter);
+       return NULL;
+}
+
+BT_HIDDEN
+struct bt_ctf_field_type_enumeration_mapping_iterator *
+bt_ctf_field_type_common_enumeration_unsigned_find_mappings_by_value(
+               struct bt_ctf_field_type_common *ft, uint64_t value)
+{
+       struct bt_ctf_field_type_enumeration_mapping_iterator *iter;
+
+       iter = bt_ctf_field_type_common_enumeration_find_mappings_type(
+                       ft, CTF_ITERATOR_BY_UNSIGNED_VALUE);
+       if (!iter) {
+               BT_LOGW("Cannot create enumeration field type mapping iterator: "
+                       "ft-addr=%p, value=%" PRIu64, ft, value);
+               goto error;
+       }
+
+       if (bt_ctf_field_type_common_integer_is_signed(
+                       BT_CTF_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",
+                       ft, iter->enumeration_ft->container_ft);
+               goto error;
+       }
+
+       iter->u.unsigned_value = value;
+       return iter;
+
+error:
+       bt_put(iter);
+       return NULL;
+}
+
+BT_HIDDEN
+int bt_ctf_field_type_enumeration_mapping_iterator_signed_get(
+               struct bt_ctf_field_type_enumeration_mapping_iterator *iter,
+               const char **mapping_name, int64_t *range_begin,
+               int64_t *range_end)
+{
+       BT_ASSERT_PRE_NON_NULL(iter, "Enumeration field type mapping iterator");
+       BT_ASSERT_PRE(iter->index != -1,
+               "Invalid enumeration field type mapping iterator access: "
+               "addr=%p, position=-1", iter);
+       return bt_ctf_field_type_common_enumeration_signed_get_mapping_by_index(
+                       (void *) iter->enumeration_ft, iter->index,
+                       mapping_name, range_begin, range_end);
+}
+
+BT_HIDDEN
+int bt_ctf_field_type_enumeration_mapping_iterator_unsigned_get(
+               struct bt_ctf_field_type_enumeration_mapping_iterator *iter,
+               const char **mapping_name, uint64_t *range_begin,
+               uint64_t *range_end)
+{
+       BT_ASSERT_PRE_NON_NULL(iter, "Enumeration field type mapping iterator");
+       BT_ASSERT_PRE(iter->index != -1,
+               "Invalid enumeration field type mapping iterator access: "
+               "addr=%p, position=-1", iter);
+       return bt_ctf_field_type_common_enumeration_unsigned_get_mapping_by_index(
+                       (void *) iter->enumeration_ft, iter->index,
+                       mapping_name, range_begin, range_end);
+}
+
+/*
+ * Note: This algorithm is O(n^2) vs number of enumeration mappings.
+ * Only used when freezing an enumeration.
+ */
+static
+void bt_ctf_field_type_common_enumeration_set_range_overlap(
+               struct bt_ctf_field_type_common_enumeration *ft)
+{
+       int64_t i, j, len;
+       int is_signed;
+
+       BT_LOGV("Setting enumeration field type's overlap flag: addr=%p",
+               ft);
+       len = ft->entries->len;
+       is_signed = bt_ctf_field_type_common_integer_is_signed(
+               BT_CTF_TO_COMMON(ft->container_ft));
+
+       for (i = 0; i < len; i++) {
+               for (j = i + 1; j < len; j++) {
+                       struct bt_ctf_enumeration_mapping *mapping[2];
+
+                       mapping[0] = bt_ctf_field_type_common_enumeration_get_mapping_by_index(
+                               BT_CTF_TO_COMMON(ft), i);
+                       mapping[1] = bt_ctf_field_type_common_enumeration_get_mapping_by_index(
+                               BT_CTF_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) {
+                                       ft->has_overlapping_ranges = BT_TRUE;
+                                       goto end;
+                               }
+                       } else {
+                               if (mapping[0]->range_start._unsigned
+                                                       <= mapping[1]->range_end._unsigned
+                                               && mapping[0]->range_end._unsigned
+                                                       >= mapping[1]->range_start._unsigned) {
+                                       ft->has_overlapping_ranges = BT_TRUE;
+                                       goto end;
+                               }
+                       }
+               }
+       }
+
+end:
+       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.");
+       }
+}
+
+BT_HIDDEN
+int bt_ctf_field_type_common_enumeration_validate_recursive(
+               struct bt_ctf_field_type_common *ft)
+{
+       int ret = 0;
+       struct bt_ctf_field_type_common_enumeration *enum_ft = BT_CTF_FROM_COMMON(ft);
+
+       ret = bt_ctf_field_type_common_integer_validate(
+                       BT_CTF_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",
+                       ft, enum_ft->container_ft);
+               goto end;
+       }
+
+       /* Ensure enum has entries */
+       if (enum_ft->entries->len == 0) {
+               BT_LOGW("Invalid enumeration field type: no entries: "
+                       "addr=%p", ft);
+               ret = -1;
+               goto end;
+       }
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+int bt_ctf_field_type_common_sequence_validate_recursive(
+               struct bt_ctf_field_type_common *ft)
+{
+       int ret = 0;
+       struct bt_ctf_field_type_common_sequence *seq_ft = BT_CTF_FROM_COMMON(ft);
+
+       /* Length field name should be set at this point */
+       if (seq_ft->length_field_name->len == 0) {
+               BT_LOGW("Invalid sequence field type: no length field name: "
+                       "addr=%p", ft);
+               ret = -1;
+               goto end;
+       }
+
+       ret = bt_ctf_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",
+                       ft, seq_ft->element_ft);
+       }
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+int bt_ctf_field_type_common_array_validate_recursive(
+               struct bt_ctf_field_type_common *ft)
+{
+       int ret = 0;
+       struct bt_ctf_field_type_common_array *array_ft = BT_CTF_FROM_COMMON(ft);
+
+       ret = bt_ctf_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",
+                       ft, array_ft->element_ft);
+       }
+
+       return ret;
+}
+
+BT_HIDDEN
+int bt_ctf_field_type_common_structure_validate_recursive(
+               struct bt_ctf_field_type_common *ft)
+{
+       int ret = 0;
+       struct bt_ctf_field_type_common *child_ft = NULL;
+       int64_t field_count =
+               bt_ctf_field_type_common_structure_get_field_count(ft);
+       int64_t i;
+
+       BT_ASSERT(field_count >= 0);
+
+       for (i = 0; i < field_count; ++i) {
+               const char *field_name;
+
+               ret = bt_ctf_field_type_common_structure_borrow_field_by_index(ft,
+                       &field_name, &child_ft, i);
+               BT_ASSERT(ret == 0);
+               ret = bt_ctf_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,
+                               ft, child_ft, field_name, i);
+                       goto end;
+               }
+       }
+
+end:
+       return ret;
+}
+
+static
+bt_bool bt_ctf_field_type_common_enumeration_has_overlapping_ranges(
+               struct bt_ctf_field_type_common_enumeration *enum_ft)
+{
+       if (!enum_ft->common.frozen) {
+               bt_ctf_field_type_common_enumeration_set_range_overlap(enum_ft);
+       }
+
+       return enum_ft->has_overlapping_ranges;
+}
+
+BT_HIDDEN
+int bt_ctf_field_type_common_variant_validate_recursive(
+               struct bt_ctf_field_type_common *ft)
+{
+       int ret = 0;
+       int64_t field_count;
+       struct bt_ctf_field_type_common *child_ft = NULL;
+       struct bt_ctf_field_type_common_variant *var_ft = BT_CTF_FROM_COMMON(ft);
+       int64_t i;
+
+       if (var_ft->tag_name->len == 0) {
+               BT_LOGW("Invalid variant field type: no tag field name: "
+                       "addr=%p", ft);
+               ret = -1;
+               goto end;
+       }
+
+       if (!var_ft->tag_ft) {
+               BT_LOGW("Invalid variant field type: no tag field type: "
+                       "addr=%p, tag-field-name=\"%s\"", var_ft,
+                       var_ft->tag_name->str);
+               ret = -1;
+               goto end;
+       }
+
+       if (bt_ctf_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", ft, var_ft->tag_name->str,
+                       var_ft->tag_ft);
+               ret = -1;
+               goto end;
+       }
+
+       /*
+        * It is valid to have a variant field type which does not have
+        * the fields corresponding to each label in the associated
+        * enumeration.
+        *
+        * It is also valid to have variant field type fields which
+        * cannot be selected because the variant field type tag has no
+        * mapping named as such. This scenario, while not ideal, cannot
+        * cause any error.
+        *
+        * If a non-existing field happens to be selected by an
+        * enumeration while reading a variant field, an error will be
+        * generated at that point (while reading the stream).
+        */
+       field_count = bt_ctf_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\"",
+                       ft, var_ft->tag_name->str);
+               ret = -1;
+               goto end;
+       }
+
+       for (i = 0; i < field_count; ++i) {
+               const char *field_name;
+
+               ret = bt_ctf_field_type_common_variant_borrow_field_by_index(ft,
+                       &field_name, &child_ft, i);
+               BT_ASSERT(ret == 0);
+               ret = bt_ctf_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,
+                               ft, var_ft->tag_name->str, child_ft,
+                               field_name, i);
+                       goto end;
+               }
+       }
+
+end:
+       return ret;
+}
+
+/*
+ * This function validates a given field type without considering
+ * where this field type is located. It only validates the properties
+ * of the given field type and the properties of its children if
+ * applicable.
+ */
+BT_HIDDEN
+int bt_ctf_field_type_common_validate(struct bt_ctf_field_type_common *ft)
+{
+       int ret = 0;
+
+       BT_ASSERT(ft);
+
+       if (ft->valid) {
+               /* Already marked as valid */
+               goto end;
+       }
+
+       if (ft->methods->validate) {
+               ret = ft->methods->validate(ft);
+       }
+
+       if (ret == 0 && ft->frozen) {
+               /* Field type is valid */
+               BT_LOGV("Marking field type as valid: addr=%p", ft);
+               ft->valid = 1;
+       }
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+int bt_ctf_field_type_common_integer_get_size(struct bt_ctf_field_type_common *ft)
+{
+       struct bt_ctf_field_type_common_integer *int_ft = BT_CTF_FROM_COMMON(ft);
+
+       BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+       BT_ASSERT_PRE_CTF_FT_COMMON_HAS_ID(ft, BT_CTF_FIELD_TYPE_ID_INTEGER,
+               "Field type");
+       return (int) int_ft->size;
+}
+
+BT_HIDDEN
+bt_bool bt_ctf_field_type_common_integer_is_signed(struct bt_ctf_field_type_common *ft)
+{
+       struct bt_ctf_field_type_common_integer *int_ft = BT_CTF_FROM_COMMON(ft);
+
+       BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+       BT_ASSERT_PRE_CTF_FT_COMMON_HAS_ID(ft, BT_CTF_FIELD_TYPE_ID_INTEGER,
+               "Field type");
+       return int_ft->is_signed;
+}
+
+BT_HIDDEN
+int bt_ctf_field_type_common_integer_set_is_signed(struct bt_ctf_field_type_common *ft,
+               bt_bool is_signed)
+{
+       int ret = 0;
+       struct bt_ctf_field_type_common_integer *int_ft = BT_CTF_FROM_COMMON(ft);
+
+       if (!ft) {
+               BT_LOGW_STR("Invalid parameter: field type is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       if (ft->frozen) {
+               BT_LOGW("Invalid parameter: field type is frozen: addr=%p",
+                       ft);
+               ret = -1;
+               goto end;
+       }
+
+       if (ft->id != BT_CTF_FIELD_TYPE_ID_INTEGER) {
+               BT_LOGW("Invalid parameter: field type is not an integer field type: "
+                       "addr=%p, ft-id=%s", ft,
+                       bt_ctf_field_type_id_string(ft->id));
+               ret = -1;
+               goto end;
+       }
+
+       int_ft->is_signed = !!is_signed;
+       BT_LOGV("Set integer field type's signedness: addr=%p, is-signed=%d",
+               ft, is_signed);
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+int bt_ctf_field_type_common_integer_set_size(struct bt_ctf_field_type_common *ft,
+               unsigned int size)
+{
+       int ret = 0;
+       struct bt_ctf_field_type_common_integer *int_ft = BT_CTF_FROM_COMMON(ft);
+
+       if (!ft) {
+               BT_LOGW_STR("Invalid parameter: field type is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       if (ft->frozen) {
+               BT_LOGW("Invalid parameter: field type is frozen: addr=%p",
+                       ft);
+               ret = -1;
+               goto end;
+       }
+
+       if (ft->id != BT_CTF_FIELD_TYPE_ID_INTEGER) {
+               BT_LOGW("Invalid parameter: field type is not an integer field type: "
+                       "addr=%p, ft-id=%s", ft,
+                       bt_ctf_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", ft, size);
+               ret = -1;
+               goto end;
+       }
+
+       int_ft->size = size;
+       BT_LOGV("Set integer field type's size: addr=%p, size=%u",
+               ft, size);
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+enum bt_ctf_integer_base bt_ctf_field_type_common_integer_get_base(
+               struct bt_ctf_field_type_common *ft)
+{
+       struct bt_ctf_field_type_common_integer *int_ft = BT_CTF_FROM_COMMON(ft);
+
+       BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+       BT_ASSERT_PRE_CTF_FT_COMMON_HAS_ID(ft, BT_CTF_FIELD_TYPE_ID_INTEGER,
+               "Field type");
+       return int_ft->base;
+}
+
+BT_HIDDEN
+int bt_ctf_field_type_common_integer_set_base(struct bt_ctf_field_type_common *ft,
+               enum bt_ctf_integer_base base)
+{
+       int ret = 0;
+       struct bt_ctf_field_type_common_integer *int_ft = BT_CTF_FROM_COMMON(ft);
+
+       if (!ft) {
+               BT_LOGW_STR("Invalid parameter: field type is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       if (ft->frozen) {
+               BT_LOGW("Invalid parameter: field type is frozen: addr=%p",
+                       ft);
+               ret = -1;
+               goto end;
+       }
+
+       if (ft->id != BT_CTF_FIELD_TYPE_ID_INTEGER) {
+               BT_LOGW("Invalid parameter: field type is not an integer field type: "
+                       "addr=%p, ft-id=%s", ft,
+                       bt_ctf_field_type_id_string(ft->id));
+               ret = -1;
+               goto end;
+       }
+
+       switch (base) {
+       case BT_CTF_INTEGER_BASE_UNSPECIFIED:
+       case BT_CTF_INTEGER_BASE_BINARY:
+       case BT_CTF_INTEGER_BASE_OCTAL:
+       case BT_CTF_INTEGER_BASE_DECIMAL:
+       case BT_CTF_INTEGER_BASE_HEXADECIMAL:
+       {
+               int_ft->base = base;
+               break;
+       }
+       default:
+               BT_LOGW("Invalid parameter: unknown integer field type base: "
+                       "addr=%p, base=%d", ft, base);
+               ret = -1;
+       }
+
+       BT_LOGV("Set integer field type's base: addr=%p, base=%s",
+               ft, bt_ctf_integer_base_string(base));
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+enum bt_ctf_string_encoding bt_ctf_field_type_common_integer_get_encoding(
+               struct bt_ctf_field_type_common *ft)
+{
+       struct bt_ctf_field_type_common_integer *int_ft = BT_CTF_FROM_COMMON(ft);
+
+       BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+       BT_ASSERT_PRE_CTF_FT_COMMON_HAS_ID(ft, BT_CTF_FIELD_TYPE_ID_INTEGER,
+               "Field type");
+       return int_ft->encoding;
+}
+
+BT_HIDDEN
+int bt_ctf_field_type_common_integer_set_encoding(struct bt_ctf_field_type_common *ft,
+               enum bt_ctf_string_encoding encoding)
+{
+       int ret = 0;
+       struct bt_ctf_field_type_common_integer *int_ft = BT_CTF_FROM_COMMON(ft);
+
+       if (!ft) {
+               BT_LOGW_STR("Invalid parameter: field type is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       if (ft->frozen) {
+               BT_LOGW("Invalid parameter: field type is frozen: addr=%p",
+                       ft);
+               ret = -1;
+               goto end;
+       }
+
+       if (ft->id != BT_CTF_FIELD_TYPE_ID_INTEGER) {
+               BT_LOGW("Invalid parameter: field type is not an integer field type: "
+                       "addr=%p, ft-id=%s", ft,
+                       bt_ctf_field_type_id_string(ft->id));
+               ret = -1;
+               goto end;
+       }
+
+       if (encoding != BT_CTF_STRING_ENCODING_UTF8 &&
+                       encoding != BT_CTF_STRING_ENCODING_ASCII &&
+                       encoding != BT_CTF_STRING_ENCODING_NONE) {
+               BT_LOGW("Invalid parameter: unknown string encoding: "
+                       "addr=%p, encoding=%d", ft, encoding);
+               ret = -1;
+               goto end;
+       }
+
+       int_ft->encoding = encoding;
+       BT_LOGV("Set integer field type's encoding: addr=%p, encoding=%s",
+               ft, bt_ctf_string_encoding_string(encoding));
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+struct bt_ctf_clock_class *bt_ctf_field_type_common_integer_borrow_mapped_clock_class(
+               struct bt_ctf_field_type_common *ft)
+{
+       struct bt_ctf_field_type_common_integer *int_ft = BT_CTF_FROM_COMMON(ft);
+
+       BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+       BT_ASSERT_PRE_CTF_FT_COMMON_HAS_ID(ft, BT_CTF_FIELD_TYPE_ID_INTEGER,
+               "Field type");
+       return int_ft->mapped_clock_class;
+}
+
+BT_HIDDEN
+int bt_ctf_field_type_common_integer_set_mapped_clock_class_no_check_frozen(
+               struct bt_ctf_field_type_common *ft,
+               struct bt_ctf_clock_class *clock_class)
+{
+       struct bt_ctf_field_type_common_integer *int_ft = BT_CTF_FROM_COMMON(ft);
+       int ret = 0;
+
+       if (!clock_class) {
+               BT_LOGW_STR("Invalid parameter: clock class is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       if (ft->id != BT_CTF_FIELD_TYPE_ID_INTEGER) {
+               BT_LOGW("Invalid parameter: field type is not an integer field type: "
+                       "addr=%p, ft-id=%s", ft,
+                       bt_ctf_field_type_id_string(ft->id));
+               goto end;
+       }
+
+       if (!bt_ctf_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\"",
+                       ft, clock_class,
+                       bt_ctf_clock_class_get_name(clock_class));
+               ret = -1;
+               goto end;
+       }
+
+       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\"",
+               ft, clock_class, bt_ctf_clock_class_get_name(clock_class));
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+int bt_ctf_field_type_common_integer_set_mapped_clock_class(
+               struct bt_ctf_field_type_common *ft,
+               struct bt_ctf_clock_class *clock_class)
+{
+       int ret = 0;
+
+       if (!ft) {
+               BT_LOGW_STR("Invalid parameter: field type is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       if (ft->frozen) {
+               BT_LOGW("Invalid parameter: field type is frozen: addr=%p",
+                       ft);
+               ret = -1;
+               goto end;
+       }
+
+       ret = bt_ctf_field_type_common_integer_set_mapped_clock_class_no_check_frozen(
+               ft, clock_class);
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+int bt_ctf_field_type_common_enumeration_signed_get_mapping_by_index(
+               struct bt_ctf_field_type_common *ft, uint64_t index,
+               const char **mapping_name, int64_t *range_begin,
+               int64_t *range_end)
+{
+       int ret = 0;
+       struct bt_ctf_enumeration_mapping *mapping;
+
+       BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+       BT_ASSERT_PRE_CTF_FT_COMMON_HAS_ID(ft,
+               BT_CTF_FIELD_TYPE_ID_ENUM, "Field type");
+       mapping = bt_ctf_field_type_common_enumeration_get_mapping_by_index(ft,
+               index);
+       if (!mapping) {
+               /* bt_ctf_field_type_common_enumeration_get_mapping_by_index() logs errors */
+               ret = -1;
+               goto end;
+       }
+
+       if (mapping_name) {
+               *mapping_name = g_quark_to_string(mapping->string);
+               BT_ASSERT(*mapping_name);
+       }
+
+       if (range_begin) {
+               *range_begin = mapping->range_start._signed;
+       }
+
+       if (range_end) {
+               *range_end = mapping->range_end._signed;
+       }
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+int bt_ctf_field_type_common_enumeration_unsigned_get_mapping_by_index(
+               struct bt_ctf_field_type_common *ft, uint64_t index,
+               const char **mapping_name, uint64_t *range_begin,
+               uint64_t *range_end)
+{
+       int ret = 0;
+       struct bt_ctf_enumeration_mapping *mapping;
+
+       BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+       BT_ASSERT_PRE_CTF_FT_COMMON_HAS_ID(ft, BT_CTF_FIELD_TYPE_ID_ENUM, "Field type");
+       mapping = bt_ctf_field_type_common_enumeration_get_mapping_by_index(
+               ft, index);
+       if (!mapping) {
+               /* bt_ctf_field_type_common_enumeration_get_mapping_by_index() reports any error */
+               ret = -1;
+               goto end;
+       }
+
+       if (mapping_name) {
+               *mapping_name = g_quark_to_string(mapping->string);
+               BT_ASSERT(*mapping_name);
+       }
+
+       if (range_begin) {
+               *range_begin = mapping->range_start._unsigned;
+       }
+
+       if (range_end) {
+               *range_end = mapping->range_end._unsigned;
+       }
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+struct bt_ctf_field_type_common *
+bt_ctf_field_type_common_enumeration_borrow_container_field_type(
+               struct bt_ctf_field_type_common *ft)
+{
+       struct bt_ctf_field_type_common_enumeration *enum_ft = BT_CTF_FROM_COMMON(ft);
+
+       BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+       BT_ASSERT_PRE_CTF_FT_COMMON_HAS_ID(ft, BT_CTF_FIELD_TYPE_ID_ENUM, "Field type");
+       return BT_CTF_TO_COMMON(enum_ft->container_ft);
+}
+
+BT_HIDDEN
+int bt_ctf_field_type_common_enumeration_signed_add_mapping(
+               struct bt_ctf_field_type_common *ft, const char *string,
+               int64_t range_start, int64_t range_end)
+{
+       int ret = 0;
+       GQuark mapping_name;
+       struct bt_ctf_enumeration_mapping *mapping;
+       struct bt_ctf_field_type_common_enumeration *enum_ft = BT_CTF_FROM_COMMON(ft);
+       char *escaped_string;
+
+       if (!ft) {
+               BT_LOGW_STR("Invalid parameter: field type is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       if (!string) {
+               BT_LOGW_STR("Invalid parameter: string is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       if (ft->frozen) {
+               BT_LOGW("Invalid parameter: field type is frozen: addr=%p",
+                       ft);
+               ret = -1;
+               goto end;
+       }
+
+       if (ft->id != BT_CTF_FIELD_TYPE_ID_ENUM) {
+               BT_LOGW("Invalid parameter: field type is not an enumeration field type: "
+                       "addr=%p, ft-id=%s", ft,
+                       bt_ctf_field_type_id_string(ft->id));
+               ret = -1;
+               goto end;
+       }
+
+       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,
+                       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", ft,
+                       string);
+               ret = -1;
+               goto end;
+       }
+
+       escaped_string = g_strescape(string, NULL);
+       if (!escaped_string) {
+               BT_LOGE("Cannot escape mapping name: enum-ft-addr=%p, "
+                       "mapping-name-addr=%p, mapping-name=\"%s\"",
+                       ft, string, string);
+               ret = -1;
+               goto end;
+       }
+
+       mapping = g_new(struct bt_ctf_enumeration_mapping, 1);
+       if (!mapping) {
+               BT_LOGE_STR("Failed to allocate one enumeration mapping.");
+               ret = -1;
+               goto error_free;
+       }
+       mapping_name = g_quark_from_string(escaped_string);
+       *mapping = (struct bt_ctf_enumeration_mapping) {
+               .range_start._signed = range_start,
+               .range_end._signed = range_end,
+               .string =  mapping_name,
+       };
+       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,
+               ft, string, range_start, range_end);
+
+error_free:
+       free(escaped_string);
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+int bt_ctf_field_type_common_enumeration_unsigned_add_mapping(
+               struct bt_ctf_field_type_common *ft, const char *string,
+               uint64_t range_start, uint64_t range_end)
+{
+       int ret = 0;
+       GQuark mapping_name;
+       struct bt_ctf_enumeration_mapping *mapping;
+       struct bt_ctf_field_type_common_enumeration *enum_ft = BT_CTF_FROM_COMMON(ft);
+       char *escaped_string;
+
+       if (!ft) {
+               BT_LOGW_STR("Invalid parameter: field type is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       if (!string) {
+               BT_LOGW_STR("Invalid parameter: string is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       if (ft->frozen) {
+               BT_LOGW("Invalid parameter: field type is frozen: addr=%p",
+                       ft);
+               ret = -1;
+               goto end;
+       }
+
+       if (ft->id != BT_CTF_FIELD_TYPE_ID_ENUM) {
+               BT_LOGW("Invalid parameter: field type is not an enumeration field type: "
+                       "addr=%p, ft-id=%s", ft,
+                       bt_ctf_field_type_id_string(ft->id));
+               ret = -1;
+               goto end;
+       }
+
+       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,
+                       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", ft,
+                       string);
+               ret = -1;
+               goto end;
+       }
+
+       escaped_string = g_strescape(string, NULL);
+       if (!escaped_string) {
+               BT_LOGE("Cannot escape mapping name: enum-ft-addr=%p, "
+                       "mapping-name-addr=%p, mapping-name=\"%s\"",
+                       ft, string, string);
+               ret = -1;
+               goto end;
+       }
+
+       mapping = g_new(struct bt_ctf_enumeration_mapping, 1);
+       if (!mapping) {
+               BT_LOGE_STR("Failed to allocate one enumeration mapping.");
+               ret = -1;
+               goto error_free;
+       }
+       mapping_name = g_quark_from_string(escaped_string);
+       *mapping = (struct bt_ctf_enumeration_mapping) {
+               .range_start._unsigned = range_start,
+               .range_end._unsigned = range_end,
+               .string = mapping_name,
+       };
+       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,
+               ft, string, range_start, range_end);
+
+error_free:
+       free(escaped_string);
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+int64_t bt_ctf_field_type_common_enumeration_get_mapping_count(
+               struct bt_ctf_field_type_common *ft)
+{
+       struct bt_ctf_field_type_common_enumeration *enum_ft = BT_CTF_FROM_COMMON(ft);
+
+       BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+       BT_ASSERT_PRE_CTF_FT_COMMON_HAS_ID(ft, BT_CTF_FIELD_TYPE_ID_ENUM, "Field type");
+       return (int64_t) enum_ft->entries->len;
+}
+
+BT_HIDDEN
+int bt_ctf_field_type_common_floating_point_get_exponent_digits(
+               struct bt_ctf_field_type_common *ft)
+{
+       struct bt_ctf_field_type_common_floating_point *flt_ft = BT_CTF_FROM_COMMON(ft);
+
+       BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+       BT_ASSERT_PRE_CTF_FT_COMMON_HAS_ID(ft, BT_CTF_FIELD_TYPE_ID_FLOAT,
+               "Field type");
+       return (int) flt_ft->exp_dig;
+}
+
+BT_HIDDEN
+int bt_ctf_field_type_common_floating_point_set_exponent_digits(
+               struct bt_ctf_field_type_common *ft,
+               unsigned int exponent_digits)
+{
+       int ret = 0;
+       struct bt_ctf_field_type_common_floating_point *flt_ft = BT_CTF_FROM_COMMON(ft);
+
+       if (!ft) {
+               BT_LOGW_STR("Invalid parameter: field type is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       if (ft->frozen) {
+               BT_LOGW("Invalid parameter: field type is frozen: addr=%p",
+                       ft);
+               ret = -1;
+               goto end;
+       }
+
+       if (ft->id != BT_CTF_FIELD_TYPE_ID_FLOAT) {
+               BT_LOGW("Invalid parameter: field type is not a floating point number field type: "
+                       "addr=%p, ft-id=%s", ft,
+                       bt_ctf_field_type_id_string(ft->id));
+               ret = -1;
+               goto end;
+       }
+
+       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", ft, exponent_digits);
+               ret = -1;
+               goto end;
+       }
+
+       flt_ft->exp_dig = exponent_digits;
+       BT_LOGV("Set floating point number field type's exponent size: addr=%p, "
+               "exp-size=%u", ft, exponent_digits);
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+int bt_ctf_field_type_common_floating_point_get_mantissa_digits(
+               struct bt_ctf_field_type_common *ft)
+{
+       struct bt_ctf_field_type_common_floating_point *flt_ft = BT_CTF_FROM_COMMON(ft);
+
+       BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+       BT_ASSERT_PRE_CTF_FT_COMMON_HAS_ID(ft, BT_CTF_FIELD_TYPE_ID_FLOAT,
+               "Field type");
+       return (int) flt_ft->mant_dig;
+}
+
+BT_HIDDEN
+int bt_ctf_field_type_common_floating_point_set_mantissa_digits(
+               struct bt_ctf_field_type_common *ft, unsigned int mantissa_digits)
+{
+       int ret = 0;
+       struct bt_ctf_field_type_common_floating_point *flt_ft = BT_CTF_FROM_COMMON(ft);
+
+       if (!ft) {
+               BT_LOGW_STR("Invalid parameter: field type is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       if (ft->frozen) {
+               BT_LOGW("Invalid parameter: field type is frozen: addr=%p",
+                       ft);
+               ret = -1;
+               goto end;
+       }
+
+       if (ft->id != BT_CTF_FIELD_TYPE_ID_FLOAT) {
+               BT_LOGW("Invalid parameter: field type is not a floating point number field type: "
+                       "addr=%p, ft-id=%s", ft,
+                       bt_ctf_field_type_id_string(ft->id));
+               ret = -1;
+               goto end;
+       }
+
+       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", ft, mantissa_digits);
+               ret = -1;
+               goto end;
+       }
+
+       flt_ft->mant_dig = mantissa_digits;
+       BT_LOGV("Set floating point number field type's mantissa size: addr=%p, "
+               "mant-size=%u", ft, mantissa_digits);
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+int bt_ctf_field_type_common_structure_replace_field(
+               struct bt_ctf_field_type_common *ft,
+               const char *field_name,
+               struct bt_ctf_field_type_common *field_type)
+{
+       int ret = 0;
+       struct bt_ctf_field_type_common_structure *struct_ft = BT_CTF_FROM_COMMON(ft);
+       GQuark name_quark;
+       uint64_t i;
+
+       BT_ASSERT(ft);
+       BT_ASSERT(field_name);
+       BT_ASSERT(field_type);
+       BT_ASSERT(ft->id == BT_CTF_FIELD_TYPE_ID_STRUCT);
+       name_quark = g_quark_from_string(field_name);
+
+       for (i = 0; i < struct_ft->fields->len; i++) {
+               struct bt_ctf_field_type_common_structure_field *field =
+                       BT_CTF_FIELD_TYPE_COMMON_STRUCTURE_FIELD_AT_INDEX(ft, i);
+
+               if (field->name == name_quark) {
+                       bt_put(field->type);
+                       field->type = bt_get(field_type);
+               }
+       }
+
+       return ret;
+}
+
+BT_HIDDEN
+int bt_ctf_field_type_common_structure_add_field(struct bt_ctf_field_type_common *ft,
+               struct bt_ctf_field_type_common *field_type,
+               const char *field_name)
+{
+       int ret = 0;
+       struct bt_ctf_field_type_common_structure *struct_ft = BT_CTF_FROM_COMMON(ft);
+
+       /*
+        * TODO: check that `field_type` does not contain `type`,
+        *       recursively.
+        */
+       if (!ft) {
+               BT_LOGW_STR("Invalid parameter: field type is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       if (!field_name) {
+               BT_LOGW_STR("Invalid parameter: field name is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       if (ft->frozen) {
+               BT_LOGW("Invalid parameter: field type is frozen: addr=%p",
+                       ft);
+               ret = -1;
+               goto end;
+       }
+
+       if (ft->id != BT_CTF_FIELD_TYPE_ID_STRUCT) {
+               BT_LOGW("Invalid parameter: field type is not a structure field type: "
+                       "addr=%p, ft-id=%s", ft,
+                       bt_ctf_field_type_id_string(ft->id));
+               ret = -1;
+               goto end;
+       }
+
+       if (ft == field_type) {
+               BT_LOGW("Invalid parameter: structure field type and field type to add are the same: "
+                       "addr=%p", ft);
+               ret = -1;
+               goto end;
+       }
+
+       if (add_structure_variant_member(struct_ft->fields,
+                       struct_ft->field_name_to_index, field_type, field_name,
+                       false)) {
+               BT_LOGW("Cannot add field to structure field type: "
+                       "struct-ft-addr=%p, field-ft-addr=%p, field-name=\"%s\"",
+                       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\"", ft,
+               field_type, field_name);
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+int64_t bt_ctf_field_type_common_structure_get_field_count(
+               struct bt_ctf_field_type_common *ft)
+{
+       struct bt_ctf_field_type_common_structure *struct_ft = BT_CTF_FROM_COMMON(ft);
+
+       BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+       BT_ASSERT_PRE_CTF_FT_COMMON_HAS_ID(ft, BT_CTF_FIELD_TYPE_ID_STRUCT,
+               "Field type");
+       return (int64_t) struct_ft->fields->len;
+}
+
+BT_HIDDEN
+int bt_ctf_field_type_common_structure_borrow_field_by_index(
+               struct bt_ctf_field_type_common *ft,
+               const char **field_name,
+               struct bt_ctf_field_type_common **field_type, uint64_t index)
+{
+       struct bt_ctf_field_type_common_structure *struct_ft = BT_CTF_FROM_COMMON(ft);
+       struct bt_ctf_field_type_common_structure_field *field;
+
+       BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+       BT_ASSERT_PRE_CTF_FT_COMMON_HAS_ID(ft, BT_CTF_FIELD_TYPE_ID_STRUCT,
+               "Field type");
+       BT_ASSERT_PRE(index < struct_ft->fields->len,
+               "Index is out of bounds: index=%" PRIu64 ", "
+               "count=%u, ft-addr=%p",
+               index, struct_ft->fields->len, ft);
+       field = BT_CTF_FIELD_TYPE_COMMON_STRUCTURE_FIELD_AT_INDEX(struct_ft, index);
+
+       if (field_type) {
+               *field_type = field->type;
+       }
+
+       if (field_name) {
+               *field_name = g_quark_to_string(field->name);
+               BT_ASSERT(*field_name);
+       }
+
+       return 0;
+}
+
+BT_HIDDEN
+struct bt_ctf_field_type_common *
+bt_ctf_field_type_common_structure_borrow_field_type_by_name(
+               struct bt_ctf_field_type_common *ft, const char *name)
+{
+       size_t index;
+       GQuark name_quark;
+       struct bt_ctf_field_type_common_structure_field *field;
+       struct bt_ctf_field_type_common_structure *struct_ft = BT_CTF_FROM_COMMON(ft);
+       struct bt_ctf_field_type_common *field_type = NULL;
+
+       BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+       BT_ASSERT_PRE_NON_NULL(name, "Name");
+       BT_ASSERT_PRE_CTF_FT_COMMON_HAS_ID(ft, BT_CTF_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\"",
+                       ft, name);
+               goto end;
+       }
+
+       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\"",
+                       ft, name);
+               goto end;
+       }
+
+       field = BT_CTF_FIELD_TYPE_COMMON_STRUCTURE_FIELD_AT_INDEX(ft, index);
+       field_type = field->type;
+
+end:
+       return field_type;
+}
+
+BT_HIDDEN
+struct bt_ctf_field_type_common *
+bt_ctf_field_type_common_variant_borrow_tag_field_type(
+               struct bt_ctf_field_type_common *ft)
+{
+       struct bt_ctf_field_type_common_variant *var_ft = BT_CTF_FROM_COMMON(ft);
+       struct bt_ctf_field_type_common *tag_ft = NULL;
+
+       BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+       BT_ASSERT_PRE_CTF_FT_COMMON_HAS_ID(ft, BT_CTF_FIELD_TYPE_ID_VARIANT,
+               "Field type");
+
+       if (!var_ft->tag_ft) {
+               BT_LOGV("Variant field type has no tag field type: "
+                       "addr=%p", ft);
+               goto end;
+       }
+
+       tag_ft = BT_CTF_TO_COMMON(var_ft->tag_ft);
+
+end:
+       return tag_ft;
+}
+
+BT_HIDDEN
+const char *bt_ctf_field_type_common_variant_get_tag_name(
+               struct bt_ctf_field_type_common *ft)
+{
+       struct bt_ctf_field_type_common_variant *var_ft = BT_CTF_FROM_COMMON(ft);
+       const char *tag_name = NULL;
+
+       BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+       BT_ASSERT_PRE_CTF_FT_COMMON_HAS_ID(ft, BT_CTF_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", ft);
+               goto end;
+       }
+
+       tag_name = var_ft->tag_name->str;
+
+end:
+       return tag_name;
+}
+
+BT_HIDDEN
+int bt_ctf_field_type_common_variant_set_tag_name(
+               struct bt_ctf_field_type_common *ft, const char *name)
+{
+       int ret = 0;
+       struct bt_ctf_field_type_common_variant *var_ft = BT_CTF_FROM_COMMON(ft);
+
+       if (!ft) {
+               BT_LOGW_STR("Invalid parameter: field type is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       if (ft->frozen) {
+               BT_LOGW("Invalid parameter: field type is frozen: addr=%p",
+                       ft);
+               ret = -1;
+               goto end;
+       }
+
+       if (ft->id != BT_CTF_FIELD_TYPE_ID_VARIANT) {
+               BT_LOGW("Invalid parameter: field type is not a variant field type: "
+                       "addr=%p, ft-id=%s", ft, bt_ctf_field_type_id_string(ft->id));
+               ret = -1;
+               goto end;
+       }
+
+       if (!bt_ctf_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\"",
+                       ft, name);
+               ret = -1;
+               goto end;
+       }
+
+       g_string_assign(var_ft->tag_name, name);
+       BT_LOGV("Set variant field type's tag field name: addr=%p, "
+               "tag-field-name=\"%s\"", ft, name);
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+int bt_ctf_field_type_common_variant_add_field(struct bt_ctf_field_type_common *ft,
+               struct bt_ctf_field_type_common *field_type,
+               const char *field_name)
+{
+       size_t i;
+       int ret = 0;
+       struct bt_ctf_field_type_common_variant *var_ft = BT_CTF_FROM_COMMON(ft);
+       GQuark field_name_quark = g_quark_from_string(field_name);
+
+       /*
+        * TODO: check that `field_type` does not contain `type`,
+        *       recursively.
+        */
+       if (!ft) {
+               BT_LOGW_STR("Invalid parameter: field type is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       if (ft->frozen) {
+               BT_LOGW("Invalid parameter: field type is frozen: addr=%p",
+                       ft);
+               ret = -1;
+               goto end;
+       }
+
+       if (ft->id != BT_CTF_FIELD_TYPE_ID_VARIANT) {
+               BT_LOGW("Invalid parameter: field type is not a variant field type: "
+                       "addr=%p, ft-id=%s", ft,
+                       bt_ctf_field_type_id_string(ft->id));
+               ret = -1;
+               goto end;
+       }
+
+       if (ft == field_type) {
+               BT_LOGW("Invalid parameter: variant field type and field type to add are the same: "
+                       "addr=%p", ft);
+               ret = -1;
+               goto end;
+       }
+
+       /* The user has explicitly provided a tag; validate against it. */
+       if (var_ft->tag_ft) {
+               int name_found = 0;
+
+               /* Make sure this name is present in the enum tag */
+               for (i = 0; i < var_ft->tag_ft->entries->len; i++) {
+                       struct bt_ctf_enumeration_mapping *mapping =
+                               g_ptr_array_index(var_ft->tag_ft->entries, i);
+
+                       if (mapping->string == field_name_quark) {
+                               name_found = 1;
+                               break;
+                       }
+               }
+
+               if (!name_found) {
+                       /* Validation failed */
+                       BT_LOGW("Invalid parameter: field name does not name a tag field type's mapping: "
+                               "variant-ft-addr=%p, tag-ft-addr=%p, "
+                               "tag-field-name=\"%s\""
+                               "field-ft-addr=%p, field-name=\"%s\"",
+                               ft, var_ft->tag_ft, var_ft->tag_name->str,
+                               field_type, field_name);
+                       ret = -1;
+                       goto end;
+               }
+       }
+
+       if (add_structure_variant_member(var_ft->choices,
+                       var_ft->choice_name_to_index, field_type,
+                       field_name, true)) {
+               BT_LOGW("Cannot add field to variant field type: "
+                       "variant-ft-addr=%p, field-ft-addr=%p, field-name=\"%s\"",
+                       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\"", ft,
+               field_type, field_name);
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+struct bt_ctf_field_type_common *
+bt_ctf_field_type_common_variant_borrow_field_type_by_name(
+               struct bt_ctf_field_type_common *ft,
+               const char *field_name)
+{
+       size_t index;
+       GQuark name_quark;
+       struct bt_ctf_field_type_common_variant_choice *choice;
+       struct bt_ctf_field_type_common_variant *var_ft = BT_CTF_FROM_COMMON(ft);
+       struct bt_ctf_field_type_common *field_type = NULL;
+
+       BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+       BT_ASSERT_PRE_NON_NULL(field_name, "Name");
+       BT_ASSERT_PRE_CTF_FT_COMMON_HAS_ID(ft, BT_CTF_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\"",
+                       ft, field_name);
+               goto end;
+       }
+
+       if (!g_hash_table_lookup_extended(var_ft->choice_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\"",
+                       ft, field_name);
+               goto end;
+       }
+
+       choice = BT_CTF_FIELD_TYPE_COMMON_VARIANT_CHOICE_AT_INDEX(ft, index);
+       field_type = choice->type;
+
+end:
+       return field_type;
+}
+
+BT_HIDDEN
+int64_t bt_ctf_field_type_common_variant_get_field_count(
+               struct bt_ctf_field_type_common *ft)
+{
+       struct bt_ctf_field_type_common_variant *var_ft = BT_CTF_FROM_COMMON(ft);
+
+       BT_ASSERT_PRE_NON_NULL(ft, "Variant field type");
+       BT_ASSERT_PRE_CTF_FT_COMMON_HAS_ID(ft, BT_CTF_FIELD_TYPE_ID_VARIANT,
+               "Field type");
+       return (int64_t) var_ft->choices->len;
+}
+
+BT_HIDDEN
+int bt_ctf_field_type_common_variant_borrow_field_by_index(
+               struct bt_ctf_field_type_common *ft,
+               const char **field_name,
+               struct bt_ctf_field_type_common **field_type, uint64_t index)
+{
+       struct bt_ctf_field_type_common_variant *var_ft = BT_CTF_FROM_COMMON(ft);
+       struct bt_ctf_field_type_common_variant_choice *choice;
+
+       BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+       BT_ASSERT_PRE_CTF_FT_COMMON_HAS_ID(ft, BT_CTF_FIELD_TYPE_ID_VARIANT,
+               "Field type");
+       BT_ASSERT_PRE(index < var_ft->choices->len,
+               "Index is out of bounds: index=%" PRIu64 ", "
+               "count=%u, ft-addr=%p",
+               index, var_ft->choices->len, ft);
+       choice = BT_CTF_FIELD_TYPE_COMMON_VARIANT_CHOICE_AT_INDEX(ft, index);
+
+       if (field_type) {
+               *field_type = choice->type;
+       }
+
+       if (field_name) {
+               *field_name = g_quark_to_string(choice->name);
+               BT_ASSERT(*field_name);
+       }
+
+       return 0;
+}
+
+BT_HIDDEN
+int64_t bt_ctf_field_type_common_variant_find_choice_index(
+               struct bt_ctf_field_type_common *ft, uint64_t uval,
+               bool is_signed)
+{
+       int64_t ret;
+       uint64_t i;
+       struct bt_ctf_field_type_common_variant *var_ft = BT_CTF_FROM_COMMON(ft);
+
+       BT_ASSERT(ft);
+       BT_ASSERT(ft->id == BT_CTF_FIELD_TYPE_ID_VARIANT);
+
+       if (bt_ctf_field_type_common_variant_update_choices(ft)) {
+               ret = INT64_C(-1);
+               goto end;
+       }
+
+       for (i = 0; i < var_ft->choices->len; i++) {
+               uint64_t range_i;
+               struct bt_ctf_field_type_common_variant_choice *choice =
+                       BT_CTF_FIELD_TYPE_COMMON_VARIANT_CHOICE_AT_INDEX(
+                               var_ft, i);
+
+               for (range_i = 0; range_i < choice->ranges->len; range_i++) {
+                       struct bt_ctf_field_type_common_variant_choice_range *range =
+                               &g_array_index(
+                                       choice->ranges,
+                                       struct bt_ctf_field_type_common_variant_choice_range,
+                                       range_i);
+
+                       if (is_signed) {
+                               int64_t tag_ival = (int64_t) uval;
+
+                               if (tag_ival >= range->lower.i &&
+                                               tag_ival <= range->upper.i) {
+                                       goto found;
+                               }
+                       } else {
+                               if (uval >= range->lower.u &&
+                                               uval <= range->upper.u) {
+                                       goto found;
+                               }
+                       }
+               }
+       }
+
+       /* Range not found */
+       ret = INT64_C(-1);
+       goto end;
+
+found:
+       ret = (int64_t) i;
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+struct bt_ctf_field_type_common *
+bt_ctf_field_type_common_array_borrow_element_field_type(
+               struct bt_ctf_field_type_common *ft)
+{
+       struct bt_ctf_field_type_common_array *array_ft = BT_CTF_FROM_COMMON(ft);
+
+       BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+       BT_ASSERT_PRE_CTF_FT_COMMON_HAS_ID(ft, BT_CTF_FIELD_TYPE_ID_ARRAY,
+               "Field type");
+       BT_ASSERT(array_ft && array_ft->element_ft);
+       return array_ft->element_ft;
+}
+
+BT_HIDDEN
+int bt_ctf_field_type_common_array_set_element_field_type(
+               struct bt_ctf_field_type_common *ft,
+               struct bt_ctf_field_type_common *element_ft)
+{
+       int ret = 0;
+       struct bt_ctf_field_type_common_array *array_ft = BT_CTF_FROM_COMMON(ft);
+
+       if (!ft) {
+               BT_LOGW_STR("Invalid parameter: array field type is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       if (!element_ft) {
+               BT_LOGW_STR("Invalid parameter: element field type is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       if (ft->id != BT_CTF_FIELD_TYPE_ID_ARRAY) {
+               BT_LOGW("Invalid parameter: field type is not an array field type: "
+                       "addr=%p, ft-id=%s", ft,
+                       bt_ctf_field_type_id_string(ft->id));
+               ret = -1;
+               goto end;
+       }
+
+       if (array_ft->element_ft) {
+               BT_PUT(array_ft->element_ft);
+       }
+
+       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", ft, element_ft);
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+int64_t bt_ctf_field_type_common_array_get_length(struct bt_ctf_field_type_common *ft)
+{
+       struct bt_ctf_field_type_common_array *array_ft = BT_CTF_FROM_COMMON(ft);
+
+       BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+       BT_ASSERT_PRE_CTF_FT_COMMON_HAS_ID(ft, BT_CTF_FIELD_TYPE_ID_ARRAY,
+               "Field type");
+       return (int64_t) array_ft->length;
+}
+
+BT_HIDDEN
+struct bt_ctf_field_type_common *bt_ctf_field_type_common_sequence_borrow_element_field_type(
+               struct bt_ctf_field_type_common *ft)
+{
+       struct bt_ctf_field_type_common_sequence *seq_ft = BT_CTF_FROM_COMMON(ft);
+
+       BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+       BT_ASSERT_PRE_CTF_FT_COMMON_HAS_ID(ft, BT_CTF_FIELD_TYPE_ID_SEQUENCE,
+               "Field type");
+       return seq_ft->element_ft;
+}
+
+BT_HIDDEN
+int bt_ctf_field_type_common_sequence_set_element_field_type(
+               struct bt_ctf_field_type_common *ft,
+               struct bt_ctf_field_type_common *element_ft)
+{
+       int ret = 0;
+       struct bt_ctf_field_type_common_sequence *seq_ft = BT_CTF_FROM_COMMON(ft);
+
+       if (!ft) {
+               BT_LOGW_STR("Invalid parameter: sequence field type is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       if (!element_ft) {
+               BT_LOGW_STR("Invalid parameter: element field type is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       if (ft->id != BT_CTF_FIELD_TYPE_ID_SEQUENCE) {
+               BT_LOGW("Invalid parameter: field type is not a sequence field type: "
+                       "addr=%p, ft-id=%s", ft,
+                       bt_ctf_field_type_id_string(ft->id));
+               ret = -1;
+               goto end;
+       }
+
+       if (seq_ft->element_ft) {
+               BT_PUT(seq_ft->element_ft);
+       }
+
+       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", ft, element_ft);
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+const char *bt_ctf_field_type_common_sequence_get_length_field_name(
+               struct bt_ctf_field_type_common *ft)
+{
+       struct bt_ctf_field_type_common_sequence *seq_ft = BT_CTF_FROM_COMMON(ft);
+
+       BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+       BT_ASSERT_PRE_CTF_FT_COMMON_HAS_ID(ft, BT_CTF_FIELD_TYPE_ID_SEQUENCE,
+               "Field type");
+       return seq_ft->length_field_name ?
+               seq_ft->length_field_name->str : NULL;
+}
+
+BT_HIDDEN
+enum bt_ctf_string_encoding bt_ctf_field_type_common_string_get_encoding(
+               struct bt_ctf_field_type_common *ft)
+{
+       struct bt_ctf_field_type_common_string *string_ft = BT_CTF_FROM_COMMON(ft);
+
+       BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+       BT_ASSERT_PRE_CTF_FT_COMMON_HAS_ID(ft, BT_CTF_FIELD_TYPE_ID_STRING,
+               "Field type");
+       return string_ft->encoding;
+}
+
+BT_HIDDEN
+int bt_ctf_field_type_common_string_set_encoding(struct bt_ctf_field_type_common *ft,
+               enum bt_ctf_string_encoding encoding)
+{
+       int ret = 0;
+       struct bt_ctf_field_type_common_string *string_ft = BT_CTF_FROM_COMMON(ft);
+
+       if (!ft) {
+               BT_LOGW_STR("Invalid parameter: field type is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       if (ft->id != BT_CTF_FIELD_TYPE_ID_STRING) {
+               BT_LOGW("Invalid parameter: field type is not a string field type: "
+                       "addr=%p, ft-id=%s", ft,
+                       bt_ctf_field_type_id_string(ft->id));
+               ret = -1;
+               goto end;
+       }
+
+       if (encoding != BT_CTF_STRING_ENCODING_UTF8 &&
+                       encoding != BT_CTF_STRING_ENCODING_ASCII) {
+               BT_LOGW("Invalid parameter: unknown string encoding: "
+                       "addr=%p, encoding=%d", ft, encoding);
+               ret = -1;
+               goto end;
+       }
+
+       string_ft->encoding = encoding;
+       BT_LOGV("Set string field type's encoding: addr=%p, encoding=%s",
+               ft, bt_ctf_string_encoding_string(encoding));
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+int bt_ctf_field_type_common_get_alignment(struct bt_ctf_field_type_common *ft)
+{
+       int ret;
+       enum bt_ctf_field_type_id type_id;
+
+       BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+
+       if (ft->frozen) {
+               ret = (int) ft->alignment;
+               goto end;
+       }
+
+       type_id = bt_ctf_field_type_common_get_type_id(ft);
+       switch (type_id) {
+       case BT_CTF_FIELD_TYPE_ID_SEQUENCE:
+       {
+               struct bt_ctf_field_type_common *element_ft =
+                       bt_ctf_field_type_common_sequence_borrow_element_field_type(ft);
+
+               BT_ASSERT(element_ft);
+               ret = bt_ctf_field_type_common_get_alignment(element_ft);
+               break;
+       }
+       case BT_CTF_FIELD_TYPE_ID_ARRAY:
+       {
+               struct bt_ctf_field_type_common *element_ft =
+                       bt_ctf_field_type_common_array_borrow_element_field_type(ft);
+
+               BT_ASSERT(element_ft);
+               ret = bt_ctf_field_type_common_get_alignment(element_ft);
+               break;
+       }
+       case BT_CTF_FIELD_TYPE_ID_STRUCT:
+       {
+               int64_t i, element_count;
+
+               element_count = bt_ctf_field_type_common_structure_get_field_count(
+                       ft);
+               BT_ASSERT(element_count >= 0);
+
+               for (i = 0; i < element_count; i++) {
+                       struct bt_ctf_field_type_common *field = NULL;
+                       int field_alignment;
+
+                       ret = bt_ctf_field_type_common_structure_borrow_field_by_index(
+                               ft, NULL, &field, i);
+                       BT_ASSERT(ret == 0);
+                       BT_ASSERT(field);
+                       field_alignment = bt_ctf_field_type_common_get_alignment(
+                               field);
+                       if (field_alignment < 0) {
+                               ret = field_alignment;
+                               goto end;
+                       }
+
+                       ft->alignment = MAX(field_alignment, ft->alignment);
+               }
+               ret = (int) ft->alignment;
+               break;
+       }
+       case BT_CTF_FIELD_TYPE_ID_UNKNOWN:
+               BT_LOGW("Invalid parameter: unknown field type ID: "
+                       "addr=%p, ft-id=%d", ft, type_id);
+               ret = -1;
+               break;
+       default:
+               ret = (int) ft->alignment;
+               break;
+       }
+
+end:
+       return ret;
+}
+
+static inline
+int is_power_of_two(unsigned int value)
+{
+       return ((value & (value - 1)) == 0) && value > 0;
+}
+
+BT_HIDDEN
+int bt_ctf_field_type_common_set_alignment(struct bt_ctf_field_type_common *ft,
+               unsigned int alignment)
+{
+       int ret = 0;
+       enum bt_ctf_field_type_id type_id;
+
+       /* Alignment must be a power of two */
+       if (!ft) {
+               BT_LOGW_STR("Invalid parameter: field type is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       if (ft->frozen) {
+               BT_LOGW("Invalid parameter: field type is frozen: addr=%p",
+                       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", ft, alignment);
+               ret = -1;
+               goto end;
+       }
+
+       type_id = bt_ctf_field_type_common_get_type_id(ft);
+       if (type_id == BT_CTF_FIELD_TYPE_ID_UNKNOWN) {
+               BT_LOGW("Invalid parameter: unknown field type ID: "
+                       "addr=%p, ft-id=%d", ft, type_id);
+               ret = -1;
+               goto end;
+       }
+
+       if (ft->id == BT_CTF_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, ft, alignment);
+               ret = -1;
+               goto end;
+       }
+
+       if (type_id == BT_CTF_FIELD_TYPE_ID_VARIANT ||
+                       type_id == BT_CTF_FIELD_TYPE_ID_SEQUENCE ||
+                       type_id == BT_CTF_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", ft,
+                       bt_ctf_field_type_id_string(ft->id));
+               ret = -1;
+               goto end;
+       }
+
+       ft->alignment = alignment;
+       ret = 0;
+       BT_LOGV("Set field type's alignment: addr=%p, align=%u",
+               ft, alignment);
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+enum bt_ctf_byte_order bt_ctf_field_type_common_get_byte_order(
+               struct bt_ctf_field_type_common *ft)
+{
+       enum bt_ctf_byte_order ret = BT_CTF_BYTE_ORDER_UNKNOWN;
+
+       BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+
+       switch (ft->id) {
+       case BT_CTF_FIELD_TYPE_ID_INTEGER:
+       {
+               struct bt_ctf_field_type_common_integer *integer =
+                       BT_CTF_FROM_COMMON(ft);
+
+               ret = integer->user_byte_order;
+               break;
+       }
+       case BT_CTF_FIELD_TYPE_ID_ENUM:
+       {
+               struct bt_ctf_field_type_common_enumeration *enum_ft =
+                       BT_CTF_FROM_COMMON(ft);
+
+               ret = bt_ctf_field_type_common_get_byte_order(
+                       BT_CTF_TO_COMMON(enum_ft->container_ft));
+               break;
+       }
+       case BT_CTF_FIELD_TYPE_ID_FLOAT:
+       {
+               struct bt_ctf_field_type_common_floating_point *floating_point =
+                       BT_CTF_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", ft,
+                       bt_ctf_field_type_id_string(ft->id));
+               goto end;
+       }
+
+       BT_ASSERT(ret == BT_CTF_BYTE_ORDER_NATIVE ||
+               ret == BT_CTF_BYTE_ORDER_LITTLE_ENDIAN ||
+               ret == BT_CTF_BYTE_ORDER_BIG_ENDIAN ||
+               ret == BT_CTF_BYTE_ORDER_NETWORK);
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+int bt_ctf_field_type_common_set_byte_order(struct bt_ctf_field_type_common *ft,
+               enum bt_ctf_byte_order byte_order)
+{
+       int ret = 0;
+
+       if (!ft) {
+               BT_LOGW_STR("Invalid parameter: field type is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       if (ft->frozen) {
+               BT_LOGW("Invalid parameter: field type is frozen: addr=%p",
+                       ft);
+               ret = -1;
+               goto end;
+       }
+
+       if (byte_order != BT_CTF_BYTE_ORDER_NATIVE &&
+                       byte_order != BT_CTF_BYTE_ORDER_LITTLE_ENDIAN &&
+                       byte_order != BT_CTF_BYTE_ORDER_BIG_ENDIAN &&
+                       byte_order != BT_CTF_BYTE_ORDER_NETWORK) {
+               BT_LOGW("Invalid parameter: invalid byte order: "
+                       "addr=%p, bo=%s", ft,
+                       bt_ctf_byte_order_string(byte_order));
+               ret = -1;
+               goto end;
+       }
+
+       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",
+               ft, bt_ctf_byte_order_string(byte_order));
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+enum bt_ctf_field_type_id bt_ctf_field_type_common_get_type_id(
+               struct bt_ctf_field_type_common *ft)
+{
+       BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+       return ft->id;
+}
+
+BT_HIDDEN
+void bt_ctf_field_type_common_freeze(struct bt_ctf_field_type_common *ft)
+{
+       if (!ft || ft->frozen) {
+               return;
+       }
+
+       BT_ASSERT(ft->methods->freeze);
+       ft->methods->freeze(ft);
+}
+
+BT_HIDDEN
+struct bt_ctf_field_type_common *
+bt_ctf_field_type_common_variant_borrow_field_type_signed(
+               struct bt_ctf_field_type_common_variant *var_ft,
+               int64_t tag_value)
+{
+       struct bt_ctf_field_type_common *field_type = NULL;
+       GQuark field_name_quark;
+       gpointer index;
+       struct bt_ctf_field_type_common_variant_choice *choice;
+       struct range_overlap_query query = {
+               .range_start._signed = tag_value,
+               .range_end._signed = tag_value,
+               .mapping_name = 0,
+               .overlaps = 0,
+       };
+
+       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(var_ft->choice_name_to_index,
+                       GUINT_TO_POINTER(field_name_quark), NULL, &index)) {
+               goto end;
+       }
+
+       choice = BT_CTF_FIELD_TYPE_COMMON_VARIANT_CHOICE_AT_INDEX(var_ft,
+               (size_t) index);
+       field_type = choice->type;
+
+end:
+       return field_type;
+}
+
+BT_HIDDEN
+struct bt_ctf_field_type_common *
+bt_ctf_field_type_common_variant_borrow_field_type_unsigned(
+               struct bt_ctf_field_type_common_variant *var_ft,
+               uint64_t tag_value)
+{
+       struct bt_ctf_field_type_common *field_type = NULL;
+       GQuark field_name_quark;
+       gpointer index;
+       struct bt_ctf_field_type_common_variant_choice *choice;
+       struct range_overlap_query query = {
+               .range_start._unsigned = tag_value,
+               .range_end._unsigned = tag_value,
+               .mapping_name = 0,
+               .overlaps = 0,
+       };
+
+       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(var_ft->choice_name_to_index,
+               GUINT_TO_POINTER(field_name_quark), NULL, &index)) {
+               goto end;
+       }
+
+       choice = BT_CTF_FIELD_TYPE_COMMON_VARIANT_CHOICE_AT_INDEX(var_ft,
+               (size_t) index);
+       field_type = choice->type;
+
+end:
+       return field_type;
+}
+
+BT_HIDDEN
+struct bt_ctf_field_type_common *bt_ctf_field_type_common_copy(
+               struct bt_ctf_field_type_common *ft)
+{
+       struct bt_ctf_field_type_common *ft_copy = NULL;
+
+       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;
+       }
+
+       ft_copy->alignment = ft->alignment;
+
+end:
+       return ft_copy;
+}
+
+BT_HIDDEN
+int bt_ctf_field_type_common_structure_get_field_name_index(
+               struct bt_ctf_field_type_common *ft, const char *name)
+{
+       int ret;
+       size_t index;
+       GQuark name_quark;
+       struct bt_ctf_field_type_common_structure *struct_ft = BT_CTF_FROM_COMMON(ft);
+
+       BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+       BT_ASSERT_PRE_NON_NULL(name, "Name");
+       BT_ASSERT_PRE_CTF_FT_COMMON_HAS_ID(ft, BT_CTF_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\"",
+                       ft, name);
+               ret = -1;
+               goto end;
+       }
+
+       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\"",
+                       ft, name);
+               ret = -1;
+               goto end;
+       }
+
+       ret = (int) index;
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+int bt_ctf_field_type_common_variant_get_field_name_index(
+               struct bt_ctf_field_type_common *ft, const char *name)
+{
+       int ret;
+       size_t index;
+       GQuark name_quark;
+       struct bt_ctf_field_type_common_variant *var_ft = BT_CTF_FROM_COMMON(ft);
+
+       BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+       BT_ASSERT_PRE_NON_NULL(name, "Name");
+       BT_ASSERT_PRE_CTF_FT_COMMON_HAS_ID(ft, BT_CTF_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\"",
+                       ft, name);
+               ret = -1;
+               goto end;
+       }
+
+       if (!g_hash_table_lookup_extended(var_ft->choice_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\"",
+                       ft, name);
+               ret = -1;
+               goto end;
+       }
+
+       ret = (int) index;
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+int bt_ctf_field_type_common_sequence_set_length_field_path(
+               struct bt_ctf_field_type_common *ft, struct bt_ctf_field_path *path)
+{
+       int ret = 0;
+       struct bt_ctf_field_type_common_sequence *seq_ft = BT_CTF_FROM_COMMON(ft);
+
+       if (!ft) {
+               BT_LOGW_STR("Invalid parameter: field type is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       if (ft->id != BT_CTF_FIELD_TYPE_ID_SEQUENCE) {
+               BT_LOGW("Invalid parameter: field type is not a sequence field type: "
+                       "addr=%p, ft-id=%s", ft,
+                       bt_ctf_field_type_id_string(ft->id));
+               ret = -1;
+               goto end;
+       }
+
+       bt_get(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", ft, path);
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+int bt_ctf_field_type_common_variant_set_tag_field_path(
+               struct bt_ctf_field_type_common *ft,
+               struct bt_ctf_field_path *path)
+{
+       int ret = 0;
+       struct bt_ctf_field_type_common_variant *var_ft = BT_CTF_FROM_COMMON(ft);
+
+       if (!ft) {
+               BT_LOGW_STR("Invalid parameter: field type is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       if (ft->id != BT_CTF_FIELD_TYPE_ID_VARIANT) {
+               BT_LOGW("Invalid parameter: field type is not a variant field type: "
+                       "addr=%p, ft-id=%s", ft,
+                       bt_ctf_field_type_id_string(ft->id));
+               ret = -1;
+               goto end;
+       }
+
+       bt_get(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", ft, path);
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+int bt_ctf_field_type_common_variant_set_tag_field_type(
+               struct bt_ctf_field_type_common *ft,
+               struct bt_ctf_field_type_common *tag_ft)
+{
+       int ret = 0;
+       struct bt_ctf_field_type_common_variant *var_ft = BT_CTF_FROM_COMMON(ft);
+
+       if (!ft) {
+               BT_LOGW_STR("Invalid parameter: variant field type is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       if (!tag_ft) {
+               BT_LOGW_STR("Invalid parameter: tag field type is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       if (tag_ft->id != BT_CTF_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_ctf_field_type_id_string(tag_ft->id));
+               ret = -1;
+               goto end;
+       }
+
+       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", ft, tag_ft);
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+void bt_ctf_field_type_common_generic_freeze(struct bt_ctf_field_type_common *ft)
+{
+       ft->frozen = 1;
+}
+
+BT_HIDDEN
+void bt_ctf_field_type_common_enumeration_freeze_recursive(
+               struct bt_ctf_field_type_common *ft)
+{
+       struct bt_ctf_field_type_common_enumeration *enum_ft = BT_CTF_FROM_COMMON(ft);
+
+       BT_LOGD("Freezing enumeration field type object: addr=%p", ft);
+       bt_ctf_field_type_common_enumeration_set_range_overlap(enum_ft);
+       bt_ctf_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_ctf_field_type_common_freeze(BT_CTF_TO_COMMON(enum_ft->container_ft));
+}
+
+BT_HIDDEN
+void bt_ctf_field_type_common_structure_freeze_recursive(
+               struct bt_ctf_field_type_common *ft)
+{
+       struct bt_ctf_field_type_common_structure *struct_ft = BT_CTF_FROM_COMMON(ft);
+       uint64_t i;
+
+       /* Cache the alignment */
+       BT_LOGD("Freezing structure field type object: addr=%p", ft);
+       ft->alignment = bt_ctf_field_type_common_get_alignment(ft);
+       bt_ctf_field_type_common_generic_freeze(ft);
+
+       for (i = 0; i < struct_ft->fields->len; i++) {
+               struct bt_ctf_field_type_common_structure_field *field =
+                       BT_CTF_FIELD_TYPE_COMMON_STRUCTURE_FIELD_AT_INDEX(ft, i);
+
+               BT_LOGD("Freezing structure field type field: "
+                       "ft-addr=%p, name=\"%s\"",
+                       field->type, g_quark_to_string(field->name));
+               bt_ctf_field_type_common_freeze(field->type);
+       }
+}
+
+BT_HIDDEN
+int bt_ctf_field_type_common_variant_update_choices(struct bt_ctf_field_type_common *ft)
+{
+       struct bt_ctf_field_type_common_variant *var_ft = BT_CTF_FROM_COMMON(ft);
+       uint64_t i;
+       int ret = 0;
+       bool is_signed;
+
+       if (ft->frozen && var_ft->choices_up_to_date) {
+               goto end;
+       }
+
+       BT_ASSERT(var_ft->tag_ft);
+       is_signed = !!var_ft->tag_ft->container_ft->is_signed;
+
+       for (i = 0; i < var_ft->choices->len; i++) {
+               struct bt_ctf_field_type_common_variant_choice *choice =
+                       BT_CTF_FIELD_TYPE_COMMON_VARIANT_CHOICE_AT_INDEX(ft, i);
+               const char *choice_name = g_quark_to_string(choice->name);
+               struct bt_ctf_field_type_enumeration_mapping_iterator *iter =
+                       bt_ctf_field_type_common_enumeration_find_mappings_by_name(
+                               BT_CTF_TO_COMMON(var_ft->tag_ft), choice_name);
+
+               if (!iter) {
+                       ret = -1;
+                       goto end;
+               }
+
+               BT_ASSERT(choice->ranges);
+               g_array_set_size(choice->ranges, 0);
+
+               while (bt_ctf_field_type_enumeration_mapping_iterator_next(iter) == 0) {
+                       struct bt_ctf_field_type_common_variant_choice_range range;
+
+                       if (is_signed) {
+                               ret = bt_ctf_field_type_enumeration_mapping_iterator_signed_get(
+                                       iter, NULL,
+                                       &range.lower.i, &range.upper.i);
+                       } else {
+                               ret = bt_ctf_field_type_enumeration_mapping_iterator_unsigned_get(
+                                       iter, NULL,
+                                       &range.lower.u, &range.upper.u);
+                       }
+
+                       BT_ASSERT(ret == 0);
+                       g_array_append_val(choice->ranges, range);
+               }
+
+               bt_put(iter);
+       }
+
+       var_ft->choices_up_to_date = true;
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+void bt_ctf_field_type_common_variant_freeze_recursive(
+               struct bt_ctf_field_type_common *ft)
+{
+       struct bt_ctf_field_type_common_variant *var_ft = BT_CTF_FROM_COMMON(ft);
+       uint64_t i;
+
+       BT_LOGD("Freezing variant field type object: addr=%p", ft);
+       bt_ctf_field_type_common_generic_freeze(ft);
+
+       for (i = 0; i < var_ft->choices->len; i++) {
+               struct bt_ctf_field_type_common_variant_choice *choice =
+                       BT_CTF_FIELD_TYPE_COMMON_VARIANT_CHOICE_AT_INDEX(ft, i);
+
+               BT_LOGD("Freezing variant field type member: "
+                       "ft-addr=%p, name=\"%s\"",
+                       choice->type, g_quark_to_string(choice->name));
+               bt_ctf_field_type_common_freeze(choice->type);
+       }
+}
+
+BT_HIDDEN
+void bt_ctf_field_type_common_array_freeze_recursive(
+               struct bt_ctf_field_type_common *ft)
+{
+       struct bt_ctf_field_type_common_array *array_ft = BT_CTF_FROM_COMMON(ft);
+
+       /* Cache the alignment */
+       BT_LOGD("Freezing array field type object: addr=%p", ft);
+       ft->alignment = bt_ctf_field_type_common_get_alignment(ft);
+       bt_ctf_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_ctf_field_type_common_freeze(array_ft->element_ft);
+}
+
+BT_HIDDEN
+void bt_ctf_field_type_common_sequence_freeze_recursive(
+               struct bt_ctf_field_type_common *ft)
+{
+       struct bt_ctf_field_type_common_sequence *seq_ft = BT_CTF_FROM_COMMON(ft);
+
+       /* Cache the alignment */
+       BT_LOGD("Freezing sequence field type object: addr=%p", ft);
+       ft->alignment = bt_ctf_field_type_common_get_alignment(ft);
+       bt_ctf_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_ctf_field_type_common_freeze(seq_ft->element_ft);
+}
+
+BT_HIDDEN
+void bt_ctf_field_type_common_integer_set_byte_order(
+               struct bt_ctf_field_type_common *ft, enum bt_ctf_byte_order byte_order)
+{
+       struct bt_ctf_field_type_common_integer *int_ft = BT_CTF_FROM_COMMON(ft);
+
+       int_ft->user_byte_order = byte_order;
+}
+
+BT_HIDDEN
+void bt_ctf_field_type_common_enumeration_set_byte_order_recursive(
+               struct bt_ctf_field_type_common *ft, enum bt_ctf_byte_order byte_order)
+{
+       struct bt_ctf_field_type_common_enumeration *enum_ft = BT_CTF_FROM_COMMON(ft);
+
+       bt_ctf_field_type_common_set_byte_order(BT_CTF_TO_COMMON(enum_ft->container_ft),
+               byte_order);
+}
+
+BT_HIDDEN
+void bt_ctf_field_type_common_floating_point_set_byte_order(
+               struct bt_ctf_field_type_common *ft, enum bt_ctf_byte_order byte_order)
+{
+       struct bt_ctf_field_type_common_floating_point *flt_ft = BT_CTF_FROM_COMMON(ft);
+
+       flt_ft->user_byte_order = byte_order;
+}
+
+BT_HIDDEN
+void bt_ctf_field_type_common_structure_set_byte_order_recursive(
+               struct bt_ctf_field_type_common *ft,
+               enum bt_ctf_byte_order byte_order)
+{
+       int i;
+       struct bt_ctf_field_type_common_structure *struct_ft = BT_CTF_FROM_COMMON(ft);
+
+       for (i = 0; i < struct_ft->fields->len; i++) {
+               struct bt_ctf_field_type_common_structure_field *field =
+                       BT_CTF_FIELD_TYPE_COMMON_STRUCTURE_FIELD_AT_INDEX(
+                               struct_ft, i);
+               struct bt_ctf_field_type_common *field_type = field->type;
+
+               bt_ctf_field_type_common_set_byte_order(field_type, byte_order);
+       }
+}
+
+BT_HIDDEN
+void bt_ctf_field_type_common_variant_set_byte_order_recursive(
+               struct bt_ctf_field_type_common *ft,
+               enum bt_ctf_byte_order byte_order)
+{
+       int i;
+       struct bt_ctf_field_type_common_variant *var_ft = BT_CTF_FROM_COMMON(ft);
+
+       for (i = 0; i < var_ft->choices->len; i++) {
+               struct bt_ctf_field_type_common_variant_choice *choice =
+                       BT_CTF_FIELD_TYPE_COMMON_VARIANT_CHOICE_AT_INDEX(
+                               var_ft, i);
+               struct bt_ctf_field_type_common *field_type = choice->type;
+
+               bt_ctf_field_type_common_set_byte_order(field_type, byte_order);
+       }
+}
+
+BT_HIDDEN
+void bt_ctf_field_type_common_array_set_byte_order_recursive(
+               struct bt_ctf_field_type_common *ft,
+               enum bt_ctf_byte_order byte_order)
+{
+       struct bt_ctf_field_type_common_array *array_ft = BT_CTF_FROM_COMMON(ft);
+
+       bt_ctf_field_type_common_set_byte_order(array_ft->element_ft, byte_order);
+}
+
+BT_HIDDEN
+void bt_ctf_field_type_common_sequence_set_byte_order_recursive(
+               struct bt_ctf_field_type_common *ft,
+               enum bt_ctf_byte_order byte_order)
+{
+       struct bt_ctf_field_type_common_sequence *seq_ft = BT_CTF_FROM_COMMON(ft);
+
+       bt_ctf_field_type_common_set_byte_order(seq_ft->element_ft, byte_order);
+}
+
+
+BT_HIDDEN
+int bt_ctf_field_type_common_integer_compare(struct bt_ctf_field_type_common *ft_a,
+               struct bt_ctf_field_type_common *ft_b)
+{
+       int ret = 1;
+       struct bt_ctf_field_type_common_integer *int_ft_a = BT_CTF_FROM_COMMON(ft_a);
+       struct bt_ctf_field_type_common_integer *int_ft_b = BT_CTF_FROM_COMMON(ft_b);
+
+       /* 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;
+       }
+
+       /* 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_ctf_byte_order_string(int_ft_a->user_byte_order),
+                       bt_ctf_byte_order_string(int_ft_b->user_byte_order));
+               goto end;
+       }
+
+       /* 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;
+       }
+
+       /* 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_ctf_integer_base_string(int_ft_a->base),
+                       bt_ctf_integer_base_string(int_ft_b->base));
+               goto end;
+       }
+
+       /* 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_ctf_string_encoding_string(int_ft_a->encoding),
+                       bt_ctf_string_encoding_string(int_ft_b->encoding));
+               goto end;
+       }
+
+       /* 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_ctf_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;
+               }
+       }
+
+       /* Equal */
+       ret = 0;
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+int bt_ctf_field_type_common_floating_point_compare(
+               struct bt_ctf_field_type_common *ft_a,
+               struct bt_ctf_field_type_common *ft_b)
+{
+       int ret = 1;
+       struct bt_ctf_field_type_common_floating_point *flt_ft_a =
+               BT_CTF_FROM_COMMON(ft_a);
+       struct bt_ctf_field_type_common_floating_point *flt_ft_b =
+               BT_CTF_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_ctf_byte_order_string(flt_ft_a->user_byte_order),
+                       bt_ctf_byte_order_string(flt_ft_b->user_byte_order));
+               goto end;
+       }
+
+       /* 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;
+       }
+
+       /* 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:
+       return ret;
+}
+
+static
+int compare_enumeration_mappings(struct bt_ctf_enumeration_mapping *mapping_a,
+               struct bt_ctf_enumeration_mapping *mapping_b)
+{
+       int ret = 1;
+
+       /* 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;
+       }
+
+       /* 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;
+       }
+
+       /* 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;
+       }
+
+       /* Equal */
+       ret = 0;
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+int bt_ctf_field_type_common_enumeration_compare_recursive(
+               struct bt_ctf_field_type_common *ft_a,
+               struct bt_ctf_field_type_common *ft_b)
+{
+       int ret = 1;
+       int i;
+       struct bt_ctf_field_type_common_enumeration *enum_ft_a =
+               BT_CTF_FROM_COMMON(ft_a);
+       struct bt_ctf_field_type_common_enumeration *enum_ft_b =
+               BT_CTF_FROM_COMMON(ft_b);
+
+       /* Container field type */
+       ret = bt_ctf_field_type_common_compare(
+               BT_CTF_TO_COMMON(enum_ft_a->container_ft),
+               BT_CTF_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;
+       }
+
+       ret = 1;
+
+       /* Entries */
+       if (enum_ft_a->entries->len != enum_ft_b->entries->len) {
+               goto end;
+       }
+
+       for (i = 0; i < enum_ft_a->entries->len; ++i) {
+               struct bt_ctf_enumeration_mapping *mapping_a =
+                       g_ptr_array_index(enum_ft_a->entries, i);
+               struct bt_ctf_enumeration_mapping *mapping_b =
+                       g_ptr_array_index(enum_ft_b->entries, i);
+
+               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;
+               }
+       }
+
+       /* Equal */
+       ret = 0;
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+int bt_ctf_field_type_common_string_compare(struct bt_ctf_field_type_common *ft_a,
+               struct bt_ctf_field_type_common *ft_b)
+{
+       int ret = 1;
+       struct bt_ctf_field_type_common_string *string_ft_a = BT_CTF_FROM_COMMON(ft_a);
+       struct bt_ctf_field_type_common_string *string_ft_b = BT_CTF_FROM_COMMON(ft_b);
+
+       /* 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_ctf_string_encoding_string(string_ft_a->encoding),
+                       bt_ctf_string_encoding_string(string_ft_b->encoding));
+               goto end;
+       }
+
+       /* Equal */
+       ret = 0;
+
+end:
+       return ret;
+}
+
+static
+int compare_structure_variant_members(
+               struct bt_ctf_field_type_common *member_a_ft,
+               struct bt_ctf_field_type_common *member_b_ft,
+               GQuark member_a_name, GQuark member_b_name)
+{
+       int ret = 1;
+
+       /* Label */
+       if (member_a_name != member_b_name) {
+               BT_LOGV("Structure/variant field type fields differ: different names: "
+                       "field-a-name=%s, field-b-name=%s",
+                       g_quark_to_string(member_a_name),
+                       g_quark_to_string(member_b_name));
+               goto end;
+       }
+
+       /* Type */
+       ret = bt_ctf_field_type_common_compare(member_a_ft, member_b_ft);
+       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(member_a_name),
+                       member_a_ft, member_b_ft);
+       }
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+int bt_ctf_field_type_common_structure_compare_recursive(
+               struct bt_ctf_field_type_common *ft_a,
+               struct bt_ctf_field_type_common *ft_b)
+{
+       int ret = 1;
+       int i;
+       struct bt_ctf_field_type_common_structure *struct_ft_a =
+               BT_CTF_FROM_COMMON(ft_a);
+       struct bt_ctf_field_type_common_structure *struct_ft_b =
+               BT_CTF_FROM_COMMON(ft_b);
+
+       /* Alignment */
+       if (bt_ctf_field_type_common_get_alignment(ft_a) !=
+                       bt_ctf_field_type_common_get_alignment(ft_b)) {
+               BT_LOGV("Structure field types differ: different alignments: "
+                       "ft-a-align=%u, ft-b-align=%u",
+                       bt_ctf_field_type_common_get_alignment(ft_a),
+                       bt_ctf_field_type_common_get_alignment(ft_b));
+               goto end;
+       }
+
+       /* 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;
+       }
+
+       for (i = 0; i < struct_ft_a->fields->len; ++i) {
+               struct bt_ctf_field_type_common_structure_field *field_a =
+                       BT_CTF_FIELD_TYPE_COMMON_STRUCTURE_FIELD_AT_INDEX(
+                               struct_ft_a, i);
+               struct bt_ctf_field_type_common_structure_field *field_b =
+                       BT_CTF_FIELD_TYPE_COMMON_STRUCTURE_FIELD_AT_INDEX(
+                               struct_ft_b, i);
+
+               ret = compare_structure_variant_members(field_a->type,
+                       field_b->type, field_a->name, field_b->name);
+               if (ret) {
+                       /* compare_structure_variant_members() logs what differs */
+                       BT_LOGV_STR("Structure field types differ: different fields.");
+                       goto end;
+               }
+       }
+
+       /* Equal */
+       ret = 0;
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+int bt_ctf_field_type_common_variant_compare_recursive(
+               struct bt_ctf_field_type_common *ft_a,
+               struct bt_ctf_field_type_common *ft_b)
+{
+       int ret = 1;
+       int i;
+       struct bt_ctf_field_type_common_variant *var_ft_a = BT_CTF_FROM_COMMON(ft_a);
+       struct bt_ctf_field_type_common_variant *var_ft_b = BT_CTF_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;
+       }
+
+       /* Tag type */
+       ret = bt_ctf_field_type_common_compare(BT_CTF_TO_COMMON(var_ft_a->tag_ft),
+               BT_CTF_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;
+       }
+
+       ret = 1;
+
+       /* Fields */
+       if (var_ft_a->choices->len != var_ft_b->choices->len) {
+               BT_LOGV("Variant field types differ: different field counts: "
+                       "ft-a-field-count=%u, ft-b-field-count=%u",
+                       var_ft_a->choices->len, var_ft_b->choices->len);
+               goto end;
+       }
+
+       for (i = 0; i < var_ft_a->choices->len; ++i) {
+               struct bt_ctf_field_type_common_variant_choice *choice_a =
+                       BT_CTF_FIELD_TYPE_COMMON_VARIANT_CHOICE_AT_INDEX(
+                               var_ft_a, i);
+               struct bt_ctf_field_type_common_variant_choice *choice_b =
+                       BT_CTF_FIELD_TYPE_COMMON_VARIANT_CHOICE_AT_INDEX(
+                               var_ft_b, i);
+
+               ret = compare_structure_variant_members(choice_a->type,
+                       choice_b->type, choice_a->name, choice_b->name);
+               if (ret) {
+                       /* compare_structure_variant_members() logs what differs */
+                       BT_LOGV_STR("Variant field types differ: different fields.");
+                       goto end;
+               }
+       }
+
+       /* Equal */
+       ret = 0;
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+int bt_ctf_field_type_common_array_compare_recursive(
+               struct bt_ctf_field_type_common *ft_a,
+               struct bt_ctf_field_type_common *ft_b)
+{
+       int ret = 1;
+       struct bt_ctf_field_type_common_array *array_ft_a = BT_CTF_FROM_COMMON(ft_a);
+       struct bt_ctf_field_type_common_array *array_ft_b = BT_CTF_FROM_COMMON(ft_b);
+
+       /* 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;
+       }
+
+       /* Element type */
+       ret = bt_ctf_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);
+       }
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+int bt_ctf_field_type_common_sequence_compare_recursive(
+               struct bt_ctf_field_type_common *ft_a,
+               struct bt_ctf_field_type_common *ft_b)
+{
+       int ret = -1;
+       struct bt_ctf_field_type_common_sequence *seq_ft_a = BT_CTF_FROM_COMMON(ft_a);
+       struct bt_ctf_field_type_common_sequence *seq_ft_b = BT_CTF_FROM_COMMON(ft_b);
+
+       /* 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;
+       }
+
+       /* Element type */
+       ret = bt_ctf_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);
+       }
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+int bt_ctf_field_type_common_compare(struct bt_ctf_field_type_common *ft_a,
+               struct bt_ctf_field_type_common *ft_b)
+{
+       int ret = 1;
+
+       BT_ASSERT_PRE_NON_NULL(ft_a, "Field type A");
+       BT_ASSERT_PRE_NON_NULL(ft_b, "Field type B");
+
+       if (ft_a == ft_b) {
+               /* Same reference: equal (even if both are NULL) */
+               ret = 0;
+               goto end;
+       }
+
+       if (!ft_a) {
+               BT_LOGW_STR("Invalid parameter: field type A is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       if (!ft_b) {
+               BT_LOGW_STR("Invalid parameter: field type B is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       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_ctf_field_type_id_string(ft_a->id),
+                       bt_ctf_field_type_id_string(ft_b->id));
+               goto end;
+       }
+
+       if (ft_a->id == BT_CTF_FIELD_TYPE_ID_UNKNOWN) {
+               /* Both have unknown type IDs */
+               BT_LOGW_STR("Invalid parameter: field type IDs are unknown.");
+               goto end;
+       }
+
+       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);
+       }
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+int64_t bt_ctf_field_type_common_get_field_count(struct bt_ctf_field_type_common *ft)
+{
+       int64_t field_count = -1;
+
+       switch (ft->id) {
+       case BT_CTF_FIELD_TYPE_ID_STRUCT:
+               field_count =
+                       bt_ctf_field_type_common_structure_get_field_count(ft);
+               break;
+       case BT_CTF_FIELD_TYPE_ID_VARIANT:
+               field_count =
+                       bt_ctf_field_type_common_variant_get_field_count(ft);
+               break;
+       case BT_CTF_FIELD_TYPE_ID_ARRAY:
+       case BT_CTF_FIELD_TYPE_ID_SEQUENCE:
+               /*
+                * Array and sequence types always contain a single member
+                * (the element type).
+                */
+               field_count = 1;
+               break;
+       default:
+               break;
+       }
+
+       return field_count;
+}
+
+BT_HIDDEN
+struct bt_ctf_field_type_common *bt_ctf_field_type_common_borrow_field_at_index(
+               struct bt_ctf_field_type_common *ft, int index)
+{
+       struct bt_ctf_field_type_common *field_type = NULL;
+
+       switch (ft->id) {
+       case BT_CTF_FIELD_TYPE_ID_STRUCT:
+       {
+               int ret = bt_ctf_field_type_common_structure_borrow_field_by_index(
+                       ft, NULL, &field_type, index);
+               if (ret) {
+                       field_type = NULL;
+                       goto end;
+               }
+               break;
+       }
+       case BT_CTF_FIELD_TYPE_ID_VARIANT:
+       {
+               int ret = bt_ctf_field_type_common_variant_borrow_field_by_index(
+                       ft, NULL, &field_type, index);
+               if (ret) {
+                       field_type = NULL;
+                       goto end;
+               }
+               break;
+       }
+       case BT_CTF_FIELD_TYPE_ID_ARRAY:
+               field_type =
+                       bt_ctf_field_type_common_array_borrow_element_field_type(ft);
+               break;
+       case BT_CTF_FIELD_TYPE_ID_SEQUENCE:
+               field_type =
+                       bt_ctf_field_type_common_sequence_borrow_element_field_type(ft);
+               break;
+       default:
+               break;
+       }
+
+end:
+       return field_type;
+}
+
+BT_HIDDEN
+int bt_ctf_field_type_common_get_field_index(struct bt_ctf_field_type_common *ft,
+               const char *name)
+{
+       int field_index = -1;
+
+       switch (ft->id) {
+       case BT_CTF_FIELD_TYPE_ID_STRUCT:
+               field_index = bt_ctf_field_type_common_structure_get_field_name_index(
+                       ft, name);
+               break;
+       case BT_CTF_FIELD_TYPE_ID_VARIANT:
+               field_index = bt_ctf_field_type_common_variant_get_field_name_index(
+                       ft, name);
+               break;
+       default:
+               break;
+       }
+
+       return field_index;
+}
+
+BT_HIDDEN
+struct bt_ctf_field_path *bt_ctf_field_type_common_variant_borrow_tag_field_path(
+               struct bt_ctf_field_type_common *ft)
+{
+       struct bt_ctf_field_type_common_variant *var_ft = BT_CTF_FROM_COMMON(ft);
+
+       BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+       BT_ASSERT_PRE_CTF_FT_COMMON_HAS_ID(ft, BT_CTF_FIELD_TYPE_ID_VARIANT,
+               "Field type");
+       return var_ft->tag_field_path;
+}
+
+BT_HIDDEN
+struct bt_ctf_field_path *bt_ctf_field_type_common_sequence_borrow_length_field_path(
+               struct bt_ctf_field_type_common *ft)
+{
+       struct bt_ctf_field_type_common_sequence *seq_ft = BT_CTF_FROM_COMMON(ft);
+
+       BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+       BT_ASSERT_PRE_CTF_FT_COMMON_HAS_ID(ft, BT_CTF_FIELD_TYPE_ID_SEQUENCE,
+               "Field type");
+       return seq_ft->length_field_path;
+}
+
+BT_HIDDEN
+int bt_ctf_field_type_common_validate_single_clock_class(
+               struct bt_ctf_field_type_common *ft,
+               struct bt_ctf_clock_class **expected_clock_class)
+{
+       int ret = 0;
+
+       if (!ft) {
+               goto end;
+       }
+
+       BT_ASSERT(expected_clock_class);
+
+       switch (ft->id) {
+       case BT_CTF_FIELD_TYPE_ID_INTEGER:
+       {
+               struct bt_ctf_clock_class *mapped_clock_class =
+                       bt_ctf_field_type_common_integer_borrow_mapped_clock_class(ft);
+
+               if (!mapped_clock_class) {
+                       goto end;
+               }
+
+               if (!*expected_clock_class) {
+                       /* Move reference to output parameter */
+                       *expected_clock_class = bt_get(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_ctf_clock_class_get_name(mapped_clock_class),
+                                       *expected_clock_class,
+                                       bt_ctf_clock_class_get_name(*expected_clock_class));
+                               bt_put(mapped_clock_class);
+                               ret = -1;
+                               goto end;
+                       }
+               }
+
+               break;
+       }
+       case BT_CTF_FIELD_TYPE_ID_ENUM:
+       case BT_CTF_FIELD_TYPE_ID_ARRAY:
+       case BT_CTF_FIELD_TYPE_ID_SEQUENCE:
+       {
+               struct bt_ctf_field_type_common *sub_ft = NULL;
+
+               switch (ft->id) {
+               case BT_CTF_FIELD_TYPE_ID_ENUM:
+                       sub_ft = bt_ctf_field_type_common_enumeration_borrow_container_field_type(
+                               ft);
+                       break;
+               case BT_CTF_FIELD_TYPE_ID_ARRAY:
+                       sub_ft = bt_ctf_field_type_common_array_borrow_element_field_type(
+                               ft);
+                       break;
+               case BT_CTF_FIELD_TYPE_ID_SEQUENCE:
+                       sub_ft = bt_ctf_field_type_common_sequence_borrow_element_field_type(
+                               ft);
+                       break;
+               default:
+                       BT_LOGF("Unexpected field type ID: id=%d", ft->id);
+                       abort();
+               }
+
+               BT_ASSERT(sub_ft);
+               ret = bt_ctf_field_type_common_validate_single_clock_class(sub_ft,
+                       expected_clock_class);
+               break;
+       }
+       case BT_CTF_FIELD_TYPE_ID_STRUCT:
+       {
+               uint64_t i;
+               int64_t count = bt_ctf_field_type_common_structure_get_field_count(
+                       ft);
+
+               for (i = 0; i < count; i++) {
+                       const char *name;
+                       struct bt_ctf_field_type_common *member_type;
+
+                       ret = bt_ctf_field_type_common_structure_borrow_field_by_index(
+                               ft, &name, &member_type, i);
+                       BT_ASSERT(ret == 0);
+                       ret = bt_ctf_field_type_common_validate_single_clock_class(
+                               member_type, expected_clock_class);
+                       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_CTF_FIELD_TYPE_ID_VARIANT:
+       {
+               uint64_t i;
+               int64_t count = bt_ctf_field_type_common_variant_get_field_count(
+                       ft);
+
+               for (i = 0; i < count; i++) {
+                       const char *name;
+                       struct bt_ctf_field_type_common *member_type;
+
+                       ret = bt_ctf_field_type_common_variant_borrow_field_by_index(
+                               ft, &name, &member_type, i);
+                       BT_ASSERT(ret == 0);
+                       ret = bt_ctf_field_type_common_validate_single_clock_class(
+                               member_type, expected_clock_class);
+                       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;
+}
+
 static
 struct bt_ctf_field_type *bt_ctf_field_type_integer_copy(
                struct bt_ctf_field_type *ft);
@@ -76,79 +4037,79 @@ 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)
+static struct bt_ctf_field_type_common_methods bt_ctf_field_type_integer_methods = {
+       .freeze = bt_ctf_field_type_common_generic_freeze,
+       .validate = bt_ctf_field_type_common_integer_validate,
+       .set_byte_order = bt_ctf_field_type_common_integer_set_byte_order,
+       .copy = (bt_ctf_field_type_common_method_copy)
                bt_ctf_field_type_integer_copy,
-       .compare = bt_field_type_common_integer_compare,
+       .compare = bt_ctf_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,
+static struct bt_ctf_field_type_common_methods bt_ctf_field_type_floating_point_methods = {
+       .freeze = bt_ctf_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)
+       .set_byte_order = bt_ctf_field_type_common_floating_point_set_byte_order,
+       .copy = (bt_ctf_field_type_common_method_copy)
                bt_ctf_field_type_floating_point_copy,
-       .compare = bt_field_type_common_floating_point_compare,
+       .compare = bt_ctf_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)
+static struct bt_ctf_field_type_common_methods bt_ctf_field_type_enumeration_methods = {
+       .freeze = bt_ctf_field_type_common_enumeration_freeze_recursive,
+       .validate = bt_ctf_field_type_common_enumeration_validate_recursive,
+       .set_byte_order = bt_ctf_field_type_common_enumeration_set_byte_order_recursive,
+       .copy = (bt_ctf_field_type_common_method_copy)
                bt_ctf_field_type_enumeration_copy_recursive,
-       .compare = bt_field_type_common_enumeration_compare_recursive,
+       .compare = bt_ctf_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,
+static struct bt_ctf_field_type_common_methods bt_ctf_field_type_string_methods = {
+       .freeze = bt_ctf_field_type_common_generic_freeze,
        .validate = NULL,
        .set_byte_order = NULL,
-       .copy = (bt_field_type_common_method_copy)
+       .copy = (bt_ctf_field_type_common_method_copy)
                bt_ctf_field_type_string_copy,
-       .compare = bt_field_type_common_string_compare,
+       .compare = bt_ctf_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)
+static struct bt_ctf_field_type_common_methods bt_ctf_field_type_array_methods = {
+       .freeze = bt_ctf_field_type_common_array_freeze_recursive,
+       .validate = bt_ctf_field_type_common_array_validate_recursive,
+       .set_byte_order = bt_ctf_field_type_common_array_set_byte_order_recursive,
+       .copy = (bt_ctf_field_type_common_method_copy)
                bt_ctf_field_type_array_copy_recursive,
-       .compare = bt_field_type_common_array_compare_recursive,
+       .compare = bt_ctf_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)
+static struct bt_ctf_field_type_common_methods bt_ctf_field_type_sequence_methods = {
+       .freeze = bt_ctf_field_type_common_sequence_freeze_recursive,
+       .validate = bt_ctf_field_type_common_sequence_validate_recursive,
+       .set_byte_order = bt_ctf_field_type_common_sequence_set_byte_order_recursive,
+       .copy = (bt_ctf_field_type_common_method_copy)
                bt_ctf_field_type_sequence_copy_recursive,
-       .compare = bt_field_type_common_sequence_compare_recursive,
+       .compare = bt_ctf_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)
+static struct bt_ctf_field_type_common_methods bt_ctf_field_type_structure_methods = {
+       .freeze = bt_ctf_field_type_common_structure_freeze_recursive,
+       .validate = bt_ctf_field_type_common_structure_validate_recursive,
+       .set_byte_order = bt_ctf_field_type_common_structure_set_byte_order_recursive,
+       .copy = (bt_ctf_field_type_common_method_copy)
                bt_ctf_field_type_structure_copy_recursive,
-       .compare = bt_field_type_common_structure_compare_recursive,
+       .compare = bt_ctf_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)
+static struct bt_ctf_field_type_common_methods bt_ctf_field_type_variant_methods = {
+       .freeze = bt_ctf_field_type_common_variant_freeze_recursive,
+       .validate = bt_ctf_field_type_common_variant_validate_recursive,
+       .set_byte_order = bt_ctf_field_type_common_variant_set_byte_order_recursive,
+       .copy = (bt_ctf_field_type_common_method_copy)
                bt_ctf_field_type_variant_copy_recursive,
-       .compare = bt_field_type_common_variant_compare_recursive,
+       .compare = bt_ctf_field_type_common_variant_compare_recursive,
 };
 
-typedef int (*bt_ctf_field_type_serialize_func)(struct bt_field_type_common *,
+typedef int (*bt_ctf_field_type_serialize_func)(struct bt_ctf_field_type_common *,
                struct metadata_context *);
 
 BT_HIDDEN
@@ -156,14 +4117,14 @@ 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;
+       struct bt_ctf_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);
+       ret = bt_ctf_field_type_common_validate((void *) type);
        if (ret) {
                BT_LOGW("Cannot serialize field type's metadata: field type is invalid: "
                        "addr=%p", type);
@@ -178,18 +4139,18 @@ end:
 }
 
 static
-const char *get_encoding_string(enum bt_string_encoding encoding)
+const char *get_encoding_string(enum bt_ctf_string_encoding encoding)
 {
        const char *encoding_string;
 
        switch (encoding) {
-       case BT_STRING_ENCODING_NONE:
+       case BT_CTF_STRING_ENCODING_NONE:
                encoding_string = "none";
                break;
-       case BT_STRING_ENCODING_ASCII:
+       case BT_CTF_STRING_ENCODING_ASCII:
                encoding_string = "ASCII";
                break;
-       case BT_STRING_ENCODING_UTF8:
+       case BT_CTF_STRING_ENCODING_UTF8:
                encoding_string = "UTF8";
                break;
        default:
@@ -201,22 +4162,22 @@ const char *get_encoding_string(enum bt_string_encoding encoding)
 }
 
 static
-const char *get_integer_base_string(enum bt_integer_base base)
+const char *get_integer_base_string(enum bt_ctf_integer_base base)
 {
        const char *base_string;
 
        switch (base) {
-       case BT_INTEGER_BASE_DECIMAL:
-       case BT_INTEGER_BASE_UNSPECIFIED:
+       case BT_CTF_INTEGER_BASE_DECIMAL:
+       case BT_CTF_INTEGER_BASE_UNSPECIFIED:
                base_string = "decimal";
                break;
-       case BT_INTEGER_BASE_HEXADECIMAL:
+       case BT_CTF_INTEGER_BASE_HEXADECIMAL:
                base_string = "hexadecimal";
                break;
-       case BT_INTEGER_BASE_OCTAL:
+       case BT_CTF_INTEGER_BASE_OCTAL:
                base_string = "octal";
                break;
-       case BT_INTEGER_BASE_BINARY:
+       case BT_CTF_INTEGER_BASE_BINARY:
                base_string = "binary";
                break;
        default:
@@ -233,7 +4194,7 @@ void append_field_name(struct metadata_context *context,
 {
        g_string_append_c(context->string, ' ');
 
-       if (!bt_identifier_is_valid(name) || *name == '_') {
+       if (!bt_ctf_identifier_is_valid(name) || *name == '_') {
                g_string_append_c(context->string, '_');
        }
 
@@ -241,10 +4202,10 @@ void append_field_name(struct metadata_context *context,
 }
 
 static
-int bt_ctf_field_type_integer_serialize(struct bt_field_type_common *type,
+int bt_ctf_field_type_integer_serialize(struct bt_ctf_field_type_common *type,
                struct metadata_context *context)
 {
-       struct bt_field_type_common_integer *integer = BT_FROM_COMMON(type);
+       struct bt_ctf_field_type_common_integer *integer = BT_CTF_FROM_COMMON(type);
        int ret = 0;
 
        BT_LOGD("Serializing CTF writer integer field type's metadata: "
@@ -255,9 +4216,9 @@ int bt_ctf_field_type_integer_serialize(struct bt_field_type_common *type,
                (integer->is_signed ? "true" : "false"),
                get_encoding_string(integer->encoding),
                get_integer_base_string(integer->base),
-               get_byte_order_string(integer->user_byte_order));
+               bt_ctf_get_byte_order_string(integer->user_byte_order));
        if (integer->mapped_clock_class) {
-               const char *clock_name = bt_clock_class_get_name(
+               const char *clock_name = bt_ctf_clock_class_get_name(
                        integer->mapped_clock_class);
 
                BT_ASSERT(clock_name);
@@ -271,22 +4232,22 @@ int bt_ctf_field_type_integer_serialize(struct bt_field_type_common *type,
 
 static
 int bt_ctf_field_type_enumeration_serialize_recursive(
-               struct bt_field_type_common *type,
+               struct bt_ctf_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;
+       struct bt_ctf_field_type_common_enumeration *enumeration =
+               BT_CTF_FROM_COMMON(type);
+       struct bt_ctf_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_borrow_container_field_type(type);
+               bt_ctf_field_type_common_enumeration_borrow_container_field_type(type);
        BT_ASSERT(container_type);
-       container_signed = bt_field_type_common_integer_is_signed(
+       container_signed = bt_ctf_field_type_common_integer_is_signed(
                container_type);
        BT_ASSERT(container_signed >= 0);
        g_string_append(context->string, "enum : ");
@@ -301,13 +4262,13 @@ int bt_ctf_field_type_enumeration_serialize_recursive(
 
        g_string_append(context->string, " { ");
        for (entry = 0; entry < enumeration->entries->len; entry++) {
-               struct enumeration_mapping *mapping =
+               struct bt_ctf_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] == '_') {
+               if (!bt_ctf_identifier_is_valid(label) || label[0] == '_') {
                        g_string_append(context->string, "_");
                }
 
@@ -355,11 +4316,11 @@ end:
 }
 
 static
-int bt_ctf_field_type_floating_point_serialize(struct bt_field_type_common *type,
+int bt_ctf_field_type_floating_point_serialize(struct bt_ctf_field_type_common *type,
                struct metadata_context *context)
 {
-       struct bt_field_type_common_floating_point *floating_point =
-               BT_FROM_COMMON(type);
+       struct bt_ctf_field_type_common_floating_point *floating_point =
+               BT_CTF_FROM_COMMON(type);
 
        BT_LOGD("Serializing CTF writer floating point number field type's metadata: "
                "ft-addr=%p, metadata-context-addr=%p", type, context);
@@ -367,20 +4328,20 @@ int bt_ctf_field_type_floating_point_serialize(struct bt_field_type_common *type
                "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),
+               bt_ctf_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 bt_ctf_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);
+       struct bt_ctf_field_type_common_structure *structure = BT_CTF_FROM_COMMON(type);
        GString *structure_field_name = context->field_name;
 
        BT_LOGD("Serializing CTF writer structure field type's metadata: "
@@ -391,8 +4352,8 @@ int bt_ctf_field_type_structure_serialize_recursive(
        g_string_append(context->string, "struct {\n");
 
        for (i = 0; i < structure->fields->len; i++) {
-               struct bt_field_type_common_structure_field *field =
-                       BT_FIELD_TYPE_COMMON_STRUCTURE_FIELD_AT_INDEX(
+               struct bt_ctf_field_type_common_structure_field *field =
+                       BT_CTF_FIELD_TYPE_COMMON_STRUCTURE_FIELD_AT_INDEX(
                                structure, i);
 
                BT_LOGD("Serializing CTF writer structure field type's field metadata: "
@@ -442,13 +4403,13 @@ end:
 
 static
 int bt_ctf_field_type_variant_serialize_recursive(
-               struct bt_field_type_common *type,
+               struct bt_ctf_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);
+       struct bt_ctf_field_type_common_variant *variant = BT_CTF_FROM_COMMON(type);
        GString *variant_field_name = context->field_name;
 
        BT_LOGD("Serializing CTF writer variant field type's metadata: "
@@ -464,8 +4425,8 @@ int bt_ctf_field_type_variant_serialize_recursive(
 
        context->current_indentation_level++;
        for (i = 0; i < variant->choices->len; i++) {
-               struct bt_field_type_common_variant_choice *field =
-                       BT_FIELD_TYPE_COMMON_VARIANT_CHOICE_AT_INDEX(
+               struct bt_ctf_field_type_common_variant_choice *field =
+                       BT_CTF_FIELD_TYPE_COMMON_VARIANT_CHOICE_AT_INDEX(
                                variant, i);
 
                BT_LOGD("Serializing CTF writer variant field type's field metadata: "
@@ -518,11 +4479,11 @@ end:
 
 static
 int bt_ctf_field_type_array_serialize_recursive(
-               struct bt_field_type_common *type,
+               struct bt_ctf_field_type_common *type,
                struct metadata_context *context)
 {
        int ret = 0;
-       struct bt_field_type_common_array *array = BT_FROM_COMMON(type);
+       struct bt_ctf_field_type_common_array *array = BT_CTF_FROM_COMMON(type);
 
        BT_LOGD("Serializing CTF writer array field type's metadata: "
                "ft-addr=%p, metadata-context-addr=%p", type, context);
@@ -551,11 +4512,11 @@ end:
 
 static
 int bt_ctf_field_type_sequence_serialize_recursive(
-               struct bt_field_type_common *type,
+               struct bt_ctf_field_type_common *type,
                struct metadata_context *context)
 {
        int ret = 0;
-       struct bt_field_type_common_sequence *sequence = BT_FROM_COMMON(type);
+       struct bt_ctf_field_type_common_sequence *sequence = BT_CTF_FROM_COMMON(type);
 
        BT_LOGD("Serializing CTF writer sequence field type's metadata: "
                "ft-addr=%p, metadata-context-addr=%p", type, context);
@@ -581,10 +4542,10 @@ end:
 }
 
 static
-int bt_ctf_field_type_string_serialize(struct bt_field_type_common *type,
+int bt_ctf_field_type_string_serialize(struct bt_ctf_field_type_common *type,
                struct metadata_context *context)
 {
-       struct bt_field_type_common_string *string = BT_FROM_COMMON(type);
+       struct bt_ctf_field_type_common_string *string = BT_CTF_FROM_COMMON(type);
 
        BT_LOGD("Serializing CTF writer string field type's metadata: "
                "ft-addr=%p, metadata-context-addr=%p", type, context);
@@ -596,7 +4557,7 @@ int bt_ctf_field_type_string_serialize(struct bt_field_type_common *type,
 
 struct bt_ctf_field_type *bt_ctf_field_type_integer_create(unsigned int size)
 {
-       struct bt_field_type_common_integer *integer = NULL;
+       struct bt_ctf_field_type_common_integer *integer = NULL;
 
        BT_LOGD("Creating CTF writer integer field type object: size=%u", size);
 
@@ -606,14 +4567,14 @@ struct bt_ctf_field_type *bt_ctf_field_type_integer_create(unsigned int size)
                goto error;
        }
 
-       integer = g_new0(struct bt_field_type_common_integer, 1);
+       integer = g_new0(struct bt_ctf_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_common_integer_initialize(BT_CTF_TO_COMMON(integer),
+               size, bt_ctf_field_type_common_integer_destroy,
                &bt_ctf_field_type_integer_methods);
        integer->common.spec.writer.serialize_func =
                bt_ctf_field_type_integer_serialize;
@@ -630,57 +4591,57 @@ end:
 
 int bt_ctf_field_type_integer_get_size(struct bt_ctf_field_type *ft)
 {
-       return bt_field_type_common_integer_get_size((void *) ft);
+       return bt_ctf_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);
+       return bt_ctf_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,
+       return bt_ctf_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);
+       return bt_ctf_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);
+       return (int) bt_ctf_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,
+       return bt_ctf_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);
+       return (int) bt_ctf_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,
+       return bt_ctf_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_get(bt_field_type_common_integer_borrow_mapped_clock_class(
+       return bt_get(bt_ctf_field_type_common_integer_borrow_mapped_clock_class(
                (void *) ft));
 }
 
@@ -688,8 +4649,8 @@ 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));
+       return bt_ctf_field_type_common_integer_set_mapped_clock_class((void *) ft,
+               clock_class);
 }
 
 int bt_ctf_field_type_enumeration_signed_get_mapping_by_index(
@@ -697,7 +4658,7 @@ int bt_ctf_field_type_enumeration_signed_get_mapping_by_index(
                const char **mapping_name, int64_t *range_begin,
                int64_t *range_end)
 {
-       return bt_field_type_common_enumeration_signed_get_mapping_by_index(
+       return bt_ctf_field_type_common_enumeration_signed_get_mapping_by_index(
                (void *) ft, index, mapping_name, range_begin, range_end);
 }
 
@@ -706,15 +4667,15 @@ int bt_ctf_field_type_enumeration_unsigned_get_mapping_by_index(
                const char **mapping_name, uint64_t *range_begin,
                uint64_t *range_end)
 {
-       return bt_field_type_common_enumeration_unsigned_get_mapping_by_index(
+       return bt_ctf_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;
+       struct bt_ctf_field_type_common_enumeration *enumeration = NULL;
+       struct bt_ctf_field_type_common *int_ft = (void *) container_ft;
 
        BT_LOGD("Creating CTF writer enumeration field type object: int-ft-addr=%p",
                container_ft);
@@ -724,21 +4685,21 @@ struct bt_ctf_field_type *bt_ctf_field_type_enumeration_create(
                goto error;
        }
 
-       if (int_ft->id != BT_FIELD_TYPE_ID_INTEGER) {
+       if (int_ft->id != BT_CTF_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));
+                       container_ft, bt_ctf_field_type_id_string(int_ft->id));
                goto error;
        }
 
-       enumeration = g_new0(struct bt_field_type_common_enumeration, 1);
+       enumeration = g_new0(struct bt_ctf_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_common_enumeration_initialize(BT_CTF_TO_COMMON(enumeration),
+               int_ft, bt_ctf_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;
@@ -759,7 +4720,7 @@ struct bt_ctf_field_type *bt_ctf_field_type_enumeration_get_container_field_type
                struct bt_ctf_field_type *ft)
 {
        return bt_get(
-               bt_field_type_common_enumeration_borrow_container_field_type(
+               bt_ctf_field_type_common_enumeration_borrow_container_field_type(
                        (void *) ft));
 }
 
@@ -767,7 +4728,7 @@ 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(
+       return bt_ctf_field_type_common_enumeration_signed_add_mapping(
                (void *) ft, string, range_start, range_end);
 }
 
@@ -775,20 +4736,20 @@ 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(
+       return bt_ctf_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);
+       return bt_ctf_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);
+       struct bt_ctf_field_type_common_floating_point *floating_point =
+               g_new0(struct bt_ctf_field_type_common_floating_point, 1);
 
        BT_LOGD_STR("Creating CTF writer floating point number field type object.");
 
@@ -797,9 +4758,9 @@ struct bt_ctf_field_type *bt_ctf_field_type_floating_point_create(void)
                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_common_floating_point_initialize(
+               BT_CTF_TO_COMMON(floating_point),
+               bt_ctf_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;
@@ -814,35 +4775,35 @@ end:
 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(
+       return bt_ctf_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(
+       return bt_ctf_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(
+       return bt_ctf_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(
+       return bt_ctf_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);
+       struct bt_ctf_field_type_common_structure *structure =
+               g_new0(struct bt_ctf_field_type_common_structure, 1);
 
        BT_LOGD_STR("Creating CTF writer structure field type object.");
 
@@ -851,8 +4812,8 @@ struct bt_ctf_field_type *bt_ctf_field_type_structure_create(void)
                goto error;
        }
 
-       bt_field_type_common_structure_initialize(BT_TO_COMMON(structure),
-               bt_field_type_common_structure_destroy_recursive,
+       bt_ctf_field_type_common_structure_initialize(BT_CTF_TO_COMMON(structure),
+               bt_ctf_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;
@@ -871,13 +4832,13 @@ 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,
+       return bt_ctf_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);
+       return bt_ctf_field_type_common_structure_get_field_count((void *) ft);
 }
 
 int bt_ctf_field_type_structure_get_field_by_index(
@@ -885,7 +4846,7 @@ int bt_ctf_field_type_structure_get_field_by_index(
                const char **field_name,
                struct bt_ctf_field_type **field_type, uint64_t index)
 {
-       int ret = bt_field_type_common_structure_borrow_field_by_index(
+       int ret = bt_ctf_field_type_common_structure_borrow_field_by_index(
                (void *) ft, field_name, (void *) field_type, index);
 
        if (ret == 0 && field_type) {
@@ -898,35 +4859,35 @@ int bt_ctf_field_type_structure_get_field_by_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 bt_get(bt_field_type_common_structure_borrow_field_type_by_name(
+       return bt_get(bt_ctf_field_type_common_structure_borrow_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;
+       struct bt_ctf_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)) {
+       if (tag_name && !bt_ctf_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);
+       var_ft = g_new0(struct bt_ctf_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),
+       bt_ctf_field_type_common_variant_initialize(BT_CTF_TO_COMMON(var_ft),
                (void *) tag_ft, tag_name,
-               bt_field_type_common_variant_destroy_recursive,
+               bt_ctf_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;
@@ -945,26 +4906,26 @@ end:
 struct bt_ctf_field_type *bt_ctf_field_type_variant_get_tag_field_type(
                struct bt_ctf_field_type *ft)
 {
-       return bt_get(bt_field_type_common_variant_borrow_tag_field_type(
+       return bt_get(bt_ctf_field_type_common_variant_borrow_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);
+       return bt_ctf_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);
+       return bt_ctf_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,
+       return bt_ctf_field_type_common_variant_add_field((void *) ft,
                (void *) field_type, field_name);
 }
 
@@ -972,7 +4933,7 @@ 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 bt_get(bt_field_type_common_variant_borrow_field_type_by_name(
+       return bt_get(bt_ctf_field_type_common_variant_borrow_field_type_by_name(
                (void *) ft, field_name));
 }
 
@@ -983,17 +4944,17 @@ struct bt_ctf_field_type *bt_ctf_field_type_variant_get_field_type_from_tag(
        int ret;
        int64_t choice_index;
        struct bt_ctf_field *container;
-       struct bt_field_type_common_variant *var_ft = (void *) ft;
+       struct bt_ctf_field_type_common_variant *var_ft = (void *) ft;
        struct bt_ctf_field_type *ret_ft = NULL;
 
        BT_ASSERT_PRE_NON_NULL(ft, "Field type");
-       BT_ASSERT_PRE_FT_COMMON_HAS_ID(ft, BT_FIELD_TYPE_ID_VARIANT,
+       BT_ASSERT_PRE_CTF_FT_COMMON_HAS_ID(ft, BT_CTF_FIELD_TYPE_ID_VARIANT,
                "Field type");
        BT_ASSERT_PRE_NON_NULL(tag_field, "Tag field");
-       BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(
-               (struct bt_field_common *) tag_field,
+       BT_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(
+               (struct bt_ctf_field_common *) tag_field,
                BT_CTF_FIELD_TYPE_ID_ENUM, "Tag field");
-       BT_ASSERT_PRE_FIELD_COMMON_IS_SET((struct bt_field_common *) tag_field,
+       BT_ASSERT_PRE_CTF_FIELD_COMMON_IS_SET((struct bt_ctf_field_common *) tag_field,
                "Tag field");
 
        container = bt_ctf_field_enumeration_borrow_container(tag_field);
@@ -1005,7 +4966,7 @@ struct bt_ctf_field_type *bt_ctf_field_type_variant_get_field_type_from_tag(
                ret = bt_ctf_field_integer_signed_get_value(container,
                        &val);
                BT_ASSERT(ret == 0);
-               choice_index = bt_field_type_common_variant_find_choice_index(
+               choice_index = bt_ctf_field_type_common_variant_find_choice_index(
                        (void *) ft, (uint64_t) val, true);
        } else {
                uint64_t val;
@@ -1013,13 +4974,13 @@ struct bt_ctf_field_type *bt_ctf_field_type_variant_get_field_type_from_tag(
                ret = bt_ctf_field_integer_unsigned_get_value(container,
                        &val);
                BT_ASSERT(ret == 0);
-               choice_index = bt_field_type_common_variant_find_choice_index(
+               choice_index = bt_ctf_field_type_common_variant_find_choice_index(
                        (void *) ft, val, false);
        }
 
        if (choice_index < 0) {
                BT_LIB_LOGW("Cannot find variant field type's field: "
-                       "%![var-ft-]+wF, %![tag-field-]+wf", ft, tag_field);
+                       "var-ft-addr=%p, tag-field-addr=%p", ft, tag_field);
                goto end;
        }
 
@@ -1033,14 +4994,14 @@ end:
 
 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);
+       return bt_ctf_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)
 {
-       int ret = bt_field_type_common_variant_borrow_field_by_index(
+       int ret = bt_ctf_field_type_common_variant_borrow_field_by_index(
                (void *) ft, field_name, (void *) field_type, index);
 
        if (ret == 0 && field_type) {
@@ -1053,7 +5014,7 @@ int bt_ctf_field_type_variant_get_field_by_index(struct bt_ctf_field_type *ft,
 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;
+       struct bt_ctf_field_type_common_array *array = NULL;
 
        BT_LOGD("Creating CTF writer array field type object: element-ft-addr=%p, "
                "length=%u", element_ft, length);
@@ -1068,15 +5029,15 @@ struct bt_ctf_field_type *bt_ctf_field_type_array_create(
                goto error;
        }
 
-       array = g_new0(struct bt_field_type_common_array, 1);
+       array = g_new0(struct bt_ctf_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),
+       bt_ctf_field_type_common_array_initialize(BT_CTF_TO_COMMON(array),
                (void *) element_ft, length,
-               bt_field_type_common_array_destroy_recursive,
+               bt_ctf_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;
@@ -1095,20 +5056,20 @@ end:
 struct bt_ctf_field_type *bt_ctf_field_type_array_get_element_field_type(
                struct bt_ctf_field_type *ft)
 {
-       return bt_get(bt_field_type_common_array_borrow_element_field_type(
+       return bt_get(bt_ctf_field_type_common_array_borrow_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);
+       return bt_ctf_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;
+       struct bt_ctf_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);
@@ -1118,21 +5079,21 @@ struct bt_ctf_field_type *bt_ctf_field_type_sequence_create(
                goto error;
        }
 
-       if (!bt_identifier_is_valid(length_field_name)) {
+       if (!bt_ctf_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);
+       sequence = g_new0(struct bt_ctf_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),
+       bt_ctf_field_type_common_sequence_initialize(BT_CTF_TO_COMMON(sequence),
                (void *) element_ft, length_field_name,
-               bt_field_type_common_sequence_destroy_recursive,
+               bt_ctf_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;
@@ -1151,20 +5112,20 @@ end:
 struct bt_ctf_field_type *bt_ctf_field_type_sequence_get_element_field_type(
                struct bt_ctf_field_type *ft)
 {
-       return bt_get(bt_field_type_common_sequence_borrow_element_field_type(
+       return bt_get(bt_ctf_field_type_common_sequence_borrow_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);
+       return bt_ctf_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);
+       struct bt_ctf_field_type_common_string *string =
+               g_new0(struct bt_ctf_field_type_common_string, 1);
 
        BT_LOGD_STR("Creating CTF writer string field type object.");
 
@@ -1173,8 +5134,8 @@ struct bt_ctf_field_type *bt_ctf_field_type_string_create(void)
                return NULL;
        }
 
-       bt_field_type_common_string_initialize(BT_TO_COMMON(string),
-               bt_field_type_common_string_destroy,
+       bt_ctf_field_type_common_string_initialize(BT_CTF_TO_COMMON(string),
+               bt_ctf_field_type_common_string_destroy,
                &bt_ctf_field_type_string_methods);
        string->common.spec.writer.serialize_func =
                bt_ctf_field_type_string_serialize;
@@ -1185,58 +5146,58 @@ struct bt_ctf_field_type *bt_ctf_field_type_string_create(void)
 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);
+       return (int) bt_ctf_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,
+       return bt_ctf_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);
+       return bt_ctf_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);
+       return bt_ctf_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);
+       return (int) bt_ctf_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,
+       return bt_ctf_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);
+       return (int) bt_ctf_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);
+       return (void *) bt_ctf_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;
+       struct bt_ctf_field_type_common_integer *int_ft = (void *) ft;
+       struct bt_ctf_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);
@@ -1263,16 +5224,16 @@ 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;
+       struct bt_ctf_field_type_common_enumeration *enum_ft = (void *) ft;
+       struct bt_ctf_field_type_common_enumeration *copy_ft = NULL;
+       struct bt_ctf_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)));
+       container_copy_ft = BT_CTF_FROM_COMMON(bt_ctf_field_type_common_copy(
+               BT_CTF_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;
@@ -1287,10 +5248,10 @@ struct bt_ctf_field_type *bt_ctf_field_type_enumeration_copy_recursive(
 
        /* Copy all enumaration entries */
        for (i = 0; i < enum_ft->entries->len; i++) {
-               struct enumeration_mapping *mapping = g_ptr_array_index(
+               struct bt_ctf_enumeration_mapping *mapping = g_ptr_array_index(
                        enum_ft->entries, i);
-               struct enumeration_mapping *copy_mapping = g_new0(
-                       struct enumeration_mapping, 1);
+               struct bt_ctf_enumeration_mapping *copy_mapping = g_new0(
+                       struct bt_ctf_enumeration_mapping, 1);
 
                if (!copy_mapping) {
                        BT_LOGE_STR("Failed to allocate one enumeration mapping.");
@@ -1318,8 +5279,8 @@ 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;
+       struct bt_ctf_field_type_common_floating_point *flt_ft = BT_CTF_FROM_COMMON(ft);
+       struct bt_ctf_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();
@@ -1345,8 +5306,8 @@ struct bt_ctf_field_type *bt_ctf_field_type_structure_copy_recursive(
        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;
+       struct bt_ctf_field_type_common_structure *struct_ft = (void *) ft;
+       struct bt_ctf_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();
@@ -1365,12 +5326,12 @@ struct bt_ctf_field_type *bt_ctf_field_type_structure_copy_recursive(
        g_array_set_size(copy_ft->fields, struct_ft->fields->len);
 
        for (i = 0; i < struct_ft->fields->len; i++) {
-               struct bt_field_type_common_structure_field *entry, *copy_entry;
-               struct bt_field_type_common *field_ft_copy;
+               struct bt_ctf_field_type_common_structure_field *entry, *copy_entry;
+               struct bt_ctf_field_type_common *field_ft_copy;
 
-               entry = BT_FIELD_TYPE_COMMON_STRUCTURE_FIELD_AT_INDEX(
+               entry = BT_CTF_FIELD_TYPE_COMMON_STRUCTURE_FIELD_AT_INDEX(
                        struct_ft, i);
-               copy_entry = BT_FIELD_TYPE_COMMON_STRUCTURE_FIELD_AT_INDEX(
+               copy_entry = BT_CTF_FIELD_TYPE_COMMON_STRUCTURE_FIELD_AT_INDEX(
                        copy_ft, i);
                BT_LOGD("Copying CTF writer structure field type's field: "
                        "index=%" PRId64 ", "
@@ -1409,15 +5370,15 @@ struct bt_ctf_field_type *bt_ctf_field_type_variant_copy_recursive(
        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;
+       struct bt_ctf_field_type_common *tag_ft_copy = NULL;
+       struct bt_ctf_field_type_common_variant *var_ft = (void *) ft;
+       struct bt_ctf_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));
+               tag_ft_copy = bt_ctf_field_type_common_copy(
+                       BT_CTF_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;
@@ -1442,12 +5403,12 @@ struct bt_ctf_field_type *bt_ctf_field_type_variant_copy_recursive(
        g_array_set_size(copy_ft->choices, var_ft->choices->len);
 
        for (i = 0; i < var_ft->choices->len; i++) {
-               struct bt_field_type_common_variant_choice *entry, *copy_entry;
-               struct bt_field_type_common *field_ft_copy;
+               struct bt_ctf_field_type_common_variant_choice *entry, *copy_entry;
+               struct bt_ctf_field_type_common *field_ft_copy;
                uint64_t range_i;
 
-               entry = BT_FIELD_TYPE_COMMON_VARIANT_CHOICE_AT_INDEX(var_ft, i);
-               copy_entry = BT_FIELD_TYPE_COMMON_VARIANT_CHOICE_AT_INDEX(
+               entry = BT_CTF_FIELD_TYPE_COMMON_VARIANT_CHOICE_AT_INDEX(var_ft, i);
+               copy_entry = BT_CTF_FIELD_TYPE_COMMON_VARIANT_CHOICE_AT_INDEX(
                        copy_ft, i);
                BT_LOGD("Copying CTF writer variant field type's field: "
                        "index=%" PRId64 ", "
@@ -1470,7 +5431,7 @@ struct bt_ctf_field_type *bt_ctf_field_type_variant_copy_recursive(
 
                /* Copy ranges */
                copy_entry->ranges = g_array_new(FALSE, TRUE,
-                       sizeof(struct bt_field_type_common_variant_choice_range));
+                       sizeof(struct bt_ctf_field_type_common_variant_choice_range));
                BT_ASSERT(copy_entry->ranges);
                g_array_set_size(copy_entry->ranges, entry->ranges->len);
 
@@ -1481,7 +5442,7 @@ struct bt_ctf_field_type *bt_ctf_field_type_variant_copy_recursive(
 
        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(
+               copy_ft->tag_field_path = bt_ctf_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.");
@@ -1507,13 +5468,13 @@ 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;
+       struct bt_ctf_field_type_common *container_ft_copy = NULL;
+       struct bt_ctf_field_type_common_array *array_ft = (void *) ft;
+       struct bt_ctf_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);
+       container_ft_copy = bt_ctf_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;
@@ -1538,13 +5499,13 @@ 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;
+       struct bt_ctf_field_type_common *container_ft_copy = NULL;
+       struct bt_ctf_field_type_common_sequence *seq_ft = (void *) ft;
+       struct bt_ctf_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);
+       container_ft_copy = bt_ctf_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;
@@ -1561,7 +5522,7 @@ struct bt_ctf_field_type *bt_ctf_field_type_sequence_copy_recursive(
 
        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(
+               copy_ft->length_field_path = bt_ctf_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.");
@@ -1584,8 +5545,8 @@ error:
 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;
+       struct bt_ctf_field_type_common_string *string_ft = (void *) ft;
+       struct bt_ctf_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();
diff --git a/lib/ctf-writer/field-wrapper.c b/lib/ctf-writer/field-wrapper.c
new file mode 100644 (file)
index 0000000..254f744
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright 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-FIELD-WRAPPER"
+#include <babeltrace/lib-logging-internal.h>
+
+#include <babeltrace/ctf-writer/field-wrapper-internal.h>
+#include <babeltrace/ctf-writer/fields-internal.h>
+#include <babeltrace/object-pool-internal.h>
+#include <babeltrace/object-internal.h>
+#include <glib.h>
+
+BT_HIDDEN
+struct bt_ctf_field_wrapper *bt_ctf_field_wrapper_new(void *data)
+{
+       struct bt_ctf_field_wrapper *field_wrapper =
+               g_new0(struct bt_ctf_field_wrapper, 1);
+
+       BT_LOGD_STR("Creating empty field wrapper object.");
+
+       if (!field_wrapper) {
+               BT_LOGE("Failed to allocate one field wrapper.");
+               goto end;
+       }
+
+       bt_object_init_unique(&field_wrapper->base);
+       BT_LOGD("Created empty field wrapper object: addr=%p",
+               field_wrapper);
+
+end:
+       return field_wrapper;
+}
+
+BT_HIDDEN
+void bt_ctf_field_wrapper_destroy(struct bt_ctf_field_wrapper *field_wrapper)
+{
+       BT_LOGD("Destroying field wrapper: addr=%p", field_wrapper);
+       BT_ASSERT(!field_wrapper->field);
+       BT_LOGD_STR("Putting stream class.");
+       g_free(field_wrapper);
+}
+
+BT_HIDDEN
+struct bt_ctf_field_wrapper *bt_ctf_field_wrapper_create(
+               struct bt_object_pool *pool, struct bt_ctf_field_type *ft)
+{
+       struct bt_ctf_field_wrapper *field_wrapper = NULL;
+
+       BT_ASSERT(pool);
+       BT_ASSERT(ft);
+       field_wrapper = bt_object_pool_create_object(pool);
+       if (!field_wrapper) {
+               BT_LIB_LOGE("Cannot allocate one field wrapper from field wrapper pool: "
+                       "%![pool-]+o", pool);
+               goto error;
+       }
+
+       BT_ASSERT(field_wrapper->field);
+       goto end;
+
+error:
+       if (field_wrapper) {
+               bt_ctf_field_wrapper_destroy(field_wrapper);
+               field_wrapper = NULL;
+       }
+
+end:
+       return field_wrapper;
+}
index 1d075078a43b672135e7ea39e4264f23bcb77add..c7cadabf1b0b77f6d40a914d660a55e132089582 100644 (file)
 #define BT_LOG_TAG "CTF-WRITER-FIELDS"
 #include <babeltrace/lib-logging-internal.h>
 
+#include <babeltrace/assert-pre-internal.h>
+#include <babeltrace/align-internal.h>
+#include <babeltrace/assert-internal.h>
 #include <babeltrace/compat/fcntl-internal.h>
-#include <babeltrace/ctf-writer/fields-internal.h>
+#include <babeltrace/compiler-internal.h>
 #include <babeltrace/ctf-writer/field-types-internal.h>
+#include <babeltrace/ctf-writer/fields-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/endian-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 <inttypes.h>
 #include <stdlib.h>
 
-static struct bt_field_common_methods bt_ctf_field_integer_methods = {
-       .set_is_frozen = bt_field_common_generic_set_is_frozen,
-       .validate = bt_field_common_generic_validate,
+#define BT_ASSERT_PRE_CTF_FIELD_IS_INT_OR_ENUM(_field, _name)          \
+       BT_ASSERT_PRE((_field)->type->id == BT_CTF_FIELD_TYPE_ID_INTEGER || \
+               (_field)->type->id == BT_CTF_FIELD_TYPE_ID_ENUM,        \
+               _name " is not an integer or an enumeration field: "    \
+               "field-addr=%p", (_field))
+
+BT_HIDDEN
+struct bt_ctf_field_common *bt_ctf_field_common_copy(struct bt_ctf_field_common *field)
+{
+       struct bt_ctf_field_common *copy = NULL;
+
+       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_ctf_field_common_set(copy, field->payload_set);
+
+end:
+       return copy;
+}
+
+BT_HIDDEN
+int bt_ctf_field_common_structure_initialize(struct bt_ctf_field_common *field,
+               struct bt_ctf_field_type_common *type,
+               bool is_shared, bt_object_release_func release_func,
+               struct bt_ctf_field_common_methods *methods,
+               bt_ctf_field_common_create_func field_create_func,
+               GDestroyNotify field_release_func)
+{
+       int ret = 0;
+       struct bt_ctf_field_type_common_structure *structure_type =
+               BT_CTF_FROM_COMMON(type);
+       struct bt_ctf_field_common_structure *structure = BT_CTF_FROM_COMMON(field);
+       size_t i;
+
+       BT_LOGD("Initializing common structure field object: ft-addr=%p", type);
+       bt_ctf_field_common_initialize(field, type, is_shared,
+               release_func, methods);
+       structure->fields = g_ptr_array_new_with_free_func(field_release_func);
+       g_ptr_array_set_size(structure->fields, structure_type->fields->len);
+
+       /* Create all fields contained in the structure field. */
+       for (i = 0; i < structure_type->fields->len; i++) {
+               struct bt_ctf_field_common *field;
+               struct bt_ctf_field_type_common_structure_field *struct_field =
+                       BT_CTF_FIELD_TYPE_COMMON_STRUCTURE_FIELD_AT_INDEX(
+                               structure_type, i);
+               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(struct_field->name), i);
+                       ret = -1;
+                       goto end;
+               }
+
+               g_ptr_array_index(structure->fields, i) = field;
+       }
+
+       BT_LOGD("Initialized common structure field object: addr=%p, ft-addr=%p",
+               field, type);
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+int bt_ctf_field_common_variant_initialize(struct bt_ctf_field_common *field,
+               struct bt_ctf_field_type_common *type,
+               bool is_shared, bt_object_release_func release_func,
+               struct bt_ctf_field_common_methods *methods,
+               bt_ctf_field_common_create_func field_create_func,
+               GDestroyNotify field_release_func)
+{
+       int ret = 0;
+       struct bt_ctf_field_type_common_variant *variant_type =
+               BT_CTF_FROM_COMMON(type);
+       struct bt_ctf_field_common_variant *variant = BT_CTF_FROM_COMMON(field);
+       size_t i;
+
+       BT_LOGD("Initializing common variant field object: ft-addr=%p", type);
+       bt_ctf_field_common_initialize(field, type, is_shared,
+               release_func, methods);
+       ret = bt_ctf_field_type_common_variant_update_choices(type);
+       if (ret) {
+               BT_LOGE("Cannot update common variant field type choices: "
+                       "ret=%d", ret);
+               goto end;
+       }
+
+       variant->fields = g_ptr_array_new_with_free_func(field_release_func);
+       g_ptr_array_set_size(variant->fields, variant_type->choices->len);
+
+       /* Create all fields contained in the variant field. */
+       for (i = 0; i < variant_type->choices->len; i++) {
+               struct bt_ctf_field_common *field;
+               struct bt_ctf_field_type_common_variant_choice *var_choice =
+                       BT_CTF_FIELD_TYPE_COMMON_VARIANT_CHOICE_AT_INDEX(
+                               variant_type, i);
+
+               field = field_create_func(var_choice->type);
+               if (!field) {
+                       BT_LOGE("Failed to create variant field's member: name=\"%s\", index=%zu",
+                               g_quark_to_string(var_choice->name), i);
+                       ret = -1;
+                       goto end;
+               }
+
+               g_ptr_array_index(variant->fields, i) = field;
+       }
+
+       BT_LOGD("Initialized common variant field object: addr=%p, ft-addr=%p",
+               field, type);
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+int bt_ctf_field_common_string_initialize(struct bt_ctf_field_common *field,
+               struct bt_ctf_field_type_common *type,
+               bool is_shared, bt_object_release_func release_func,
+               struct bt_ctf_field_common_methods *methods)
+{
+       int ret = 0;
+       struct bt_ctf_field_common_string *string = BT_CTF_FROM_COMMON(field);
+
+       BT_LOGD("Initializing common string field object: ft-addr=%p", type);
+       bt_ctf_field_common_initialize(field, type, is_shared,
+               release_func, methods);
+       string->buf = g_array_sized_new(FALSE, FALSE, sizeof(char), 1);
+       if (!string->buf) {
+               ret = -1;
+               goto end;
+       }
+
+       g_array_index(string->buf, char, 0) = '\0';
+       BT_LOGD("Initialized common string field object: addr=%p, ft-addr=%p",
+               field, type);
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+int bt_ctf_field_common_array_initialize(struct bt_ctf_field_common *field,
+               struct bt_ctf_field_type_common *type,
+               bool is_shared, bt_object_release_func release_func,
+               struct bt_ctf_field_common_methods *methods,
+               bt_ctf_field_common_create_func field_create_func,
+               GDestroyNotify field_destroy_func)
+{
+       struct bt_ctf_field_type_common_array *array_type = BT_CTF_FROM_COMMON(type);
+       struct bt_ctf_field_common_array *array = BT_CTF_FROM_COMMON(field);
+       unsigned int array_length;
+       int ret = 0;
+       uint64_t i;
+
+       BT_LOGD("Initializing common array field object: ft-addr=%p", type);
+       BT_ASSERT(type);
+       bt_ctf_field_common_initialize(field, type, is_shared,
+               release_func, methods);
+       array_length = array_type->length;
+       array->elements = g_ptr_array_sized_new(array_length);
+       if (!array->elements) {
+               ret = -1;
+               goto end;
+       }
+
+       g_ptr_array_set_free_func(array->elements, field_destroy_func);
+       g_ptr_array_set_size(array->elements, array_length);
+
+       for (i = 0; i < array_length; i++) {
+               array->elements->pdata[i] = field_create_func(
+                       array_type->element_ft);
+               if (!array->elements->pdata[i]) {
+                       ret = -1;
+                       goto end;
+               }
+       }
+
+       BT_LOGD("Initialized common array field object: addr=%p, ft-addr=%p",
+               field, type);
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+int bt_ctf_field_common_sequence_initialize(struct bt_ctf_field_common *field,
+               struct bt_ctf_field_type_common *type,
+               bool is_shared, bt_object_release_func release_func,
+               struct bt_ctf_field_common_methods *methods,
+               GDestroyNotify field_destroy_func)
+{
+       struct bt_ctf_field_common_sequence *sequence = BT_CTF_FROM_COMMON(field);
+       int ret = 0;
+
+       BT_LOGD("Initializing common sequence field object: ft-addr=%p", type);
+       BT_ASSERT(type);
+       bt_ctf_field_common_initialize(field, type, is_shared,
+               release_func, methods);
+       sequence->elements = g_ptr_array_new();
+       if (!sequence->elements) {
+               ret = -1;
+               goto end;
+       }
+
+       g_ptr_array_set_free_func(sequence->elements, field_destroy_func);
+       BT_LOGD("Initialized common sequence field object: addr=%p, ft-addr=%p",
+               field, type);
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+int bt_ctf_field_common_generic_validate(struct bt_ctf_field_common *field)
+{
+       return (field && field->payload_set) ? 0 : -1;
+}
+
+BT_HIDDEN
+int bt_ctf_field_common_structure_validate_recursive(struct bt_ctf_field_common *field)
+{
+       int64_t i;
+       int ret = 0;
+       struct bt_ctf_field_common_structure *structure = BT_CTF_FROM_COMMON(field);
+
+       BT_ASSERT(field);
+
+       for (i = 0; i < structure->fields->len; i++) {
+               ret = bt_ctf_field_common_validate_recursive(
+                       (void *) structure->fields->pdata[i]);
+
+               if (ret) {
+                       int this_ret;
+                       const char *name;
+
+                       this_ret = bt_ctf_field_type_common_structure_borrow_field_by_index(
+                               field->type, &name, NULL, i);
+                       BT_ASSERT(this_ret == 0);
+                       BT_ASSERT_PRE_MSG("Invalid structure field's field: "
+                               "struct-field-addr=%p, field-name=\"%s\", "
+                               "index=%" PRId64 ", field-addr=%p",
+                               field, name, i, structure->fields->pdata[i]);
+                       goto end;
+               }
+       }
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+int bt_ctf_field_common_variant_validate_recursive(struct bt_ctf_field_common *field)
+{
+       int ret = 0;
+       struct bt_ctf_field_common_variant *variant = BT_CTF_FROM_COMMON(field);
+
+       BT_ASSERT(field);
+
+       if (!variant->current_field) {
+               ret = -1;
+               goto end;
+       }
+
+       ret = bt_ctf_field_common_validate_recursive(variant->current_field);
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+int bt_ctf_field_common_array_validate_recursive(struct bt_ctf_field_common *field)
+{
+       int64_t i;
+       int ret = 0;
+       struct bt_ctf_field_common_array *array = BT_CTF_FROM_COMMON(field);
+
+       BT_ASSERT(field);
+
+       for (i = 0; i < array->elements->len; i++) {
+               ret = bt_ctf_field_common_validate_recursive((void *) array->elements->pdata[i]);
+               if (ret) {
+                       BT_ASSERT_PRE_MSG("Invalid array field's element field: "
+                               "array-field-addr=%p, " PRId64 ", "
+                               "elem-field-addr=%p",
+                               field, i, array->elements->pdata[i]);
+                       goto end;
+               }
+       }
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+int bt_ctf_field_common_sequence_validate_recursive(struct bt_ctf_field_common *field)
+{
+       size_t i;
+       int ret = 0;
+       struct bt_ctf_field_common_sequence *sequence = BT_CTF_FROM_COMMON(field);
+
+       BT_ASSERT(field);
+
+       for (i = 0; i < sequence->elements->len; i++) {
+               ret = bt_ctf_field_common_validate_recursive(
+                       (void *) sequence->elements->pdata[i]);
+               if (ret) {
+                       BT_ASSERT_PRE_MSG("Invalid sequence field's element field: "
+                               "seq-field-addr=%p, " PRId64 ", "
+                               "elem-field-addr=%p",
+                               field, i, sequence->elements->pdata[i]);
+                       goto end;
+               }
+       }
+end:
+       return ret;
+}
+
+BT_HIDDEN
+void bt_ctf_field_common_generic_reset(struct bt_ctf_field_common *field)
+{
+       BT_ASSERT(field);
+       field->payload_set = false;
+}
+
+BT_HIDDEN
+void bt_ctf_field_common_structure_reset_recursive(struct bt_ctf_field_common *field)
+{
+       int64_t i;
+       struct bt_ctf_field_common_structure *structure = BT_CTF_FROM_COMMON(field);
+
+       BT_ASSERT(field);
+
+       for (i = 0; i < structure->fields->len; i++) {
+               struct bt_ctf_field_common *member = structure->fields->pdata[i];
+
+               if (!member) {
+                       /*
+                        * Structure members are lazily initialized;
+                        * skip if this member has not been allocated
+                        * yet.
+                        */
+                       continue;
+               }
+
+               bt_ctf_field_common_reset_recursive(member);
+       }
+}
+
+BT_HIDDEN
+void bt_ctf_field_common_variant_reset_recursive(struct bt_ctf_field_common *field)
+{
+       struct bt_ctf_field_common_variant *variant = BT_CTF_FROM_COMMON(field);
+
+       BT_ASSERT(field);
+       variant->current_field = NULL;
+}
+
+BT_HIDDEN
+void bt_ctf_field_common_array_reset_recursive(struct bt_ctf_field_common *field)
+{
+       size_t i;
+       struct bt_ctf_field_common_array *array = BT_CTF_FROM_COMMON(field);
+
+       BT_ASSERT(field);
+
+       for (i = 0; i < array->elements->len; i++) {
+               struct bt_ctf_field_common *member = array->elements->pdata[i];
+
+               if (!member) {
+                       /*
+                        * Array elements are lazily initialized; skip
+                        * if this member has not been allocated yet.
+                        */
+                       continue;
+               }
+
+               bt_ctf_field_common_reset_recursive(member);
+       }
+}
+
+BT_HIDDEN
+void bt_ctf_field_common_sequence_reset_recursive(struct bt_ctf_field_common *field)
+{
+       struct bt_ctf_field_common_sequence *sequence = BT_CTF_FROM_COMMON(field);
+       uint64_t i;
+
+       BT_ASSERT(field);
+
+       for (i = 0; i < sequence->elements->len; i++) {
+               if (sequence->elements->pdata[i]) {
+                       bt_ctf_field_common_reset_recursive(
+                               sequence->elements->pdata[i]);
+               }
+       }
+
+       sequence->length = 0;
+}
+
+BT_HIDDEN
+void bt_ctf_field_common_generic_set_is_frozen(struct bt_ctf_field_common *field,
+               bool is_frozen)
+{
+       field->frozen = is_frozen;
+}
+
+BT_HIDDEN
+void bt_ctf_field_common_structure_set_is_frozen_recursive(
+               struct bt_ctf_field_common *field, bool is_frozen)
+{
+       uint64_t i;
+       struct bt_ctf_field_common_structure *structure_field =
+               BT_CTF_FROM_COMMON(field);
+
+       BT_LOGD("Freezing structure field object: addr=%p", field);
+
+       for (i = 0; i < structure_field->fields->len; i++) {
+               struct bt_ctf_field_common *struct_field =
+                       g_ptr_array_index(structure_field->fields, i);
+
+               BT_LOGD("Freezing structure field's field: field-addr=%p, index=%" PRId64,
+                       struct_field, i);
+               bt_ctf_field_common_set_is_frozen_recursive(struct_field,
+                       is_frozen);
+       }
+
+       bt_ctf_field_common_generic_set_is_frozen(field, is_frozen);
+}
+
+BT_HIDDEN
+void bt_ctf_field_common_variant_set_is_frozen_recursive(
+               struct bt_ctf_field_common *field, bool is_frozen)
+{
+       uint64_t i;
+       struct bt_ctf_field_common_variant *variant_field = BT_CTF_FROM_COMMON(field);
+
+       BT_LOGD("Freezing variant field object: addr=%p", field);
+
+       for (i = 0; i < variant_field->fields->len; i++) {
+               struct bt_ctf_field_common *var_field =
+                       g_ptr_array_index(variant_field->fields, i);
+
+               BT_LOGD("Freezing variant field's field: field-addr=%p, index=%" PRId64,
+                       var_field, i);
+               bt_ctf_field_common_set_is_frozen_recursive(var_field, is_frozen);
+       }
+
+       bt_ctf_field_common_generic_set_is_frozen(field, is_frozen);
+}
+
+BT_HIDDEN
+void bt_ctf_field_common_array_set_is_frozen_recursive(
+               struct bt_ctf_field_common *field, bool is_frozen)
+{
+       int64_t i;
+       struct bt_ctf_field_common_array *array_field = BT_CTF_FROM_COMMON(field);
+
+       BT_LOGD("Freezing array field object: addr=%p", field);
+
+       for (i = 0; i < array_field->elements->len; i++) {
+               struct bt_ctf_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_ctf_field_common_set_is_frozen_recursive(elem_field, is_frozen);
+       }
+
+       bt_ctf_field_common_generic_set_is_frozen(field, is_frozen);
+}
+
+BT_HIDDEN
+void bt_ctf_field_common_sequence_set_is_frozen_recursive(
+               struct bt_ctf_field_common *field, bool is_frozen)
+{
+       int64_t i;
+       struct bt_ctf_field_common_sequence *sequence_field =
+               BT_CTF_FROM_COMMON(field);
+
+       BT_LOGD("Freezing sequence field object: addr=%p", field);
+
+       for (i = 0; i < sequence_field->length; i++) {
+               struct bt_ctf_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_ctf_field_common_set_is_frozen_recursive(elem_field, is_frozen);
+       }
+
+       bt_ctf_field_common_generic_set_is_frozen(field, is_frozen);
+}
+
+BT_HIDDEN
+void _bt_ctf_field_common_set_is_frozen_recursive(struct bt_ctf_field_common *field,
+               bool is_frozen)
+{
+       if (!field) {
+               goto end;
+       }
+
+       BT_LOGD("Setting field object's frozen state: addr=%p, is-frozen=%d",
+               field, is_frozen);
+       BT_ASSERT(field_type_common_has_known_id(field->type));
+       BT_ASSERT(field->methods->set_is_frozen);
+       field->methods->set_is_frozen(field, is_frozen);
+
+end:
+       return;
+}
+
+BT_HIDDEN
+bt_bool bt_ctf_field_common_generic_is_set(struct bt_ctf_field_common *field)
+{
+       return field && field->payload_set;
+}
+
+BT_HIDDEN
+bt_bool bt_ctf_field_common_structure_is_set_recursive(
+               struct bt_ctf_field_common *field)
+{
+       bt_bool is_set = BT_FALSE;
+       size_t i;
+       struct bt_ctf_field_common_structure *structure = BT_CTF_FROM_COMMON(field);
+
+       BT_ASSERT(field);
+
+       for (i = 0; i < structure->fields->len; i++) {
+               is_set = bt_ctf_field_common_is_set_recursive(
+                       structure->fields->pdata[i]);
+               if (!is_set) {
+                       goto end;
+               }
+       }
+
+end:
+       return is_set;
+}
+
+BT_HIDDEN
+bt_bool bt_ctf_field_common_variant_is_set_recursive(struct bt_ctf_field_common *field)
+{
+       struct bt_ctf_field_common_variant *variant = BT_CTF_FROM_COMMON(field);
+       bt_bool is_set = BT_FALSE;
+
+       BT_ASSERT(field);
+
+       if (variant->current_field) {
+               is_set = bt_ctf_field_common_is_set_recursive(
+                       variant->current_field);
+       }
+
+       return is_set;
+}
+
+BT_HIDDEN
+bt_bool bt_ctf_field_common_array_is_set_recursive(struct bt_ctf_field_common *field)
+{
+       size_t i;
+       bt_bool is_set = BT_FALSE;
+       struct bt_ctf_field_common_array *array = BT_CTF_FROM_COMMON(field);
+
+       BT_ASSERT(field);
+
+       for (i = 0; i < array->elements->len; i++) {
+               is_set = bt_ctf_field_common_is_set_recursive(array->elements->pdata[i]);
+               if (!is_set) {
+                       goto end;
+               }
+       }
+
+end:
+       return is_set;
+}
+
+BT_HIDDEN
+bt_bool bt_ctf_field_common_sequence_is_set_recursive(struct bt_ctf_field_common *field)
+{
+       size_t i;
+       bt_bool is_set = BT_FALSE;
+       struct bt_ctf_field_common_sequence *sequence = BT_CTF_FROM_COMMON(field);
+
+       BT_ASSERT(field);
+
+       if (!sequence->elements) {
+               goto end;
+       }
+
+       for (i = 0; i < sequence->elements->len; i++) {
+               is_set = bt_ctf_field_common_is_set_recursive(
+                       sequence->elements->pdata[i]);
+               if (!is_set) {
+                       goto end;
+               }
+       }
+
+end:
+       return is_set;
+}
+
+static struct bt_ctf_field_common_methods bt_ctf_field_integer_methods = {
+       .set_is_frozen = bt_ctf_field_common_generic_set_is_frozen,
+       .validate = bt_ctf_field_common_generic_validate,
        .copy = NULL,
-       .is_set = bt_field_common_generic_is_set,
-       .reset = bt_field_common_generic_reset,
+       .is_set = bt_ctf_field_common_generic_is_set,
+       .reset = bt_ctf_field_common_generic_reset,
 };
 
-static struct bt_field_common_methods bt_ctf_field_floating_point_methods = {
-       .set_is_frozen = bt_field_common_generic_set_is_frozen,
-       .validate = bt_field_common_generic_validate,
+static struct bt_ctf_field_common_methods bt_ctf_field_floating_point_methods = {
+       .set_is_frozen = bt_ctf_field_common_generic_set_is_frozen,
+       .validate = bt_ctf_field_common_generic_validate,
        .copy = NULL,
-       .is_set = bt_field_common_generic_is_set,
-       .reset = bt_field_common_generic_reset,
+       .is_set = bt_ctf_field_common_generic_is_set,
+       .reset = bt_ctf_field_common_generic_reset,
 };
 
 static
 void bt_ctf_field_enumeration_set_is_frozen_recursive(
-               struct bt_field_common *field, bool is_frozen);
+               struct bt_ctf_field_common *field, bool is_frozen);
 
 static
-int bt_ctf_field_enumeration_validate_recursive(struct bt_field_common *field);
+int bt_ctf_field_enumeration_validate_recursive(struct bt_ctf_field_common *field);
 
 static
 bt_bool bt_ctf_field_enumeration_is_set_recursive(
-               struct bt_field_common *field);
+               struct bt_ctf_field_common *field);
 
 static
-void bt_ctf_field_enumeration_reset_recursive(struct bt_field_common *field);
+void bt_ctf_field_enumeration_reset_recursive(struct bt_ctf_field_common *field);
 
-static struct bt_field_common_methods bt_ctf_field_enumeration_methods = {
+static struct bt_ctf_field_common_methods bt_ctf_field_enumeration_methods = {
        .set_is_frozen = bt_ctf_field_enumeration_set_is_frozen_recursive,
        .validate = bt_ctf_field_enumeration_validate_recursive,
        .copy = NULL,
@@ -79,52 +688,52 @@ static struct bt_field_common_methods bt_ctf_field_enumeration_methods = {
        .reset = bt_ctf_field_enumeration_reset_recursive,
 };
 
-static struct bt_field_common_methods bt_ctf_field_string_methods = {
-       .set_is_frozen = bt_field_common_generic_set_is_frozen,
-       .validate = bt_field_common_generic_validate,
+static struct bt_ctf_field_common_methods bt_ctf_field_string_methods = {
+       .set_is_frozen = bt_ctf_field_common_generic_set_is_frozen,
+       .validate = bt_ctf_field_common_generic_validate,
        .copy = NULL,
-       .is_set = bt_field_common_generic_is_set,
-       .reset = bt_field_common_generic_reset,
+       .is_set = bt_ctf_field_common_generic_is_set,
+       .reset = bt_ctf_field_common_generic_reset,
 };
 
-static struct bt_field_common_methods bt_ctf_field_structure_methods = {
-       .set_is_frozen = bt_field_common_structure_set_is_frozen_recursive,
-       .validate = bt_field_common_structure_validate_recursive,
+static struct bt_ctf_field_common_methods bt_ctf_field_structure_methods = {
+       .set_is_frozen = bt_ctf_field_common_structure_set_is_frozen_recursive,
+       .validate = bt_ctf_field_common_structure_validate_recursive,
        .copy = NULL,
-       .is_set = bt_field_common_structure_is_set_recursive,
-       .reset = bt_field_common_structure_reset_recursive,
+       .is_set = bt_ctf_field_common_structure_is_set_recursive,
+       .reset = bt_ctf_field_common_structure_reset_recursive,
 };
 
-static struct bt_field_common_methods bt_ctf_field_sequence_methods = {
-       .set_is_frozen = bt_field_common_sequence_set_is_frozen_recursive,
-       .validate = bt_field_common_sequence_validate_recursive,
+static struct bt_ctf_field_common_methods bt_ctf_field_sequence_methods = {
+       .set_is_frozen = bt_ctf_field_common_sequence_set_is_frozen_recursive,
+       .validate = bt_ctf_field_common_sequence_validate_recursive,
        .copy = NULL,
-       .is_set = bt_field_common_sequence_is_set_recursive,
-       .reset = bt_field_common_sequence_reset_recursive,
+       .is_set = bt_ctf_field_common_sequence_is_set_recursive,
+       .reset = bt_ctf_field_common_sequence_reset_recursive,
 };
 
-static struct bt_field_common_methods bt_ctf_field_array_methods = {
-       .set_is_frozen = bt_field_common_array_set_is_frozen_recursive,
-       .validate = bt_field_common_array_validate_recursive,
+static struct bt_ctf_field_common_methods bt_ctf_field_array_methods = {
+       .set_is_frozen = bt_ctf_field_common_array_set_is_frozen_recursive,
+       .validate = bt_ctf_field_common_array_validate_recursive,
        .copy = NULL,
-       .is_set = bt_field_common_array_is_set_recursive,
-       .reset = bt_field_common_array_reset_recursive,
+       .is_set = bt_ctf_field_common_array_is_set_recursive,
+       .reset = bt_ctf_field_common_array_reset_recursive,
 };
 
 static
-void bt_ctf_field_variant_set_is_frozen_recursive(struct bt_field_common *field,
+void bt_ctf_field_variant_set_is_frozen_recursive(struct bt_ctf_field_common *field,
                bool is_frozen);
 
 static
-int bt_ctf_field_variant_validate_recursive(struct bt_field_common *field);
+int bt_ctf_field_variant_validate_recursive(struct bt_ctf_field_common *field);
 
 static
-bt_bool bt_ctf_field_variant_is_set_recursive(struct bt_field_common *field);
+bt_bool bt_ctf_field_variant_is_set_recursive(struct bt_ctf_field_common *field);
 
 static
-void bt_ctf_field_variant_reset_recursive(struct bt_field_common *field);
+void bt_ctf_field_variant_reset_recursive(struct bt_ctf_field_common *field);
 
-static struct bt_field_common_methods bt_ctf_field_variant_methods = {
+static struct bt_ctf_field_common_methods bt_ctf_field_variant_methods = {
        .set_is_frozen = bt_ctf_field_variant_set_is_frozen_recursive,
        .validate = bt_ctf_field_variant_validate_recursive,
        .copy = NULL,
@@ -158,25 +767,25 @@ 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,
+       [BT_CTF_FIELD_TYPE_ID_INTEGER] =        bt_ctf_field_integer_create,
+       [BT_CTF_FIELD_TYPE_ID_ENUM] =           bt_ctf_field_enumeration_create,
+       [BT_CTF_FIELD_TYPE_ID_FLOAT] =          bt_ctf_field_floating_point_create,
+       [BT_CTF_FIELD_TYPE_ID_STRUCT] =         bt_ctf_field_structure_create,
+       [BT_CTF_FIELD_TYPE_ID_VARIANT] =        bt_ctf_field_variant_create,
+       [BT_CTF_FIELD_TYPE_ID_ARRAY] =          bt_ctf_field_array_create,
+       [BT_CTF_FIELD_TYPE_ID_SEQUENCE] =       bt_ctf_field_sequence_create,
+       [BT_CTF_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 *,
+               struct bt_ctf_field_common *, struct bt_ctf_stream_pos *,
                enum bt_ctf_byte_order);
 
 static
 void bt_ctf_field_integer_destroy(struct bt_ctf_field *field)
 {
        BT_LOGD("Destroying CTF writer integer field object: addr=%p", field);
-       bt_field_common_integer_finalize((void *) field);
+       bt_ctf_field_common_integer_finalize((void *) field);
        g_free(field);
 }
 
@@ -185,20 +794,20 @@ void bt_ctf_field_floating_point_destroy(struct bt_ctf_field *field)
 {
        BT_LOGD("Destroying CTF writer floating point field object: addr=%p",
                field);
-       bt_field_common_floating_point_finalize((void *) field);
+       bt_ctf_field_common_floating_point_finalize((void *) field);
        g_free(field);
 }
 
 static
 void bt_ctf_field_enumeration_destroy_recursive(struct bt_ctf_field *field)
 {
-       struct bt_ctf_field_enumeration *enumeration = BT_FROM_COMMON(field);
+       struct bt_ctf_field_enumeration *enumeration = BT_CTF_FROM_COMMON(field);
 
        BT_LOGD("Destroying CTF writer enumeration field object: addr=%p",
                field);
        BT_LOGD_STR("Putting container field.");
        bt_put(enumeration->container);
-       bt_field_common_finalize((void *) field);
+       bt_ctf_field_common_finalize((void *) field);
        g_free(field);
 }
 
@@ -206,19 +815,19 @@ static
 void bt_ctf_field_structure_destroy_recursive(struct bt_ctf_field *field)
 {
        BT_LOGD("Destroying CTF writer structure field object: addr=%p", field);
-       bt_field_common_structure_finalize_recursive((void *) field);
+       bt_ctf_field_common_structure_finalize_recursive((void *) field);
        g_free(field);
 }
 
 static
 void bt_ctf_field_variant_destroy_recursive(struct bt_ctf_field *field)
 {
-       struct bt_ctf_field_variant *variant = BT_FROM_COMMON(field);
+       struct bt_ctf_field_variant *variant = BT_CTF_FROM_COMMON(field);
 
        BT_LOGD("Destroying CTF writer variant field object: addr=%p", field);
        BT_LOGD_STR("Putting tag field.");
        bt_put(variant->tag);
-       bt_field_common_variant_finalize_recursive((void *) field);
+       bt_ctf_field_common_variant_finalize_recursive((void *) field);
        g_free(field);
 }
 
@@ -226,7 +835,7 @@ static
 void bt_ctf_field_array_destroy_recursive(struct bt_ctf_field *field)
 {
        BT_LOGD("Destroying CTF writer array field object: addr=%p", field);
-       bt_field_common_array_finalize_recursive((void *) field);
+       bt_ctf_field_common_array_finalize_recursive((void *) field);
        g_free(field);
 }
 
@@ -234,7 +843,7 @@ static
 void bt_ctf_field_sequence_destroy_recursive(struct bt_ctf_field *field)
 {
        BT_LOGD("Destroying CTF writer sequence field object: addr=%p", field);
-       bt_field_common_sequence_finalize_recursive((void *) field);
+       bt_ctf_field_common_sequence_finalize_recursive((void *) field);
        g_free(field);
 }
 
@@ -242,7 +851,7 @@ static
 void bt_ctf_field_string_destroy(struct bt_ctf_field *field)
 {
        BT_LOGD("Destroying CTF writer string field object: addr=%p", field);
-       bt_field_common_string_finalize((void *) field);
+       bt_ctf_field_common_string_finalize((void *) field);
        g_free(field);
 }
 
@@ -251,7 +860,7 @@ 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;
+       struct bt_ctf_field_common *field_common = (void *) field;
        bt_ctf_field_serialize_recursive_func serialize_func;
 
        BT_ASSERT(pos);
@@ -309,16 +918,16 @@ end:
 }
 
 static
-int bt_ctf_field_integer_serialize(struct bt_field_common *field,
+int bt_ctf_field_integer_serialize(struct bt_ctf_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_ASSERT_PRE_CTF_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));
+               bt_ctf_byte_order_string((int) native_byte_order));
 
 retry:
        ret = bt_ctf_field_integer_write(field, pos, native_byte_order);
@@ -340,7 +949,7 @@ end:
 }
 
 static
-int bt_ctf_field_enumeration_serialize_recursive(struct bt_field_common *field,
+int bt_ctf_field_enumeration_serialize_recursive(struct bt_ctf_field_common *field,
                struct bt_ctf_stream_pos *pos,
                enum bt_ctf_byte_order native_byte_order)
 {
@@ -348,23 +957,23 @@ int bt_ctf_field_enumeration_serialize_recursive(struct bt_field_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_ctf_byte_order_string((int) native_byte_order));
        BT_LOGV_STR("Serializing enumeration field's payload field.");
        return bt_ctf_field_serialize_recursive(
                (void *) enumeration->container, pos, native_byte_order);
 }
 
 static
-int bt_ctf_field_floating_point_serialize(struct bt_field_common *field,
+int bt_ctf_field_floating_point_serialize(struct bt_ctf_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_ASSERT_PRE_CTF_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));
+               bt_ctf_byte_order_string((int) native_byte_order));
 
 retry:
        ret = bt_ctf_field_floating_point_write(field, pos,
@@ -387,17 +996,17 @@ end:
 }
 
 static
-int bt_ctf_field_structure_serialize_recursive(struct bt_field_common *field,
+int bt_ctf_field_structure_serialize_recursive(struct bt_ctf_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);
+       struct bt_ctf_field_common_structure *structure = BT_CTF_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));
+               bt_ctf_byte_order_string((int) native_byte_order));
 
        while (!bt_ctf_stream_pos_access_ok(pos,
                offset_align(pos->offset, field->type->alignment))) {
@@ -416,7 +1025,7 @@ int bt_ctf_field_structure_serialize_recursive(struct bt_field_common *field,
        }
 
        for (i = 0; i < structure->fields->len; i++) {
-               struct bt_field_common *member = g_ptr_array_index(
+               struct bt_ctf_field_common *member = g_ptr_array_index(
                        structure->fields, i);
                const char *field_name = NULL;
 
@@ -425,7 +1034,7 @@ int bt_ctf_field_structure_serialize_recursive(struct bt_field_common *field,
                        pos->offset, member, i);
 
                if (!member) {
-                       ret = bt_field_type_common_structure_borrow_field_by_index(
+                       ret = bt_ctf_field_type_common_structure_borrow_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: "
@@ -439,7 +1048,7 @@ int bt_ctf_field_structure_serialize_recursive(struct bt_field_common *field,
                ret = bt_ctf_field_serialize_recursive((void *) member, pos,
                        native_byte_order);
                if (ret) {
-                       ret = bt_field_type_common_structure_borrow_field_by_index(
+                       ret = bt_ctf_field_type_common_structure_borrow_field_by_index(
                                field->type, &field_name, NULL, i);
                        BT_ASSERT(ret == 0);
                        BT_LOGW("Cannot serialize structure field's field: "
@@ -455,35 +1064,35 @@ end:
 }
 
 static
-int bt_ctf_field_variant_serialize_recursive(struct bt_field_common *field,
+int bt_ctf_field_variant_serialize_recursive(struct bt_ctf_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);
+       struct bt_ctf_field_common_variant *variant = BT_CTF_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_ctf_byte_order_string((int) native_byte_order));
        BT_LOGV_STR("Serializing variant field's payload field.");
        return bt_ctf_field_serialize_recursive(
                (void *) variant->current_field, pos, native_byte_order);
 }
 
 static
-int bt_ctf_field_array_serialize_recursive(struct bt_field_common *field,
+int bt_ctf_field_array_serialize_recursive(struct bt_ctf_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);
+       struct bt_ctf_field_common_array *array = BT_CTF_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));
+               bt_ctf_byte_order_string((int) native_byte_order));
 
        for (i = 0; i < array->elements->len; i++) {
-               struct bt_field_common *elem_field =
+               struct bt_ctf_field_common *elem_field =
                        g_ptr_array_index(array->elements, i);
 
                BT_LOGV("Serializing array field's element field: "
@@ -504,20 +1113,20 @@ end:
 }
 
 static
-int bt_ctf_field_sequence_serialize_recursive(struct bt_field_common *field,
+int bt_ctf_field_sequence_serialize_recursive(struct bt_ctf_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);
+       struct bt_ctf_field_common_sequence *sequence = BT_CTF_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));
+               bt_ctf_byte_order_string((int) native_byte_order));
 
        for (i = 0; i < sequence->elements->len; i++) {
-               struct bt_field_common *elem_field =
+               struct bt_ctf_field_common *elem_field =
                        g_ptr_array_index(sequence->elements, i);
 
                BT_LOGV("Serializing sequence field's element field: "
@@ -538,21 +1147,21 @@ end:
 }
 
 static
-int bt_ctf_field_string_serialize(struct bt_field_common *field,
+int bt_ctf_field_string_serialize(struct bt_ctf_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_common_string *string = BT_CTF_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_ASSERT_PRE_CTF_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_ctf_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);
@@ -587,15 +1196,15 @@ struct bt_ctf_field *bt_ctf_field_create(struct bt_ctf_field_type *type)
 
        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);
+       BT_ASSERT_PRE(bt_ctf_field_type_common_validate((void *) type) == 0,
+               "Field type is invalid: ft-addr=%p", 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);
+       bt_ctf_field_type_common_freeze((void *) type);
 
 end:
        return field;
@@ -603,12 +1212,12 @@ end:
 
 struct bt_ctf_field_type *bt_ctf_field_get_type(struct bt_ctf_field *field)
 {
-       return bt_get(bt_field_common_borrow_type((void *) field));
+       return bt_get(bt_ctf_field_common_borrow_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;
+       struct bt_ctf_field_common *field_common = (void *) field;
 
        BT_ASSERT_PRE_NON_NULL(field, "Field");
        return (int) field_common->type->id;
@@ -618,17 +1227,17 @@ int bt_ctf_field_sequence_set_length(struct bt_ctf_field *field,
                struct bt_ctf_field *length_field)
 {
        int ret;
-       struct bt_field_common *common_length_field = (void *) length_field;
+       struct bt_ctf_field_common *common_length_field = (void *) length_field;
        uint64_t length;
 
        BT_ASSERT_PRE_NON_NULL(length_field, "Length field");
-       BT_ASSERT_PRE_FIELD_COMMON_IS_SET((void *) length_field, "Length field");
-       BT_ASSERT_PRE(common_length_field->type->id == BT_FIELD_TYPE_ID_INTEGER ||
-                       common_length_field->type->id == BT_FIELD_TYPE_ID_ENUM,
-               "Length field must be an integer or enumeration field: %!+wf",
+       BT_ASSERT_PRE_CTF_FIELD_COMMON_IS_SET((void *) length_field, "Length field");
+       BT_ASSERT_PRE(common_length_field->type->id == BT_CTF_FIELD_TYPE_ID_INTEGER ||
+                       common_length_field->type->id == BT_CTF_FIELD_TYPE_ID_ENUM,
+               "Length field must be an integer or enumeration field: field-addr=%p",
                length_field);
 
-       if (common_length_field->type->id == BT_FIELD_TYPE_ID_ENUM) {
+       if (common_length_field->type->id == BT_CTF_FIELD_TYPE_ID_ENUM) {
                struct bt_ctf_field_enumeration *enumeration = (void *)
                        length_field;
 
@@ -637,21 +1246,21 @@ int bt_ctf_field_sequence_set_length(struct bt_ctf_field *field,
 
        ret = bt_ctf_field_integer_unsigned_get_value(length_field, &length);
        BT_ASSERT(ret == 0);
-       return bt_field_common_sequence_set_length((void *) field,
-               length, (bt_field_common_create_func) bt_ctf_field_create);
+       return bt_ctf_field_common_sequence_set_length((void *) field,
+               length, (bt_ctf_field_common_create_func) bt_ctf_field_create);
 }
 
 struct bt_ctf_field *bt_ctf_field_structure_get_field_by_index(
                struct bt_ctf_field *field, uint64_t index)
 {
-       return bt_get(bt_field_common_structure_borrow_field_by_index(
+       return bt_get(bt_ctf_field_common_structure_borrow_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 bt_get(bt_field_common_structure_borrow_field_by_name(
+       return bt_get(bt_ctf_field_common_structure_borrow_field_by_name(
                (void *) field, name));
 }
 
@@ -659,14 +1268,14 @@ struct bt_ctf_field *bt_ctf_field_array_get_field(
                struct bt_ctf_field *field, uint64_t index)
 {
        return bt_get(
-               bt_field_common_array_borrow_field((void *) field, index));
+               bt_ctf_field_common_array_borrow_field((void *) field, index));
 }
 
 struct bt_ctf_field *bt_ctf_field_sequence_get_field(
                struct bt_ctf_field *field, uint64_t index)
 {
        return bt_get(
-               bt_field_common_sequence_borrow_field((void *) field, index));
+               bt_ctf_field_common_sequence_borrow_field((void *) field, index));
 }
 
 struct bt_ctf_field *bt_ctf_field_variant_get_field(struct bt_ctf_field *field,
@@ -674,8 +1283,8 @@ struct bt_ctf_field *bt_ctf_field_variant_get_field(struct bt_ctf_field *field,
 {
        struct bt_ctf_field_variant *variant_field = (void *) field;
        struct bt_ctf_field_enumeration *enum_field = (void *) tag_field;
-       struct bt_field_type_common_variant *variant_ft;
-       struct bt_field_type_common_enumeration *tag_ft;
+       struct bt_ctf_field_type_common_variant *variant_ft;
+       struct bt_ctf_field_type_common_enumeration *tag_ft;
        struct bt_ctf_field *current_field = NULL;
        bt_bool is_signed;
        uint64_t tag_uval;
@@ -683,23 +1292,23 @@ struct bt_ctf_field *bt_ctf_field_variant_get_field(struct bt_ctf_field *field,
 
        BT_ASSERT_PRE_NON_NULL(field, "Variant field");
        BT_ASSERT_PRE_NON_NULL(tag_field, "Tag field");
-       BT_ASSERT_PRE_FIELD_COMMON_IS_SET((void *) tag_field, "Tag field");
-       BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(
-               (struct bt_field_common *) tag_field,
-               BT_FIELD_TYPE_ID_ENUM, "Tag field");
-       BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(
-               (struct bt_field_common *) field,
-               BT_FIELD_TYPE_ID_VARIANT, "Field");
+       BT_ASSERT_PRE_CTF_FIELD_COMMON_IS_SET((void *) tag_field, "Tag field");
+       BT_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(
+               (struct bt_ctf_field_common *) tag_field,
+               BT_CTF_FIELD_TYPE_ID_ENUM, "Tag field");
+       BT_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(
+               (struct bt_ctf_field_common *) field,
+               BT_CTF_FIELD_TYPE_ID_VARIANT, "Field");
        BT_ASSERT_PRE(
-               bt_field_common_validate_recursive((void *) tag_field) == 0,
-               "Tag field is invalid: %!+wf", tag_field);
-       variant_ft = BT_FROM_COMMON(variant_field->common.common.type);
-       BT_ASSERT_PRE(bt_field_type_common_compare(
-               BT_TO_COMMON(variant_ft->tag_ft), enum_field->common.type) == 0,
-               "Unexpected tag field's type: %![expected-ft-]+wF, "
-               "%![tag-ft-]+wF", variant_ft->tag_ft,
+               bt_ctf_field_common_validate_recursive((void *) tag_field) == 0,
+               "Tag field is invalid: field-addr=%p", tag_field);
+       variant_ft = BT_CTF_FROM_COMMON(variant_field->common.common.type);
+       BT_ASSERT_PRE(bt_ctf_field_type_common_compare(
+               BT_CTF_TO_COMMON(variant_ft->tag_ft), enum_field->common.type) == 0,
+               "Unexpected tag field's type: expected-ft-addr=%p, "
+               "tag-ft-addr=%p", variant_ft->tag_ft,
                enum_field->common.type);
-       tag_ft = BT_FROM_COMMON(enum_field->common.type);
+       tag_ft = BT_CTF_FROM_COMMON(enum_field->common.type);
        is_signed = tag_ft->container_ft->is_signed;
 
        if (is_signed) {
@@ -714,7 +1323,7 @@ struct bt_ctf_field *bt_ctf_field_variant_get_field(struct bt_ctf_field *field,
        }
 
        BT_ASSERT(ret == 0);
-       ret = bt_field_variant_common_set_tag((void *) field, tag_uval,
+       ret = bt_ctf_field_common_variant_set_tag((void *) field, tag_uval,
                is_signed);
        if (ret) {
                goto end;
@@ -732,7 +1341,7 @@ end:
 struct bt_ctf_field *bt_ctf_field_variant_get_current_field(
                struct bt_ctf_field *variant_field)
 {
-       return bt_get(bt_field_common_variant_borrow_current_field(
+       return bt_get(bt_ctf_field_common_variant_borrow_current_field(
                (void *) variant_field));
 }
 
@@ -743,7 +1352,7 @@ struct bt_ctf_field *bt_ctf_field_enumeration_borrow_container(
        struct bt_ctf_field_enumeration *enumeration = (void *) field;
 
        BT_ASSERT_PRE_NON_NULL(field, "Enumeration field");
-       BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID((struct bt_field_common *) field,
+       BT_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID((struct bt_ctf_field_common *) field,
                BT_CTF_FIELD_TYPE_ID_ENUM, "Field");
        BT_ASSERT(enumeration->container);
        return (void *) enumeration->container;
@@ -758,16 +1367,16 @@ struct bt_ctf_field *bt_ctf_field_enumeration_get_container(
 int bt_ctf_field_integer_signed_get_value(struct bt_ctf_field *field,
                int64_t *value)
 {
-       struct bt_field_common_integer *integer = (void *) field;
+       struct bt_ctf_field_common_integer *integer = (void *) field;
 
        BT_ASSERT_PRE_NON_NULL(field, "Integer field");
        BT_ASSERT_PRE_NON_NULL(value, "Value");
-       BT_ASSERT_PRE_FIELD_COMMON_IS_SET(BT_TO_COMMON(integer), "Integer field");
-       BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(BT_TO_COMMON(integer),
-               BT_FIELD_TYPE_ID_INTEGER, "Field");
-       BT_ASSERT_PRE(bt_field_type_common_integer_is_signed(
+       BT_ASSERT_PRE_CTF_FIELD_COMMON_IS_SET(BT_CTF_TO_COMMON(integer), "Integer field");
+       BT_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(BT_CTF_TO_COMMON(integer),
+               BT_CTF_FIELD_TYPE_ID_INTEGER, "Field");
+       BT_ASSERT_PRE(bt_ctf_field_type_common_integer_is_signed(
                integer->common.type),
-               "Field's type is unsigned: %!+_f", field);
+               "Field's type is unsigned: field-addr=%p", field);
        *value = integer->payload.signd;
        return 0;
 }
@@ -776,38 +1385,38 @@ int bt_ctf_field_integer_signed_set_value(struct bt_ctf_field *field,
                int64_t value)
 {
        int ret = 0;
-       struct bt_field_common_integer *integer = (void *) field;
-       struct bt_field_type_common_integer *integer_type;
+       struct bt_ctf_field_common_integer *integer = (void *) field;
+       struct bt_ctf_field_type_common_integer *integer_type;
 
        BT_ASSERT_PRE_NON_NULL(field, "Integer field");
-       BT_ASSERT_PRE_FIELD_COMMON_HOT(BT_TO_COMMON(integer), "Integer field");
-       BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(BT_TO_COMMON(integer),
-               BT_FIELD_TYPE_ID_INTEGER, "Field");
-       integer_type = BT_FROM_COMMON(integer->common.type);
+       BT_ASSERT_PRE_CTF_FIELD_COMMON_HOT(BT_CTF_TO_COMMON(integer), "Integer field");
+       BT_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(BT_CTF_TO_COMMON(integer),
+               BT_CTF_FIELD_TYPE_ID_INTEGER, "Field");
+       integer_type = BT_CTF_FROM_COMMON(integer->common.type);
        BT_ASSERT_PRE(
-               bt_field_type_common_integer_is_signed(integer->common.type),
-               "Field's type is unsigned: %!+wf", field);
+               bt_ctf_field_type_common_integer_is_signed(integer->common.type),
+               "Field's type is unsigned: field-addr=%p", field);
        BT_ASSERT_PRE(value_is_in_range_signed(integer_type->size, value),
-               "Value is out of bounds: value=%" PRId64 ", %![field-]+wf",
+               "Value is out of bounds: value=%" PRId64 ", field-addr=%p",
                value, field);
        integer->payload.signd = value;
-       bt_field_common_set(BT_TO_COMMON(integer), true);
+       bt_ctf_field_common_set(BT_CTF_TO_COMMON(integer), true);
        return ret;
 }
 
 int bt_ctf_field_integer_unsigned_get_value(struct bt_ctf_field *field,
                uint64_t *value)
 {
-       struct bt_field_common_integer *integer = (void *) field;
+       struct bt_ctf_field_common_integer *integer = (void *) field;
 
        BT_ASSERT_PRE_NON_NULL(field, "Integer field");
        BT_ASSERT_PRE_NON_NULL(value, "Value");
-       BT_ASSERT_PRE_FIELD_COMMON_IS_SET(BT_TO_COMMON(integer), "Integer field");
-       BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(BT_TO_COMMON(integer),
-               BT_FIELD_TYPE_ID_INTEGER, "Field");
+       BT_ASSERT_PRE_CTF_FIELD_COMMON_IS_SET(BT_CTF_TO_COMMON(integer), "Integer field");
+       BT_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(BT_CTF_TO_COMMON(integer),
+               BT_CTF_FIELD_TYPE_ID_INTEGER, "Field");
        BT_ASSERT_PRE(
-               !bt_field_type_common_integer_is_signed(integer->common.type),
-               "Field's type is signed: %!+wf", field);
+               !bt_ctf_field_type_common_integer_is_signed(integer->common.type),
+               "Field's type is signed: field-addr=%p", field);
        *value = integer->payload.unsignd;
        return 0;
 }
@@ -815,73 +1424,73 @@ int bt_ctf_field_integer_unsigned_get_value(struct bt_ctf_field *field,
 int bt_ctf_field_integer_unsigned_set_value(struct bt_ctf_field *field,
                uint64_t value)
 {
-       struct bt_field_common_integer *integer = (void *) field;
-       struct bt_field_type_common_integer *integer_type;
+       struct bt_ctf_field_common_integer *integer = (void *) field;
+       struct bt_ctf_field_type_common_integer *integer_type;
 
        BT_ASSERT_PRE_NON_NULL(field, "Integer field");
-       BT_ASSERT_PRE_FIELD_COMMON_HOT(BT_TO_COMMON(integer), "Integer field");
-       BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(BT_TO_COMMON(integer),
-               BT_FIELD_TYPE_ID_INTEGER, "Field");
-       integer_type = BT_FROM_COMMON(integer->common.type);
+       BT_ASSERT_PRE_CTF_FIELD_COMMON_HOT(BT_CTF_TO_COMMON(integer), "Integer field");
+       BT_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(BT_CTF_TO_COMMON(integer),
+               BT_CTF_FIELD_TYPE_ID_INTEGER, "Field");
+       integer_type = BT_CTF_FROM_COMMON(integer->common.type);
        BT_ASSERT_PRE(
-               !bt_field_type_common_integer_is_signed(integer->common.type),
-               "Field's type is signed: %!+wf", field);
+               !bt_ctf_field_type_common_integer_is_signed(integer->common.type),
+               "Field's type is signed: field-addr=%p", field);
        BT_ASSERT_PRE(value_is_in_range_unsigned(integer_type->size, value),
-               "Value is out of bounds: value=%" PRIu64 ", %![field-]+wf",
+               "Value is out of bounds: value=%" PRIu64 ", field-addr=%p",
                value, field);
        integer->payload.unsignd = value;
-       bt_field_common_set(BT_TO_COMMON(integer), true);
+       bt_ctf_field_common_set(BT_CTF_TO_COMMON(integer), true);
        return 0;
 }
 
 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);
+       return bt_ctf_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);
+       return bt_ctf_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);
+       return bt_ctf_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);
+       return bt_ctf_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);
+       return bt_ctf_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);
+       return bt_ctf_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);
+       return (void *) bt_ctf_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);
+       struct bt_ctf_field_common_integer *integer =
+               g_new0(struct bt_ctf_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_ctf_field_common_initialize(BT_CTF_TO_COMMON(integer), (void *) type,
                        true,
                        (bt_object_release_func) bt_ctf_field_integer_destroy,
                        &bt_ctf_field_integer_methods);
@@ -900,7 +1509,7 @@ static
 struct bt_ctf_field *bt_ctf_field_enumeration_create(
                struct bt_ctf_field_type *type)
 {
-       struct bt_field_type_common_enumeration *enum_ft = (void *) type;
+       struct bt_ctf_field_type_common_enumeration *enum_ft = (void *) type;
        struct bt_ctf_field_enumeration *enumeration = g_new0(
                struct bt_ctf_field_enumeration, 1);
 
@@ -911,13 +1520,13 @@ struct bt_ctf_field *bt_ctf_field_enumeration_create(
                goto end;
        }
 
-       bt_field_common_initialize(BT_TO_COMMON(enumeration),
+       bt_ctf_field_common_initialize(BT_CTF_TO_COMMON(enumeration),
                (void *) type,
                true, (bt_object_release_func)
                        bt_ctf_field_enumeration_destroy_recursive,
                &bt_ctf_field_enumeration_methods);
        enumeration->container = (void *) bt_ctf_field_create(
-               BT_FROM_COMMON(enum_ft->container_ft));
+               BT_CTF_FROM_COMMON(enum_ft->container_ft));
        if (!enumeration->container) {
                BT_PUT(enumeration);
                goto end;
@@ -937,13 +1546,13 @@ 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;
+       struct bt_ctf_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);
+       floating_point = g_new0(struct bt_ctf_field_common_floating_point, 1);
 
        if (floating_point) {
-               bt_field_common_initialize(BT_TO_COMMON(floating_point),
+               bt_ctf_field_common_initialize(BT_CTF_TO_COMMON(floating_point),
                        (void *) type,
                        true, (bt_object_release_func)
                                bt_ctf_field_floating_point_destroy,
@@ -963,8 +1572,8 @@ 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);
+       struct bt_ctf_field_common_structure *structure = g_new0(
+               struct bt_ctf_field_common_structure, 1);
        int iret;
 
        BT_LOGD("Creating CTF writer structure field object: ft-addr=%p", type);
@@ -974,12 +1583,12 @@ struct bt_ctf_field *bt_ctf_field_structure_create(
                goto end;
        }
 
-       iret = bt_field_common_structure_initialize(BT_TO_COMMON(structure),
+       iret = bt_ctf_field_common_structure_initialize(BT_CTF_TO_COMMON(structure),
                (void *) type,
                true, (bt_object_release_func)
                        bt_ctf_field_structure_destroy_recursive,
                &bt_ctf_field_structure_methods,
-               (bt_field_common_create_func) bt_ctf_field_create,
+               (bt_ctf_field_common_create_func) bt_ctf_field_create,
                (GDestroyNotify) bt_put);
        structure->common.spec.writer.serialize_func =
                (bt_ctf_field_serialize_recursive_func) bt_ctf_field_structure_serialize_recursive;
@@ -998,7 +1607,7 @@ end:
 static
 struct bt_ctf_field *bt_ctf_field_variant_create(struct bt_ctf_field_type *type)
 {
-       struct bt_field_type_common_variant *var_ft = (void *) type;
+       struct bt_ctf_field_type_common_variant *var_ft = (void *) type;
        struct bt_ctf_field_variant *variant = g_new0(
                struct bt_ctf_field_variant, 1);
 
@@ -1009,15 +1618,15 @@ struct bt_ctf_field *bt_ctf_field_variant_create(struct bt_ctf_field_type *type)
                goto end;
        }
 
-       bt_field_common_variant_initialize(BT_TO_COMMON(BT_TO_COMMON(variant)),
+       bt_ctf_field_common_variant_initialize(BT_CTF_TO_COMMON(BT_CTF_TO_COMMON(variant)),
                (void *) type,
                true, (bt_object_release_func)
                        bt_ctf_field_variant_destroy_recursive,
                &bt_ctf_field_variant_methods,
-               (bt_field_common_create_func) bt_ctf_field_create,
+               (bt_ctf_field_common_create_func) bt_ctf_field_create,
                (GDestroyNotify) bt_put);
        variant->tag = (void *) bt_ctf_field_create(
-               BT_FROM_COMMON(var_ft->tag_ft));
+               BT_CTF_FROM_COMMON(var_ft->tag_ft));
        variant->common.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",
@@ -1030,8 +1639,8 @@ end:
 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);
+       struct bt_ctf_field_common_array *array =
+               g_new0(struct bt_ctf_field_common_array, 1);
        int ret;
 
        BT_LOGD("Creating CTF writer array field object: ft-addr=%p", type);
@@ -1042,12 +1651,12 @@ struct bt_ctf_field *bt_ctf_field_array_create(struct bt_ctf_field_type *type)
                goto end;
        }
 
-       ret = bt_field_common_array_initialize(BT_TO_COMMON(array),
+       ret = bt_ctf_field_common_array_initialize(BT_CTF_TO_COMMON(array),
                (void *) type,
                true, (bt_object_release_func)
                        bt_ctf_field_array_destroy_recursive,
                &bt_ctf_field_array_methods,
-               (bt_field_common_create_func) bt_ctf_field_create,
+               (bt_ctf_field_common_create_func) bt_ctf_field_create,
                (GDestroyNotify) bt_put);
        array->common.spec.writer.serialize_func =
                (bt_ctf_field_serialize_recursive_func) bt_ctf_field_array_serialize_recursive;
@@ -1066,13 +1675,13 @@ end:
 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);
+       struct bt_ctf_field_common_sequence *sequence = g_new0(
+               struct bt_ctf_field_common_sequence, 1);
 
        BT_LOGD("Creating CTF writer sequence field object: ft-addr=%p", type);
 
        if (sequence) {
-               bt_field_common_sequence_initialize(BT_TO_COMMON(sequence),
+               bt_ctf_field_common_sequence_initialize(BT_CTF_TO_COMMON(sequence),
                        (void *) type,
                        true, (bt_object_release_func)
                                bt_ctf_field_sequence_destroy_recursive,
@@ -1092,13 +1701,13 @@ struct bt_ctf_field *bt_ctf_field_sequence_create(struct bt_ctf_field_type *type
 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);
+       struct bt_ctf_field_common_string *string = g_new0(
+               struct bt_ctf_field_common_string, 1);
 
        BT_LOGD("Creating CTF writer string field object: ft-addr=%p", type);
 
        if (string) {
-               bt_field_common_string_initialize(BT_TO_COMMON(string),
+               bt_ctf_field_common_string_initialize(BT_CTF_TO_COMMON(string),
                        (void *) type,
                        true, (bt_object_release_func)
                                bt_ctf_field_string_destroy,
@@ -1116,26 +1725,26 @@ struct bt_ctf_field *bt_ctf_field_string_create(struct bt_ctf_field_type *type)
 
 static
 void bt_ctf_field_enumeration_set_is_frozen_recursive(
-               struct bt_field_common *field, bool is_frozen)
+               struct bt_ctf_field_common *field, bool is_frozen)
 {
        struct bt_ctf_field_enumeration *enumeration = (void *) field;
 
        if (enumeration->container) {
-               bt_field_common_set_is_frozen_recursive(
+               bt_ctf_field_common_set_is_frozen_recursive(
                        (void *) enumeration->container, is_frozen);
        }
 
-       bt_field_common_generic_set_is_frozen((void *) field, is_frozen);
+       bt_ctf_field_common_generic_set_is_frozen((void *) field, is_frozen);
 }
 
 static
-int bt_ctf_field_enumeration_validate_recursive(struct bt_field_common *field)
+int bt_ctf_field_enumeration_validate_recursive(struct bt_ctf_field_common *field)
 {
        int ret = -1;
        struct bt_ctf_field_enumeration *enumeration = (void *) field;
 
        if (enumeration->container) {
-               ret = bt_field_common_validate_recursive(
+               ret = bt_ctf_field_common_validate_recursive(
                        (void *) enumeration->container);
        }
 
@@ -1143,13 +1752,13 @@ int bt_ctf_field_enumeration_validate_recursive(struct bt_field_common *field)
 }
 
 static
-bt_bool bt_ctf_field_enumeration_is_set_recursive(struct bt_field_common *field)
+bt_bool bt_ctf_field_enumeration_is_set_recursive(struct bt_ctf_field_common *field)
 {
        bt_bool is_set = BT_FALSE;
        struct bt_ctf_field_enumeration *enumeration = (void *) field;
 
        if (enumeration->container) {
-               is_set = bt_field_common_is_set_recursive(
+               is_set = bt_ctf_field_common_is_set_recursive(
                        (void *) enumeration->container);
        }
 
@@ -1157,101 +1766,101 @@ bt_bool bt_ctf_field_enumeration_is_set_recursive(struct bt_field_common *field)
 }
 
 static
-void bt_ctf_field_enumeration_reset_recursive(struct bt_field_common *field)
+void bt_ctf_field_enumeration_reset_recursive(struct bt_ctf_field_common *field)
 {
        struct bt_ctf_field_enumeration *enumeration = (void *) field;
 
        if (enumeration->container) {
-               bt_field_common_reset_recursive(
+               bt_ctf_field_common_reset_recursive(
                        (void *) enumeration->container);
        }
 
-       bt_field_common_generic_reset((void *) field);
+       bt_ctf_field_common_generic_reset((void *) field);
 }
 
 static
 void bt_ctf_field_variant_set_is_frozen_recursive(
-               struct bt_field_common *field, bool is_frozen)
+               struct bt_ctf_field_common *field, bool is_frozen)
 {
        struct bt_ctf_field_variant *variant = (void *) field;
 
        if (variant->tag) {
-               bt_field_common_set_is_frozen_recursive(
+               bt_ctf_field_common_set_is_frozen_recursive(
                        (void *) variant->tag, is_frozen);
        }
 
-       bt_field_common_variant_set_is_frozen_recursive((void *) field,
+       bt_ctf_field_common_variant_set_is_frozen_recursive((void *) field,
                is_frozen);
 }
 
 static
-int bt_ctf_field_variant_validate_recursive(struct bt_field_common *field)
+int bt_ctf_field_variant_validate_recursive(struct bt_ctf_field_common *field)
 {
        int ret;
        struct bt_ctf_field_variant *variant = (void *) field;
 
        if (variant->tag) {
-               ret = bt_field_common_validate_recursive(
+               ret = bt_ctf_field_common_validate_recursive(
                        (void *) variant->tag);
                if (ret) {
                        goto end;
                }
        }
 
-       ret = bt_field_common_variant_validate_recursive((void *) field);
+       ret = bt_ctf_field_common_variant_validate_recursive((void *) field);
 
 end:
        return ret;
 }
 
 static
-bt_bool bt_ctf_field_variant_is_set_recursive(struct bt_field_common *field)
+bt_bool bt_ctf_field_variant_is_set_recursive(struct bt_ctf_field_common *field)
 {
        bt_bool is_set;
        struct bt_ctf_field_variant *variant = (void *) field;
 
        if (variant->tag) {
-               is_set = bt_field_common_is_set_recursive(
+               is_set = bt_ctf_field_common_is_set_recursive(
                        (void *) variant->tag);
                if (is_set) {
                        goto end;
                }
        }
 
-       is_set = bt_field_common_variant_is_set_recursive((void *) field);
+       is_set = bt_ctf_field_common_variant_is_set_recursive((void *) field);
 
 end:
        return is_set;
 }
 
 static
-void bt_ctf_field_variant_reset_recursive(struct bt_field_common *field)
+void bt_ctf_field_variant_reset_recursive(struct bt_ctf_field_common *field)
 {
        struct bt_ctf_field_variant *variant = (void *) field;
 
        if (variant->tag) {
-               bt_field_common_reset_recursive(
+               bt_ctf_field_common_reset_recursive(
                        (void *) variant->tag);
        }
 
-       bt_field_common_variant_reset_recursive((void *) field);
+       bt_ctf_field_common_variant_reset_recursive((void *) field);
 }
 
 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)
+               struct bt_ctf_field_common *struct_field,
+               const char *name, struct bt_ctf_field_common *value)
 {
        bool ret = true;
-       struct bt_field_type_common *expected_field_type = NULL;
+       struct bt_ctf_field_type_common *expected_field_type = NULL;
 
        expected_field_type =
-               bt_field_type_common_structure_borrow_field_type_by_name(
+               bt_ctf_field_type_common_structure_borrow_field_type_by_name(
                        struct_field->type, name);
 
-       if (bt_field_type_common_compare(expected_field_type, value->type)) {
+       if (bt_ctf_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,
+                       "value-ft-addr=%p, expected-ft-addr=%p", value->type,
                        expected_field_type);
                ret = false;
                goto end;
@@ -1267,24 +1876,24 @@ int bt_ctf_field_structure_set_field_by_name(struct bt_ctf_field *field,
 {
        int ret = 0;
        GQuark field_quark;
-       struct bt_field_common *common_field = (void *) field;
-       struct bt_field_common_structure *structure =
-               BT_FROM_COMMON(common_field);
-       struct bt_field_common *common_value = (void *) value;
+       struct bt_ctf_field_common *common_field = (void *) field;
+       struct bt_ctf_field_common_structure *structure =
+               BT_CTF_FROM_COMMON(common_field);
+       struct bt_ctf_field_common *common_value = (void *) value;
        size_t index;
        GHashTable *field_name_to_index;
-       struct bt_field_type_common_structure *structure_ft;
+       struct bt_ctf_field_type_common_structure *structure_ft;
 
        BT_ASSERT_PRE_NON_NULL(field, "Parent 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(common_field,
-               BT_FIELD_TYPE_ID_STRUCT, "Parent field");
+       BT_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(common_field,
+               BT_CTF_FIELD_TYPE_ID_STRUCT, "Parent field");
        BT_ASSERT_PRE(field_to_set_has_expected_type(common_field,
                name, common_value),
                "Value field's type is different from the expected field type.");
        field_quark = g_quark_from_string(name);
-       structure_ft = BT_FROM_COMMON(common_field->type);
+       structure_ft = BT_CTF_FROM_COMMON(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,
index 29af02ca51e41a1c895a4cd2723eea6c1194cf73..d1dffc2c99bfc2646355c9b13d1bdb418bf35d92 100644 (file)
 
 #include <glib.h>
 #include <babeltrace/ctf-writer/functor-internal.h>
-#include <babeltrace/ctf-ir/utils-internal.h>
+#include <babeltrace/ctf-writer/utils-internal.h>
 
 BT_HIDDEN
 void value_exists(gpointer element, gpointer search_query)
 {
-       if (element == ((struct search_query *)search_query)->value) {
-               ((struct search_query *)search_query)->found = 1;
+       if (element == ((struct bt_ctf_search_query *)search_query)->value) {
+               ((struct bt_ctf_search_query *)search_query)->found = 1;
        }
 }
diff --git a/lib/ctf-writer/resolve.c b/lib/ctf-writer/resolve.c
new file mode 100644 (file)
index 0000000..90ace15
--- /dev/null
@@ -0,0 +1,1339 @@
+/*
+ * resolve.c
+ *
+ * Babeltrace - CTF writer: Type resolving internal
+ *
+ * Copyright 2015 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ * Copyright 2016 Philippe Proulx <pproulx@efficios.com>
+ *
+ * Authors: Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *          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-RESOLVE"
+#include <babeltrace/lib-logging-internal.h>
+
+#include <babeltrace/assert-internal.h>
+#include <babeltrace/babeltrace-internal.h>
+#include <babeltrace/ctf-writer/field-path-internal.h>
+#include <babeltrace/ctf-writer/field-types.h>
+#include <babeltrace/ctf-writer/resolve-internal.h>
+#include <babeltrace/ctf-writer/stream-class.h>
+#include <babeltrace/ctf-writer/utils-internal.h>
+#include <babeltrace/ref.h>
+#include <babeltrace/types.h>
+#include <babeltrace/values.h>
+#include <glib.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <stdlib.h>
+
+typedef GPtrArray type_stack;
+
+/*
+ * A stack frame.
+ *
+ * `type` contains a compound field type (structure, variant, array,
+ * or sequence) and `index` indicates the index of the field type in
+ * the upper frame (-1 for array and sequence field types).
+ *
+ * `type` is owned by the stack frame.
+ */
+struct type_stack_frame {
+       struct bt_ctf_field_type_common *type;
+       int index;
+};
+
+/*
+ * The current context of the resolving engine.
+ *
+ * `scopes` contain the 6 CTF scope field types (see CTF, sect. 7.3.2)
+ * in the following order:
+ *
+ *   * Packet header
+ *   * Packet context
+ *   * Event header
+ *   * Stream event context
+ *   * Event context
+ *   * Event payload
+ */
+struct resolve_context {
+       struct bt_value *environment;
+       struct bt_ctf_field_type_common *scopes[6];
+
+       /* Root scope being visited */
+       enum bt_ctf_scope root_scope;
+       type_stack *type_stack;
+       struct bt_ctf_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_CTF_SCOPE_ENV]                              = "env.",
+       [BT_CTF_SCOPE_TRACE_PACKET_HEADER]              = "trace.packet.header.",
+       [BT_CTF_SCOPE_STREAM_PACKET_CONTEXT]    = "stream.packet.context.",
+       [BT_CTF_SCOPE_STREAM_EVENT_HEADER]              = "stream.event.header.",
+       [BT_CTF_SCOPE_STREAM_EVENT_CONTEXT]             = "stream.event.context.",
+       [BT_CTF_SCOPE_EVENT_CONTEXT]            = "event.context.",
+       [BT_CTF_SCOPE_EVENT_FIELDS]                     = "event.fields.",
+};
+
+/* Number of path tokens used for the absolute prefixes */
+static const int absolute_path_prefix_ptoken_counts[] = {
+       [BT_CTF_SCOPE_ENV]                      = 1,
+       [BT_CTF_SCOPE_TRACE_PACKET_HEADER]      = 3,
+       [BT_CTF_SCOPE_STREAM_PACKET_CONTEXT]    = 3,
+       [BT_CTF_SCOPE_STREAM_EVENT_HEADER]      = 3,
+       [BT_CTF_SCOPE_STREAM_EVENT_CONTEXT]     = 3,
+       [BT_CTF_SCOPE_EVENT_CONTEXT]            = 2,
+       [BT_CTF_SCOPE_EVENT_FIELDS]             = 2,
+};
+
+/*
+ * Destroys a type stack frame.
+ */
+static
+void type_stack_destroy_notify(gpointer data)
+{
+       struct type_stack_frame *frame = data;
+
+       BT_PUT(frame->type);
+       g_free(frame);
+}
+
+/*
+ * Creates a type stack.
+ *
+ * Return value is owned by the caller.
+ */
+static
+type_stack *type_stack_create(void)
+{
+       return g_ptr_array_new_with_free_func(type_stack_destroy_notify);
+}
+
+/*
+ * Destroys a type stack.
+ */
+static
+void type_stack_destroy(type_stack *stack)
+{
+       g_ptr_array_free(stack, TRUE);
+}
+
+/*
+ * Pushes a field type onto a type stack.
+ *
+ * `type` is owned by the caller (stack frame gets a new reference).
+ */
+static
+int type_stack_push(type_stack *stack, struct bt_ctf_field_type_common *type)
+{
+       int ret = 0;
+       struct type_stack_frame *frame = NULL;
+
+       if (!stack || !type) {
+               BT_LOGW("Invalid parameter: stack or type is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       frame = g_new0(struct type_stack_frame, 1);
+       if (!frame) {
+               BT_LOGE_STR("Failed to allocate one field type stack frame.");
+               ret = -1;
+               goto end;
+       }
+
+       BT_LOGV("Pushing field type on context's stack: "
+               "ft-addr=%p, stack-size-before=%u", type, stack->len);
+       frame->type = bt_get(type);
+       g_ptr_array_add(stack, frame);
+
+end:
+       return ret;
+}
+
+/*
+ * Checks whether or not `stack` is empty.
+ */
+static
+bt_bool type_stack_empty(type_stack *stack)
+{
+       return stack->len == 0;
+}
+
+/*
+ * Returns the number of frames in `stack`.
+ */
+static
+size_t type_stack_size(type_stack *stack)
+{
+       return stack->len;
+}
+
+/*
+ * Returns the top frame of `stack`.
+ *
+ * Return value is owned by `stack`.
+ */
+static
+struct type_stack_frame *type_stack_peek(type_stack *stack)
+{
+       struct type_stack_frame *entry = NULL;
+
+       if (!stack || type_stack_empty(stack)) {
+               goto end;
+       }
+
+       entry = g_ptr_array_index(stack, stack->len - 1);
+end:
+       return entry;
+}
+
+/*
+ * Returns the frame at index `index` in `stack`.
+ *
+ * Return value is owned by `stack`.
+ */
+static
+struct type_stack_frame *type_stack_at(type_stack *stack,
+               size_t index)
+{
+       struct type_stack_frame *entry = NULL;
+
+       if (!stack || index >= stack->len) {
+               goto end;
+       }
+
+       entry = g_ptr_array_index(stack, index);
+
+end:
+       return entry;
+}
+
+/*
+ * Removes the top frame of `stack`.
+ */
+static
+void type_stack_pop(type_stack *stack)
+{
+       if (!type_stack_empty(stack)) {
+               /*
+                * This will call the frame's destructor and free it, as
+                * well as put its contained field type.
+                */
+               BT_LOGV("Popping context's stack: stack-size-before=%u",
+                       stack->len);
+               g_ptr_array_set_size(stack, stack->len - 1);
+       }
+}
+
+/*
+ * Returns the scope field type of `scope` in the context `ctx`.
+ *
+ * Return value is owned by `ctx` on success.
+ */
+static
+struct bt_ctf_field_type_common *get_type_from_ctx(struct resolve_context *ctx,
+               enum bt_ctf_scope scope)
+{
+       BT_ASSERT(scope >= BT_CTF_SCOPE_TRACE_PACKET_HEADER &&
+               scope <= BT_CTF_SCOPE_EVENT_FIELDS);
+
+       return ctx->scopes[scope - BT_CTF_SCOPE_TRACE_PACKET_HEADER];
+}
+
+/*
+ * Returns the CTF scope from a path string. May return
+ * CTF_NODE_UNKNOWN if the path is found to be relative.
+ */
+static
+enum bt_ctf_scope get_root_scope_from_absolute_pathstr(const char *pathstr)
+{
+       enum bt_ctf_scope scope;
+       enum bt_ctf_scope ret = BT_CTF_SCOPE_UNKNOWN;
+       const size_t prefixes_count = sizeof(absolute_path_prefixes) /
+               sizeof(*absolute_path_prefixes);
+
+       for (scope = BT_CTF_SCOPE_ENV; scope < BT_CTF_SCOPE_ENV +
+                       prefixes_count; scope++) {
+               /*
+                * Chech if path string starts with a known absolute
+                * path prefix.
+                *
+                * Refer to CTF 7.3.2 STATIC AND DYNAMIC SCOPES.
+                */
+               if (strncmp(pathstr, absolute_path_prefixes[scope],
+                               strlen(absolute_path_prefixes[scope]))) {
+                       /* Prefix does not match: try the next one */
+                       BT_LOGV("Prefix does not match: trying the next one: "
+                               "path=\"%s\", path-prefix=\"%s\", scope=%s",
+                               pathstr, absolute_path_prefixes[scope],
+                               bt_ctf_scope_string(scope));
+                       continue;
+               }
+
+               /* Found it! */
+               ret = scope;
+               BT_LOGV("Found root scope from absolute path: "
+                       "path=\"%s\", scope=%s", pathstr,
+                       bt_ctf_scope_string(scope));
+               goto end;
+       }
+
+end:
+       return ret;
+}
+
+/*
+ * Destroys a path token.
+ */
+static
+void ptokens_destroy_func(gpointer ptoken, gpointer data)
+{
+       g_string_free(ptoken, TRUE);
+}
+
+/*
+ * Destroys a path token list.
+ */
+static
+void ptokens_destroy(GList *ptokens)
+{
+       if (!ptokens) {
+               return;
+       }
+
+       g_list_foreach(ptokens, ptokens_destroy_func, NULL);
+       g_list_free(ptokens);
+}
+
+/*
+ * Returns the string contained in a path token.
+ */
+static
+const char *ptoken_get_string(GList *ptoken)
+{
+       GString *tokenstr = (GString *) ptoken->data;
+
+       return tokenstr->str;
+}
+
+/*
+ * Converts a path string to a path token list, that is, splits the
+ * individual words of a path string into a list of individual
+ * strings.
+ *
+ * Return value is owned by the caller on success.
+ */
+static
+GList *pathstr_to_ptokens(const char *pathstr)
+{
+       const char *at = pathstr;
+       const char *last = at;
+       GList *ptokens = NULL;
+
+       for (;;) {
+               if (*at == '.' || *at == '\0') {
+                       GString *tokenstr;
+
+                       if (at == last) {
+                               /* Error: empty token */
+                               BT_LOGW("Empty path token: path=\"%s\", pos=%u",
+                                       pathstr, (int) (at - pathstr));
+                               goto error;
+                       }
+
+                       tokenstr = g_string_new(NULL);
+                       g_string_append_len(tokenstr, last, at - last);
+                       ptokens = g_list_append(ptokens, tokenstr);
+                       last = at + 1;
+               }
+
+               if (*at == '\0') {
+                       break;
+               }
+
+               at++;
+       }
+
+       return ptokens;
+
+error:
+       ptokens_destroy(ptokens);
+       return NULL;
+}
+
+/*
+ * Converts a path token list to a field path object. The path token
+ * list is relative from `type`. The index of the source looking for
+ * its target within `type` is indicated by `src_index`. This can be
+ * `INT_MAX` if the source is contained in `type`.
+ *
+ * `ptokens` is owned by the caller. `field_path` is an output parameter
+ * owned by the caller that must be filled here. `type` is owned by the
+ * caller.
+ */
+static
+int ptokens_to_field_path(GList *ptokens, struct bt_ctf_field_path *field_path,
+               struct bt_ctf_field_type_common *type, int src_index)
+{
+       int ret = 0;
+       GList *cur_ptoken = ptokens;
+       bt_bool first_level_done = BT_FALSE;
+
+       /* Get our own reference */
+       bt_get(type);
+
+       /* Locate target */
+       while (cur_ptoken) {
+               int child_index;
+               struct bt_ctf_field_type_common *child_type;
+               const char *field_name = ptoken_get_string(cur_ptoken);
+               enum bt_ctf_field_type_id type_id =
+                       bt_ctf_field_type_common_get_type_id(type);
+
+               BT_LOGV("Current path token: token=\"%s\"", field_name);
+
+               /* Find to which index corresponds the current path token */
+               if (type_id == BT_CTF_FIELD_TYPE_ID_ARRAY ||
+                               type_id == BT_CTF_FIELD_TYPE_ID_SEQUENCE) {
+                       child_index = -1;
+               } else {
+                       child_index = bt_ctf_field_type_common_get_field_index(type,
+                               field_name);
+                       if (child_index < 0) {
+                               /*
+                                * Error: field name does not exist or
+                                * wrong current type.
+                                */
+                               BT_LOGW("Cannot get index of field type: "
+                                       "field-name=\"%s\", src-index=%d, child-index=%d, first-level-done=%d",
+                                       field_name, src_index, child_index, first_level_done);
+                               ret = -1;
+                               goto end;
+                       } else if (child_index > src_index &&
+                                       !first_level_done) {
+                               BT_LOGW("Child field type is located after source field type: "
+                                       "field-name=\"%s\", src-index=%d, child-index=%d, first-level-done=%d",
+                                       field_name, src_index, child_index, first_level_done);
+                               ret = -1;
+                               goto end;
+                       }
+
+                       /* Next path token */
+                       cur_ptoken = g_list_next(cur_ptoken);
+                       first_level_done = BT_TRUE;
+               }
+
+               /* Create new field path entry */
+               g_array_append_val(field_path->indexes, child_index);
+
+               /* Get child field type */
+               child_type = bt_ctf_field_type_common_borrow_field_at_index(type,
+                       child_index);
+               if (!child_type) {
+                       BT_LOGW("Cannot get child field type: "
+                               "field-name=\"%s\", src-index=%d, child-index=%d, first-level-done=%d",
+                               field_name, src_index, child_index, first_level_done);
+                       ret = -1;
+                       goto end;
+               }
+
+               /* Move child type to current type */
+               bt_get(child_type);
+               BT_MOVE(type, child_type);
+       }
+
+end:
+       bt_put(type);
+       return ret;
+}
+
+/*
+ * Converts a known absolute path token list to a field path object
+ * within the resolving context `ctx`.
+ *
+ * `ptokens` is owned by the caller. `field_path` is an output parameter
+ * owned by the caller that must be filled here.
+ */
+static
+int absolute_ptokens_to_field_path(GList *ptokens,
+               struct bt_ctf_field_path *field_path,
+               struct resolve_context *ctx)
+{
+       int ret = 0;
+       GList *cur_ptoken;
+       struct bt_ctf_field_type_common *type;
+
+       /* Skip absolute path tokens */
+       cur_ptoken = g_list_nth(ptokens,
+               absolute_path_prefix_ptoken_counts[field_path->root]);
+
+       /* Start with root type */
+       type = get_type_from_ctx(ctx, field_path->root);
+       if (!type) {
+               /* Error: root type is not available */
+               BT_LOGW("Root field type is not available: "
+                       "root-scope=%s",
+                       bt_ctf_scope_string(field_path->root));
+               ret = -1;
+               goto end;
+       }
+
+       /* Locate target */
+       ret = ptokens_to_field_path(cur_ptoken, field_path, type, INT_MAX);
+
+end:
+       return ret;
+}
+
+/*
+ * Converts a known relative path token list to a field path object
+ * within the resolving context `ctx`.
+ *
+ * `ptokens` is owned by the caller. `field_path` is an output parameter
+ * owned by the caller that must be filled here.
+ */
+static
+int relative_ptokens_to_field_path(GList *ptokens,
+               struct bt_ctf_field_path *field_path,
+               struct resolve_context *ctx)
+{
+       int ret = 0;
+       int parent_pos_in_stack;
+       struct bt_ctf_field_path *tail_field_path = bt_ctf_field_path_create();
+
+       if (!tail_field_path) {
+               BT_LOGE_STR("Cannot create empty field path.");
+               ret = -1;
+               goto end;
+       }
+
+       parent_pos_in_stack = type_stack_size(ctx->type_stack) - 1;
+
+       while (parent_pos_in_stack >= 0) {
+               struct bt_ctf_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,
+                       parent_pos_in_stack)->index;
+
+               BT_LOGV("Locating target field type from current parent field type: "
+                       "parent-pos=%d, parent-ft-addr=%p, cur-index=%d",
+                       parent_pos_in_stack, parent_type, cur_index);
+
+               /* Locate target from current parent type */
+               ret = ptokens_to_field_path(ptokens, tail_field_path,
+                       parent_type, cur_index);
+               if (ret) {
+                       /* Not found... yet */
+                       BT_LOGV_STR("Not found at this point.");
+                       bt_ctf_field_path_clear(tail_field_path);
+               } else {
+                       /* Found: stitch tail field path to head field path */
+                       int i = 0;
+                       int tail_field_path_len =
+                               tail_field_path->indexes->len;
+
+                       while (BT_TRUE) {
+                               struct bt_ctf_field_type_common *cur_type =
+                                       type_stack_at(ctx->type_stack, i)->type;
+                               int index = type_stack_at(
+                                       ctx->type_stack, i)->index;
+
+                               if (cur_type == parent_type) {
+                                       break;
+                               }
+
+                               g_array_append_val(field_path->indexes,
+                                       index);
+                               i++;
+                       }
+
+                       for (i = 0; i < tail_field_path_len; i++) {
+                               int index = g_array_index(
+                                       tail_field_path->indexes,
+                                       int, i);
+
+                               g_array_append_val(field_path->indexes,
+                                       index);
+                       }
+                       break;
+               }
+
+               parent_pos_in_stack--;
+       }
+
+       if (parent_pos_in_stack < 0) {
+               /* Not found: look in previous scopes */
+               field_path->root--;
+
+               while (field_path->root >= BT_CTF_SCOPE_TRACE_PACKET_HEADER) {
+                       struct bt_ctf_field_type_common *root_type;
+                       bt_ctf_field_path_clear(field_path);
+
+                       BT_LOGV("Looking into potential root scope: scope=%s",
+                               bt_ctf_scope_string(field_path->root));
+                       root_type = get_type_from_ctx(ctx, field_path->root);
+                       if (!root_type) {
+                               field_path->root--;
+                               continue;
+                       }
+
+                       /* Locate target in previous scope */
+                       ret = ptokens_to_field_path(ptokens, field_path,
+                               root_type, INT_MAX);
+                       if (ret) {
+                               /* Not found yet */
+                               BT_LOGV_STR("Not found in this scope.");
+                               field_path->root--;
+                               continue;
+                       }
+
+                       /* Found */
+                       BT_LOGV_STR("Found in this scope.");
+                       break;
+               }
+       }
+
+end:
+       BT_PUT(tail_field_path);
+       return ret;
+}
+
+/*
+ * Converts a path string to a field path object within the resolving
+ * context `ctx`.
+ *
+ * Return value is owned by the caller on success.
+ */
+static
+struct bt_ctf_field_path *pathstr_to_field_path(const char *pathstr,
+               struct resolve_context *ctx)
+{
+       int ret;
+       enum bt_ctf_scope root_scope;
+       GList *ptokens = NULL;
+       struct bt_ctf_field_path *field_path = NULL;
+
+       /* Create field path */
+       field_path = bt_ctf_field_path_create();
+       if (!field_path) {
+               BT_LOGE_STR("Cannot create empty field path.");
+               ret = -1;
+               goto end;
+       }
+
+       /* Convert path string to path tokens */
+       ptokens = pathstr_to_ptokens(pathstr);
+       if (!ptokens) {
+               BT_LOGW("Cannot convert path string to path tokens: "
+                       "path=\"%s\"", pathstr);
+               ret = -1;
+               goto end;
+       }
+
+       /* Absolute or relative path? */
+       root_scope = get_root_scope_from_absolute_pathstr(pathstr);
+
+       if (root_scope == BT_CTF_SCOPE_UNKNOWN) {
+               /* 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_ctf_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_ctf_scope_string(ctx->root_scope),
+                               bt_ctf_scope_string(field_path->root));
+                       goto end;
+               }
+       } else if (root_scope == BT_CTF_SCOPE_ENV) {
+               BT_LOGW("Sequence field types referring the trace environment are not supported as of this version: "
+                       "path=\"%s\"", pathstr);
+               ret = -1;
+               goto end;
+       } else {
+               /* Absolute path: use found root scope */
+               field_path->root = root_scope;
+               BT_LOGV("Detected absolute path: using root scope: "
+                       "scope=%s", bt_ctf_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_ctf_scope_string(root_scope));
+                       goto end;
+               }
+       }
+
+       if (ret == 0) {
+               GString *field_path_pretty =
+                       bt_ctf_field_path_string(field_path);
+               const char *field_path_pretty_str =
+                       field_path_pretty ? field_path_pretty->str : NULL;
+
+               BT_LOGV("Found field path: path=\"%s\", field-path=\"%s\"",
+                       pathstr, field_path_pretty_str);
+
+               if (field_path_pretty) {
+                       g_string_free(field_path_pretty, TRUE);
+               }
+       }
+
+end:
+       if (ret) {
+               BT_PUT(field_path);
+       }
+
+       ptokens_destroy(ptokens);
+       return field_path;
+}
+
+/*
+ * Retrieves a field type by following the field path `field_path` in
+ * the resolving context `ctx`.
+ *
+ * Return value is owned by the caller on success.
+ */
+static
+struct bt_ctf_field_type_common *field_path_to_field_type(
+               struct bt_ctf_field_path *field_path,
+               struct resolve_context *ctx)
+{
+       int i;
+       struct bt_ctf_field_type_common *type;
+
+       /* Start with root type */
+       type = get_type_from_ctx(ctx, field_path->root);
+       bt_get(type);
+       if (!type) {
+               /* Error: root type is not available */
+               BT_LOGW("Root field type is not available: root-scope=%s",
+                       bt_ctf_scope_string(field_path->root));
+               goto error;
+       }
+
+       /* Locate target */
+       for (i = 0; i < field_path->indexes->len; i++) {
+               struct bt_ctf_field_type_common *child_type;
+               int child_index =
+                       g_array_index(field_path->indexes, int, i);
+
+               /* Get child field type */
+               child_type = bt_ctf_field_type_common_borrow_field_at_index(type,
+                       child_index);
+               if (!child_type) {
+                       BT_LOGW("Cannot get field type: "
+                               "parent-ft-addr=%p, index=%d", type, i);
+                       goto error;
+               }
+
+               /* Move child type to current type */
+               bt_get(child_type);
+               BT_MOVE(type, child_type);
+       }
+
+       return type;
+
+error:
+       BT_PUT(type);
+       return type;
+}
+
+/*
+ * Returns the equivalent field path object of the context type stack.
+ *
+ * Return value is owned by the caller on success.
+ */
+static
+struct bt_ctf_field_path *get_ctx_stack_field_path(struct resolve_context *ctx)
+{
+       int i;
+       struct bt_ctf_field_path *field_path;
+
+       /* Create field path */
+       field_path = bt_ctf_field_path_create();
+       if (!field_path) {
+               BT_LOGE_STR("Cannot create empty field path.");
+               goto error;
+       }
+
+       field_path->root = ctx->root_scope;
+
+       for (i = 0; i < type_stack_size(ctx->type_stack); i++) {
+               struct type_stack_frame *frame;
+
+               frame = type_stack_at(ctx->type_stack, i);
+               g_array_append_val(field_path->indexes, frame->index);
+       }
+
+       return field_path;
+
+error:
+       BT_PUT(field_path);
+       return field_path;
+}
+
+/*
+ * Returns the lowest common ancestor of two field path objects
+ * having the same root scope.
+ *
+ * `field_path1` and `field_path2` are owned by the caller.
+ */
+static
+int get_field_paths_lca_index(struct bt_ctf_field_path *field_path1,
+               struct bt_ctf_field_path *field_path2)
+{
+       int lca_index = 0;
+       int field_path1_len, field_path2_len;
+
+       if (BT_LOG_ON_VERBOSE) {
+               GString *field_path1_pretty =
+                       bt_ctf_field_path_string(field_path1);
+               GString *field_path2_pretty =
+                       bt_ctf_field_path_string(field_path2);
+               const char *field_path1_pretty_str =
+                       field_path1_pretty ? field_path1_pretty->str : NULL;
+               const char *field_path2_pretty_str =
+                       field_path2_pretty ? field_path2_pretty->str : NULL;
+
+               BT_LOGV("Finding lowest common ancestor (LCA) between two field paths: "
+                       "field-path-1=\"%s\", field-path-2=\"%s\"",
+                       field_path1_pretty_str, field_path2_pretty_str);
+
+               if (field_path1_pretty) {
+                       g_string_free(field_path1_pretty, TRUE);
+               }
+
+               if (field_path2_pretty) {
+                       g_string_free(field_path2_pretty, TRUE);
+               }
+       }
+
+       /*
+        * Start from both roots and find the first mismatch.
+        */
+       BT_ASSERT(field_path1->root == field_path2->root);
+       field_path1_len = field_path1->indexes->len;
+       field_path2_len = field_path2->indexes->len;
+
+       while (BT_TRUE) {
+               int target_index, ctx_index;
+
+               if (lca_index == field_path2_len ||
+                               lca_index == field_path1_len) {
+                       /*
+                        * This means that both field paths never split.
+                        * This is invalid because the target cannot be
+                        * an ancestor of the source.
+                        */
+                       BT_LOGW("Source field type is an ancestor of target field type or vice versa: "
+                               "lca-index=%d, field-path-1-len=%d, "
+                               "field-path-2-len=%d",
+                               lca_index, field_path1_len, field_path2_len);
+                       lca_index = -1;
+                       break;
+               }
+
+               target_index = g_array_index(field_path1->indexes, int,
+                       lca_index);
+               ctx_index = g_array_index(field_path2->indexes, int,
+                       lca_index);
+
+               if (target_index != ctx_index) {
+                       /* LCA index is the previous */
+                       break;
+               }
+
+               lca_index++;
+       }
+
+       BT_LOGV("Found LCA: lca-index=%d", lca_index);
+       return lca_index;
+}
+
+/*
+ * Validates a target field path.
+ *
+ * `target_field_path` and `target_type` are owned by the caller.
+ */
+static
+int validate_target_field_path(struct bt_ctf_field_path *target_field_path,
+               struct bt_ctf_field_type_common *target_type,
+               struct resolve_context *ctx)
+{
+       int ret = 0;
+       struct bt_ctf_field_path *ctx_field_path;
+       int target_field_path_len = target_field_path->indexes->len;
+       int lca_index;
+       enum bt_ctf_field_type_id ctx_cur_field_type_id;
+       enum bt_ctf_field_type_id target_type_id;
+
+       /* Get context field path */
+       ctx_field_path = get_ctx_stack_field_path(ctx);
+       if (!ctx_field_path) {
+               BT_LOGW_STR("Cannot get field path from context's stack.");
+               ret = -1;
+               goto end;
+       }
+
+       /*
+        * Make sure the target is not a root.
+        */
+       if (target_field_path_len == 0) {
+               BT_LOGW_STR("Target field path's length is 0 (targeting the root).");
+               ret = -1;
+               goto end;
+       }
+
+       /*
+        * Make sure the root of the target field path is not located
+        * after the context field path's root.
+        */
+       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_ctf_scope_string(target_field_path->root),
+                       bt_ctf_scope_string(ctx_field_path->root));
+               ret = -1;
+               goto end;
+       }
+
+       if (target_field_path->root == ctx_field_path->root) {
+               int target_index, ctx_index;
+
+               /*
+                * Find the index of the lowest common ancestor of both field
+                * paths.
+                */
+               lca_index = get_field_paths_lca_index(target_field_path,
+                       ctx_field_path);
+               if (lca_index < 0) {
+                       BT_LOGW_STR("Cannot get least common ancestor.");
+                       ret = -1;
+                       goto end;
+               }
+
+               /*
+                * Make sure the target field path is located before the
+                * context field path.
+                */
+               target_index = g_array_index(target_field_path->indexes,
+                       int, lca_index);
+               ctx_index = g_array_index(ctx_field_path->indexes,
+                       int, lca_index);
+
+               if (target_index >= ctx_index) {
+                       BT_LOGW("Target field type's index is greater than or equal to source field type's index in LCA: "
+                               "lca-index=%d, target-index=%d, source-index=%d",
+                               lca_index, target_index, ctx_index);
+                       ret = -1;
+                       goto end;
+               }
+       }
+
+       /*
+        * Make sure the target type has the right type and properties.
+        */
+       ctx_cur_field_type_id = bt_ctf_field_type_common_get_type_id(
+               ctx->cur_field_type);
+       target_type_id = bt_ctf_field_type_common_get_type_id(target_type);
+
+       switch (ctx_cur_field_type_id) {
+       case BT_CTF_FIELD_TYPE_ID_VARIANT:
+               if (target_type_id != BT_CTF_FIELD_TYPE_ID_ENUM) {
+                       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_ctf_field_type_id_string(target_type_id));
+                       ret = -1;
+                       goto end;
+               }
+               break;
+       case BT_CTF_FIELD_TYPE_ID_SEQUENCE:
+               if (target_type_id != BT_CTF_FIELD_TYPE_ID_INTEGER ||
+                               bt_ctf_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_ctf_field_type_id_string(target_type_id));
+                       ret = -1;
+                       goto end;
+               }
+               break;
+       default:
+               abort();
+       }
+
+end:
+       BT_PUT(ctx_field_path);
+       return ret;
+}
+
+/*
+ * Resolves a variant or sequence field type `type`.
+ *
+ * `type` is owned by the caller.
+ */
+static
+int resolve_sequence_or_variant_type(struct bt_ctf_field_type_common *type,
+               struct resolve_context *ctx)
+{
+       int ret = 0;
+       const char *pathstr;
+       enum bt_ctf_field_type_id type_id = bt_ctf_field_type_common_get_type_id(type);
+       struct bt_ctf_field_path *target_field_path = NULL;
+       struct bt_ctf_field_type_common *target_type = NULL;
+       GString *target_field_path_pretty = NULL;
+       const char *target_field_path_pretty_str;
+
+
+       /* Get path string */
+       switch (type_id) {
+       case BT_CTF_FIELD_TYPE_ID_SEQUENCE:
+               pathstr =
+                       bt_ctf_field_type_common_sequence_get_length_field_name(type);
+               break;
+       case BT_CTF_FIELD_TYPE_ID_VARIANT:
+               pathstr =
+                       bt_ctf_field_type_common_variant_get_tag_name(type);
+               break;
+       default:
+               abort();
+       }
+
+       if (!pathstr) {
+               BT_LOGW_STR("Cannot get path string.");
+               ret = -1;
+               goto end;
+       }
+
+       /* Get target field path out of path string */
+       target_field_path = pathstr_to_field_path(pathstr, ctx);
+       if (!target_field_path) {
+               BT_LOGW("Cannot get target field path for path string: "
+                       "path=\"%s\"", pathstr);
+               ret = -1;
+               goto end;
+       }
+
+       target_field_path_pretty = bt_ctf_field_path_string(target_field_path);
+       target_field_path_pretty_str =
+               target_field_path_pretty ? target_field_path_pretty->str : NULL;
+
+       /* Get target field type */
+       target_type = field_path_to_field_type(target_field_path, ctx);
+       if (!target_type) {
+               BT_LOGW("Cannot get target field type for path string: "
+                       "path=\"%s\", target-field-path=\"%s\"",
+                       pathstr, target_field_path_pretty_str);
+               ret = -1;
+               goto end;
+       }
+
+       ret = validate_target_field_path(target_field_path, target_type, ctx);
+       if (ret) {
+               BT_LOGW("Invalid target field path for path string: "
+                       "path=\"%s\", target-field-path=\"%s\"",
+                       pathstr, target_field_path_pretty_str);
+               goto end;
+       }
+
+       /* Set target field path and target field type */
+       switch (type_id) {
+       case BT_CTF_FIELD_TYPE_ID_SEQUENCE:
+               ret = bt_ctf_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: "
+                               "ret=%d, ft-addr=%p, path=\"%s\", target-field-path=\"%s\"",
+                               ret, type, pathstr,
+                               target_field_path_pretty_str);
+                       goto end;
+               }
+               break;
+       case BT_CTF_FIELD_TYPE_ID_VARIANT:
+               ret = bt_ctf_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: "
+                               "ret=%d, ft-addr=%p, path=\"%s\", target-field-path=\"%s\"",
+                               ret, type, pathstr,
+                               target_field_path_pretty_str);
+                       goto end;
+               }
+
+               ret = bt_ctf_field_type_common_variant_set_tag_field_type(
+                       type, target_type);
+               if (ret) {
+                       BT_LOGW("Cannot set varaint field type's tag field type: "
+                               "ret=%d, ft-addr=%p, path=\"%s\", target-field-path=\"%s\"",
+                               ret, type, pathstr,
+                               target_field_path_pretty_str);
+                       goto end;
+               }
+               break;
+       default:
+               abort();
+       }
+
+end:
+       if (target_field_path_pretty) {
+               g_string_free(target_field_path_pretty, TRUE);
+       }
+
+       BT_PUT(target_field_path);
+       BT_PUT(target_type);
+       return ret;
+}
+
+/*
+ * Resolves a field type `type`.
+ *
+ * `type` is owned by the caller.
+ */
+static
+int resolve_type(struct bt_ctf_field_type_common *type, struct resolve_context *ctx)
+{
+       int ret = 0;
+       enum bt_ctf_field_type_id type_id;
+
+       if (!type) {
+               /* Type is not available; still valid */
+               goto end;
+       }
+
+       type_id = bt_ctf_field_type_common_get_type_id(type);
+       ctx->cur_field_type = type;
+
+       /* Resolve sequence/variant field type */
+       switch (type_id) {
+       case BT_CTF_FIELD_TYPE_ID_SEQUENCE:
+       case BT_CTF_FIELD_TYPE_ID_VARIANT:
+               ret = resolve_sequence_or_variant_type(type, ctx);
+               if (ret) {
+                       BT_LOGW("Cannot resolve sequence field type's length or variant field type's tag: "
+                               "ret=%d, ft-addr=%p", ret, type);
+                       goto end;
+               }
+               break;
+       default:
+               break;
+       }
+
+       /* Recurse into compound types */
+       switch (type_id) {
+       case BT_CTF_FIELD_TYPE_ID_STRUCT:
+       case BT_CTF_FIELD_TYPE_ID_VARIANT:
+       case BT_CTF_FIELD_TYPE_ID_SEQUENCE:
+       case BT_CTF_FIELD_TYPE_ID_ARRAY:
+       {
+               int64_t field_count, f_index;
+
+               ret = type_stack_push(ctx->type_stack, type);
+               if (ret) {
+                       BT_LOGW("Cannot push field type on context's stack: "
+                               "ft-addr=%p", type);
+                       goto end;
+               }
+
+               field_count = bt_ctf_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",
+                               field_count, type);
+                       ret = field_count;
+                       goto end;
+               }
+
+               for (f_index = 0; f_index < field_count; f_index++) {
+                       struct bt_ctf_field_type_common *child_type =
+                               bt_ctf_field_type_common_borrow_field_at_index(type,
+                                       f_index);
+
+                       if (!child_type) {
+                               BT_LOGW("Cannot get field type's child field: "
+                                       "ft-addr=%p, index=%" PRId64 ", "
+                                       "count=%" PRId64, type, f_index,
+                                       field_count);
+                               ret = -1;
+                               goto end;
+                       }
+
+                       if (type_id == BT_CTF_FIELD_TYPE_ID_ARRAY||
+                                       type_id == BT_CTF_FIELD_TYPE_ID_SEQUENCE) {
+                               type_stack_peek(ctx->type_stack)->index = -1;
+                       } else {
+                               type_stack_peek(ctx->type_stack)->index =
+                                       f_index;
+                       }
+
+                       BT_LOGV("Resolving field type's child field type: "
+                               "parent-ft-addr=%p, child-ft-addr=%p, "
+                               "index=%" PRId64 ", count=%" PRId64,
+                               type, child_type, f_index, field_count);
+                       ret = resolve_type(child_type, ctx);
+                       if (ret) {
+                               goto end;
+                       }
+               }
+
+               type_stack_pop(ctx->type_stack);
+               break;
+       }
+       default:
+               break;
+       }
+
+end:
+       return ret;
+}
+
+/*
+ * Resolves the root field type corresponding to the scope `root_scope`.
+ */
+static
+int resolve_root_type(enum bt_ctf_scope root_scope, struct resolve_context *ctx)
+{
+       int ret;
+
+       BT_ASSERT(type_stack_size(ctx->type_stack) == 0);
+       ctx->root_scope = root_scope;
+       ret = resolve_type(get_type_from_ctx(ctx, root_scope), ctx);
+       ctx->root_scope = BT_CTF_SCOPE_UNKNOWN;
+
+       return ret;
+}
+
+BT_HIDDEN
+int bt_ctf_resolve_types(
+               struct bt_value *environment,
+               struct bt_ctf_field_type_common *packet_header_type,
+               struct bt_ctf_field_type_common *packet_context_type,
+               struct bt_ctf_field_type_common *event_header_type,
+               struct bt_ctf_field_type_common *stream_event_ctx_type,
+               struct bt_ctf_field_type_common *event_context_type,
+               struct bt_ctf_field_type_common *event_payload_type,
+               enum bt_ctf_resolve_flag flags)
+{
+       int ret = 0;
+       struct resolve_context ctx = {
+               .environment = environment,
+               .scopes = {
+                       packet_header_type,
+                       packet_context_type,
+                       event_header_type,
+                       stream_event_ctx_type,
+                       event_context_type,
+                       event_payload_type,
+               },
+               .root_scope = BT_CTF_SCOPE_UNKNOWN,
+       };
+
+       BT_LOGV("Resolving field types: "
+               "packet-header-ft-addr=%p, "
+               "packet-context-ft-addr=%p, "
+               "event-header-ft-addr=%p, "
+               "stream-event-context-ft-addr=%p, "
+               "event-context-ft-addr=%p, "
+               "event-payload-ft-addr=%p",
+               packet_header_type, packet_context_type, event_header_type,
+               stream_event_ctx_type, event_context_type, event_payload_type);
+
+       /* Initialize type stack */
+       ctx.type_stack = type_stack_create();
+       if (!ctx.type_stack) {
+               BT_LOGE_STR("Cannot create field type stack.");
+               ret = -1;
+               goto end;
+       }
+
+       /* Resolve packet header type */
+       if (flags & BT_CTF_RESOLVE_FLAG_PACKET_HEADER) {
+               ret = resolve_root_type(BT_CTF_SCOPE_TRACE_PACKET_HEADER, &ctx);
+               if (ret) {
+                       BT_LOGW("Cannot resolve trace packet header field type: "
+                               "ret=%d", ret);
+                       goto end;
+               }
+       }
+
+       /* Resolve packet context type */
+       if (flags & BT_CTF_RESOLVE_FLAG_PACKET_CONTEXT) {
+               ret = resolve_root_type(BT_CTF_SCOPE_STREAM_PACKET_CONTEXT, &ctx);
+               if (ret) {
+                       BT_LOGW("Cannot resolve stream packet context field type: "
+                               "ret=%d", ret);
+                       goto end;
+               }
+       }
+
+       /* Resolve event header type */
+       if (flags & BT_CTF_RESOLVE_FLAG_EVENT_HEADER) {
+               ret = resolve_root_type(BT_CTF_SCOPE_STREAM_EVENT_HEADER, &ctx);
+               if (ret) {
+                       BT_LOGW("Cannot resolve stream event header field type: "
+                               "ret=%d", ret);
+                       goto end;
+               }
+       }
+
+       /* Resolve stream event context type */
+       if (flags & BT_CTF_RESOLVE_FLAG_STREAM_EVENT_CTX) {
+               ret = resolve_root_type(BT_CTF_SCOPE_STREAM_EVENT_CONTEXT, &ctx);
+               if (ret) {
+                       BT_LOGW("Cannot resolve stream event context field type: "
+                               "ret=%d", ret);
+                       goto end;
+               }
+       }
+
+       /* Resolve event context type */
+       if (flags & BT_CTF_RESOLVE_FLAG_EVENT_CONTEXT) {
+               ret = resolve_root_type(BT_CTF_SCOPE_EVENT_CONTEXT, &ctx);
+               if (ret) {
+                       BT_LOGW("Cannot resolve event context field type: "
+                               "ret=%d", ret);
+                       goto end;
+               }
+       }
+
+       /* Resolve event payload type */
+       if (flags & BT_CTF_RESOLVE_FLAG_EVENT_PAYLOAD) {
+               ret = resolve_root_type(BT_CTF_SCOPE_EVENT_FIELDS, &ctx);
+               if (ret) {
+                       BT_LOGW("Cannot resolve event payload field type: "
+                               "ret=%d", ret);
+                       goto end;
+               }
+       }
+
+       BT_LOGV_STR("Resolved field types.");
+
+end:
+       type_stack_destroy(ctx.type_stack);
+
+       return ret;
+}
index 4d2abecbddbcdcd8718e1fb0ca603aff61db1813..6461a7cb3386ee24d22cf24008adc55307a2362d 100644 (file)
 #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-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>
 #include <babeltrace/bitfield-internal.h>
+#include <babeltrace/common-internal.h>
 #include <babeltrace/compat/fcntl-internal.h>
+#include <babeltrace/ctf-writer/field-types-internal.h>
+#include <babeltrace/ctf-writer/field-types.h>
+#include <babeltrace/ctf-writer/fields-internal.h>
+#include <babeltrace/ctf-writer/fields.h>
+#include <babeltrace/ctf-writer/serialize-internal.h>
+#include <babeltrace/ctf-writer/utils-internal.h>
+#include <babeltrace/endian-internal.h>
+#include <babeltrace/mmap-align-internal.h>
 #include <babeltrace/types.h>
-#include <babeltrace/common-internal.h>
 #include <glib.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
 
 #if (FLT_RADIX != 2)
 # error "Unsupported floating point radix"
@@ -205,18 +205,18 @@ int integer_write(struct bt_ctf_stream_pos *pos, union intval value,
 }
 
 BT_HIDDEN
-int bt_ctf_field_integer_write(struct bt_field_common *field,
+int bt_ctf_field_integer_write(struct bt_ctf_field_common *field,
                struct bt_ctf_stream_pos *pos,
                enum bt_ctf_byte_order native_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);
+       struct bt_ctf_field_type_common_integer *int_type =
+               BT_CTF_FROM_COMMON(field->type);
+       struct bt_ctf_field_common_integer *int_field = BT_CTF_FROM_COMMON(field);
        enum bt_ctf_byte_order byte_order;
        union intval value;
 
        byte_order = (int) int_type->user_byte_order;
-       if ((int) byte_order == BT_BYTE_ORDER_NATIVE) {
+       if ((int) byte_order == BT_CTF_BYTE_ORDER_NATIVE) {
                byte_order = native_byte_order;
        }
 
@@ -229,19 +229,19 @@ int bt_ctf_field_integer_write(struct bt_field_common *field,
 
 BT_HIDDEN
 int bt_ctf_field_floating_point_write(
-               struct bt_field_common *field,
+               struct bt_ctf_field_common *field,
                struct bt_ctf_stream_pos *pos,
                enum bt_ctf_byte_order native_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);
+       struct bt_ctf_field_type_common_floating_point *flt_type =
+               BT_CTF_FROM_COMMON(field->type);
+       struct bt_ctf_field_common_floating_point *flt_field = BT_CTF_FROM_COMMON(field);
        enum bt_ctf_byte_order byte_order;
        union intval value;
        unsigned int size;
 
        byte_order = (int) flt_type->user_byte_order;
-       if ((int) byte_order == BT_BYTE_ORDER_NATIVE) {
+       if ((int) byte_order == BT_CTF_BYTE_ORDER_NATIVE) {
                byte_order = native_byte_order;
        }
 
index a371f400d09f002688476079e62e7c4dc1c47bcc..67550f0b5a6db128c00b7b1415e6a289d4ad9a81 100644 (file)
 #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/assert-pre-internal.h>
+#include <babeltrace/align-internal.h>
+#include <babeltrace/assert-internal.h>
+#include <babeltrace/compiler-internal.h>
+#include <babeltrace/ctf-writer/clock-class-internal.h>
+#include <babeltrace/ctf-writer/event-class-internal.h>
 #include <babeltrace/ctf-writer/event-internal.h>
 #include <babeltrace/ctf-writer/event.h>
+#include <babeltrace/ctf-writer/field-types-internal.h>
+#include <babeltrace/ctf-writer/field-wrapper-internal.h>
+#include <babeltrace/ctf-writer/fields-internal.h>
+#include <babeltrace/ctf-writer/stream-class-internal.h>
 #include <babeltrace/ctf-writer/trace.h>
-#include <babeltrace/compiler-internal.h>
-#include <babeltrace/assert-internal.h>
-#include <babeltrace/assert-pre-internal.h>
+#include <babeltrace/ctf-writer/utils-internal.h>
+#include <babeltrace/ctf-writer/utils.h>
+#include <babeltrace/ctf-writer/validation-internal.h>
+#include <babeltrace/ctf-writer/visitor-internal.h>
+#include <babeltrace/ctf-writer/writer-internal.h>
+#include <babeltrace/endian-internal.h>
+#include <babeltrace/ref.h>
 #include <inttypes.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+BT_HIDDEN
+int bt_ctf_stream_class_common_initialize(struct bt_ctf_stream_class_common *stream_class,
+               const char *name, bt_object_release_func release_func)
+{
+       BT_LOGD("Initializing common stream class object: name=\"%s\"", name);
+
+       bt_object_init_shared_with_parent(&stream_class->base, release_func);
+       stream_class->name = g_string_new(name);
+       stream_class->event_classes = g_ptr_array_new_with_free_func(
+               (GDestroyNotify) bt_object_try_spec_release);
+       if (!stream_class->event_classes) {
+               BT_LOGE_STR("Failed to allocate a GPtrArray.");
+               goto error;
+       }
+
+       stream_class->event_classes_ht = g_hash_table_new_full(g_int64_hash,
+                       g_int64_equal, g_free, NULL);
+       if (!stream_class->event_classes_ht) {
+               BT_LOGE_STR("Failed to allocate a GHashTable.");
+               goto error;
+       }
+
+       BT_LOGD("Initialized common stream class object: addr=%p, name=\"%s\"",
+               stream_class, name);
+       return 0;
+
+error:
+       return -1;
+}
+
+BT_HIDDEN
+void bt_ctf_stream_class_common_finalize(struct bt_ctf_stream_class_common *stream_class)
+{
+       BT_LOGD("Finalizing common stream class: addr=%p, name=\"%s\", id=%" PRId64,
+               stream_class, bt_ctf_stream_class_common_get_name(stream_class),
+               bt_ctf_stream_class_common_get_id(stream_class));
+       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_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);
+}
+
+static
+void event_class_exists(gpointer element, gpointer query)
+{
+       struct bt_ctf_event_class_common *event_class_a = element;
+       struct bt_ctf_search_query *search_query = query;
+       struct bt_ctf_event_class_common *event_class_b = search_query->value;
+       int64_t id_a, id_b;
+
+       if (search_query->value == element) {
+               search_query->found = 1;
+               goto end;
+       }
+
+       /*
+        * Two event classes cannot share the same ID in a given
+        * stream class.
+        */
+       id_a = bt_ctf_event_class_common_get_id(event_class_a);
+       id_b = bt_ctf_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 */
+               goto end;
+       }
+
+       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_ctf_event_class_common_get_name(event_class_a));
+               search_query->found = 1;
+               goto end;
+       }
+
+end:
+       return;
+}
+
+BT_HIDDEN
+int bt_ctf_stream_class_common_add_event_class(
+               struct bt_ctf_stream_class_common *stream_class,
+               struct bt_ctf_event_class_common *event_class,
+               bt_ctf_validation_flag_copy_field_type_func copy_field_type_func)
+{
+       int ret = 0;
+       int64_t *event_id = NULL;
+       struct bt_ctf_trace_common *trace = NULL;
+       struct bt_ctf_stream_class_common *old_stream_class = NULL;
+       struct bt_ctf_validation_output validation_output = { 0 };
+       struct bt_ctf_field_type_common *packet_header_type = NULL;
+       struct bt_ctf_field_type_common *packet_context_type = NULL;
+       struct bt_ctf_field_type_common *event_header_type = NULL;
+       struct bt_ctf_field_type_common *stream_event_ctx_type = NULL;
+       struct bt_ctf_field_type_common *event_context_type = NULL;
+       struct bt_ctf_field_type_common *event_payload_type = NULL;
+       const enum bt_ctf_validation_flag validation_flags =
+               BT_CTF_VALIDATION_FLAG_EVENT;
+       struct bt_ctf_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",
+                       stream_class, event_class);
+               ret = -1;
+               goto end;
+       }
+
+       BT_LOGD("Adding 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_ctf_stream_class_common_get_name(stream_class),
+               bt_ctf_stream_class_common_get_id(stream_class),
+               event_class,
+               bt_ctf_event_class_common_get_name(event_class),
+               bt_ctf_event_class_common_get_id(event_class));
+       trace = bt_ctf_stream_class_common_borrow_trace(stream_class);
+
+       if (stream_class->frozen) {
+               /*
+                * We only check that the event class to be added has a
+                * single class which matches the stream class's
+                * expected clock class if the stream class is frozen.
+                * If it's not, then this event class is added "as is"
+                * and the validation will be performed when calling
+                * either bt_ctf_trace_add_stream_class() or
+                * bt_ctf_event_create(). This is because the stream class's
+                * field types (packet context, event header, event
+                * context) could change before the next call to one of
+                * those two functions.
+                */
+               expected_clock_class = bt_get(stream_class->clock_class);
+
+               /*
+                * At this point, `expected_clock_class` can be NULL,
+                * and bt_ctf_event_class_validate_single_clock_class()
+                * below can set it.
+                */
+               ret = bt_ctf_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 "
+                               "recursively mapped to its 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_common_get_id(stream_class),
+                               bt_ctf_stream_class_common_get_name(stream_class),
+                               expected_clock_class,
+                               expected_clock_class ?
+                                       bt_ctf_clock_class_get_name(expected_clock_class) :
+                                       NULL);
+                       goto end;
+               }
+       }
+
+       event_id = g_new(int64_t, 1);
+       if (!event_id) {
+               BT_LOGE_STR("Failed to allocate one int64_t.");
+               ret = -1;
+               goto end;
+       }
+
+       /* Check for duplicate event classes */
+       struct bt_ctf_search_query query = { .value = event_class, .found = 0 };
+       g_ptr_array_foreach(stream_class->event_classes, event_class_exists,
+               &query);
+       if (query.found) {
+               BT_LOGW_STR("Another event class part of this stream class has the same ID.");
+               ret = -1;
+               goto end;
+       }
+
+       old_stream_class = bt_ctf_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: "
+                       "event-class-stream-class-addr=%p, "
+                       "event-class-stream-class-name=\"%s\", "
+                       "event-class-stream-class-id=%" PRId64,
+                       old_stream_class,
+                       bt_ctf_stream_class_common_get_name(old_stream_class),
+                       bt_ctf_stream_class_common_get_id(old_stream_class));
+               ret = -1;
+               goto end;
+       }
+
+       if (trace) {
+               /*
+                * If the stream class is associated with a trace, then
+                * both those objects are frozen. Also, this event class
+                * is about to be frozen.
+                *
+                * Therefore the event class must be validated here.
+                * The trace and stream class should be valid at this
+                * point.
+                */
+               BT_ASSERT(trace->valid);
+               BT_ASSERT(stream_class->valid);
+               packet_header_type =
+                       bt_ctf_trace_common_borrow_packet_header_field_type(trace);
+               packet_context_type =
+                       bt_ctf_stream_class_common_borrow_packet_context_field_type(
+                               stream_class);
+               event_header_type =
+                       bt_ctf_stream_class_common_borrow_event_header_field_type(
+                               stream_class);
+               stream_event_ctx_type =
+                       bt_ctf_stream_class_common_borrow_event_context_field_type(
+                               stream_class);
+               event_context_type =
+                       bt_ctf_event_class_common_borrow_context_field_type(
+                               event_class);
+               event_payload_type =
+                       bt_ctf_event_class_common_borrow_payload_field_type(
+                               event_class);
+               ret = bt_ctf_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,
+                       copy_field_type_func);
+
+               if (ret) {
+                       /*
+                        * This means something went wrong during the
+                        * validation process, not that the objects are
+                        * invalid.
+                        */
+                       BT_LOGE("Failed to validate event class: ret=%d", ret);
+                       goto end;
+               }
+
+               if ((validation_output.valid_flags & validation_flags) !=
+                               validation_flags) {
+                       /* Invalid event class */
+                       BT_LOGW("Invalid trace, stream class, or event class: "
+                               "valid-flags=0x%x",
+                               validation_output.valid_flags);
+                       ret = -1;
+                       goto end;
+               }
+       }
+
+       /* Only set an event ID if none was explicitly set before */
+       *event_id = bt_ctf_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_ctf_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);
+                       ret = -1;
+                       goto end;
+               }
+               stream_class->next_event_id++;
+               *event_id = stream_class->next_event_id;
+       }
+
+       bt_object_set_parent(&event_class->base, &stream_class->base);
+
+       if (trace) {
+               /*
+                * At this point we know that the function will be
+                * successful. Therefore we can replace the event
+                * class's field types with what's in the validation
+                * output structure and mark this event class as valid.
+                */
+               bt_ctf_validation_replace_types(NULL, NULL, event_class,
+                       &validation_output, validation_flags);
+               event_class->valid = 1;
+
+               /*
+                * Put what was not moved in
+                * bt_ctf_validation_replace_types().
+                */
+               bt_ctf_validation_output_put_types(&validation_output);
+       }
+
+       /* Add to the event classes of the stream class */
+       g_ptr_array_add(stream_class->event_classes, event_class);
+       g_hash_table_insert(stream_class->event_classes_ht, event_id,
+                       event_class);
+       event_id = NULL;
+
+       /* Freeze the event class */
+       bt_ctf_event_class_common_freeze(event_class);
+
+       /*
+        * It is safe to set the stream class's unique clock class
+        * now if the stream class is frozen.
+        */
+       if (stream_class->frozen && expected_clock_class) {
+               BT_ASSERT(!stream_class->clock_class ||
+                       stream_class->clock_class == expected_clock_class);
+               BT_MOVE(stream_class->clock_class, expected_clock_class);
+       }
+
+       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_ctf_stream_class_common_get_name(stream_class),
+               bt_ctf_stream_class_common_get_id(stream_class),
+               event_class,
+               bt_ctf_event_class_common_get_name(event_class),
+               bt_ctf_event_class_common_get_id(event_class));
+
+end:
+       bt_ctf_validation_output_put_types(&validation_output);
+       bt_put(expected_clock_class);
+       g_free(event_id);
+       return ret;
+}
+
+static
+int64_t get_event_class_count(void *element)
+{
+       return bt_ctf_stream_class_get_event_class_count(
+                       (struct bt_ctf_stream_class *) element);
+}
+
+static
+void *get_event_class(void *element, int i)
+{
+       return bt_ctf_stream_class_get_event_class_by_index(
+                       (struct bt_ctf_stream_class *) element, i);
+}
+
+static
+int visit_event_class(void *object, bt_ctf_visitor visitor,void *data)
+{
+       struct bt_ctf_visitor_object obj = {
+               .object = object,
+               .type = BT_CTF_VISITOR_OBJECT_TYPE_EVENT_CLASS
+       };
+
+       return visitor(&obj, data);
+}
+
+BT_HIDDEN
+int bt_ctf_stream_class_common_visit(struct bt_ctf_stream_class_common *stream_class,
+               bt_ctf_visitor visitor, void *data)
+{
+       int ret;
+       struct bt_ctf_visitor_object obj = {
+               .object = stream_class,
+               .type = BT_CTF_VISITOR_OBJECT_TYPE_STREAM_CLASS
+       };
+
+       if (!stream_class || !visitor) {
+               BT_LOGW("Invalid parameter: stream class or visitor is NULL: "
+                       "stream-class-addr=%p, visitor=%p",
+                       stream_class, visitor);
+               ret = -1;
+               goto end;
+       }
+
+       ret = visitor_helper(&obj, get_event_class_count,
+                       get_event_class,
+                       visit_event_class, visitor, data);
+       BT_LOGV("visitor_helper() returned: ret=%d", ret);
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+int bt_ctf_stream_class_visit(struct bt_ctf_stream_class *stream_class,
+               bt_ctf_visitor visitor, void *data)
+{
+       return bt_ctf_stream_class_common_visit(BT_CTF_FROM_COMMON(stream_class),
+               visitor, data);
+}
+
+BT_HIDDEN
+void bt_ctf_stream_class_common_freeze(struct bt_ctf_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_ctf_stream_class_common_get_name(stream_class),
+               bt_ctf_stream_class_common_get_id(stream_class));
+       stream_class->frozen = 1;
+       bt_ctf_field_type_common_freeze(stream_class->event_header_field_type);
+       bt_ctf_field_type_common_freeze(stream_class->packet_context_field_type);
+       bt_ctf_field_type_common_freeze(stream_class->event_context_field_type);
+       bt_ctf_clock_class_freeze(stream_class->clock_class);
+}
+
+BT_HIDDEN
+int bt_ctf_stream_class_common_validate_single_clock_class(
+               struct bt_ctf_stream_class_common *stream_class,
+               struct bt_ctf_clock_class **expected_clock_class)
+{
+       int ret;
+       uint64_t i;
+
+       BT_ASSERT(stream_class);
+       BT_ASSERT(expected_clock_class);
+       ret = bt_ctf_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 "
+                       "is not recursively mapped to the "
+                       "expected clock class: "
+                       "stream-class-addr=%p, "
+                       "stream-class-name=\"%s\", "
+                       "stream-class-id=%" PRId64 ", "
+                       "ft-addr=%p",
+                       stream_class,
+                       bt_ctf_stream_class_common_get_name(stream_class),
+                       stream_class->id,
+                       stream_class->packet_context_field_type);
+               goto end;
+       }
+
+       ret = bt_ctf_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 "
+                       "is not recursively mapped to the "
+                       "expected clock class: "
+                       "stream-class-addr=%p, "
+                       "stream-class-name=\"%s\", "
+                       "stream-class-id=%" PRId64 ", "
+                       "ft-addr=%p",
+                       stream_class,
+                       bt_ctf_stream_class_common_get_name(stream_class),
+                       stream_class->id,
+                       stream_class->event_header_field_type);
+               goto end;
+       }
+
+       ret = bt_ctf_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 "
+                       "is not recursively mapped to the "
+                       "expected clock class: "
+                       "stream-class-addr=%p, "
+                       "stream-class-name=\"%s\", "
+                       "stream-class-id=%" PRId64 ", "
+                       "ft-addr=%p",
+                       stream_class,
+                       bt_ctf_stream_class_common_get_name(stream_class),
+                       stream_class->id,
+                       stream_class->event_context_field_type);
+               goto end;
+       }
+
+       for (i = 0; i < stream_class->event_classes->len; i++) {
+               struct bt_ctf_event_class_common *event_class =
+                       g_ptr_array_index(stream_class->event_classes, i);
+
+               BT_ASSERT(event_class);
+               ret = bt_ctf_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 "
+                               "the expected clock class: "
+                               "stream-class-addr=%p, "
+                               "stream-class-name=\"%s\", "
+                               "stream-class-id=%" PRId64,
+                               stream_class,
+                               bt_ctf_stream_class_common_get_name(stream_class),
+                               stream_class->id);
+                       goto end;
+               }
+       }
+
+end:
+       return ret;
+}
 
 static
 int init_event_header(struct bt_ctf_stream_class *stream_class)
@@ -169,7 +689,7 @@ void bt_ctf_stream_class_destroy(struct bt_object *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_ctf_stream_class_common_finalize(BT_CTF_TO_COMMON(stream_class));
        bt_put(stream_class->clock);
        g_free(stream_class);
 }
@@ -186,10 +706,10 @@ struct bt_ctf_stream_class *bt_ctf_stream_class_create(const char *name)
                goto error;
        }
 
-       ret = bt_stream_class_common_initialize(BT_TO_COMMON(stream_class),
+       ret = bt_ctf_stream_class_common_initialize(BT_CTF_TO_COMMON(stream_class),
                name, bt_ctf_stream_class_destroy);
        if (ret) {
-               /* bt_stream_class_common_initialize() logs errors */
+               /* bt_ctf_stream_class_common_initialize() logs errors */
                goto error;
        }
 
@@ -231,8 +751,8 @@ int try_map_clock_class(struct bt_ctf_stream_class *stream_class,
                goto end;
        }
 
-       BT_ASSERT(((struct bt_field_type_common *) ft)->id ==
-               BT_FIELD_TYPE_ID_INTEGER);
+       BT_ASSERT(((struct bt_ctf_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) {
@@ -255,12 +775,11 @@ int try_map_clock_class(struct bt_ctf_stream_class *stream_class,
                                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));
+               ret = bt_ctf_field_type_common_integer_set_mapped_clock_class_no_check_frozen(
+                       (void *) ft_copy, stream_class->clock->clock_class);
                BT_ASSERT(ret == 0);
 
-               ret = bt_field_type_common_structure_replace_field(
+               ret = bt_ctf_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: "
@@ -420,8 +939,8 @@ int bt_ctf_stream_class_serialize(struct bt_ctf_stream_class *stream_class,
         * 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)));
+       trace = BT_CTF_FROM_COMMON(bt_ctf_stream_class_common_borrow_trace(
+               BT_CTF_TO_COMMON(stream_class)));
        BT_ASSERT(trace);
        packet_header_type = bt_ctf_trace_get_packet_header_field_type(trace);
        trace = NULL;
@@ -514,49 +1033,49 @@ end:
 struct bt_ctf_trace *bt_ctf_stream_class_get_trace(
                struct bt_ctf_stream_class *stream_class)
 {
-       return bt_get(bt_stream_class_common_borrow_trace(
-               BT_TO_COMMON(stream_class)));
+       return bt_get(bt_ctf_stream_class_common_borrow_trace(
+               BT_CTF_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));
+       return bt_ctf_stream_class_common_get_name(BT_CTF_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),
+       return bt_ctf_stream_class_common_set_name(BT_CTF_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));
+       return bt_ctf_stream_class_common_get_id(BT_CTF_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);
+       return bt_ctf_stream_class_common_set_id(BT_CTF_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_get(
-               bt_stream_class_common_borrow_packet_context_field_type(
-                       BT_TO_COMMON(stream_class)));
+               bt_ctf_stream_class_common_borrow_packet_context_field_type(
+                       BT_CTF_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);
+       return bt_ctf_stream_class_common_set_packet_context_field_type(
+               BT_CTF_TO_COMMON(stream_class), (void *) packet_context_type);
 }
 
 struct bt_ctf_field_type *
@@ -564,16 +1083,16 @@ bt_ctf_stream_class_get_event_header_type(
                struct bt_ctf_stream_class *stream_class)
 {
        return bt_get(
-               bt_stream_class_common_borrow_event_header_field_type(
-                       BT_TO_COMMON(stream_class)));
+               bt_ctf_stream_class_common_borrow_event_header_field_type(
+                       BT_CTF_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);
+       return bt_ctf_stream_class_common_set_event_header_field_type(
+               BT_CTF_TO_COMMON(stream_class), (void *) event_header_type);
 }
 
 struct bt_ctf_field_type *
@@ -581,46 +1100,46 @@ bt_ctf_stream_class_get_event_context_type(
                struct bt_ctf_stream_class *stream_class)
 {
        return bt_get(
-               bt_stream_class_common_borrow_event_context_field_type(
-                       BT_TO_COMMON(stream_class)));
+               bt_ctf_stream_class_common_borrow_event_context_field_type(
+                       BT_CTF_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);
+       return bt_ctf_stream_class_common_set_event_context_field_type(
+               BT_CTF_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));
+       return bt_ctf_stream_class_common_get_event_class_count(
+               BT_CTF_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_get(
-               bt_stream_class_common_borrow_event_class_by_index(
-                       BT_TO_COMMON(stream_class), index));
+               bt_ctf_stream_class_common_borrow_event_class_by_index(
+                       BT_CTF_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_get(
-               bt_stream_class_common_borrow_event_class_by_id(
-                       BT_TO_COMMON(stream_class), id));
+               bt_ctf_stream_class_common_borrow_event_class_by_id(
+                       BT_CTF_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);
+       return bt_ctf_stream_class_common_add_event_class(
+               BT_CTF_TO_COMMON(stream_class), BT_CTF_TO_COMMON(event_class),
+               (bt_ctf_validation_flag_copy_field_type_func) bt_ctf_field_type_copy);
 }
index 4145a0caa7d03e498f2d54209d1525d33e238746..455027ce723332175c45ff4453c257b30a53f37f 100644 (file)
 #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/assert-pre-internal.h>
+#include <babeltrace/align-internal.h>
+#include <babeltrace/assert-internal.h>
+#include <babeltrace/compiler-internal.h>
+#include <babeltrace/ctf-writer/event-class-internal.h>
+#include <babeltrace/ctf-writer/event-internal.h>
 #include <babeltrace/ctf-writer/field-types.h>
 #include <babeltrace/ctf-writer/fields-internal.h>
+#include <babeltrace/ctf-writer/stream-class-internal.h>
+#include <babeltrace/ctf-writer/stream-class.h>
+#include <babeltrace/ctf-writer/stream-internal.h>
+#include <babeltrace/ctf-writer/stream.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 <babeltrace/ctf-writer/trace.h>
+#include <babeltrace/ctf-writer/writer-internal.h>
+#include <babeltrace/ref.h>
 #include <inttypes.h>
+#include <stdint.h>
+#include <unistd.h>
+
+BT_HIDDEN
+void bt_ctf_stream_common_finalize(struct bt_ctf_stream_common *stream)
+{
+       BT_LOGD("Finalizing common stream object: addr=%p, name=\"%s\"",
+               stream, bt_ctf_stream_common_get_name(stream));
+
+       if (stream->name) {
+               g_string_free(stream->name, TRUE);
+       }
+}
+
+BT_HIDDEN
+int bt_ctf_stream_common_initialize(
+               struct bt_ctf_stream_common *stream,
+               struct bt_ctf_stream_class_common *stream_class, const char *name,
+               uint64_t id, bt_object_release_func release_func)
+{
+       int ret = 0;
+       struct bt_ctf_trace_common *trace = NULL;
+
+       bt_object_init_shared_with_parent(&stream->base, release_func);
+
+       if (!stream_class) {
+               BT_LOGW_STR("Invalid parameter: stream class is NULL.");
+               goto error;
+       }
+
+       BT_LOGD("Initializing common stream object: stream-class-addr=%p, "
+               "stream-class-name=\"%s\", stream-name=\"%s\", "
+               "stream-id=%" PRIu64,
+               stream_class, bt_ctf_stream_class_common_get_name(stream_class),
+               name, id);
+       trace = bt_ctf_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_ctf_stream_class_common_get_name(stream_class), name);
+               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_ctf_stream_common *trace_stream =
+                               g_ptr_array_index(trace->streams, i);
+
+                       if (trace_stream->stream_class != (void *) 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;
+                       }
+               }
+       }
+
+       /*
+        * Acquire reference to parent since stream will become publicly
+        * reachable; it needs its parent to remain valid.
+        */
+       bt_object_set_parent(&stream->base, &trace->base);
+       stream->stream_class = stream_class;
+       stream->id = (int64_t) id;
+
+       if (name) {
+               stream->name = g_string_new(name);
+               if (!stream->name) {
+                       BT_LOGE_STR("Failed to allocate a GString.");
+                       goto error;
+               }
+       }
+
+       BT_LOGD("Set common stream's trace parent: trace-addr=%p", trace);
+
+       /* Add this stream to the trace's streams */
+       BT_LOGD("Created common stream object: addr=%p", stream);
+       goto end;
+
+error:
+       ret = -1;
+
+end:
+       return ret;
+}
 
 static
 void bt_ctf_stream_destroy(struct bt_object *obj);
@@ -68,7 +165,7 @@ int set_integer_field_value(struct bt_ctf_field* field, uint64_t value)
                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_id_string((int)
                                bt_ctf_field_type_get_type_id(field_type)));
                ret = -1;
                goto end;
@@ -438,7 +535,7 @@ 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;
+       struct bt_ctf_field_common *field_common = (void *) field;
 
        if (!field) {
                goto end;
@@ -514,7 +611,7 @@ int visit_field_update_clock_value(struct bt_ctf_field *field, uint64_t *val)
        case BT_CTF_FIELD_TYPE_ID_SEQUENCE:
        {
                uint64_t i;
-               int64_t len = bt_field_common_sequence_get_length(
+               int64_t len = bt_ctf_field_common_sequence_get_length(
                        (void *) field);
 
                if (len < 0) {
@@ -634,7 +731,7 @@ int set_packet_context_timestamps(struct bt_ctf_stream *stream)
                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 =
+       struct bt_ctf_field_common *packet_context =
                (void *) stream->packet_context;
        uint64_t i;
        int64_t len;
@@ -749,8 +846,8 @@ int set_packet_context_timestamps(struct bt_ctf_stream *stream)
                                "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));
+                               bt_ctf_event_class_common_get_id(event->common.class),
+                               bt_ctf_event_class_common_get_name(event->common.class));
                        goto end;
                }
        }
@@ -923,7 +1020,7 @@ int create_stream_file(struct bt_ctf_writer *writer,
        g_string_assign(filename, "stream");
 
 append_ids:
-       stream_class_id = bt_stream_class_common_get_id(stream->common.stream_class);
+       stream_class_id = bt_ctf_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,
@@ -989,15 +1086,15 @@ struct bt_ctf_stream *bt_ctf_stream_create_with_id(
                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);
+       ret = bt_ctf_stream_common_initialize(BT_CTF_TO_COMMON(stream),
+               BT_CTF_TO_COMMON(stream_class), name, id, bt_ctf_stream_destroy);
        if (ret) {
-               /* bt_stream_common_initialize() logs errors */
+               /* bt_ctf_stream_common_initialize() logs errors */
                goto error;
        }
 
-       trace = BT_FROM_COMMON(bt_stream_class_common_borrow_trace(
-               BT_TO_COMMON(stream_class)));
+       trace = BT_CTF_FROM_COMMON(bt_ctf_stream_class_common_borrow_trace(
+               BT_CTF_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\", "
@@ -1230,8 +1327,8 @@ static int auto_populate_event_header(struct bt_ctf_stream *stream,
        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)));
+               BT_CTF_FROM_COMMON(bt_ctf_stream_common_borrow_class(
+                       BT_CTF_TO_COMMON(stream)));
        int64_t event_class_id;
 
        BT_ASSERT(event);
@@ -1252,7 +1349,7 @@ static int auto_populate_event_header(struct bt_ctf_stream *stream,
 
        id_field = bt_ctf_field_structure_get_field_by_name(
                (void *) event->common.header_field->field, "id");
-       event_class_id = bt_event_class_common_get_id(event->common.class);
+       event_class_id = bt_ctf_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) {
@@ -1281,7 +1378,7 @@ static int auto_populate_event_header(struct bt_ctf_stream *stream,
                        !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);
+                               (void *) ((struct bt_ctf_field_common *) timestamp_field)->type);
                if (mapped_clock_class) {
                        uint64_t timestamp;
 
@@ -1340,10 +1437,10 @@ int bt_ctf_stream_append_event(struct bt_ctf_stream *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))));
+               bt_ctf_event_class_common_get_name(
+                       bt_ctf_event_common_borrow_class(BT_CTF_TO_COMMON(event))),
+               bt_ctf_event_class_common_get_id(
+                       bt_ctf_event_common_borrow_class(BT_CTF_TO_COMMON(event))));
 
        /*
         * The event is not supposed to have a parent stream at this
@@ -1368,12 +1465,12 @@ int bt_ctf_stream_append_event(struct bt_ctf_stream *stream,
 
        /* Make sure the various scopes of the event are set */
        BT_LOGV_STR("Validating event to append.");
-       BT_ASSERT_PRE(bt_event_common_validate(BT_TO_COMMON(event)) == 0,
-               "Invalid event: %!+we", event);
+       BT_ASSERT_PRE(bt_ctf_event_common_validate(BT_CTF_TO_COMMON(event)) == 0,
+               "Invalid event: event-addr=%p", event);
 
        /* Save the new event and freeze it */
        BT_LOGV_STR("Freezing the event to append.");
-       bt_event_common_set_is_frozen(BT_TO_COMMON(event), true);
+       bt_ctf_event_common_set_is_frozen(BT_CTF_TO_COMMON(event), true);
        g_ptr_array_add(stream->events, event);
 
        /*
@@ -1388,10 +1485,10 @@ int bt_ctf_stream_append_event(struct bt_ctf_stream *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))));
+               bt_ctf_event_class_common_get_name(
+                       bt_ctf_event_common_borrow_class(BT_CTF_TO_COMMON(event))),
+               bt_ctf_event_class_common_get_id(
+                       bt_ctf_event_common_borrow_class(BT_CTF_TO_COMMON(event))));
 
 end:
        return ret;
@@ -1448,7 +1545,7 @@ int bt_ctf_stream_set_packet_context(struct bt_ctf_stream *stream,
        }
 
        field_type = bt_ctf_field_get_type(field);
-       if (bt_field_type_common_compare((void *) field_type,
+       if (bt_ctf_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\", "
@@ -1535,7 +1632,7 @@ int bt_ctf_stream_set_packet_header(struct bt_ctf_stream *stream,
        field_type = bt_ctf_field_get_type(field);
        BT_ASSERT(field_type);
 
-       if (bt_field_type_common_compare((void *) field_type,
+       if (bt_ctf_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\", "
@@ -1567,7 +1664,7 @@ void reset_structure_field(struct bt_ctf_field *structure, const char *name)
 
        member = bt_ctf_field_structure_get_field_by_name(structure, name);
        if (member) {
-               bt_field_common_reset_recursive((void *) member);
+               bt_ctf_field_common_reset_recursive((void *) member);
                bt_put(member);
        }
 }
@@ -1619,7 +1716,7 @@ int bt_ctf_stream_flush(struct bt_ctf_stream *stream)
        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(
+       trace = BT_CTF_FROM_COMMON(bt_ctf_stream_class_common_borrow_trace(
                stream->common.stream_class));
        BT_ASSERT(trace);
        native_byte_order = bt_ctf_trace_get_native_byte_order(trace);
@@ -1675,8 +1772,8 @@ int bt_ctf_stream_flush(struct bt_ctf_stream *stream)
                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_CTF_FROM_COMMON(bt_ctf_event_common_borrow_class(
+                               BT_CTF_TO_COMMON(event)));
 
                BT_LOGV("Serializing event: index=%zu, event-addr=%p, "
                        "event-class-name=\"%s\", event-class-id=%" PRId64 ", "
@@ -1829,7 +1926,7 @@ void bt_ctf_stream_destroy(struct bt_object *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));
+       bt_ctf_stream_common_finalize(BT_CTF_TO_COMMON(stream));
        (void) bt_ctf_stream_pos_fini(&stream->pos);
 
        if (stream->pos.fd >= 0) {
@@ -1905,7 +2002,7 @@ int _set_structure_field_integer(struct bt_ctf_field *structure, char *name,
                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_id_string((int)
                                bt_ctf_field_type_get_type_id(field_type)));
                ret = -1;
                goto end;
@@ -1940,15 +2037,15 @@ int try_set_structure_field_integer(struct bt_ctf_field *structure, char *name,
 struct bt_ctf_stream_class *bt_ctf_stream_get_class(
                struct bt_ctf_stream *stream)
 {
-       return bt_get(bt_stream_common_borrow_class(BT_TO_COMMON(stream)));
+       return bt_get(bt_ctf_stream_common_borrow_class(BT_CTF_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));
+       return bt_ctf_stream_common_get_name(BT_CTF_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));
+       return bt_ctf_stream_common_get_id(BT_CTF_TO_COMMON(stream));
 }
index 035f3b3cf22eeb0caa468027d7561415bae9e5bc..25055383b2c8431a66fa5997ef4f39b43c937f61 100644 (file)
 #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/assert-internal.h>
+#include <babeltrace/compiler-internal.h>
+#include <babeltrace/ctf-writer/attributes-internal.h>
+#include <babeltrace/ctf-writer/clock-class-internal.h>
 #include <babeltrace/ctf-writer/clock-internal.h>
-#include <babeltrace/ctf-writer/trace-internal.h>
+#include <babeltrace/ctf-writer/event-class-internal.h>
+#include <babeltrace/ctf-writer/event.h>
+#include <babeltrace/ctf-writer/event-internal.h>
+#include <babeltrace/ctf-writer/field-types-internal.h>
+#include <babeltrace/ctf-writer/field-wrapper-internal.h>
+#include <babeltrace/ctf-writer/functor-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/utils-internal.h>
+#include <babeltrace/ctf-writer/utils.h>
+#include <babeltrace/ctf-writer/validation-internal.h>
+#include <babeltrace/ctf-writer/visitor-internal.h>
 #include <babeltrace/ctf-writer/writer-internal.h>
-#include <babeltrace/ctf-writer/field-types-internal.h>
+#include <babeltrace/endian-internal.h>
+#include <babeltrace/ref.h>
+#include <babeltrace/types.h>
+#include <babeltrace/values-internal.h>
+#include <babeltrace/values.h>
+#include <inttypes.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define DEFAULT_IDENTIFIER_SIZE                128
+#define DEFAULT_METADATA_STRING_SIZE   4096
+
+BT_HIDDEN
+int bt_ctf_trace_common_initialize(struct bt_ctf_trace_common *trace,
+               bt_object_release_func release_func)
+{
+       int ret = 0;
+
+       BT_LOGD_STR("Initializing common trace object.");
+       trace->native_byte_order = BT_CTF_BYTE_ORDER_UNSPECIFIED;
+       bt_object_init_shared_with_parent(&trace->base, release_func);
+       trace->clock_classes = g_ptr_array_new_with_free_func(
+               (GDestroyNotify) bt_put);
+       if (!trace->clock_classes) {
+               BT_LOGE_STR("Failed to allocate one GPtrArray.");
+               goto error;
+       }
+
+       trace->streams = g_ptr_array_new_with_free_func(
+               (GDestroyNotify) bt_object_try_spec_release);
+       if (!trace->streams) {
+               BT_LOGE_STR("Failed to allocate one GPtrArray.");
+               goto error;
+       }
+
+       trace->stream_classes = g_ptr_array_new_with_free_func(
+               (GDestroyNotify) bt_object_try_spec_release);
+       if (!trace->stream_classes) {
+               BT_LOGE_STR("Failed to allocate one GPtrArray.");
+               goto error;
+       }
+
+       /* Create the environment array object */
+       trace->environment = bt_ctf_attributes_create();
+       if (!trace->environment) {
+               BT_LOGE_STR("Cannot create empty attributes object.");
+               goto error;
+       }
+
+       BT_LOGD("Initialized common trace object: addr=%p", trace);
+       goto end;
+
+error:
+       ret = -1;
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+void bt_ctf_trace_common_finalize(struct bt_ctf_trace_common *trace)
+{
+       BT_LOGD("Finalizing common trace object: addr=%p, name=\"%s\"",
+               trace, bt_ctf_trace_common_get_name(trace));
+
+       if (trace->environment) {
+               BT_LOGD_STR("Destroying environment attributes.");
+               bt_ctf_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);
+}
+
+BT_HIDDEN
+int bt_ctf_trace_common_set_name(struct bt_ctf_trace_common *trace, const char *name)
+{
+       int ret = 0;
+
+       if (!trace) {
+               BT_LOGW_STR("Invalid parameter: trace is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       if (!name) {
+               BT_LOGW_STR("Invalid parameter: name is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       if (trace->frozen) {
+               BT_LOGW("Invalid parameter: trace is frozen: "
+                       "addr=%p, name=\"%s\"",
+                       trace, bt_ctf_trace_common_get_name(trace));
+               ret = -1;
+               goto end;
+       }
+
+       trace->name = trace->name ? g_string_assign(trace->name, name) :
+                       g_string_new(name);
+       if (!trace->name) {
+               BT_LOGE_STR("Failed to allocate one GString.");
+               ret = -1;
+               goto end;
+       }
+
+       BT_LOGV("Set trace's name: addr=%p, name=\"%s\"", trace, name);
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+int bt_ctf_trace_common_set_uuid(struct bt_ctf_trace_common *trace,
+               const unsigned char *uuid)
+{
+       int ret = 0;
+
+       if (!trace) {
+               BT_LOGW_STR("Invalid parameter: trace is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       if (!uuid) {
+               BT_LOGW_STR("Invalid parameter: UUID is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       if (trace->frozen) {
+               BT_LOGW("Invalid parameter: trace is frozen: "
+                       "addr=%p, name=\"%s\"",
+                       trace, bt_ctf_trace_common_get_name(trace));
+               ret = -1;
+               goto end;
+       }
+
+       memcpy(trace->uuid, uuid, BABELTRACE_UUID_LEN);
+       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_ctf_trace_common_get_name(trace),
+               (unsigned int) uuid[0],
+               (unsigned int) uuid[1],
+               (unsigned int) uuid[2],
+               (unsigned int) uuid[3],
+               (unsigned int) uuid[4],
+               (unsigned int) uuid[5],
+               (unsigned int) uuid[6],
+               (unsigned int) uuid[7],
+               (unsigned int) uuid[8],
+               (unsigned int) uuid[9],
+               (unsigned int) uuid[10],
+               (unsigned int) uuid[11],
+               (unsigned int) uuid[12],
+               (unsigned int) uuid[13],
+               (unsigned int) uuid[14],
+               (unsigned int) uuid[15]);
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+int bt_ctf_trace_common_set_environment_field(struct bt_ctf_trace_common *trace,
+               const char *name, struct bt_value *value)
+{
+       int ret = 0;
+
+       if (!trace) {
+               BT_LOGW_STR("Invalid parameter: trace is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       if (!name) {
+               BT_LOGW_STR("Invalid parameter: name is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       if (!value) {
+               BT_LOGW_STR("Invalid parameter: value is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       if (!bt_ctf_identifier_is_valid(name)) {
+               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_ctf_trace_common_get_name(trace), name);
+               ret = -1;
+               goto end;
+       }
+
+       if (!bt_value_is_integer(value) && !bt_value_is_string(value)) {
+               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_ctf_trace_common_get_name(trace), name,
+                       bt_value_type_string(bt_value_get_type(value)));
+               ret = -1;
+               goto end;
+       }
+
+       if (trace->frozen) {
+               /*
+                * New environment fields may be added to a frozen trace,
+                * but existing fields may not be changed.
+                *
+                * The object passed is frozen like all other attributes.
+                */
+               struct bt_value *attribute =
+                       bt_ctf_attributes_borrow_field_value_by_name(
+                               trace->environment, name);
+
+               if (attribute) {
+                       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_ctf_trace_common_get_name(trace), name);
+                       ret = -1;
+                       goto end;
+               }
+
+               bt_value_freeze(value);
+       }
+
+       ret = bt_ctf_attributes_set_field_value(trace->environment, name,
+               value);
+       if (ret) {
+               BT_LOGE("Cannot set environment field's value: "
+                       "trace-addr=%p, trace-name=\"%s\", "
+                       "env-name=\"%s\"",
+                       trace, bt_ctf_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_ctf_trace_common_get_name(trace), name, value);
+       }
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+int bt_ctf_trace_common_set_environment_field_string(struct bt_ctf_trace_common *trace,
+               const char *name, const char *value)
+{
+       int ret = 0;
+       struct bt_value *env_value_string_obj = NULL;
+
+       if (!value) {
+               BT_LOGW_STR("Invalid parameter: value is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       env_value_string_obj = bt_value_string_create_init(value);
+       if (!env_value_string_obj) {
+               BT_LOGE_STR("Cannot create string value object.");
+               ret = -1;
+               goto end;
+       }
+
+       /* bt_ctf_trace_common_set_environment_field() logs errors */
+       ret = bt_ctf_trace_common_set_environment_field(trace, name,
+               env_value_string_obj);
+
+end:
+       bt_put(env_value_string_obj);
+       return ret;
+}
+
+BT_HIDDEN
+int bt_ctf_trace_common_set_environment_field_integer(
+               struct bt_ctf_trace_common *trace, const char *name, int64_t value)
+{
+       int ret = 0;
+       struct bt_value *env_value_integer_obj = NULL;
+
+       env_value_integer_obj = bt_value_integer_create_init(value);
+       if (!env_value_integer_obj) {
+               BT_LOGE_STR("Cannot create integer value object.");
+               ret = -1;
+               goto end;
+       }
+
+       /* bt_ctf_trace_common_set_environment_field() logs errors */
+       ret = bt_ctf_trace_common_set_environment_field(trace, name,
+               env_value_integer_obj);
+
+end:
+       bt_put(env_value_integer_obj);
+       return ret;
+}
+
+BT_HIDDEN
+int bt_ctf_trace_common_add_clock_class(struct bt_ctf_trace_common *trace,
+               struct bt_ctf_clock_class *clock_class)
+{
+       int ret = 0;
+
+       if (!trace) {
+               BT_LOGW_STR("Invalid parameter: trace is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       if (!bt_ctf_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_ctf_trace_common_get_name(trace),
+                       clock_class, bt_ctf_clock_class_get_name(clock_class));
+               ret = -1;
+               goto end;
+       }
+
+       /* Check for duplicate clock classes */
+       if (bt_ctf_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_ctf_trace_common_get_name(trace),
+                       clock_class, bt_ctf_clock_class_get_name(clock_class));
+               ret = -1;
+               goto end;
+       }
+
+       bt_get(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.");
+               bt_ctf_clock_class_freeze(clock_class);
+       }
+
+       BT_LOGV("Added clock class to trace: "
+               "trace-addr=%p, trace-name=\"%s\", "
+               "clock-class-addr=%p, clock-class-name=\"%s\"",
+               trace, bt_ctf_trace_common_get_name(trace),
+               clock_class, bt_ctf_clock_class_get_name(clock_class));
+
+end:
+       return ret;
+}
+
+static
+bool packet_header_field_type_is_valid(struct bt_ctf_trace_common *trace,
+               struct bt_ctf_field_type_common *packet_header_type)
+{
+       int ret;
+       bool is_valid = true;
+       struct bt_ctf_field_type_common *field_type = NULL;
+
+       if (!packet_header_type) {
+               /*
+                * No packet header field type: trace must have only
+                * one stream. At this point the stream class being
+                * added is not part of the trace yet, so we validate
+                * that the trace contains no stream classes yet.
+                */
+               if (trace->stream_classes->len >= 1) {
+                       BT_LOGW_STR("Invalid packet header field type: "
+                               "packet header field type does not exist but there's more than one stream class in the trace.");
+                       goto invalid;
+               }
+
+               /* No packet header field type: valid at this point */
+               goto end;
+       }
+
+       /* Packet header field type, if it exists, must be a structure */
+       if (packet_header_type->id != BT_CTF_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_ctf_field_type_id_string(packet_header_type->id));
+               goto invalid;
+       }
+
+       /*
+        * If there's a `magic` field, it must be a 32-bit unsigned
+        * integer field type. Also it must be the first field of the
+        * packet header field type.
+        */
+       field_type = bt_ctf_field_type_common_structure_borrow_field_type_by_name(
+               packet_header_type, "magic");
+       if (field_type) {
+               const char *field_name;
+
+               if (field_type->id != BT_CTF_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_ctf_field_type_id_string(field_type->id));
+                       goto invalid;
+               }
+
+               if (bt_ctf_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_ctf_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_ctf_field_type_common_integer_get_size(field_type));
+                       goto invalid;
+               }
+
+               ret = bt_ctf_field_type_common_structure_borrow_field_by_index(
+                       packet_header_type, &field_name, NULL, 0);
+               BT_ASSERT(ret == 0);
+
+               if (strcmp(field_name, "magic") != 0) {
+                       BT_LOGW("Invalid packet header field type: `magic` field must be the first field: "
+                               "magic-ft-addr=%p, first-field-name=\"%s\"",
+                               field_type, field_name);
+                       goto invalid;
+               }
+       }
+
+       /*
+        * 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_ctf_field_type_common_structure_borrow_field_type_by_name(
+               packet_header_type, "uuid");
+       if (field_type) {
+               struct bt_ctf_field_type_common *elem_ft;
+
+               if (field_type->id != BT_CTF_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_ctf_field_type_id_string(field_type->id));
+                       goto invalid;
+               }
+
+               if (bt_ctf_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_ctf_field_type_common_array_get_length(field_type));
+                       goto invalid;
+               }
+
+               elem_ft = bt_ctf_field_type_common_array_borrow_element_field_type(field_type);
+               BT_ASSERT(elem_ft);
+
+               if (elem_ft->id != BT_CTF_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_ctf_field_type_id_string(elem_ft->id));
+                       goto invalid;
+               }
+
+               if (bt_ctf_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);
+                       goto invalid;
+               }
+
+               if (bt_ctf_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_ctf_field_type_common_integer_get_size(elem_ft));
+                       goto invalid;
+               }
+       }
+
+       /*
+        * The `stream_id` field must exist if there's more than one
+        * stream classes in the trace.
+        */
+       field_type = bt_ctf_field_type_common_structure_borrow_field_type_by_name(
+               packet_header_type, "stream_id");
+
+       if (!field_type && trace->stream_classes->len >= 1) {
+               BT_LOGW_STR("Invalid packet header field type: "
+                       "`stream_id` field does not exist but there's more than one stream class in the trace.");
+               goto invalid;
+       }
+
+       /*
+        * If there's a `stream_id` field, it must be an unsigned
+        * integer field type.
+        */
+       if (field_type) {
+               if (field_type->id != BT_CTF_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_ctf_field_type_id_string(field_type->id));
+                       goto invalid;
+               }
+
+               if (bt_ctf_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;
+               }
+       }
+
+       /*
+        * If there's a `packet_seq_num` field, it must be an unsigned
+        * integer field type.
+        */
+       field_type = bt_ctf_field_type_common_structure_borrow_field_type_by_name(
+               packet_header_type, "packet_seq_num");
+       if (field_type) {
+               if (field_type->id != BT_CTF_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_ctf_field_type_id_string(field_type->id));
+                       goto invalid;
+               }
+
+               if (bt_ctf_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;
+               }
+       }
+
+       goto end;
+
+invalid:
+       is_valid = false;
+
+end:
+       return is_valid;
+}
+
+static
+bool packet_context_field_type_is_valid(struct bt_ctf_trace_common *trace,
+               struct bt_ctf_stream_class_common *stream_class,
+               struct bt_ctf_field_type_common *packet_context_type,
+               bool check_ts_begin_end_mapped)
+{
+       bool is_valid = true;
+       struct bt_ctf_field_type_common *field_type = NULL;
+
+       if (!packet_context_type) {
+               /* No packet context field type: valid at this point */
+               goto end;
+       }
+
+       /* Packet context field type, if it exists, must be a structure */
+       if (packet_context_type->id != BT_CTF_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_ctf_field_type_id_string(packet_context_type->id));
+               goto invalid;
+       }
+
+       /*
+        * If there's a `packet_size` field, it must be an unsigned
+        * integer field type.
+        */
+       field_type = bt_ctf_field_type_common_structure_borrow_field_type_by_name(
+               packet_context_type, "packet_size");
+       if (field_type) {
+               if (field_type->id != BT_CTF_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_ctf_field_type_id_string(field_type->id));
+                       goto invalid;
+               }
+
+               if (bt_ctf_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;
+               }
+       }
+
+       /*
+        * If there's a `content_size` field, it must be an unsigned
+        * integer field type.
+        */
+       field_type = bt_ctf_field_type_common_structure_borrow_field_type_by_name(
+               packet_context_type, "content_size");
+       if (field_type) {
+               if (field_type->id != BT_CTF_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_ctf_field_type_id_string(field_type->id));
+                       goto invalid;
+               }
+
+               if (bt_ctf_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;
+               }
+       }
+
+       /*
+        * If there's a `events_discarded` field, it must be an unsigned
+        * integer field type.
+        */
+       field_type = bt_ctf_field_type_common_structure_borrow_field_type_by_name(
+               packet_context_type, "events_discarded");
+       if (field_type) {
+               if (field_type->id != BT_CTF_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_ctf_field_type_id_string(field_type->id));
+                       goto invalid;
+               }
+
+               if (bt_ctf_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;
+               }
+       }
+
+       /*
+        * If there's a `timestamp_begin` field, it must be an unsigned
+        * integer field type. Also, if the trace is not a CTF writer's
+        * trace, then we cannot automatically set the mapped clock
+        * class of this field, so it must have a mapped clock class.
+        */
+       field_type = bt_ctf_field_type_common_structure_borrow_field_type_by_name(
+               packet_context_type, "timestamp_begin");
+       if (field_type) {
+               if (field_type->id != BT_CTF_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_ctf_field_type_id_string(field_type->id));
+                       goto invalid;
+               }
+
+               if (bt_ctf_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 (check_ts_begin_end_mapped) {
+                       struct bt_ctf_clock_class *clock_class =
+                               bt_ctf_field_type_common_integer_borrow_mapped_clock_class(
+                                       field_type);
+
+                       if (!clock_class) {
+                               BT_LOGW("Invalid packet context field type: `timestamp_begin` field must be mapped to a clock class: "
+                                       "timestamp-begin-ft-addr=%p", field_type);
+                               goto invalid;
+                       }
+               }
+       }
 
-#define DEFAULT_IDENTIFIER_SIZE                128
-#define DEFAULT_METADATA_STRING_SIZE   4096
+       /*
+        * If there's a `timestamp_end` field, it must be an unsigned
+        * integer field type. Also, if the trace is not a CTF writer's
+        * trace, then we cannot automatically set the mapped clock
+        * class of this field, so it must have a mapped clock class.
+        */
+       field_type = bt_ctf_field_type_common_structure_borrow_field_type_by_name(
+               packet_context_type, "timestamp_end");
+       if (field_type) {
+               if (field_type->id != BT_CTF_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_ctf_field_type_id_string(field_type->id));
+                       goto invalid;
+               }
+
+               if (bt_ctf_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 (check_ts_begin_end_mapped) {
+                       struct bt_ctf_clock_class *clock_class =
+                               bt_ctf_field_type_common_integer_borrow_mapped_clock_class(
+                                       field_type);
+
+                       if (!clock_class) {
+                               BT_LOGW("Invalid packet context field type: `timestamp_end` field must be mapped to a clock class: "
+                                       "timestamp-end-ft-addr=%p", field_type);
+                               goto invalid;
+                       }
+               }
+       }
+
+       goto end;
+
+invalid:
+       is_valid = false;
+
+end:
+       return is_valid;
+}
+
+static
+bool event_header_field_type_is_valid(struct bt_ctf_trace_common *trace,
+               struct bt_ctf_stream_class_common *stream_class,
+               struct bt_ctf_field_type_common *event_header_type)
+{
+       bool is_valid = true;
+       struct bt_ctf_field_type_common *field_type = NULL;
+
+       /*
+        * We do not validate that the `timestamp` field exists here
+        * because CTF does not require this exact name to be mapped to
+        * a clock class.
+        */
+
+       if (!event_header_type) {
+               /*
+                * No event header field type: stream class must have
+                * only one event class.
+                */
+               if (bt_ctf_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;
+               }
+
+               /* No event header field type: valid at this point */
+               goto end;
+       }
+
+       /* Event header field type, if it exists, must be a structure */
+       if (event_header_type->id != BT_CTF_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_ctf_field_type_id_string(event_header_type->id));
+               goto invalid;
+       }
+
+       /*
+        * If there's an `id` field, it must be an unsigned integer
+        * field type or an enumeration field type with an unsigned
+        * integer container field type.
+        */
+       field_type = bt_ctf_field_type_common_structure_borrow_field_type_by_name(
+               event_header_type, "id");
+       if (field_type) {
+               struct bt_ctf_field_type_common *int_ft;
+
+               if (field_type->id == BT_CTF_FIELD_TYPE_ID_INTEGER) {
+                       int_ft = field_type;
+               } else if (field_type->id == BT_CTF_FIELD_TYPE_ID_ENUM) {
+                       int_ft = bt_ctf_field_type_common_enumeration_borrow_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_ctf_field_type_id_string(field_type->id));
+                       goto invalid;
+               }
+
+               BT_ASSERT(int_ft);
+               if (bt_ctf_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;
+               }
+       }
+
+       goto end;
+
+invalid:
+       is_valid = false;
+
+end:
+       return is_valid;
+}
+
+static
+int check_packet_header_type_has_no_clock_class(struct bt_ctf_trace_common *trace)
+{
+       int ret = 0;
+
+       if (trace->packet_header_field_type) {
+               struct bt_ctf_clock_class *clock_class = NULL;
+
+               ret = bt_ctf_field_type_common_validate_single_clock_class(
+                       trace->packet_header_field_type,
+                       &clock_class);
+               bt_put(clock_class);
+               if (ret || clock_class) {
+                       BT_LOGW("Trace's packet header field type cannot "
+                               "contain a field type which is mapped to "
+                               "a clock class: "
+                               "trace-addr=%p, trace-name=\"%s\", "
+                               "clock-class-name=\"%s\"",
+                               trace, bt_ctf_trace_common_get_name(trace),
+                               clock_class ?
+                                       bt_ctf_clock_class_get_name(clock_class) :
+                                       NULL);
+                       ret = -1;
+               }
+       }
+
+       return ret;
+}
+
+BT_HIDDEN
+int bt_ctf_trace_common_add_stream_class(struct bt_ctf_trace_common *trace,
+               struct bt_ctf_stream_class_common *stream_class,
+               bt_ctf_validation_flag_copy_field_type_func copy_field_type_func,
+               struct bt_ctf_clock_class *init_expected_clock_class,
+               int (*map_clock_classes_func)(struct bt_ctf_stream_class_common *stream_class,
+                       struct bt_ctf_field_type_common *packet_context_field_type,
+                       struct bt_ctf_field_type_common *event_header_field_type),
+               bool check_ts_begin_end_mapped)
+{
+       int ret;
+       int64_t i;
+       int64_t stream_id;
+       struct bt_ctf_validation_output trace_sc_validation_output = { 0 };
+       struct bt_ctf_validation_output *ec_validation_outputs = NULL;
+       const enum bt_ctf_validation_flag trace_sc_validation_flags =
+               BT_CTF_VALIDATION_FLAG_TRACE |
+               BT_CTF_VALIDATION_FLAG_STREAM;
+       const enum bt_ctf_validation_flag ec_validation_flags =
+               BT_CTF_VALIDATION_FLAG_EVENT;
+       struct bt_ctf_field_type_common *packet_header_type = NULL;
+       struct bt_ctf_field_type_common *packet_context_type = NULL;
+       struct bt_ctf_field_type_common *event_header_type = NULL;
+       struct bt_ctf_field_type_common *stream_event_ctx_type = NULL;
+       int64_t event_class_count;
+       struct bt_ctf_trace_common *current_parent_trace = NULL;
+       struct bt_ctf_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.");
+               ret = -1;
+               goto end;
+       }
+
+       if (!stream_class) {
+               BT_LOGW_STR("Invalid parameter: stream class is NULL.");
+               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_ctf_trace_common_get_name(trace),
+               stream_class, bt_ctf_stream_class_common_get_name(stream_class),
+               bt_ctf_stream_class_common_get_id(stream_class));
+
+       current_parent_trace = bt_ctf_stream_class_common_borrow_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_ctf_trace_common_get_name(current_parent_trace));
+               ret = -1;
+               goto end;
+       }
+
+       event_class_count =
+               bt_ctf_stream_class_common_get_event_class_count(stream_class);
+       BT_ASSERT(event_class_count >= 0);
+
+       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_ctf_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_ctf_stream_class_common_validate_single_clock_class()
+                * succeeds below, the call to
+                * bt_ctf_stream_class_map_clock_class() at the end of this
+                * function is safe because it maps to the same, single
+                * clock class.
+                */
+               ret = bt_ctf_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 "
+                               "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_ctf_stream_class_common_get_id(stream_class),
+                               bt_ctf_stream_class_common_get_name(stream_class),
+                               expected_clock_class,
+                               expected_clock_class ?
+                                       bt_ctf_clock_class_get_name(expected_clock_class) :
+                                       NULL);
+                       goto end;
+               }
+       }
+
+       ret = check_packet_header_type_has_no_clock_class(trace);
+       if (ret) {
+               /* check_packet_header_type_has_no_clock_class() logs errors */
+               goto end;
+       }
+
+       /*
+        * We're about to freeze both the trace and the stream class.
+        * Also, each event class contained in this stream class are
+        * already frozen.
+        *
+        * This trace, this stream class, and all its event classes
+        * should be valid at this point.
+        *
+        * Validate trace and stream class first, then each event
+        * class of this stream class can be validated individually.
+        */
+       packet_header_type =
+               bt_ctf_trace_common_borrow_packet_header_field_type(trace);
+       packet_context_type =
+               bt_ctf_stream_class_common_borrow_packet_context_field_type(stream_class);
+       event_header_type =
+               bt_ctf_stream_class_common_borrow_event_header_field_type(stream_class);
+       stream_event_ctx_type =
+               bt_ctf_stream_class_common_borrow_event_context_field_type(stream_class);
+
+       BT_LOGD("Validating trace and stream class field types.");
+       ret = bt_ctf_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, copy_field_type_func);
+
+       if (ret) {
+               /*
+                * This means something went wrong during the validation
+                * process, not that the objects are invalid.
+                */
+               BT_LOGE("Failed to validate trace and stream class field types: "
+                       "ret=%d", ret);
+               goto end;
+       }
+
+       if ((trace_sc_validation_output.valid_flags &
+                       trace_sc_validation_flags) !=
+                       trace_sc_validation_flags) {
+               /* Invalid trace/stream class */
+               BT_LOGW("Invalid trace or stream class field types: "
+                       "valid-flags=0x%x",
+                       trace_sc_validation_output.valid_flags);
+               ret = -1;
+               goto end;
+       }
+
+       if (event_class_count > 0) {
+               ec_validation_outputs = g_new0(struct bt_ctf_validation_output,
+                       event_class_count);
+               if (!ec_validation_outputs) {
+                       BT_LOGE_STR("Failed to allocate one validation output structure.");
+                       ret = -1;
+                       goto end;
+               }
+       }
+
+       /* Validate each event class individually */
+       for (i = 0; i < event_class_count; i++) {
+               struct bt_ctf_event_class_common *event_class =
+                       bt_ctf_stream_class_common_borrow_event_class_by_index(
+                               stream_class, i);
+               struct bt_ctf_field_type_common *event_context_type = NULL;
+               struct bt_ctf_field_type_common *event_payload_type = NULL;
+
+               event_context_type =
+                       bt_ctf_event_class_common_borrow_context_field_type(
+                               event_class);
+               event_payload_type =
+                       bt_ctf_event_class_common_borrow_payload_field_type(
+                               event_class);
+
+               /*
+                * It is important to use the field types returned by
+                * the previous trace and stream class validation here
+                * because copies could have been made.
+                */
+               BT_LOGD("Validating event class's field types: "
+                       "addr=%p, name=\"%s\", id=%" PRId64,
+                       event_class, bt_ctf_event_class_common_get_name(event_class),
+                       bt_ctf_event_class_common_get_id(event_class));
+               ret = bt_ctf_validate_class_types(trace->environment,
+                       trace_sc_validation_output.packet_header_type,
+                       trace_sc_validation_output.packet_context_type,
+                       trace_sc_validation_output.event_header_type,
+                       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, copy_field_type_func);
+
+               if (ret) {
+                       BT_LOGE("Failed to validate event class field types: "
+                               "ret=%d", ret);
+                       goto end;
+               }
+
+               if ((ec_validation_outputs[i].valid_flags &
+                               ec_validation_flags) != ec_validation_flags) {
+                       /* Invalid event class */
+                       BT_LOGW("Invalid event class field types: "
+                               "valid-flags=0x%x",
+                               ec_validation_outputs[i].valid_flags);
+                       ret = -1;
+                       goto end;
+               }
+       }
+
+       stream_id = bt_ctf_stream_class_common_get_id(stream_class);
+       if (stream_id < 0) {
+               stream_id = trace->next_stream_id++;
+               if (stream_id < 0) {
+                       BT_LOGE_STR("No more stream class IDs available.");
+                       ret = -1;
+                       goto end;
+               }
+
+               /* Try to assign a new stream id */
+               for (i = 0; i < trace->stream_classes->len; i++) {
+                       if (stream_id == bt_ctf_stream_class_common_get_id(
+                               trace->stream_classes->pdata[i])) {
+                               /* Duplicate stream id found */
+                               BT_LOGW("Duplicate stream class ID: "
+                                       "id=%" PRId64, (int64_t) stream_id);
+                               ret = -1;
+                               goto end;
+                       }
+               }
+
+               if (bt_ctf_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: "
+                               "id=%" PRId64, (int64_t) stream_id);
+                       ret = -1;
+                       goto end;
+               }
+       }
+
+       /*
+        * At this point all the field types in the validation output
+        * are valid. Validate the semantics of some scopes according to
+        * the CTF specification.
+        */
+       if (!packet_header_field_type_is_valid(trace,
+                       trace_sc_validation_output.packet_header_type)) {
+               BT_LOGW_STR("Invalid trace's packet header field type.");
+               ret = -1;
+               goto end;
+       }
+
+       if (!packet_context_field_type_is_valid(trace,
+                       stream_class,
+                       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;
+       }
+
+       if (!event_header_field_type_is_valid(trace,
+                       stream_class,
+                       trace_sc_validation_output.event_header_type)) {
+               BT_LOGW_STR("Invalid steam class's event header field type.");
+               ret = -1;
+               goto end;
+       }
+
+       /*
+        * Now is the time to automatically map specific field types of
+        * the stream class's packet context and event header field
+        * types to the stream class's clock's class if they are not
+        * mapped to a clock class yet. We do it here because we know
+        * that after this point, everything is frozen so it won't be
+        * possible for the user to modify the stream class's clock, or
+        * to map those field types to other clock classes.
+        */
+       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)) {
+                       /* map_clock_classes_func() logs errors */
+                       ret = -1;
+                       goto end;
+               }
+       }
+
+       bt_object_set_parent(&stream_class->base, &trace->base);
+       g_ptr_array_add(trace->stream_classes, stream_class);
+
+       /*
+        * At this point we know that the function will be successful.
+        * Therefore we can replace the trace and stream class field
+        * types with what's in their validation output structure and
+        * mark them as valid. We can also replace the field types of
+        * all the event classes of the stream class and mark them as
+        * valid.
+        */
+       bt_ctf_validation_replace_types(trace, stream_class, NULL,
+               &trace_sc_validation_output, trace_sc_validation_flags);
+       trace->valid = 1;
+       stream_class->valid = 1;
+
+       /*
+        * Put what was not moved in bt_ctf_validation_replace_types().
+        */
+       bt_ctf_validation_output_put_types(&trace_sc_validation_output);
+
+       for (i = 0; i < event_class_count; i++) {
+               struct bt_ctf_event_class_common *event_class =
+                       bt_ctf_stream_class_common_borrow_event_class_by_index(
+                               stream_class, i);
+
+               bt_ctf_validation_replace_types(NULL, NULL, event_class,
+                       &ec_validation_outputs[i], ec_validation_flags);
+               event_class->valid = 1;
+
+               /*
+                * Put what was not moved in
+                * bt_ctf_validation_replace_types().
+                */
+               bt_ctf_validation_output_put_types(&ec_validation_outputs[i]);
+       }
+
+       /*
+        * Freeze the trace and the stream class.
+        */
+       bt_ctf_stream_class_common_freeze(stream_class);
+       bt_ctf_trace_common_freeze(trace);
+
+       /*
+        * It is safe to set the stream class's unique clock class
+        * now because the stream class is frozen.
+        */
+       if (expected_clock_class) {
+               BT_MOVE(stream_class->clock_class, expected_clock_class);
+       }
+
+       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_ctf_trace_common_get_name(trace),
+               stream_class, bt_ctf_stream_class_common_get_name(stream_class),
+               bt_ctf_stream_class_common_get_id(stream_class));
+
+end:
+       if (ret) {
+               bt_object_set_parent(&stream_class->base, NULL);
+
+               if (ec_validation_outputs) {
+                       for (i = 0; i < event_class_count; i++) {
+                               bt_ctf_validation_output_put_types(
+                                       &ec_validation_outputs[i]);
+                       }
+               }
+       }
+
+       g_free(ec_validation_outputs);
+       bt_ctf_validation_output_put_types(&trace_sc_validation_output);
+       bt_put(expected_clock_class);
+       return ret;
+}
+
+BT_HIDDEN
+bt_bool bt_ctf_trace_common_has_clock_class(struct bt_ctf_trace_common *trace,
+               struct bt_ctf_clock_class *clock_class)
+{
+       struct bt_ctf_search_query query = { .value = clock_class, .found = 0 };
+
+       BT_ASSERT(trace);
+       BT_ASSERT(clock_class);
+
+       g_ptr_array_foreach(trace->clock_classes, value_exists, &query);
+       return query.found;
+}
+
+BT_HIDDEN
+int bt_ctf_trace_common_set_native_byte_order(struct bt_ctf_trace_common *trace,
+               enum bt_ctf_byte_order byte_order, bool allow_unspecified)
+{
+       int ret = 0;
+
+       if (!trace) {
+               BT_LOGW_STR("Invalid parameter: trace is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       if (trace->frozen) {
+               BT_LOGW("Invalid parameter: trace is frozen: "
+                       "addr=%p, name=\"%s\"",
+                       trace, bt_ctf_trace_common_get_name(trace));
+               ret = -1;
+               goto end;
+       }
+
+       if (byte_order == BT_CTF_BYTE_ORDER_UNSPECIFIED && !allow_unspecified) {
+               BT_LOGW("Invalid parameter: BT_CTF_BYTE_ORDER_UNSPECIFIED byte order is not allowed: "
+                       "addr=%p, name=\"%s\"",
+                       trace, bt_ctf_trace_common_get_name(trace));
+               ret = -1;
+               goto end;
+       }
+
+       if (byte_order != BT_CTF_BYTE_ORDER_LITTLE_ENDIAN &&
+                       byte_order != BT_CTF_BYTE_ORDER_BIG_ENDIAN &&
+                       byte_order != BT_CTF_BYTE_ORDER_NETWORK) {
+               BT_LOGW("Invalid parameter: invalid byte order: "
+                       "addr=%p, name=\"%s\", bo=%s",
+                       trace, bt_ctf_trace_common_get_name(trace),
+                       bt_ctf_byte_order_string(byte_order));
+               ret = -1;
+               goto end;
+       }
+
+       trace->native_byte_order = byte_order;
+       BT_LOGV("Set trace's native byte order: "
+               "addr=%p, name=\"%s\", bo=%s",
+               trace, bt_ctf_trace_common_get_name(trace),
+               bt_ctf_byte_order_string(byte_order));
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+int bt_ctf_trace_common_set_packet_header_field_type(struct bt_ctf_trace_common *trace,
+               struct bt_ctf_field_type_common *packet_header_type)
+{
+       int ret = 0;
+
+       if (!trace) {
+               BT_LOGW_STR("Invalid parameter: trace is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       if (trace->frozen) {
+               BT_LOGW("Invalid parameter: trace is frozen: "
+                       "addr=%p, name=\"%s\"",
+                       trace, bt_ctf_trace_common_get_name(trace));
+               ret = -1;
+               goto end;
+       }
+
+       /* packet_header_type must be a structure. */
+       if (packet_header_type &&
+                       packet_header_type->id != BT_CTF_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_ctf_trace_common_get_name(trace),
+                       packet_header_type,
+                       bt_ctf_field_type_id_string(packet_header_type->id));
+               ret = -1;
+               goto end;
+       }
+
+       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_ctf_trace_common_get_name(trace), packet_header_type);
+end:
+       return ret;
+}
+
+static
+int64_t get_stream_class_count(void *element)
+{
+       return bt_ctf_trace_get_stream_class_count(
+                       (struct bt_ctf_trace *) element);
+}
+
+static
+void *get_stream_class(void *element, int i)
+{
+       return bt_ctf_trace_get_stream_class_by_index(
+                       (struct bt_ctf_trace *) element, i);
+}
+
+static
+int visit_stream_class(void *object, bt_ctf_visitor visitor,void *data)
+{
+       return bt_ctf_stream_class_visit(object, visitor, data);
+}
+
+int bt_ctf_trace_visit(struct bt_ctf_trace *trace,
+               bt_ctf_visitor visitor, void *data)
+{
+       int ret;
+       struct bt_ctf_visitor_object obj = {
+               .object = trace,
+               .type = BT_CTF_VISITOR_OBJECT_TYPE_TRACE
+       };
+
+       if (!trace) {
+               BT_LOGW_STR("Invalid parameter: trace is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       if (!visitor) {
+               BT_LOGW_STR("Invalid parameter: visitor is NULL.");
+               ret = -1;
+               goto end;
+       }
+
+       BT_LOGV("Visiting trace: addr=%p, name=\"%s\"",
+               trace, bt_ctf_trace_get_name(trace));
+       ret = visitor_helper(&obj, get_stream_class_count,
+                       get_stream_class, visit_stream_class, visitor, data);
+end:
+       return ret;
+}
 
 static
 void bt_ctf_trace_destroy(struct bt_object *obj)
@@ -42,7 +1424,7 @@ void bt_ctf_trace_destroy(struct bt_object *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));
+       bt_ctf_trace_common_finalize(BT_CTF_TO_COMMON(trace));
        g_free(trace);
 }
 
@@ -59,10 +1441,10 @@ struct bt_ctf_trace *bt_ctf_trace_create(void)
                goto error;
        }
 
-       ret = bt_trace_common_initialize(BT_TO_COMMON(trace),
+       ret = bt_ctf_trace_common_initialize(BT_CTF_TO_COMMON(trace),
                bt_ctf_trace_destroy);
        if (ret) {
-               /* bt_trace_common_initialize() logs errors */
+               /* bt_ctf_trace_common_initialize() logs errors */
                goto error;
        }
 
@@ -76,91 +1458,94 @@ error:
 
 const unsigned char *bt_ctf_trace_get_uuid(struct bt_ctf_trace *trace)
 {
-       return bt_trace_common_get_uuid(BT_TO_COMMON(trace));
+       return bt_ctf_trace_common_get_uuid(BT_CTF_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);
+       return bt_ctf_trace_common_set_uuid(BT_CTF_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),
+       return bt_ctf_trace_common_set_environment_field(BT_CTF_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),
+       return bt_ctf_trace_common_set_environment_field_string(BT_CTF_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);
+       return bt_ctf_trace_common_set_environment_field_integer(
+               BT_CTF_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));
+       return bt_ctf_trace_common_get_environment_field_count(BT_CTF_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);
+       return bt_ctf_trace_common_get_environment_field_name_by_index(
+               BT_CTF_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_get(bt_trace_common_borrow_environment_field_value_by_index(
-               BT_TO_COMMON(trace), index));
+       return bt_get(bt_ctf_trace_common_borrow_environment_field_value_by_index(
+               BT_CTF_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_get(bt_trace_common_borrow_environment_field_value_by_name(
-               BT_TO_COMMON(trace), name));
+       return bt_get(bt_ctf_trace_common_borrow_environment_field_value_by_name(
+               BT_CTF_TO_COMMON(trace), name));
 }
 
+BT_HIDDEN
 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),
+       return bt_ctf_trace_common_add_clock_class(BT_CTF_TO_COMMON(trace),
                (void *) clock_class);
 }
 
+BT_HIDDEN
 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));
+       return bt_ctf_trace_common_get_clock_class_count(BT_CTF_TO_COMMON(trace));
 }
 
+BT_HIDDEN
 struct bt_ctf_clock_class *bt_ctf_trace_get_clock_class_by_index(
                struct bt_ctf_trace *trace, uint64_t index)
 {
-       return bt_get(bt_trace_common_borrow_clock_class_by_index(
-               BT_TO_COMMON(trace), index));
+       return bt_get(bt_ctf_trace_common_borrow_clock_class_by_index(
+               BT_CTF_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 map_clock_classes_func(struct bt_ctf_stream_class_common *stream_class,
+               struct bt_ctf_field_type_common *packet_context_type,
+               struct bt_ctf_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));
+               BT_CTF_FROM_COMMON(stream_class),
+               BT_CTF_FROM_COMMON(packet_context_type),
+               BT_CTF_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.");
@@ -173,7 +1558,7 @@ 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;
+       struct bt_ctf_clock_class *expected_clock_class = NULL;
 
        if (!trace) {
                BT_LOGW_STR("Invalid parameter: trace is NULL.");
@@ -211,15 +1596,14 @@ int bt_ctf_trace_add_stream_class(struct bt_ctf_trace *trace,
                        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)));
+                               bt_ctf_clock_class_get_name(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->clock->clock_class) {
                        /*
                         * Stream class already has an expected clock
                         * class, but it does not match its clock's
@@ -237,21 +1621,20 @@ int bt_ctf_trace_add_stream_class(struct bt_ctf_trace *trace,
                                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));
+                               bt_ctf_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);
+                       expected_clock_class = 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,
+       ret = bt_ctf_trace_common_add_stream_class(BT_CTF_TO_COMMON(trace),
+               BT_CTF_TO_COMMON(stream_class),
+               (bt_ctf_validation_flag_copy_field_type_func) bt_ctf_field_type_copy,
                expected_clock_class, map_clock_classes_func,
                false);
 
@@ -261,40 +1644,41 @@ end:
 
 int64_t bt_ctf_trace_get_stream_count(struct bt_ctf_trace *trace)
 {
-       return bt_trace_common_get_stream_count(BT_TO_COMMON(trace));
+       return bt_ctf_trace_common_get_stream_count(BT_CTF_TO_COMMON(trace));
 }
 
 struct bt_ctf_stream *bt_ctf_trace_get_stream_by_index(
                struct bt_ctf_trace *trace, uint64_t index)
 {
-       return bt_get(bt_trace_common_borrow_stream_by_index(
-               BT_TO_COMMON(trace), index));
+       return bt_get(bt_ctf_trace_common_borrow_stream_by_index(
+               BT_CTF_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));
+       return bt_ctf_trace_common_get_stream_class_count(BT_CTF_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_get(bt_trace_common_borrow_stream_class_by_index(
-               BT_TO_COMMON(trace), index));
+       return bt_get(bt_ctf_trace_common_borrow_stream_class_by_index(
+               BT_CTF_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_get(bt_trace_common_borrow_stream_class_by_id(
-               BT_TO_COMMON(trace), id));
+       return bt_get(bt_ctf_trace_common_borrow_stream_class_by_id(
+               BT_CTF_TO_COMMON(trace), id));
 }
 
+BT_HIDDEN
 struct bt_ctf_clock_class *bt_ctf_trace_get_clock_class_by_name(
                struct bt_ctf_trace *trace, const char *name)
 {
        return bt_get(
-               bt_trace_common_borrow_clock_class_by_name(BT_TO_COMMON(trace),
+               bt_ctf_trace_common_borrow_clock_class_by_name(BT_CTF_TO_COMMON(trace),
                        name));
 }
 
@@ -305,8 +1689,8 @@ int append_trace_metadata(struct bt_ctf_trace *trace,
        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) {
+       if (trace->common.native_byte_order == BT_CTF_BYTE_ORDER_NATIVE ||
+                       trace->common.native_byte_order == BT_CTF_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\"",
@@ -318,9 +1702,9 @@ int append_trace_metadata(struct bt_ctf_trace *trace,
        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);
+       BT_ASSERT(trace->common.native_byte_order == BT_CTF_BYTE_ORDER_LITTLE_ENDIAN ||
+               trace->common.native_byte_order == BT_CTF_BYTE_ORDER_BIG_ENDIAN ||
+               trace->common.native_byte_order == BT_CTF_BYTE_ORDER_NETWORK);
 
        if (trace->common.uuid_set) {
                g_string_append_printf(context->string,
@@ -332,7 +1716,7 @@ int append_trace_metadata(struct bt_ctf_trace *trace,
        }
 
        g_string_append_printf(context->string, "\tbyte_order = %s;\n",
-               get_byte_order_string(trace->common.native_byte_order));
+               bt_ctf_get_byte_order_string(trace->common.native_byte_order));
 
        if (trace->common.packet_header_field_type) {
                g_string_append(context->string, "\tpacket.header := ");
@@ -360,7 +1744,7 @@ void append_env_metadata(struct bt_ctf_trace *trace,
        int64_t i;
        int64_t env_size;
 
-       env_size = bt_attributes_get_count(trace->common.environment);
+       env_size = bt_ctf_attributes_get_count(trace->common.environment);
        if (env_size <= 0) {
                return;
        }
@@ -371,9 +1755,9 @@ void append_env_metadata(struct bt_ctf_trace *trace,
                struct bt_value *env_field_value_obj = NULL;
                const char *entry_name;
 
-               entry_name = bt_attributes_get_field_name(
+               entry_name = bt_ctf_attributes_get_field_name(
                        trace->common.environment, i);
-               env_field_value_obj = bt_attributes_borrow_field_value(
+               env_field_value_obj = bt_ctf_attributes_borrow_field_value(
                        trace->common.environment, i);
 
                BT_ASSERT(entry_name);
@@ -452,11 +1836,11 @@ char *bt_ctf_trace_get_metadata_string(struct bt_ctf_trace *trace)
                (GFunc) bt_ctf_clock_class_serialize, context);
 
        for (i = 0; i < trace->common.stream_classes->len; i++) {
-               /* bt_stream_class_serialize() logs details */
+               /* bt_ctf_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 */
+                       /* bt_ctf_stream_class_serialize() logs errors */
                        goto error;
                }
        }
@@ -475,31 +1859,31 @@ end:
 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));
+       return (int) bt_ctf_trace_common_get_native_byte_order(BT_CTF_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),
+       return bt_ctf_trace_common_set_native_byte_order(BT_CTF_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_get(bt_trace_common_borrow_packet_header_field_type(
-               BT_TO_COMMON(trace)));
+       return bt_get(bt_ctf_trace_common_borrow_packet_header_field_type(
+               BT_CTF_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),
+       return bt_ctf_trace_common_set_packet_header_field_type(BT_CTF_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));
+       return bt_ctf_trace_common_get_name(BT_CTF_TO_COMMON(trace));
 }
diff --git a/lib/ctf-writer/utils.c b/lib/ctf-writer/utils.c
new file mode 100644 (file)
index 0000000..67c4eca
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * utils.c
+ *
+ * Babeltrace CTF writer - Utilities
+ *
+ * Copyright 2015 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-UTILS"
+#include <babeltrace/lib-logging-internal.h>
+
+#include <babeltrace/assert-internal.h>
+#include <babeltrace/ctf-writer/clock-class-internal.h>
+#include <babeltrace/ctf-writer/field-types-internal.h>
+#include <babeltrace/ctf-writer/utils.h>
+#include <babeltrace/ref.h>
+#include <glib.h>
+#include <stdlib.h>
+
+static
+const char * const reserved_keywords_str[] = {"align", "callsite",
+       "const", "char", "clock", "double", "enum", "env", "event",
+       "floating_point", "float", "integer", "int", "long", "short", "signed",
+       "stream", "string", "struct", "trace", "typealias", "typedef",
+       "unsigned", "variant", "void" "_Bool", "_Complex", "_Imaginary"};
+
+static GHashTable *reserved_keywords_set;
+static int init_done;
+
+static
+void try_init_reserved_keywords(void)
+{
+       size_t i;
+       const size_t reserved_keywords_count =
+               sizeof(reserved_keywords_str) / sizeof(char *);
+
+       if (reserved_keywords_set) {
+               return;
+       }
+
+       reserved_keywords_set = g_hash_table_new(g_direct_hash, g_direct_equal);
+       BT_ASSERT(reserved_keywords_set);
+
+       for (i = 0; i < reserved_keywords_count; i++) {
+               gpointer quark = GINT_TO_POINTER(g_quark_from_string(
+                       reserved_keywords_str[i]));
+
+               g_hash_table_insert(reserved_keywords_set, quark, quark);
+       }
+
+       init_done = 1;
+}
+
+static __attribute__((destructor))
+void trace_finalize(void)
+{
+       if (reserved_keywords_set) {
+               g_hash_table_destroy(reserved_keywords_set);
+       }
+}
+
+bt_bool bt_ctf_identifier_is_valid(const char *identifier)
+{
+       bt_bool is_valid = BT_TRUE;
+       char *string = NULL;
+       char *save_ptr, *token;
+
+       if (!identifier) {
+               BT_LOGV_STR("Invalid parameter: input string is NULL.");
+               is_valid = BT_FALSE;
+               goto end;
+       }
+
+       try_init_reserved_keywords();
+
+       if (identifier[0] == '\0') {
+               is_valid = BT_FALSE;
+               goto end;
+       }
+
+       string = strdup(identifier);
+       if (!string) {
+               BT_LOGE("strdup() failed.");
+               is_valid = BT_FALSE;
+               goto end;
+       }
+
+       token = strtok_r(string, " ", &save_ptr);
+       while (token) {
+               if (g_hash_table_lookup_extended(reserved_keywords_set,
+                       GINT_TO_POINTER(g_quark_from_string(token)),
+                       NULL, NULL)) {
+                       is_valid = BT_FALSE;
+                       goto end;
+               }
+
+               token = strtok_r(NULL, " ", &save_ptr);
+       }
+end:
+       free(string);
+       return is_valid;
+}
diff --git a/lib/ctf-writer/validation.c b/lib/ctf-writer/validation.c
new file mode 100644 (file)
index 0000000..92e5626
--- /dev/null
@@ -0,0 +1,652 @@
+/*
+ * validation.c
+ *
+ * Babeltrace - CTF writer: Validation of trace, stream class, and event class
+ *
+ * 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
+ * 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-VALIDATION"
+#include <babeltrace/lib-logging-internal.h>
+
+#include <babeltrace/assert-pre-internal.h>
+#include <babeltrace/babeltrace-internal.h>
+#include <babeltrace/ctf-writer/event-class-internal.h>
+#include <babeltrace/ctf-writer/field-types-internal.h>
+#include <babeltrace/ctf-writer/field-types-internal.h>
+#include <babeltrace/ctf-writer/resolve-internal.h>
+#include <babeltrace/ctf-writer/stream-class-internal.h>
+#include <babeltrace/ctf-writer/trace-internal.h>
+#include <babeltrace/ctf-writer/validation-internal.h>
+#include <babeltrace/ref.h>
+#include <babeltrace/values.h>
+
+/*
+ * This function resolves and validates the field types of an event
+ * class. Only `event_context_type` and `event_payload_type` are
+ * resolved and validated; the other field types are used as eventual
+ * resolving targets.
+ *
+ * All parameters are owned by the caller.
+ */
+static
+int validate_event_class_types(struct bt_value *environment,
+               struct bt_ctf_field_type_common *packet_header_type,
+               struct bt_ctf_field_type_common *packet_context_type,
+               struct bt_ctf_field_type_common *event_header_type,
+               struct bt_ctf_field_type_common *stream_event_ctx_type,
+               struct bt_ctf_field_type_common *event_context_type,
+               struct bt_ctf_field_type_common *event_payload_type)
+{
+       int ret = 0;
+
+       BT_LOGV("Validating event class field types: "
+               "packet-header-ft-addr=%p, "
+               "packet-context-ft-addr=%p, "
+               "event-header-ft-addr=%p, "
+               "stream-event-context-ft-addr=%p, "
+               "event-context-ft-addr=%p, "
+               "event-payload-ft-addr=%p",
+               packet_header_type, packet_context_type, event_header_type,
+               stream_event_ctx_type, event_context_type, event_payload_type);
+
+       /* Resolve sequence type lengths and variant type tags first */
+       ret = bt_ctf_resolve_types(environment, packet_header_type,
+               packet_context_type, event_header_type, stream_event_ctx_type,
+               event_context_type, event_payload_type,
+               BT_CTF_RESOLVE_FLAG_EVENT_CONTEXT |
+               BT_CTF_RESOLVE_FLAG_EVENT_PAYLOAD);
+       if (ret) {
+               BT_LOGW("Cannot resolve event class field types: ret=%d",
+                       ret);
+               goto end;
+       }
+
+       /* Validate field types individually */
+       if (event_context_type) {
+               ret = bt_ctf_field_type_common_validate(event_context_type);
+               if (ret) {
+                       BT_LOGW("Invalid event class's context field type: "
+                               "ret=%d", ret);
+                       goto end;
+               }
+       }
+
+       if (event_payload_type) {
+               ret = bt_ctf_field_type_common_validate(event_payload_type);
+               if (ret) {
+                       BT_LOGW("Invalid event class's payload field type: "
+                               "ret=%d", ret);
+                       goto end;
+               }
+       }
+
+end:
+       return ret;
+}
+
+/*
+ * This function resolves and validates the field types of a stream
+ * class. Only `packet_context_type`, `event_header_type`, and
+ * `stream_event_ctx_type` are resolved and validated; the other field
+ * type is used as an eventual resolving target.
+ *
+ * All parameters are owned by the caller.
+ */
+static
+int validate_stream_class_types(struct bt_value *environment,
+               struct bt_ctf_field_type_common *packet_header_type,
+               struct bt_ctf_field_type_common *packet_context_type,
+               struct bt_ctf_field_type_common *event_header_type,
+               struct bt_ctf_field_type_common *stream_event_ctx_type)
+{
+       int ret = 0;
+
+       BT_LOGV("Validating stream class field types: "
+               "packet-header-ft-addr=%p, "
+               "packet-context-ft-addr=%p, "
+               "event-header-ft-addr=%p, "
+               "stream-event-context-ft-addr=%p",
+               packet_header_type, packet_context_type, event_header_type,
+               stream_event_ctx_type);
+
+       /* Resolve sequence type lengths and variant type tags first */
+       ret = bt_ctf_resolve_types(environment, packet_header_type,
+               packet_context_type, event_header_type, stream_event_ctx_type,
+               NULL, NULL,
+               BT_CTF_RESOLVE_FLAG_PACKET_CONTEXT |
+               BT_CTF_RESOLVE_FLAG_EVENT_HEADER |
+               BT_CTF_RESOLVE_FLAG_STREAM_EVENT_CTX);
+       if (ret) {
+               BT_LOGW("Cannot resolve stream class field types: ret=%d",
+                       ret);
+               goto end;
+       }
+
+       /* Validate field types individually */
+       if (packet_context_type) {
+               ret = bt_ctf_field_type_common_validate(packet_context_type);
+               if (ret) {
+                       BT_LOGW("Invalid stream class's packet context field type: "
+                               "ret=%d", ret);
+                       goto end;
+               }
+       }
+
+       if (event_header_type) {
+               ret = bt_ctf_field_type_common_validate(event_header_type);
+               if (ret) {
+                       BT_LOGW("Invalid stream class's event header field type: "
+                               "ret=%d", ret);
+                       goto end;
+               }
+       }
+
+       if (stream_event_ctx_type) {
+               ret = bt_ctf_field_type_common_validate(
+                       stream_event_ctx_type);
+               if (ret) {
+                       BT_LOGW("Invalid stream class's event context field type: "
+                               "ret=%d", ret);
+                       goto end;
+               }
+       }
+
+end:
+       return ret;
+}
+
+/*
+ * This function resolves and validates the field types of a trace.
+ *
+ * All parameters are owned by the caller.
+ */
+static
+int validate_trace_types(struct bt_value *environment,
+               struct bt_ctf_field_type_common *packet_header_type)
+{
+       int ret = 0;
+
+       BT_LOGV("Validating event class field types: "
+               "packet-header-ft-addr=%p", packet_header_type);
+
+       /* Resolve sequence type lengths and variant type tags first */
+       ret = bt_ctf_resolve_types(environment, packet_header_type,
+               NULL, NULL, NULL, NULL, NULL,
+               BT_CTF_RESOLVE_FLAG_PACKET_HEADER);
+       if (ret) {
+               BT_LOGW("Cannot resolve trace field types: ret=%d",
+                       ret);
+               goto end;
+       }
+
+       /* Validate field types individually */
+       if (packet_header_type) {
+               ret = bt_ctf_field_type_common_validate(packet_header_type);
+               if (ret) {
+                       BT_LOGW("Invalid trace's packet header field type: "
+                               "ret=%d", ret);
+                       goto end;
+               }
+       }
+
+end:
+       return ret;
+}
+
+/*
+ * Checks whether or not `field_type` contains a variant or a sequence
+ * field type, recursively. Returns 1 if it's the case.
+ *
+ * `field_type` is owned by the caller.
+ */
+static
+int field_type_contains_sequence_or_variant_ft(struct bt_ctf_field_type_common *type)
+{
+       int ret = 0;
+       enum bt_ctf_field_type_id type_id = bt_ctf_field_type_common_get_type_id(type);
+
+       switch (type_id) {
+       case BT_CTF_FIELD_TYPE_ID_SEQUENCE:
+       case BT_CTF_FIELD_TYPE_ID_VARIANT:
+               ret = 1;
+               goto end;
+       case BT_CTF_FIELD_TYPE_ID_ARRAY:
+       case BT_CTF_FIELD_TYPE_ID_STRUCT:
+       {
+               int i;
+               int field_count = bt_ctf_field_type_common_get_field_count(type);
+
+               if (field_count < 0) {
+                       ret = -1;
+                       goto end;
+               }
+
+               for (i = 0; i < field_count; ++i) {
+                       struct bt_ctf_field_type_common *child_type =
+                               bt_ctf_field_type_common_borrow_field_at_index(
+                                       type, i);
+
+                       ret = field_type_contains_sequence_or_variant_ft(
+                               child_type);
+                       if (ret != 0) {
+                               goto end;
+                       }
+               }
+               break;
+       }
+       default:
+               break;
+       }
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+int bt_ctf_validate_class_types(struct bt_value *environment,
+               struct bt_ctf_field_type_common *packet_header_type,
+               struct bt_ctf_field_type_common *packet_context_type,
+               struct bt_ctf_field_type_common *event_header_type,
+               struct bt_ctf_field_type_common *stream_event_ctx_type,
+               struct bt_ctf_field_type_common *event_context_type,
+               struct bt_ctf_field_type_common *event_payload_type,
+               int trace_valid, int stream_class_valid, int event_class_valid,
+               struct bt_ctf_validation_output *output,
+               enum bt_ctf_validation_flag validate_flags,
+               bt_ctf_validation_flag_copy_field_type_func copy_field_type_func)
+{
+       int ret = 0;
+       int contains_seq_var;
+       int valid_ret;
+
+       BT_LOGV("Validating field types: "
+               "packet-header-ft-addr=%p, "
+               "packet-context-ft-addr=%p, "
+               "event-header-ft-addr=%p, "
+               "stream-event-context-ft-addr=%p, "
+               "event-context-ft-addr=%p, "
+               "event-payload-ft-addr=%p, "
+               "trace-is-valid=%d, stream-class-is-valid=%d, "
+               "event-class-is-valid=%d, validation-flags=%x",
+               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,
+               (unsigned int) validate_flags);
+
+       /* Clean output values */
+       memset(output, 0, sizeof(*output));
+
+       /* Set initial valid flags according to valid parameters */
+       if (trace_valid) {
+               output->valid_flags |= BT_CTF_VALIDATION_FLAG_TRACE;
+       }
+
+       if (stream_class_valid) {
+               output->valid_flags |= BT_CTF_VALIDATION_FLAG_STREAM;
+       }
+
+       if (event_class_valid) {
+               output->valid_flags |= BT_CTF_VALIDATION_FLAG_EVENT;
+       }
+
+       /* Own the type parameters */
+       bt_get(packet_header_type);
+       bt_get(packet_context_type);
+       bt_get(event_header_type);
+       bt_get(stream_event_ctx_type);
+       bt_get(event_context_type);
+       bt_get(event_payload_type);
+
+       /* Validate trace */
+       if ((validate_flags & BT_CTF_VALIDATION_FLAG_TRACE) && !trace_valid) {
+               struct bt_ctf_field_type_common *packet_header_type_copy = NULL;
+
+               /* Create field type copies */
+               if (packet_header_type) {
+                       contains_seq_var =
+                               field_type_contains_sequence_or_variant_ft(
+                                       packet_header_type);
+                       if (contains_seq_var < 0) {
+                               ret = contains_seq_var;
+                               goto error;
+                       } else if (!contains_seq_var) {
+                               /* No copy is needed */
+                               packet_header_type_copy = packet_header_type;
+                               bt_get(packet_header_type_copy);
+                               goto skip_packet_header_type_copy;
+                       }
+
+                       BT_LOGV_STR("Copying packet header field type because it contains at least one sequence or variant field type.");
+                       packet_header_type_copy =
+                               copy_field_type_func(packet_header_type);
+                       if (!packet_header_type_copy) {
+                               ret = -1;
+                               BT_LOGE_STR("Cannot copy packet header field type.");
+                               goto error;
+                       }
+
+                       /*
+                        * Freeze this copy: if it's returned to the
+                        * caller, it cannot be modified any way since
+                        * it will be resolved.
+                        */
+                       bt_ctf_field_type_common_freeze(packet_header_type_copy);
+               }
+
+skip_packet_header_type_copy:
+               /* Put original reference and move copy */
+               BT_MOVE(packet_header_type, packet_header_type_copy);
+
+               /* Validate trace field types */
+               valid_ret = validate_trace_types(environment,
+                       packet_header_type);
+               if (valid_ret == 0) {
+                       /* Trace is valid */
+                       output->valid_flags |= BT_CTF_VALIDATION_FLAG_TRACE;
+               }
+       }
+
+       /* Validate stream class */
+       if ((validate_flags & BT_CTF_VALIDATION_FLAG_STREAM) &&
+                       !stream_class_valid) {
+               struct bt_ctf_field_type_common *packet_context_type_copy = NULL;
+               struct bt_ctf_field_type_common *event_header_type_copy = NULL;
+               struct bt_ctf_field_type_common *stream_event_ctx_type_copy = NULL;
+
+               if (packet_context_type) {
+                       contains_seq_var =
+                               field_type_contains_sequence_or_variant_ft(
+                                       packet_context_type);
+                       if (contains_seq_var < 0) {
+                               ret = contains_seq_var;
+                               goto error;
+                       } else if (!contains_seq_var) {
+                               /* No copy is needed */
+                               packet_context_type_copy = packet_context_type;
+                               bt_get(packet_context_type_copy);
+                               goto skip_packet_context_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 =
+                               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;
+                       }
+
+                       /*
+                        * Freeze this copy: if it's returned to the
+                        * caller, it cannot be modified any way since
+                        * it will be resolved.
+                        */
+                       bt_ctf_field_type_common_freeze(packet_context_type_copy);
+               }
+
+skip_packet_context_type_copy:
+               if (event_header_type) {
+                       contains_seq_var =
+                               field_type_contains_sequence_or_variant_ft(
+                                       event_header_type);
+                       if (contains_seq_var < 0) {
+                               ret = contains_seq_var;
+                               goto error;
+                       } else if (!contains_seq_var) {
+                               /* No copy is needed */
+                               event_header_type_copy = event_header_type;
+                               bt_get(event_header_type_copy);
+                               goto skip_event_header_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 =
+                               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;
+                       }
+
+                       /*
+                        * Freeze this copy: if it's returned to the
+                        * caller, it cannot be modified any way since
+                        * it will be resolved.
+                        */
+                       bt_ctf_field_type_common_freeze(event_header_type_copy);
+               }
+
+skip_event_header_type_copy:
+               if (stream_event_ctx_type) {
+                       contains_seq_var =
+                               field_type_contains_sequence_or_variant_ft(
+                                       stream_event_ctx_type);
+                       if (contains_seq_var < 0) {
+                               ret = contains_seq_var;
+                               goto error;
+                       } else if (!contains_seq_var) {
+                               /* No copy is needed */
+                               stream_event_ctx_type_copy =
+                                       stream_event_ctx_type;
+                               bt_get(stream_event_ctx_type_copy);
+                               goto skip_stream_event_ctx_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 =
+                               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;
+                       }
+
+                       /*
+                        * Freeze this copy: if it's returned to the
+                        * caller, it cannot be modified any way since
+                        * it will be resolved.
+                        */
+                       bt_ctf_field_type_common_freeze(stream_event_ctx_type_copy);
+               }
+
+skip_stream_event_ctx_type_copy:
+               /* Put original references and move copies */
+               BT_MOVE(packet_context_type, packet_context_type_copy);
+               BT_MOVE(event_header_type, event_header_type_copy);
+               BT_MOVE(stream_event_ctx_type, stream_event_ctx_type_copy);
+
+               /* Validate stream class field types */
+               valid_ret = validate_stream_class_types(environment,
+                       packet_header_type, packet_context_type,
+                       event_header_type, stream_event_ctx_type);
+               if (valid_ret == 0) {
+                       /* Stream class is valid */
+                       output->valid_flags |= BT_CTF_VALIDATION_FLAG_STREAM;
+               }
+
+               goto sc_validation_done;
+
+sc_validation_error:
+               BT_PUT(packet_context_type_copy);
+               BT_PUT(event_header_type_copy);
+               BT_PUT(stream_event_ctx_type_copy);
+               ret = -1;
+               goto error;
+       }
+
+sc_validation_done:
+       /* Validate event class */
+       if ((validate_flags & BT_CTF_VALIDATION_FLAG_EVENT) &&
+                       !event_class_valid) {
+               struct bt_ctf_field_type_common *event_context_type_copy = NULL;
+               struct bt_ctf_field_type_common *event_payload_type_copy = NULL;
+
+               if (event_context_type) {
+                       contains_seq_var =
+                               field_type_contains_sequence_or_variant_ft(
+                                       event_context_type);
+                       if (contains_seq_var < 0) {
+                               ret = contains_seq_var;
+                               goto error;
+                       } else if (!contains_seq_var) {
+                               /* No copy is needed */
+                               event_context_type_copy = event_context_type;
+                               bt_get(event_context_type_copy);
+                               goto skip_event_context_type_copy;
+                       }
+
+                       BT_LOGV_STR("Copying event context field type because it contains at least one sequence or variant field type.");
+                       event_context_type_copy =
+                               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;
+                       }
+
+                       /*
+                        * Freeze this copy: if it's returned to the
+                        * caller, it cannot be modified any way since
+                        * it will be resolved.
+                        */
+                       bt_ctf_field_type_common_freeze(event_context_type_copy);
+               }
+
+skip_event_context_type_copy:
+               if (event_payload_type) {
+                       contains_seq_var =
+                               field_type_contains_sequence_or_variant_ft(
+                                       event_payload_type);
+                       if (contains_seq_var < 0) {
+                               ret = contains_seq_var;
+                               goto error;
+                       } else if (!contains_seq_var) {
+                               /* No copy is needed */
+                               event_payload_type_copy = event_payload_type;
+                               bt_get(event_payload_type_copy);
+                               goto skip_event_payload_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 =
+                               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;
+                       }
+
+                       /*
+                        * Freeze this copy: if it's returned to the
+                        * caller, it cannot be modified any way since
+                        * it will be resolved.
+                        */
+                       bt_ctf_field_type_common_freeze(event_payload_type_copy);
+               }
+
+skip_event_payload_type_copy:
+               /* Put original references and move copies */
+               BT_MOVE(event_context_type, event_context_type_copy);
+               BT_MOVE(event_payload_type, event_payload_type_copy);
+
+               /* Validate event class field types */
+               valid_ret = validate_event_class_types(environment,
+                       packet_header_type, packet_context_type,
+                       event_header_type, stream_event_ctx_type,
+                       event_context_type, event_payload_type);
+               if (valid_ret == 0) {
+                       /* Event class is valid */
+                       output->valid_flags |= BT_CTF_VALIDATION_FLAG_EVENT;
+               }
+
+               goto ec_validation_done;
+
+ec_validation_error:
+               BT_PUT(event_context_type_copy);
+               BT_PUT(event_payload_type_copy);
+               ret = -1;
+               goto error;
+       }
+
+ec_validation_done:
+       /*
+        * Validation is complete. Move the field types that were used
+        * to validate (and that were possibly altered by the validation
+        * process) to the output values.
+        */
+       BT_MOVE(output->packet_header_type, packet_header_type);
+       BT_MOVE(output->packet_context_type, packet_context_type);
+       BT_MOVE(output->event_header_type, event_header_type);
+       BT_MOVE(output->stream_event_ctx_type, stream_event_ctx_type);
+       BT_MOVE(output->event_context_type, event_context_type);
+       BT_MOVE(output->event_payload_type, event_payload_type);
+       return ret;
+
+error:
+       BT_PUT(packet_header_type);
+       BT_PUT(packet_context_type);
+       BT_PUT(event_header_type);
+       BT_PUT(stream_event_ctx_type);
+       BT_PUT(event_context_type);
+       BT_PUT(event_payload_type);
+       return ret;
+}
+
+BT_HIDDEN
+void bt_ctf_validation_replace_types(struct bt_ctf_trace_common *trace,
+               struct bt_ctf_stream_class_common *stream_class,
+               struct bt_ctf_event_class_common *event_class,
+               struct bt_ctf_validation_output *output,
+               enum bt_ctf_validation_flag replace_flags)
+{
+       if ((replace_flags & BT_CTF_VALIDATION_FLAG_TRACE) && trace) {
+               bt_ctf_field_type_common_freeze(trace->packet_header_field_type);
+               BT_MOVE(trace->packet_header_field_type,
+                       output->packet_header_type);
+       }
+
+       if ((replace_flags & BT_CTF_VALIDATION_FLAG_STREAM) && stream_class) {
+               bt_ctf_field_type_common_freeze(stream_class->packet_context_field_type);
+               bt_ctf_field_type_common_freeze(stream_class->event_header_field_type);
+               bt_ctf_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_field_type,
+                       output->event_header_type);
+               BT_MOVE(stream_class->event_context_field_type,
+                       output->stream_event_ctx_type);
+       }
+
+       if ((replace_flags & BT_CTF_VALIDATION_FLAG_EVENT) && event_class) {
+               bt_ctf_field_type_common_freeze(event_class->context_field_type);
+               bt_ctf_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);
+       }
+}
+
+BT_HIDDEN
+void bt_ctf_validation_output_put_types(
+               struct bt_ctf_validation_output *output)
+{
+       BT_PUT(output->packet_header_type);
+       BT_PUT(output->packet_context_type);
+       BT_PUT(output->event_header_type);
+       BT_PUT(output->stream_event_ctx_type);
+       BT_PUT(output->event_context_type);
+       BT_PUT(output->event_payload_type);
+}
diff --git a/lib/ctf-writer/visitor.c b/lib/ctf-writer/visitor.c
new file mode 100644 (file)
index 0000000..726512c
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * visitor.c
+ *
+ * Babeltrace CTF writer - Visitor
+ *
+ * Copyright 2016 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.
+ */
+
+#include <babeltrace/ctf-writer/visitor-internal.h>
+#include <babeltrace/ref.h>
+
+BT_HIDDEN
+int bt_ctf_visitor_helper(struct bt_ctf_visitor_object *root,
+               bt_ctf_child_count_accessor child_counter,
+               bt_ctf_child_accessor child_accessor,
+               bt_ctf_child_visitor child_visitor,
+               bt_ctf_visitor visitor,
+               void *data)
+{
+       int ret, child_count, i;
+
+       ret = visitor(root, data);
+       if (ret) {
+               goto end;
+       }
+
+       child_count = child_counter(root->object);
+       if (child_count < 0) {
+               ret = child_count;
+               goto end;
+       }
+
+       for (i = 0; i < child_count; i++) {
+               void *child;
+
+               child = child_accessor(root->object, i);
+               if (!child) {
+                       ret = -1;
+                       goto end;
+               }
+               ret = child_visitor(child, visitor, data);
+               BT_PUT(child);
+               if (ret) {
+                       goto end;
+               }
+       }
+end:
+       return ret;
+}
+
+enum bt_ctf_visitor_object_type bt_ctf_visitor_object_get_type(
+               struct bt_ctf_visitor_object *object)
+{
+       enum bt_ctf_visitor_object_type ret = BT_CTF_VISITOR_OBJECT_TYPE_UNKNOWN;
+
+       if (!object) {
+               goto end;
+       }
+
+       ret = object->type;
+end:
+       return ret;
+}
+
+void *bt_ctf_visitor_object_get_object(struct bt_ctf_visitor_object *object)
+{
+       void *ret = NULL;
+
+       if (!object) {
+               goto end;
+       }
+
+       ret = object->object;
+end:
+       return ret;
+}
index 0b360c378a34bac90c9e0071a09ad33468e4170f..4a5a45ff56e8f7133b095c1fe01ea7233a8d2242 100644 (file)
@@ -29,6 +29,9 @@
 #define BT_LOG_TAG "CTF-WRITER"
 #include <babeltrace/lib-logging-internal.h>
 
+#include <babeltrace/assert-internal.h>
+#include <babeltrace/compat/uuid-internal.h>
+#include <babeltrace/compiler-internal.h>
 #include <babeltrace/ctf-writer/clock-internal.h>
 #include <babeltrace/ctf-writer/field-types-internal.h>
 #include <babeltrace/ctf-writer/fields-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>
-#include <babeltrace/compat/uuid-internal.h>
-#include <babeltrace/assert-internal.h>
+#include <babeltrace/ref.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <sys/stat.h>
-#include <errno.h>
 #include <unistd.h>
-#include <fcntl.h>
-#include <inttypes.h>
 
 static
 void bt_ctf_writer_destroy(struct bt_object *obj);
@@ -429,18 +429,18 @@ end:
 }
 
 BT_HIDDEN
-const char *get_byte_order_string(enum bt_byte_order byte_order)
+const char *bt_ctf_get_byte_order_string(enum bt_ctf_byte_order byte_order)
 {
        const char *string;
 
        switch (byte_order) {
-       case BT_BYTE_ORDER_LITTLE_ENDIAN:
+       case BT_CTF_BYTE_ORDER_LITTLE_ENDIAN:
                string = "le";
                break;
-       case BT_BYTE_ORDER_BIG_ENDIAN:
+       case BT_CTF_BYTE_ORDER_BIG_ENDIAN:
                string = "be";
                break;
-       case BT_BYTE_ORDER_NATIVE:
+       case BT_CTF_BYTE_ORDER_NATIVE:
                string = "native";
                break;
        default:
index b8ab574580ec5234e76ebca274bfbf6bc369c1ae..7556a545b4481ca4f62e8b53807c2d6a9f98354b 100644 (file)
 #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/component-class-internal.h>
 #include <babeltrace/graph/component-class-sink-colander-internal.h>
 #include <babeltrace/graph/component-filter-internal.h>
@@ -272,13 +264,6 @@ static inline void format_field_type(char **buf_ch, bool extended,
                (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)
 {
@@ -425,44 +410,6 @@ static inline void format_field(char **buf_ch, bool extended,
        }
 }
 
-static inline void format_writer_field(char **buf_ch, bool extended,
-               const char *prefix, struct bt_ctf_field *field)
-{
-       struct bt_field_common *common_field = (void *) field;
-
-       format_field_common(buf_ch, extended, prefix, (void *) field);
-
-       if (!extended) {
-               return;
-       }
-
-       if (!common_field->type) {
-               return;
-       }
-
-       switch (common_field->type->id) {
-       case BT_FIELD_TYPE_ID_ENUM:
-       {
-               struct bt_ctf_field_enumeration *enumeration = (void *) field;
-
-               if (enumeration->container) {
-                       format_writer_field(buf_ch, extended, prefix,
-                               (void *) enumeration->container);
-               }
-               break;
-       }
-       case BT_FIELD_TYPE_ID_VARIANT:
-       {
-               struct bt_ctf_field_variant *variant = (void *) field;
-
-               BUF_APPEND(", %stag-field-addr=%p", PRFIELD(variant->tag));
-               break;
-       }
-       default:
-               break;
-       }
-}
-
 static inline void format_field_path(char **buf_ch, bool extended,
                const char *prefix, struct bt_field_path *field_path)
 {
@@ -541,12 +488,6 @@ static inline void format_trace(char **buf_ch, bool extended,
                &trace->packet_header_field_pool);
 }
 
-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)
@@ -608,21 +549,6 @@ static inline void format_stream_class(char **buf_ch, bool extended,
                &stream_class->packet_context_field_pool);
 }
 
-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,
@@ -690,15 +616,6 @@ static inline void format_event_class(char **buf_ch, bool extended,
        format_object_pool(buf_ch, extended, prefix, &event_class->event_pool);
 }
 
-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,
@@ -753,55 +670,6 @@ static inline void format_stream(char **buf_ch, bool extended,
        format_object_pool(buf_ch, extended, prefix, &stream->packet_pool);
 }
 
-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));
-
-       if (stream->events) {
-               BUF_APPEND(", %sevent-count=%u", PRFIELD(stream->events->len));
-       }
-
-       BUF_APPEND(", %sheader-field-addr=%p, %scontext-field-addr=%p"
-               ", %sfd=%d, %smmap-offset=%zu, "
-               "%smmap-base-offset=%zu, %spacket-size=%" PRIu64 ", "
-               "%soffset=%" PRId64 ", "
-               "%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->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,
                const char *prefix, struct bt_packet *packet)
 {
@@ -917,15 +785,6 @@ 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)
 {
@@ -1359,12 +1218,6 @@ static inline void format_plugin(char **buf_ch, bool extended,
        }
 }
 
-static inline void format_ctf_writer(char **buf_ch, bool extended,
-               const char *prefix, struct bt_ctf_writer *writer)
-{
-       /* TODO */
-}
-
 static inline void format_stream_class_common_common(char **buf_ch,
                bool extended, const char *prefix,
                struct bt_stream_class_common *stream_class)
@@ -1411,7 +1264,6 @@ static inline void handle_conversion_specifier_bt(void *priv_data,
        void *obj;
        enum {
                CAT_DEFAULT,
-               CAT_WRITER,
                CAT_COMMON,
        } cat = CAT_DEFAULT;
 
@@ -1442,10 +1294,7 @@ 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 == '_') {
+       if (*fmt_ch == '_') {
                cat = CAT_COMMON;
                fmt_ch++;
        }
@@ -1530,36 +1379,6 @@ static inline void handle_conversion_specifier_bt(void *priv_data,
                        abort();
                }
                break;
-       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 CAT_COMMON:
                switch (*fmt_ch) {
                case 'F':
index 34967e66d6fad84c2215b2f2f01cb3a21420ac45..c5f57ae3a62dc45d9416fb2128f6b32d5ec9f34a 100644 (file)
@@ -1262,9 +1262,9 @@ enum bt_component_status print_field(struct pretty_component *pretty,
 
        type_id = bt_field_get_type_id(field);
        switch (type_id) {
-       case BT_CTF_FIELD_TYPE_ID_INTEGER:
+       case BT_FIELD_TYPE_ID_INTEGER:
                return print_integer(pretty, field);
-       case BT_CTF_FIELD_TYPE_ID_FLOAT:
+       case BT_FIELD_TYPE_ID_FLOAT:
        {
                double v;
 
@@ -1280,9 +1280,9 @@ enum bt_component_status print_field(struct pretty_component *pretty,
                }
                return BT_COMPONENT_STATUS_OK;
        }
-       case BT_CTF_FIELD_TYPE_ID_ENUM:
+       case BT_FIELD_TYPE_ID_ENUM:
                return print_enum(pretty, field);
-       case BT_CTF_FIELD_TYPE_ID_STRING:
+       case BT_FIELD_TYPE_ID_STRING:
        {
                const char *str;
 
@@ -1300,14 +1300,14 @@ enum bt_component_status print_field(struct pretty_component *pretty,
                }
                return BT_COMPONENT_STATUS_OK;
        }
-       case BT_CTF_FIELD_TYPE_ID_STRUCT:
+       case BT_FIELD_TYPE_ID_STRUCT:
                return print_struct(pretty, field, print_names, filter_fields,
                                filter_array_len);
-       case BT_CTF_FIELD_TYPE_ID_VARIANT:
+       case BT_FIELD_TYPE_ID_VARIANT:
                return print_variant(pretty, field, print_names);
-       case BT_CTF_FIELD_TYPE_ID_ARRAY:
+       case BT_FIELD_TYPE_ID_ARRAY:
                return print_array(pretty, field, print_names);
-       case BT_CTF_FIELD_TYPE_ID_SEQUENCE:
+       case BT_FIELD_TYPE_ID_SEQUENCE:
                return print_sequence(pretty, field, print_names);
        default:
                // TODO: log instead
index a70fd8a16cfd5a7f46f7475956cd339f8d45a280..4b73b054c61852217e257c0cad7db70624b36eaf 100644 (file)
@@ -286,7 +286,7 @@ int ns_from_integer_field(struct bt_field *integer, int64_t *ns)
                goto end;
        }
 
-       is_signed = bt_ctf_field_type_integer_get_signed(integer_type);
+       is_signed = bt_field_type_integer_is_signed(integer_type);
        if (!is_signed) {
                ret = bt_field_unsigned_integer_get_value(integer,
                                &raw_clock_value);
index 95b7dbcc5bd2b10c66275cbe85ae943aecec3967..97c11cd38c2ecb055ddb0c6b0079372e21fc3878 100644 (file)
@@ -57,7 +57,7 @@
 #define DEFAULT_CLOCK_TIME 0
 #define DEFAULT_CLOCK_VALUE 0
 
-#define NR_TESTS 346
+#define NR_TESTS 342
 
 struct bt_utsname {
        char sysname[BABELTRACE_HOST_NAME_MAX];
@@ -1596,7 +1596,6 @@ 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_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;
@@ -2018,20 +2017,6 @@ int main(int argc, char **argv)
         * class to the writer's trace, thus registering the stream
         * class's clock to the trace.
         */
-       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_ctf_trace_get_clock_class returns the right clock instance");
-       bt_put(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_ctf_trace_get_clock_class returns the right clock instance");
-       bt_put(ret_clock_class);
-       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_ctf_stream_get_class(stream1);
        ok(ret_stream_class,
This page took 0.296581 seconds and 4 git commands to generate.